@@ -23,6 +23,7 @@ import (
2323 "github.com/vishvananda/netlink"
2424 "github.com/vishvananda/netns"
2525 "golang.org/x/sys/unix"
26+ kerrors "k8s.io/apimachinery/pkg/util/errors"
2627)
2728
2829// $BPF_CLANG and $BPF_CFLAGS are set by the Makefile.
@@ -42,6 +43,8 @@ const (
4243 pktDropHook = "kfree_skb"
4344 constPcaEnable = "enable_pca"
4445 pcaRecordsMap = "packet_record"
46+ tcEgressFilterName = "tc/tc_egress_flow_parse"
47+ tcIngressFilterName = "tc/tc_ingress_flow_parse"
4548)
4649
4750var log = logrus .WithField ("component" , "ebpf.FlowFetcher" )
@@ -249,6 +252,84 @@ func (m *FlowFetcher) AttachTCX(iface ifaces.Interface) error {
249252 return nil
250253}
251254
255+ func removeTCFilters (ifName string , tcDir uint32 ) error {
256+ link , err := netlink .LinkByName (ifName )
257+ if err != nil {
258+ return err
259+ }
260+
261+ filters , err := netlink .FilterList (link , tcDir )
262+ if err != nil {
263+ return err
264+ }
265+ var errs []error
266+ for _ , f := range filters {
267+ if err := netlink .FilterDel (f ); err != nil {
268+ errs = append (errs , err )
269+ }
270+ }
271+
272+ return kerrors .NewAggregate (errs )
273+ }
274+
275+ func (m * FlowFetcher ) removePreviousFilters (iface ifaces.Interface ) error {
276+ ilog := log .WithField ("iface" , iface )
277+ ilog .Debugf ("looking for previously installed TC filters on %s" , iface .Name )
278+ links , err := netlink .LinkList ()
279+ if err != nil {
280+ return fmt .Errorf ("retrieving all netlink devices: %w" , err )
281+ }
282+
283+ egressDevs := []netlink.Link {}
284+ ingressDevs := []netlink.Link {}
285+ for _ , l := range links {
286+ if l .Attrs ().Name != iface .Name {
287+ continue
288+ }
289+ ingressFilters , err := netlink .FilterList (l , netlink .HANDLE_MIN_INGRESS )
290+ if err != nil {
291+ return fmt .Errorf ("listing ingress filters: %w" , err )
292+ }
293+ for _ , filter := range ingressFilters {
294+ if bpfFilter , ok := filter .(* netlink.BpfFilter ); ok {
295+ if strings .HasPrefix (bpfFilter .Name , tcIngressFilterName ) {
296+ ingressDevs = append (ingressDevs , l )
297+ }
298+ }
299+ }
300+
301+ egressFilters , err := netlink .FilterList (l , netlink .HANDLE_MIN_EGRESS )
302+ if err != nil {
303+ return fmt .Errorf ("listing egress filters: %w" , err )
304+ }
305+ for _ , filter := range egressFilters {
306+ if bpfFilter , ok := filter .(* netlink.BpfFilter ); ok {
307+ if strings .HasPrefix (bpfFilter .Name , tcEgressFilterName ) {
308+ egressDevs = append (egressDevs , l )
309+ }
310+ }
311+ }
312+ }
313+
314+ for _ , dev := range ingressDevs {
315+ ilog .Debugf ("removing ingress stale tc filters from %s" , dev .Attrs ().Name )
316+ err = removeTCFilters (dev .Attrs ().Name , netlink .HANDLE_MIN_INGRESS )
317+ if err != nil {
318+ ilog .WithError (err ).Errorf ("couldn't remove ingress tc filters from %s" , dev .Attrs ().Name )
319+ }
320+ }
321+
322+ for _ , dev := range egressDevs {
323+ ilog .Debugf ("removing egress stale tc filters from %s" , dev .Attrs ().Name )
324+ err = removeTCFilters (dev .Attrs ().Name , netlink .HANDLE_MIN_EGRESS )
325+ if err != nil {
326+ ilog .WithError (err ).Errorf ("couldn't remove egress tc filters from %s" , dev .Attrs ().Name )
327+ }
328+ }
329+
330+ return nil
331+ }
332+
252333// Register and links the eBPF fetcher into the system. The program should invoke Unregister
253334// before exiting.
254335func (m * FlowFetcher ) Register (iface ifaces.Interface ) error {
@@ -285,6 +366,11 @@ func (m *FlowFetcher) Register(iface ifaces.Interface) error {
285366 }
286367 m .qdiscs [iface ] = qdisc
287368
369+ // Remove previously installed filters
370+ if err := m .removePreviousFilters (iface ); err != nil {
371+ return fmt .Errorf ("failed to remove previous filters: %w" , err )
372+ }
373+
288374 if err := m .registerEgress (iface , ipvlan , handle ); err != nil {
289375 return err
290376 }
@@ -309,7 +395,7 @@ func (m *FlowFetcher) registerEgress(iface ifaces.Interface, ipvlan netlink.Link
309395 egressFilter := & netlink.BpfFilter {
310396 FilterAttrs : egressAttrs ,
311397 Fd : m .objects .TcEgressFlowParse .FD (),
312- Name : "tc/tc_egress_flow_parse" ,
398+ Name : tcEgressFilterName ,
313399 DirectAction : true ,
314400 }
315401 if err := handle .FilterDel (egressFilter ); err == nil {
@@ -343,7 +429,7 @@ func (m *FlowFetcher) registerIngress(iface ifaces.Interface, ipvlan netlink.Lin
343429 ingressFilter := & netlink.BpfFilter {
344430 FilterAttrs : ingressAttrs ,
345431 Fd : m .objects .TcIngressFlowParse .FD (),
346- Name : "tc/tc_ingress_flow_parse" ,
432+ Name : tcIngressFilterName ,
347433 DirectAction : true ,
348434 }
349435 if err := handle .FilterDel (ingressFilter ); err == nil {
0 commit comments