@@ -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