@@ -25,9 +25,11 @@ import (
2525 "github.com/onmetal/controller-utils/clientutils"
2626 metalnetv1alpha1 "github.com/onmetal/metalnet/api/v1alpha1"
2727 "github.com/onmetal/metalnet/dpdk"
28+ "github.com/onmetal/metalnet/dpdkmetalbond"
2829 "github.com/onmetal/metalnet/metalbond"
2930 "k8s.io/apimachinery/pkg/runtime"
3031 "k8s.io/apimachinery/pkg/types"
32+ "k8s.io/apimachinery/pkg/util/sets"
3133 ctrl "sigs.k8s.io/controller-runtime"
3234 "sigs.k8s.io/controller-runtime/pkg/builder"
3335 "sigs.k8s.io/controller-runtime/pkg/client"
@@ -47,9 +49,9 @@ type NetworkReconciler struct {
4749 client.Client
4850 Scheme * runtime.Scheme
4951
50- DPDK dpdk.Client
51- Metalbond metalbond.Client
52-
52+ DPDK dpdk.Client
53+ Metalbond metalbond.Client
54+ MBInternal dpdkmetalbond. MbInternalAccess
5355 RouterAddress netip.Addr
5456 NodeName string
5557}
@@ -103,6 +105,12 @@ func (r *NetworkReconciler) delete(ctx context.Context, log logr.Logger, network
103105 }
104106 log .V (1 ).Info ("Deleted default route if existed" )
105107
108+ log .V (1 ).Info ("Deleting peered VNIs" )
109+ if err := r .deletePeeredVNIs (ctx , log , network , vni ); err != nil {
110+ return ctrl.Result {}, err
111+ }
112+ log .V (1 ).Info ("Deleted peered VNIs" )
113+
106114 log .V (1 ).Info ("Cleanup done, removing finalizer" )
107115 if err := clientutils .PatchRemoveFinalizer (ctx , r .Client , network , r .networkFinalizer ()); err != nil {
108116 return ctrl.Result {}, fmt .Errorf ("error removing finalizer: %w" , err )
@@ -135,11 +143,19 @@ func (r *NetworkReconciler) reconcile(ctx context.Context, log logr.Logger, netw
135143 }
136144
137145 if ! vniAvail {
138- log .V (1 ).Info ("VNI doesn't exist in dp-service, unsubscribe from it" )
139- if err := r .unsubscribeIfSubscribed (ctx , vni ); err != nil {
146+ if ! r .MBInternal .IsVniPeered (vni ) {
147+ log .V (1 ).Info ("VNI doesn't exist in dp-service and no peering, unsubscribe from it" )
148+ if err := r .unsubscribeIfSubscribed (ctx , vni ); err != nil {
149+ return ctrl.Result {}, err
150+ }
151+ log .V (1 ).Info ("VNI doesn't exist in dp-service and no peering, unsubscribed from it" )
152+ }
153+
154+ log .V (1 ).Info ("Reconciling peered VNIs" )
155+ if err := r .reconcilePeeredVNIs (ctx , log , network , vni , vniAvail ); err != nil {
140156 return ctrl.Result {}, err
141157 }
142- log .V (1 ).Info ("VNI doesn't exist in dp-service, unsubscribed from it " )
158+ log .V (1 ).Info ("Reconciled peered VNIs " )
143159 return ctrl.Result {}, nil
144160 }
145161 log .V (1 ).Info ("Checked existence of the VNI" )
@@ -150,6 +166,12 @@ func (r *NetworkReconciler) reconcile(ctx context.Context, log logr.Logger, netw
150166 }
151167 log .V (1 ).Info ("Created dpdk default route if not existed" )
152168
169+ log .V (1 ).Info ("Reconciling peered VNIs" )
170+ if err := r .reconcilePeeredVNIs (ctx , log , network , vni , vniAvail ); err != nil {
171+ return ctrl.Result {}, err
172+ }
173+ log .V (1 ).Info ("Reconciled peered VNIs" )
174+
153175 log .V (1 ).Info ("Subscribing to metalbond if not subscribed" )
154176 if err := r .subscribeIfNotSubscribed (ctx , vni ); err != nil {
155177 return ctrl.Result {}, err
@@ -202,6 +224,142 @@ func (r *NetworkReconciler) subscribeIfNotSubscribed(ctx context.Context, vni ui
202224 return nil
203225}
204226
227+ func (r * NetworkReconciler ) setDifference (s1 , s2 sets.Set [uint32 ]) sets.Set [uint32 ] {
228+ diff := sets .New [uint32 ]()
229+ for k := range s1 {
230+ if _ , ok := s2 [k ]; ! ok {
231+ diff .Insert (k )
232+ }
233+ }
234+ return diff
235+ }
236+
237+ func (r * NetworkReconciler ) reconcilePeeredVNIs (ctx context.Context , log logr.Logger , network * metalnetv1alpha1.Network , vni uint32 , ownVniAvail bool ) error {
238+ mbPeerVnis , err := r .MBInternal .GetPeerVnis (vni )
239+ if err != nil {
240+ return err
241+ }
242+ specPeerVnis := sets .New [uint32 ]()
243+ if network .Spec .PeeredIDs != nil {
244+ for _ , v := range network .Spec .PeeredIDs {
245+ specPeerVnis .Insert (uint32 (v ))
246+ }
247+ }
248+ missing := r .setDifference (mbPeerVnis , specPeerVnis )
249+ added := r .setDifference (specPeerVnis , mbPeerVnis )
250+
251+ if missing .Len () == 0 && added .Len () == 0 {
252+ if mbPeerVnis .Len () == 0 {
253+ return nil
254+ }
255+
256+ for _ , peeredVNI := range mbPeerVnis .UnsortedList () {
257+ if ! ownVniAvail {
258+ if err := r .MBInternal .RemoveVniFromPeerVnis (log , vni , peeredVNI ); err != nil {
259+ return err
260+ }
261+ }
262+ }
263+ }
264+
265+ if missing .Len () != 0 || added .Len () != 0 {
266+ for _ , peeredVNI := range missing .UnsortedList () {
267+ log .V (1 ).Info ("Checking the existence of the peeredVNI in dp-service" , "peeredVNI" , peeredVNI )
268+ peeredVniAvail , err := r .DPDK .IsVniAvailable (ctx , peeredVNI )
269+ if err != nil {
270+ return err
271+ }
272+ log .V (1 ).Info ("Checked the existence of the peeredVNI in dp-service" , "peeredVNI" , peeredVNI )
273+
274+ if ! peeredVniAvail {
275+ if err := r .unsubscribeIfSubscribed (ctx , peeredVNI ); err != nil {
276+ return err
277+ }
278+ } else if peeredVniAvail && ownVniAvail {
279+ if err := r .recycleVNISubscription (ctx , vni ); err != nil {
280+ return err
281+ }
282+ if err := r .recycleVNISubscription (ctx , peeredVNI ); err != nil {
283+ return err
284+ }
285+ } else {
286+ if err := r .recycleVNISubscription (ctx , peeredVNI ); err != nil {
287+ return err
288+ }
289+ }
290+ if err := r .MBInternal .RemoveVniFromPeerVnis (log , vni , peeredVNI ); err != nil {
291+ return err
292+ }
293+ }
294+
295+ for _ , peeredVNI := range added .UnsortedList () {
296+ if ! ownVniAvail {
297+ return nil
298+ }
299+ log .V (1 ).Info ("Checking the existence of the peeredVNI in dp-service" , "peeredVNI" , peeredVNI )
300+ peeredVniAvail , err := r .DPDK .IsVniAvailable (ctx , peeredVNI )
301+ if err != nil {
302+ return err
303+ }
304+ log .V (1 ).Info ("Checked the existence of the peeredVNI in dp-service" , "peeredVNI" , peeredVNI )
305+ if ownVniAvail && ! peeredVniAvail {
306+ if err := r .subscribeIfNotSubscribed (ctx , peeredVNI ); err != nil {
307+ return err
308+ }
309+ }
310+ if ownVniAvail && peeredVniAvail {
311+ if err := r .recycleVNISubscription (ctx , vni ); err != nil {
312+ return err
313+ }
314+ if err := r .recycleVNISubscription (ctx , peeredVNI ); err != nil {
315+ return err
316+ }
317+ }
318+ if err := r .MBInternal .AddVniToPeerVnis (log , vni , peeredVNI ); err != nil {
319+ return err
320+ }
321+ }
322+ }
323+
324+ return nil
325+ }
326+
327+ func (r * NetworkReconciler ) deletePeeredVNIs (ctx context.Context , log logr.Logger , network * metalnetv1alpha1.Network , vni uint32 ) error {
328+ mbPeerVnis , _ := r .MBInternal .GetPeerVnis (vni )
329+
330+ for _ , peeredVNI := range mbPeerVnis .UnsortedList () {
331+ log .V (1 ).Info ("Checking existence of the " , "peered VNI" , peeredVNI )
332+ vniAvail , err := r .DPDK .IsVniAvailable (ctx , peeredVNI )
333+ if err != nil {
334+ return err
335+ }
336+ if ! vniAvail {
337+ if err := r .unsubscribeIfSubscribed (ctx , peeredVNI ); err != nil {
338+ return err
339+ }
340+ }
341+ if err := r .MBInternal .RemoveVniFromPeerVnis (log , vni , peeredVNI ); err != nil {
342+ return err
343+ }
344+ }
345+ return nil
346+ }
347+
348+ func (r * NetworkReconciler ) recycleVNISubscription (ctx context.Context , vni uint32 ) error {
349+ if err := r .unsubscribeIfSubscribed (ctx , vni ); err != nil {
350+ return err
351+ }
352+
353+ if err := r .DPDK .ResetVni (ctx , vni ); err != nil {
354+ return fmt .Errorf ("error resetting vni: %w" , err )
355+ }
356+
357+ if err := r .subscribeIfNotSubscribed (ctx , vni ); err != nil {
358+ return err
359+ }
360+ return nil
361+ }
362+
205363func (r * NetworkReconciler ) unsubscribeIfSubscribed (ctx context.Context , vni uint32 ) error {
206364 if err := r .Metalbond .Unsubscribe (ctx , metalbond .VNI (vni )); metalbond .IgnoreNotSubscribedToVNIError (err ) != nil {
207365 return fmt .Errorf ("error subscribing to vni: %w" , err )
0 commit comments