Skip to content

Commit 0b48675

Browse files
authored
Merge pull request #1619 from contiv/dev
dev->master
2 parents c287772 + 039e265 commit 0b48675

File tree

5 files changed

+135
-97
lines changed

5 files changed

+135
-97
lines changed

plugins/service/processor/processor_impl.go

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@ func (sp *ServiceProcessor) renderService(svc *Service, oldContivSvc *renderer.C
283283
var err error
284284
newContivSvc := svc.GetContivService()
285285
newBackends := svc.GetLocalBackends()
286+
otherContiveServices := sp.otherContivServices(svc)
286287

287288
// Render service.
288289
if newContivSvc != nil {
@@ -294,15 +295,15 @@ func (sp *ServiceProcessor) renderService(svc *Service, oldContivSvc *renderer.C
294295
}
295296
} else {
296297
for _, renderer := range sp.renderers {
297-
if err = renderer.UpdateService(oldContivSvc, newContivSvc); err != nil {
298+
if err = renderer.UpdateService(oldContivSvc, newContivSvc, otherContiveServices); err != nil {
298299
return err
299300
}
300301
}
301302
}
302303
} else {
303304
if oldContivSvc != nil {
304305
for _, renderer := range sp.renderers {
305-
if err = renderer.DeleteService(oldContivSvc); err != nil {
306+
if err = renderer.DeleteService(oldContivSvc, otherContiveServices); err != nil {
306307
return err
307308
}
308309
}
@@ -362,6 +363,19 @@ func (sp *ServiceProcessor) renderService(svc *Service, oldContivSvc *renderer.C
362363
return err
363364
}
364365

366+
// otherContivServices retrieves all existing ContivService-s except the one given as parameter <exceludeService>
367+
func (sp *ServiceProcessor) otherContivServices(excludedService *Service) []*renderer.ContivService {
368+
otherServices := make([]*renderer.ContivService, 0, len(sp.services))
369+
for _, service := range sp.services {
370+
if service != excludedService {
371+
if contivService := service.GetContivService(); contivService != nil {
372+
otherServices = append(otherServices, contivService)
373+
}
374+
}
375+
}
376+
return otherServices
377+
}
378+
365379
// renderNodePorts re-renders all services with a node port.
366380
func (sp *ServiceProcessor) renderNodePorts() error {
367381
sp.Log.Debug("ServiceProcessor - renderNodePorts()")

plugins/service/renderer/api.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,11 +80,13 @@ type ServiceRendererAPI interface {
8080
AddService(service *ContivService) error
8181

8282
// UpdateService informs renderer about a change in the configuration
83-
// or in the state of a service.
84-
UpdateService(oldService, newService *ContivService) error
83+
// or in the state of a service. The renderer can also use info about
84+
// other existing services to perform update correctly.
85+
UpdateService(oldService, newService *ContivService, otherExistingServices []*ContivService) error
8586

86-
// DeleteService is called for every removed service.
87-
DeleteService(service *ContivService) error
87+
// DeleteService is called for every removed service. The renderer can
88+
// also use info about other existing services to handle service removal correctly.
89+
DeleteService(service *ContivService, otherExistingServices []*ContivService) error
8890

8991
// UpdateNodePortServices is called whenever the set of node IPs in the cluster
9092
// changes.

plugins/service/renderer/ipv6route/ipv6route_renderer.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ func (rndr *Renderer) AddService(service *renderer.ContivService) error {
128128
}
129129

130130
// UpdateService updates VPP config for a changed service.
131-
func (rndr *Renderer) UpdateService(oldService, newService *renderer.ContivService) error {
131+
func (rndr *Renderer) UpdateService(oldService, newService *renderer.ContivService, otherExistingServices []*renderer.ContivService) error {
132132
if rndr.snatOnly {
133133
return nil
134134
}
@@ -147,7 +147,7 @@ func (rndr *Renderer) UpdateService(oldService, newService *renderer.ContivServi
147147
}
148148

149149
// DeleteService removes VPP config associated with a freshly un-deployed service.
150-
func (rndr *Renderer) DeleteService(service *renderer.ContivService) error {
150+
func (rndr *Renderer) DeleteService(service *renderer.ContivService, otherExistingServices []*renderer.ContivService) error {
151151
if rndr.snatOnly {
152152
return nil
153153
}

plugins/service/renderer/nat44/nat44_renderer.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ func (rndr *Renderer) AddService(service *renderer.ContivService) error {
155155
}
156156

157157
// UpdateService updates destination-NAT rules for a changed service.
158-
func (rndr *Renderer) UpdateService(oldService, newService *renderer.ContivService) error {
158+
func (rndr *Renderer) UpdateService(oldService, newService *renderer.ContivService, otherExistingServices []*renderer.ContivService) error {
159159
if rndr.snatOnly {
160160
return nil
161161
}
@@ -167,7 +167,7 @@ func (rndr *Renderer) UpdateService(oldService, newService *renderer.ContivServi
167167

168168
// DeleteService removes destination-NAT configuration associated with a freshly
169169
// un-deployed service.
170-
func (rndr *Renderer) DeleteService(service *renderer.ContivService) error {
170+
func (rndr *Renderer) DeleteService(service *renderer.ContivService, otherExistingServices []*renderer.ContivService) error {
171171
if rndr.snatOnly {
172172
return nil
173173
}

plugins/service/renderer/srv6/srv6_renderer.go

Lines changed: 109 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -125,41 +125,41 @@ func (r *Renderer) AddService(service *renderer.ContivService) error {
125125

126126
txn := r.UpdateTxnFactory(fmt.Sprintf("add service '%v'", service.ID))
127127

128-
addDelConfig, updateConfig := r.renderService(service, serviceAdd)
128+
addDelConfig, updateConfig := r.renderService(service, serviceAdd, nil)
129129
controller.PutAll(txn, addDelConfig)
130130
controller.PutAll(txn, updateConfig)
131131

132132
return nil
133133
}
134134

135135
// UpdateService updates VPP config for a changed service.
136-
func (r *Renderer) UpdateService(oldService, newService *renderer.ContivService) error {
136+
func (r *Renderer) UpdateService(oldService, newService *renderer.ContivService, otherExistingServices []*renderer.ContivService) error {
137137
if r.snatOnly {
138138
return nil
139139
}
140140

141141
txn := r.UpdateTxnFactory(fmt.Sprintf("update service '%v'", newService.ID))
142142

143-
addDelConfig, updateConfig := r.renderService(oldService, serviceDel)
143+
addDelConfig, updateConfig := r.renderService(oldService, serviceDel, otherExistingServices)
144144
controller.DeleteAll(txn, addDelConfig)
145145
controller.PutAll(txn, updateConfig)
146146

147-
addDelConfig, updateConfig = r.renderService(newService, serviceAdd)
147+
addDelConfig, updateConfig = r.renderService(newService, serviceAdd, nil)
148148
controller.PutAll(txn, addDelConfig)
149149
controller.PutAll(txn, updateConfig)
150150

151151
return nil
152152
}
153153

154154
// DeleteService removes VPP config associated with a freshly un-deployed service.
155-
func (r *Renderer) DeleteService(service *renderer.ContivService) error {
155+
func (r *Renderer) DeleteService(service *renderer.ContivService, otherExistingServices []*renderer.ContivService) error {
156156
if r.snatOnly {
157157
return nil
158158
}
159159

160160
txn := r.UpdateTxnFactory(fmt.Sprintf("delete service '%v'", service.ID))
161161

162-
addDelConfig, updateConfig := r.renderService(service, serviceDel)
162+
addDelConfig, updateConfig := r.renderService(service, serviceDel, otherExistingServices)
163163
controller.DeleteAll(txn, addDelConfig)
164164
controller.PutAll(txn, updateConfig)
165165

@@ -191,7 +191,7 @@ func (r *Renderer) Resync(resyncEv *renderer.ResyncEventData) error {
191191

192192
// add configuration for current services (resync should return desired state, not remove previous state)
193193
for _, service := range resyncEv.Services {
194-
addDelConfig, updateConfig := r.renderService(service, serviceAdd)
194+
addDelConfig, updateConfig := r.renderService(service, serviceAdd, nil)
195195
controller.PutAll(txn, addDelConfig)
196196
controller.PutAll(txn, updateConfig)
197197
}
@@ -202,73 +202,24 @@ func (r *Renderer) Resync(resyncEv *renderer.ResyncEventData) error {
202202
// renderService renders Contiv service to VPP configuration.
203203
// addDelConfig sliceContains KV pairs that should be added/deleted,
204204
// updateConfig sliceContains KV pair that should be updated.
205-
func (r *Renderer) renderService(service *renderer.ContivService, oper operation) (
205+
func (r *Renderer) renderService(service *renderer.ContivService, oper operation, otherExistingServices []*renderer.ContivService) (
206206
addDelConfig controller.KeyValuePairs, updateConfig controller.KeyValuePairs) {
207207

208208
r.Log.Debugf("Rendering %s", service.String())
209209

210210
addDelConfig = make(controller.KeyValuePairs)
211211
updateConfig = make(controller.KeyValuePairs)
212-
localBackends := make(map[localBackendKey]*localBackend, 0)
213-
hasHostNetworkLocalBackend := false
214-
remoteBackends := make(map[remoteBackendKey]*remoteBackend, 0)
215212

216-
// collect info about the backends
217-
for servicePortName, servicePort := range service.Ports {
218-
for _, backend := range service.Backends[servicePortName] {
219-
if backend.Local {
220-
// collect local backend info
221-
if backend.HostNetwork {
222-
hasHostNetworkLocalBackend = true
223-
lb := &localBackend{
224-
useHostNetwork: true,
225-
ip: backend.IP,
226-
}
227-
localBackends[lb.Key()] = lb
228-
} else {
229-
lb := &localBackend{ip: backend.IP}
230-
if servicePort.Port != backend.Port {
231-
previousForwards := lb.portForwards
232-
if previousLB, exists := localBackends[lb.Key()]; exists {
233-
previousForwards = previousLB.portForwards
234-
}
235-
lb.portForwards = append(previousForwards, &portForward{
236-
proto: servicePort.Protocol,
237-
from: servicePort.Port,
238-
to: backend.Port,
239-
})
240-
}
241-
localBackends[lb.Key()] = lb
242-
}
243-
} else {
244-
// collect remote backend info
245-
var nodeID uint32
246-
var err error
247-
if backend.HostNetwork {
248-
nodeID, err = r.nodeIDFromNodeOrHostIP(backend.IP)
249-
if err != nil {
250-
r.Log.Warnf("Error by extracting node ID from host IP: %v", err)
251-
continue
252-
}
253-
} else {
254-
nodeID, err = r.IPAM.NodeIDFromPodIP(backend.IP)
255-
if err != nil {
256-
r.Log.Warnf("Error by extracting node ID from pod ID: %v", err)
257-
continue
258-
}
259-
}
260-
nodeIP, _, err := r.IPAM.NodeIPAddress(nodeID)
261-
if err != nil {
262-
r.Log.Warnf("Error by extracting node IP from node ID %v due to: %v", nodeID, err)
263-
} else {
264-
rb := &remoteBackend{
265-
ip: backend.IP,
266-
nodeID: nodeID,
267-
nodeIP: nodeIP,
268-
useHostNetwork: backend.HostNetwork,
269-
}
270-
remoteBackends[rb.Key()] = rb
271-
}
213+
// collecting/transforming needed information
214+
localBackends, remoteBackends, hasHostNetworkLocalBackend := r.collectBackendInfo(service)
215+
var hostNetworkLocalBackendInOtherServices bool
216+
otherServiceLocalBackends := make(map[localBackendKey]*localBackend)
217+
if oper == serviceDel {
218+
for _, otherService := range otherExistingServices {
219+
otherLocalBackends, _, otherHostLocalBackend := r.collectBackendInfo(otherService)
220+
hostNetworkLocalBackendInOtherServices = hostNetworkLocalBackendInOtherServices || otherHostLocalBackend
221+
for k, v := range otherLocalBackends {
222+
otherServiceLocalBackends[k] = v
272223
}
273224
}
274225
}
@@ -386,15 +337,18 @@ func (r *Renderer) renderService(service *renderer.ContivService, oper operation
386337
}
387338

388339
// adding LocalSID
389-
localSID := &vpp_srv6.LocalSID{
390-
Sid: r.IPAM.SidForServicePodLocalsid(backend.ip).String(),
391-
InstallationVrfId: r.ContivConf.GetRoutingConfig().PodVRFID,
392-
EndFunction: &vpp_srv6.LocalSID_EndFunction_DX6{EndFunction_DX6: &vpp_srv6.LocalSID_EndDX6{
393-
NextHop: backend.ip.String(),
394-
OutgoingInterface: vppIfName,
395-
}},
340+
_, usedInOtherService := otherServiceLocalBackends[backend.Key()]
341+
if !(oper == serviceDel && usedInOtherService) { // don't delete local sid if it is used in other service
342+
localSID := &vpp_srv6.LocalSID{
343+
Sid: r.IPAM.SidForServicePodLocalsid(backend.ip).String(),
344+
InstallationVrfId: r.ContivConf.GetRoutingConfig().PodVRFID,
345+
EndFunction: &vpp_srv6.LocalSID_EndFunction_DX6{EndFunction_DX6: &vpp_srv6.LocalSID_EndDX6{
346+
NextHop: backend.ip.String(),
347+
OutgoingInterface: vppIfName,
348+
}},
349+
}
350+
addDelConfig[models.Key(localSID)] = localSID
396351
}
397-
addDelConfig[models.Key(localSID)] = localSID
398352

399353
for _, serviceIP := range serviceIPs {
400354
// assign serviceIPs on the backend pod loopbacks
@@ -448,24 +402,92 @@ func (r *Renderer) renderService(service *renderer.ContivService, oper operation
448402
// policy in main vrf table -> no need to for inter-vrf table route like in ipv6 renderer
449403

450404
// from main VRF to host (create localsid with decapsulation and crossconnect to the host (DX6 end function))
451-
nextHop := r.IPAM.HostInterconnectIPInLinux()
452-
if r.ContivConf.InSTNMode() {
453-
nextHop, _ = r.IPNet.GetNodeIP()
454-
}
455-
localSID := &vpp_srv6.LocalSID{
456-
Sid: r.IPAM.SidForServiceHostLocalsid().String(),
457-
InstallationVrfId: r.ContivConf.GetRoutingConfig().MainVRFID,
458-
EndFunction: &vpp_srv6.LocalSID_EndFunction_DX6{EndFunction_DX6: &vpp_srv6.LocalSID_EndDX6{
459-
NextHop: nextHop.String(),
460-
OutgoingInterface: r.IPNet.GetHostInterconnectIfName(),
461-
}},
405+
if !(oper == serviceDel && hostNetworkLocalBackendInOtherServices) { // don't delete host network local sid if it is used in other services
406+
nextHop := r.IPAM.HostInterconnectIPInLinux()
407+
if r.ContivConf.InSTNMode() {
408+
nextHop, _ = r.IPNet.GetNodeIP()
409+
}
410+
localSID := &vpp_srv6.LocalSID{
411+
Sid: r.IPAM.SidForServiceHostLocalsid().String(),
412+
InstallationVrfId: r.ContivConf.GetRoutingConfig().MainVRFID,
413+
EndFunction: &vpp_srv6.LocalSID_EndFunction_DX6{EndFunction_DX6: &vpp_srv6.LocalSID_EndDX6{
414+
NextHop: nextHop.String(),
415+
OutgoingInterface: r.IPNet.GetHostInterconnectIfName(),
416+
}},
417+
}
418+
addDelConfig[models.Key(localSID)] = localSID
462419
}
463-
addDelConfig[models.Key(localSID)] = localSID
464420
}
465421

466422
return addDelConfig, updateConfig
467423
}
468424

425+
func (r *Renderer) collectBackendInfo(service *renderer.ContivService) (map[localBackendKey]*localBackend, map[remoteBackendKey]*remoteBackend, bool) {
426+
localBackends := make(map[localBackendKey]*localBackend, 0)
427+
hasHostNetworkLocalBackend := false
428+
remoteBackends := make(map[remoteBackendKey]*remoteBackend, 0)
429+
430+
for servicePortName, servicePort := range service.Ports {
431+
for _, backend := range service.Backends[servicePortName] {
432+
if backend.Local {
433+
// collect local backend info
434+
if backend.HostNetwork {
435+
hasHostNetworkLocalBackend = true
436+
lb := &localBackend{
437+
useHostNetwork: true,
438+
ip: backend.IP,
439+
}
440+
localBackends[lb.Key()] = lb
441+
} else {
442+
lb := &localBackend{ip: backend.IP}
443+
if servicePort.Port != backend.Port {
444+
previousForwards := lb.portForwards
445+
if previousLB, exists := localBackends[lb.Key()]; exists {
446+
previousForwards = previousLB.portForwards
447+
}
448+
lb.portForwards = append(previousForwards, &portForward{
449+
proto: servicePort.Protocol,
450+
from: servicePort.Port,
451+
to: backend.Port,
452+
})
453+
}
454+
localBackends[lb.Key()] = lb
455+
}
456+
} else {
457+
// collect remote backend info
458+
var nodeID uint32
459+
var err error
460+
if backend.HostNetwork {
461+
nodeID, err = r.nodeIDFromNodeOrHostIP(backend.IP)
462+
if err != nil {
463+
r.Log.Warnf("Error by extracting node ID from host IP: %v", err)
464+
continue
465+
}
466+
} else {
467+
nodeID, err = r.IPAM.NodeIDFromPodIP(backend.IP)
468+
if err != nil {
469+
r.Log.Warnf("Error by extracting node ID from pod ID: %v", err)
470+
continue
471+
}
472+
}
473+
nodeIP, _, err := r.IPAM.NodeIPAddress(nodeID)
474+
if err != nil {
475+
r.Log.Warnf("Error by extracting node IP from node ID %v due to: %v", nodeID, err)
476+
} else {
477+
rb := &remoteBackend{
478+
ip: backend.IP,
479+
nodeID: nodeID,
480+
nodeIP: nodeIP,
481+
useHostNetwork: backend.HostNetwork,
482+
}
483+
remoteBackends[rb.Key()] = rb
484+
}
485+
}
486+
}
487+
}
488+
return localBackends, remoteBackends, hasHostNetworkLocalBackend
489+
}
490+
469491
// getPodPFRuleChain returns the config of the pod-local iptables rule chain of given chain type -
470492
// At first it is looked up in currentConfig. If it is not found it's
471493
// retrieved from the controller (if it already exists), or an empty one.

0 commit comments

Comments
 (0)