@@ -21,8 +21,6 @@ import (
2121 "github.com/cilium/statedb"
2222 "github.com/vishvananda/netlink"
2323 "go4.org/netipx"
24- "golang.org/x/sys/unix"
25- "k8s.io/apimachinery/pkg/util/wait"
2624
2725 "github.com/cilium/cilium/pkg/common"
2826 linuxrouting "github.com/cilium/cilium/pkg/datapath/linux/routing"
@@ -33,6 +31,7 @@ import (
3331 "github.com/cilium/cilium/pkg/ipam"
3432 ipamOption "github.com/cilium/cilium/pkg/ipam/option"
3533 "github.com/cilium/cilium/pkg/logging/logfields"
34+ "github.com/cilium/cilium/pkg/mac"
3635 "github.com/cilium/cilium/pkg/mtu"
3736 "github.com/cilium/cilium/pkg/node"
3837 "github.com/cilium/cilium/pkg/option"
@@ -220,33 +219,21 @@ func (r *infraIPAllocator) reallocateOldRouterIPs(fromK8s, fromFS net.IP) (resul
220219 return result
221220}
222221
222+ // waitForENI blocks until the ENI's netlink interface for macAddr is
223+ // observed on the node, guarding against the case where the operator has
224+ // reported the ENI as attached (and handed out IPs from it) before the
225+ // interface is actually visible via netlink. This delegates to the shared
226+ // linuxrouting.WaitForENIInterface helper, which is also used by the CNI ADD
227+ // datapath setup path and (below) the ingress IP path; see
228+ // https://github.com/cilium/cilium/pull/41954,
229+ // https://github.com/cilium/cilium/pull/47295, and
230+ // https://github.com/cilium/cilium/issues/45414.
223231func (r * infraIPAllocator ) waitForENI (ctx context.Context , macAddr string ) error {
224- bo := wait.Backoff {
225- Duration : 250 * time .Millisecond ,
226- Factor : 2 ,
227- Jitter : 0.2 ,
228- Steps : 5 ,
229- }
230-
231- findENIByMAC := func (ctx context.Context ) (bool , error ) {
232- links , err := safenetlink .LinkList ()
233- if err != nil {
234- return false , fmt .Errorf ("unable to list interfaces: %w" , err )
235- }
236-
237- for _ , l := range links {
238- // filter out slave devices
239- if l .Attrs ().RawFlags & unix .IFF_SLAVE != 0 {
240- continue
241- }
242- if l .Attrs ().HardwareAddr .String () == macAddr {
243- return true , nil
244- }
245- }
246- return false , nil
232+ parsedMAC , err := net .ParseMAC (macAddr )
233+ if err != nil {
234+ return fmt .Errorf ("invalid MAC address %q: %w" , macAddr , err )
247235 }
248-
249- return wait .ExponentialBackoffWithContext (ctx , bo , findENIByMAC )
236+ return linuxrouting .WaitForENIInterface (ctx , mac .MAC (parsedMAC ))
250237}
251238
252239func (r * infraIPAllocator ) reallocateRouterIPs (ctx context.Context , family node.AddressingFamily , fromK8s , fromFS net.IP ) (routerIP net.IP , err error ) {
@@ -299,6 +286,7 @@ func (r *infraIPAllocator) reallocateRouterIPs(ctx context.Context, family node.
299286 if err := r .waitForENI (ctx , result .PrimaryMAC ); err != nil {
300287 r .logger .Warn ("unable to find ENI netlink interface, this will likely lead to an error in configuring the router routes and rules" ,
301288 logfields .MACAddr , result .PrimaryMAC ,
289+ logfields .Error , err ,
302290 )
303291 }
304292 }
@@ -425,7 +413,7 @@ func (r *infraIPAllocator) allocateHealthIPs(oldV4HealthIP netip.Addr, oldV6Heal
425413 return nil
426414}
427415
428- func (r * infraIPAllocator ) allocateIngressIPs (oldV4IngressIP net.IP , oldV6IngressIP net.IP ) error {
416+ func (r * infraIPAllocator ) allocateIngressIPs (ctx context. Context , oldV4IngressIP net.IP , oldV6IngressIP net.IP ) error {
429417 if ! r .daemonConfig .EnableEnvoyConfig {
430418 return nil
431419 }
@@ -475,6 +463,20 @@ func (r *infraIPAllocator) allocateIngressIPs(oldV4IngressIP net.IP, oldV6Ingres
475463 if ingressRouting , err := r .parseRoutingInfo (result ); err != nil {
476464 r .logger .Warn ("Unable to allocate ingress information for ENI" , logfields .Error , err )
477465 } else {
466+ // wait for the ENI to be up and running before configuring
467+ // routes and rules, mirroring the guard used for the router
468+ // interface above. See
469+ // https://github.com/cilium/cilium/pull/41954 and
470+ // https://github.com/cilium/cilium/pull/47295.
471+ if r .daemonConfig .IPAM == ipamOption .IPAMENI {
472+ if err := r .waitForENI (ctx , result .PrimaryMAC ); err != nil {
473+ r .logger .Warn ("unable to find ENI netlink interface, this will likely lead to an error in configuring the ingress routes and rules" ,
474+ logfields .MACAddr , result .PrimaryMAC ,
475+ logfields .Error , err ,
476+ )
477+ }
478+ }
479+
478480 if err := ingressRouting .Configure (
479481 result .IP ,
480482 r .mtuManager .GetDeviceMTU (),
@@ -553,7 +555,7 @@ func (r *infraIPAllocator) AllocateIPs(ctx context.Context) error {
553555 return fmt .Errorf ("failed to allocate service loopback IPs: %w" , err )
554556 }
555557
556- if err := r .allocateIngressIPs (localNode .IPv4IngressIP , localNode .IPv6IngressIP ); err != nil {
558+ if err := r .allocateIngressIPs (ctx , localNode .IPv4IngressIP , localNode .IPv6IngressIP ); err != nil {
557559 return fmt .Errorf ("failed to allocate ingress IPs: %w" , err )
558560 }
559561
0 commit comments