@@ -7,11 +7,13 @@ import (
77 "path/filepath"
88 "sync"
99 "syscall"
10+ "time"
1011
1112 "github.com/fsnotify/fsnotify"
1213 "github.com/sirupsen/logrus"
1314 "github.com/vishvananda/netlink"
1415 "github.com/vishvananda/netns"
16+ "k8s.io/apimachinery/pkg/util/wait"
1517)
1618
1719const (
@@ -23,7 +25,7 @@ const (
2325type Watcher struct {
2426 bufLen int
2527 current map [Interface ]struct {}
26- interfaces func () ([]Interface , error )
28+ interfaces func (handle netns. NsHandle ) ([]Interface , error )
2729 // linkSubscriber abstracts netlink.LinkSubscribe implementation, allowing the injection of
2830 // mocks for unit testing
2931 linkSubscriberAt func (ns netns.NsHandle , ch chan <- netlink.LinkUpdate , done <- chan struct {}) error
@@ -45,34 +47,58 @@ func NewWatcher(bufLen int) *Watcher {
4547func (w * Watcher ) Subscribe (ctx context.Context ) (<- chan Event , error ) {
4648 out := make (chan Event , w .bufLen )
4749
48- nsHandles , err := getNetNSHandles ()
50+ netns , err := getNetNS ()
4951 if err != nil {
50- go w .sendUpdates (ctx , netns . None () , out )
52+ go w .sendUpdates (ctx , "" , out )
5153 } else {
52- for _ , nsh := range nsHandles {
53- nsHandle := nsh
54- go w .sendUpdates (ctx , nsHandle , out )
54+ for _ , n := range netns {
55+ go w .sendUpdates (ctx , n , out )
5556 }
5657 }
5758 // register to get notification when netns is created or deleted and register for link update for new netns
5859 w .netnsNotify (ctx , out )
5960 return out , nil
6061}
6162
62- func (w * Watcher ) sendUpdates (ctx context.Context , netnsHandle netns.NsHandle , out chan Event ) {
63+ func (w * Watcher ) sendUpdates (ctx context.Context , ns string , out chan Event ) {
64+ var netnsHandle netns.NsHandle
65+ var err error
6366 log := logrus .WithField ("component" , "ifaces.Watcher" )
6467 // subscribe for interface events
6568 links := make (chan netlink.LinkUpdate )
66- log .WithField ("netns" , netnsHandle .String ()).Debug ("linkSubscribe to receive links update" )
67- if err := w .linkSubscriberAt (netnsHandle , links , ctx .Done ()); err != nil {
68- log .WithError (err ).Errorf ("can't subscribe to links netns %s" , netnsHandle .String ())
69+ doneChan := make (chan struct {})
70+ if err = wait .PollUntilContextTimeout (ctx , 50 * time .Microsecond , time .Second , true , func (ctx context.Context ) (done bool , err error ) {
71+ if ns == "" {
72+ netnsHandle = netns .None ()
73+ } else {
74+ if netnsHandle , err = netns .GetFromName (ns ); err != nil {
75+ return false , nil
76+ }
77+ }
78+
79+ if err = w .linkSubscriberAt (netnsHandle , links , doneChan ); err != nil {
80+ log .WithFields (logrus.Fields {
81+ "netns" : ns ,
82+ "netnsHandle" : netnsHandle .String (),
83+ "error" : err ,
84+ }).Debug ("linkSubscribe failed retry" )
85+ return false , nil
86+ }
87+
88+ log .WithFields (logrus.Fields {
89+ "netns" : ns ,
90+ "netnsHandle" : netnsHandle .String (),
91+ }).Debug ("linkSubscribe to receive links update" )
92+ return true , nil
93+ }); err != nil {
94+ log .WithError (err ).Errorf ("can't subscribe to links netns %s netnsHandle %s" , ns , netnsHandle .String ())
6995 return
7096 }
7197
7298 // before sending netlink updates, send all the existing interfaces at the moment of starting
7399 // the Watcher
74- if netnsHandle .Equal (netns .None ()) {
75- if names , err := w .interfaces (); err != nil {
100+ if netnsHandle .IsOpen () || netnsHandle . Equal (netns .None ()) {
101+ if names , err := w .interfaces (netnsHandle ); err != nil {
76102 log .WithError (err ).Error ("can't fetch network interfaces. You might be missing flows" )
77103 } else {
78104 for _ , name := range names {
@@ -119,35 +145,28 @@ func (w *Watcher) sendUpdates(ctx context.Context, netnsHandle netns.NsHandle, o
119145 }
120146}
121147
122- func getNetNSHandles () ([]netns. NsHandle , error ) {
148+ func getNetNS () ([]string , error ) {
123149 log := logrus .WithField ("component" , "ifaces.Watcher" )
124150 files , err := os .ReadDir (netnsVolume )
125151 if err != nil {
126152 log .Warningf ("can't detect any network-namespaces err: %v [Ignore if the agent privileged flag is not set]" , err )
127153 return nil , fmt .Errorf ("failed to list network-namespaces: %w" , err )
128154 }
129155
130- handles := []netns. NsHandle { netns . None () }
156+ netns := []string { "" }
131157 if len (files ) == 0 {
132158 log .WithField ("netns" , files ).Debug ("empty network-namespaces list" )
133- return handles , nil
159+ return netns , nil
134160 }
135161 for _ , f := range files {
136162 ns := f .Name ()
137- handle , err := netns .GetFromName (ns )
138- if err != nil {
139- log .WithField ("netns" , ns ).Debug ("can't get NsHandle for this netns. Ignoring" )
140- continue
141- }
142- handles = append (handles , handle )
163+ netns = append (netns , ns )
143164 log .WithFields (logrus.Fields {
144- "netns" : ns ,
145- "handle" : handle .String (),
165+ "netns" : ns ,
146166 }).Debug ("Detected network-namespace" )
147-
148167 }
149168
150- return handles , nil
169+ return netns , nil
151170}
152171
153172func (w * Watcher ) netnsNotify (ctx context.Context , out chan Event ) {
@@ -170,12 +189,7 @@ func (w *Watcher) netnsNotify(ctx context.Context, out chan Event) {
170189 if event .Op & fsnotify .Create == fsnotify .Create {
171190 ns := filepath .Base (event .Name )
172191 log .WithField ("netns" , ns ).Debug ("netns notification" )
173- handle , err := netns .GetFromName (ns )
174- if err != nil {
175- log .WithField ("netns" , ns ).Debug ("can't get NsHandle for this netns. Ignoring" )
176- return
177- }
178- go w .sendUpdates (ctx , handle , out )
192+ go w .sendUpdates (ctx , ns , out )
179193 }
180194 case err , ok := <- w .netnsWatcher .Errors :
181195 if ! ok {
0 commit comments