github.com/vishvananda/netlink@v1.3.1/filter_linux.go (about)

     1  package netlink
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/binary"
     6  	"encoding/hex"
     7  	"errors"
     8  	"fmt"
     9  	"net"
    10  	"syscall"
    11  
    12  	"github.com/vishvananda/netlink/nl"
    13  	"golang.org/x/sys/unix"
    14  )
    15  
    16  // Constants used in TcU32Sel.Flags.
    17  const (
    18  	TC_U32_TERMINAL  = nl.TC_U32_TERMINAL
    19  	TC_U32_OFFSET    = nl.TC_U32_OFFSET
    20  	TC_U32_VAROFFSET = nl.TC_U32_VAROFFSET
    21  	TC_U32_EAT       = nl.TC_U32_EAT
    22  )
    23  
    24  // Sel of the U32 filters that contains multiple TcU32Key. This is the type
    25  // alias and the frontend representation of nl.TcU32Sel. It is serialized into
    26  // canonical nl.TcU32Sel with the appropriate endianness.
    27  type TcU32Sel = nl.TcU32Sel
    28  
    29  // TcU32Key contained of Sel in the U32 filters. This is the type alias and the
    30  // frontend representation of nl.TcU32Key. It is serialized into chanonical
    31  // nl.TcU32Sel with the appropriate endianness.
    32  type TcU32Key = nl.TcU32Key
    33  
    34  // U32 filters on many packet related properties
    35  type U32 struct {
    36  	FilterAttrs
    37  	ClassId    uint32
    38  	Divisor    uint32 // Divisor MUST be power of 2.
    39  	Hash       uint32
    40  	Link       uint32
    41  	RedirIndex int
    42  	Sel        *TcU32Sel
    43  	Actions    []Action
    44  	Police     *PoliceAction
    45  }
    46  
    47  func (filter *U32) Attrs() *FilterAttrs {
    48  	return &filter.FilterAttrs
    49  }
    50  
    51  func (filter *U32) Type() string {
    52  	return "u32"
    53  }
    54  
    55  type Flower struct {
    56  	FilterAttrs
    57  	ClassId         uint32
    58  	DestIP          net.IP
    59  	DestIPMask      net.IPMask
    60  	SrcIP           net.IP
    61  	SrcIPMask       net.IPMask
    62  	EthType         uint16
    63  	EncDestIP       net.IP
    64  	EncDestIPMask   net.IPMask
    65  	EncSrcIP        net.IP
    66  	EncSrcIPMask    net.IPMask
    67  	EncDestPort     uint16
    68  	EncKeyId        uint32
    69  	SrcMac          net.HardwareAddr
    70  	DestMac         net.HardwareAddr
    71  	VlanId          uint16
    72  	SkipHw          bool
    73  	SkipSw          bool
    74  	IPProto         *nl.IPProto
    75  	DestPort        uint16
    76  	SrcPort         uint16
    77  	SrcPortRangeMin uint16
    78  	SrcPortRangeMax uint16
    79  	DstPortRangeMin uint16
    80  	DstPortRangeMax uint16
    81  
    82  	Actions []Action
    83  }
    84  
    85  func (filter *Flower) Attrs() *FilterAttrs {
    86  	return &filter.FilterAttrs
    87  }
    88  
    89  func (filter *Flower) Type() string {
    90  	return "flower"
    91  }
    92  
    93  func (filter *Flower) encodeIP(parent *nl.RtAttr, ip net.IP, mask net.IPMask, v4Type, v6Type int, v4MaskType, v6MaskType int) {
    94  	ipType := v4Type
    95  	maskType := v4MaskType
    96  
    97  	encodeMask := mask
    98  	if mask == nil {
    99  		encodeMask = net.CIDRMask(32, 32)
   100  	}
   101  	v4IP := ip.To4()
   102  	if v4IP == nil {
   103  		ipType = v6Type
   104  		maskType = v6MaskType
   105  		if mask == nil {
   106  			encodeMask = net.CIDRMask(128, 128)
   107  		}
   108  	} else {
   109  		ip = v4IP
   110  	}
   111  
   112  	parent.AddRtAttr(ipType, ip)
   113  	parent.AddRtAttr(maskType, encodeMask)
   114  }
   115  
   116  func (filter *Flower) encode(parent *nl.RtAttr) error {
   117  	if filter.EthType != 0 {
   118  		parent.AddRtAttr(nl.TCA_FLOWER_KEY_ETH_TYPE, htons(filter.EthType))
   119  	}
   120  	if filter.SrcIP != nil {
   121  		filter.encodeIP(parent, filter.SrcIP, filter.SrcIPMask,
   122  			nl.TCA_FLOWER_KEY_IPV4_SRC, nl.TCA_FLOWER_KEY_IPV6_SRC,
   123  			nl.TCA_FLOWER_KEY_IPV4_SRC_MASK, nl.TCA_FLOWER_KEY_IPV6_SRC_MASK)
   124  	}
   125  	if filter.DestIP != nil {
   126  		filter.encodeIP(parent, filter.DestIP, filter.DestIPMask,
   127  			nl.TCA_FLOWER_KEY_IPV4_DST, nl.TCA_FLOWER_KEY_IPV6_DST,
   128  			nl.TCA_FLOWER_KEY_IPV4_DST_MASK, nl.TCA_FLOWER_KEY_IPV6_DST_MASK)
   129  	}
   130  	if filter.EncSrcIP != nil {
   131  		filter.encodeIP(parent, filter.EncSrcIP, filter.EncSrcIPMask,
   132  			nl.TCA_FLOWER_KEY_ENC_IPV4_SRC, nl.TCA_FLOWER_KEY_ENC_IPV6_SRC,
   133  			nl.TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK, nl.TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK)
   134  	}
   135  	if filter.EncDestIP != nil {
   136  		filter.encodeIP(parent, filter.EncDestIP, filter.EncSrcIPMask,
   137  			nl.TCA_FLOWER_KEY_ENC_IPV4_DST, nl.TCA_FLOWER_KEY_ENC_IPV6_DST,
   138  			nl.TCA_FLOWER_KEY_ENC_IPV4_DST_MASK, nl.TCA_FLOWER_KEY_ENC_IPV6_DST_MASK)
   139  	}
   140  	if filter.EncDestPort != 0 {
   141  		parent.AddRtAttr(nl.TCA_FLOWER_KEY_ENC_UDP_DST_PORT, htons(filter.EncDestPort))
   142  	}
   143  	if filter.EncKeyId != 0 {
   144  		parent.AddRtAttr(nl.TCA_FLOWER_KEY_ENC_KEY_ID, htonl(filter.EncKeyId))
   145  	}
   146  	if filter.SrcMac != nil {
   147  		parent.AddRtAttr(nl.TCA_FLOWER_KEY_ETH_SRC, filter.SrcMac)
   148  	}
   149  	if filter.DestMac != nil {
   150  		parent.AddRtAttr(nl.TCA_FLOWER_KEY_ETH_DST, filter.DestMac)
   151  	}
   152  	if filter.VlanId != 0 {
   153  		parent.AddRtAttr(nl.TCA_FLOWER_KEY_VLAN_ID, nl.Uint16Attr(filter.VlanId))
   154  	}
   155  	if filter.IPProto != nil {
   156  		ipproto := *filter.IPProto
   157  		parent.AddRtAttr(nl.TCA_FLOWER_KEY_IP_PROTO, ipproto.Serialize())
   158  		if filter.SrcPort != 0 {
   159  			switch ipproto {
   160  			case nl.IPPROTO_TCP:
   161  				parent.AddRtAttr(nl.TCA_FLOWER_KEY_TCP_SRC, htons(filter.SrcPort))
   162  			case nl.IPPROTO_UDP:
   163  				parent.AddRtAttr(nl.TCA_FLOWER_KEY_UDP_SRC, htons(filter.SrcPort))
   164  			case nl.IPPROTO_SCTP:
   165  				parent.AddRtAttr(nl.TCA_FLOWER_KEY_SCTP_SRC, htons(filter.SrcPort))
   166  			}
   167  		}
   168  		if filter.DestPort != 0 {
   169  			switch ipproto {
   170  			case nl.IPPROTO_TCP:
   171  				parent.AddRtAttr(nl.TCA_FLOWER_KEY_TCP_DST, htons(filter.DestPort))
   172  			case nl.IPPROTO_UDP:
   173  				parent.AddRtAttr(nl.TCA_FLOWER_KEY_UDP_DST, htons(filter.DestPort))
   174  			case nl.IPPROTO_SCTP:
   175  				parent.AddRtAttr(nl.TCA_FLOWER_KEY_SCTP_DST, htons(filter.DestPort))
   176  			}
   177  		}
   178  	}
   179  	if filter.SrcPortRangeMin != 0 && filter.SrcPortRangeMax != 0 {
   180  		parent.AddRtAttr(nl.TCA_FLOWER_KEY_PORT_SRC_MIN, htons(filter.SrcPortRangeMin))
   181  		parent.AddRtAttr(nl.TCA_FLOWER_KEY_PORT_SRC_MAX, htons(filter.SrcPortRangeMax))
   182  	}
   183  
   184  	if filter.DstPortRangeMin != 0 && filter.DstPortRangeMax != 0 {
   185  		parent.AddRtAttr(nl.TCA_FLOWER_KEY_PORT_DST_MIN, htons(filter.DstPortRangeMin))
   186  		parent.AddRtAttr(nl.TCA_FLOWER_KEY_PORT_DST_MAX, htons(filter.DstPortRangeMax))
   187  	}
   188  
   189  	if filter.ClassId != 0 {
   190  		parent.AddRtAttr(nl.TCA_FLOWER_CLASSID, nl.Uint32Attr(filter.ClassId))
   191  	}
   192  
   193  	var flags uint32 = 0
   194  	if filter.SkipHw {
   195  		flags |= nl.TCA_CLS_FLAGS_SKIP_HW
   196  	}
   197  	if filter.SkipSw {
   198  		flags |= nl.TCA_CLS_FLAGS_SKIP_SW
   199  	}
   200  	parent.AddRtAttr(nl.TCA_FLOWER_FLAGS, htonl(flags))
   201  
   202  	actionsAttr := parent.AddRtAttr(nl.TCA_FLOWER_ACT, nil)
   203  	if err := EncodeActions(actionsAttr, filter.Actions); err != nil {
   204  		return err
   205  	}
   206  	return nil
   207  }
   208  
   209  func (filter *Flower) decode(data []syscall.NetlinkRouteAttr) error {
   210  	for _, datum := range data {
   211  		switch datum.Attr.Type {
   212  		case nl.TCA_FLOWER_KEY_ETH_TYPE:
   213  			filter.EthType = ntohs(datum.Value)
   214  		case nl.TCA_FLOWER_KEY_IPV4_SRC, nl.TCA_FLOWER_KEY_IPV6_SRC:
   215  			filter.SrcIP = datum.Value
   216  		case nl.TCA_FLOWER_KEY_IPV4_SRC_MASK, nl.TCA_FLOWER_KEY_IPV6_SRC_MASK:
   217  			filter.SrcIPMask = datum.Value
   218  		case nl.TCA_FLOWER_KEY_IPV4_DST, nl.TCA_FLOWER_KEY_IPV6_DST:
   219  			filter.DestIP = datum.Value
   220  		case nl.TCA_FLOWER_KEY_IPV4_DST_MASK, nl.TCA_FLOWER_KEY_IPV6_DST_MASK:
   221  			filter.DestIPMask = datum.Value
   222  		case nl.TCA_FLOWER_KEY_ENC_IPV4_SRC, nl.TCA_FLOWER_KEY_ENC_IPV6_SRC:
   223  			filter.EncSrcIP = datum.Value
   224  		case nl.TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK, nl.TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK:
   225  			filter.EncSrcIPMask = datum.Value
   226  		case nl.TCA_FLOWER_KEY_ENC_IPV4_DST, nl.TCA_FLOWER_KEY_ENC_IPV6_DST:
   227  			filter.EncDestIP = datum.Value
   228  		case nl.TCA_FLOWER_KEY_ENC_IPV4_DST_MASK, nl.TCA_FLOWER_KEY_ENC_IPV6_DST_MASK:
   229  			filter.EncDestIPMask = datum.Value
   230  		case nl.TCA_FLOWER_KEY_ENC_UDP_DST_PORT:
   231  			filter.EncDestPort = ntohs(datum.Value)
   232  		case nl.TCA_FLOWER_KEY_ENC_KEY_ID:
   233  			filter.EncKeyId = ntohl(datum.Value)
   234  		case nl.TCA_FLOWER_KEY_ETH_SRC:
   235  			filter.SrcMac = datum.Value
   236  		case nl.TCA_FLOWER_KEY_ETH_DST:
   237  			filter.DestMac = datum.Value
   238  		case nl.TCA_FLOWER_KEY_VLAN_ID:
   239  			filter.VlanId = native.Uint16(datum.Value[0:2])
   240  			filter.EthType = unix.ETH_P_8021Q
   241  		case nl.TCA_FLOWER_KEY_IP_PROTO:
   242  			val := new(nl.IPProto)
   243  			*val = nl.IPProto(datum.Value[0])
   244  			filter.IPProto = val
   245  		case nl.TCA_FLOWER_KEY_TCP_SRC, nl.TCA_FLOWER_KEY_UDP_SRC, nl.TCA_FLOWER_KEY_SCTP_SRC:
   246  			filter.SrcPort = ntohs(datum.Value)
   247  		case nl.TCA_FLOWER_KEY_TCP_DST, nl.TCA_FLOWER_KEY_UDP_DST, nl.TCA_FLOWER_KEY_SCTP_DST:
   248  			filter.DestPort = ntohs(datum.Value)
   249  		case nl.TCA_FLOWER_ACT:
   250  			tables, err := nl.ParseRouteAttr(datum.Value)
   251  			if err != nil {
   252  				return err
   253  			}
   254  			filter.Actions, err = parseActions(tables)
   255  			if err != nil {
   256  				return err
   257  			}
   258  		case nl.TCA_FLOWER_FLAGS:
   259  			attr := nl.DeserializeUint32Bitfield(datum.Value)
   260  			skipSw := attr.Value & nl.TCA_CLS_FLAGS_SKIP_HW
   261  			skipHw := attr.Value & nl.TCA_CLS_FLAGS_SKIP_SW
   262  			if skipSw != 0 {
   263  				filter.SkipSw = true
   264  			}
   265  			if skipHw != 0 {
   266  				filter.SkipHw = true
   267  			}
   268  		case nl.TCA_FLOWER_KEY_PORT_SRC_MIN:
   269  			filter.SrcPortRangeMin = ntohs(datum.Value)
   270  		case nl.TCA_FLOWER_KEY_PORT_SRC_MAX:
   271  			filter.SrcPortRangeMax = ntohs(datum.Value)
   272  		case nl.TCA_FLOWER_KEY_PORT_DST_MIN:
   273  			filter.DstPortRangeMin = ntohs(datum.Value)
   274  		case nl.TCA_FLOWER_KEY_PORT_DST_MAX:
   275  			filter.DstPortRangeMax = ntohs(datum.Value)
   276  		case nl.TCA_FLOWER_CLASSID:
   277  			filter.ClassId = native.Uint32(datum.Value)
   278  		}
   279  	}
   280  	return nil
   281  }
   282  
   283  // FilterDel will delete a filter from the system.
   284  // Equivalent to: `tc filter del $filter`
   285  func FilterDel(filter Filter) error {
   286  	return pkgHandle.FilterDel(filter)
   287  }
   288  
   289  // FilterDel will delete a filter from the system.
   290  // Equivalent to: `tc filter del $filter`
   291  func (h *Handle) FilterDel(filter Filter) error {
   292  	return h.filterModify(filter, unix.RTM_DELTFILTER, 0)
   293  }
   294  
   295  // FilterAdd will add a filter to the system.
   296  // Equivalent to: `tc filter add $filter`
   297  func FilterAdd(filter Filter) error {
   298  	return pkgHandle.FilterAdd(filter)
   299  }
   300  
   301  // FilterAdd will add a filter to the system.
   302  // Equivalent to: `tc filter add $filter`
   303  func (h *Handle) FilterAdd(filter Filter) error {
   304  	return h.filterModify(filter, unix.RTM_NEWTFILTER, unix.NLM_F_CREATE|unix.NLM_F_EXCL)
   305  }
   306  
   307  // FilterReplace will replace a filter.
   308  // Equivalent to: `tc filter replace $filter`
   309  func FilterReplace(filter Filter) error {
   310  	return pkgHandle.FilterReplace(filter)
   311  }
   312  
   313  // FilterReplace will replace a filter.
   314  // Equivalent to: `tc filter replace $filter`
   315  func (h *Handle) FilterReplace(filter Filter) error {
   316  	return h.filterModify(filter, unix.RTM_NEWTFILTER, unix.NLM_F_CREATE)
   317  }
   318  
   319  func (h *Handle) filterModify(filter Filter, proto, flags int) error {
   320  	req := h.newNetlinkRequest(proto, flags|unix.NLM_F_ACK)
   321  	base := filter.Attrs()
   322  	msg := &nl.TcMsg{
   323  		Family:  nl.FAMILY_ALL,
   324  		Ifindex: int32(base.LinkIndex),
   325  		Handle:  base.Handle,
   326  		Parent:  base.Parent,
   327  		Info:    MakeHandle(base.Priority, nl.Swap16(base.Protocol)),
   328  	}
   329  	req.AddData(msg)
   330  	if filter.Attrs().Chain != nil {
   331  		req.AddData(nl.NewRtAttr(nl.TCA_CHAIN, nl.Uint32Attr(*filter.Attrs().Chain)))
   332  	}
   333  	req.AddData(nl.NewRtAttr(nl.TCA_KIND, nl.ZeroTerminated(filter.Type())))
   334  
   335  	options := nl.NewRtAttr(nl.TCA_OPTIONS, nil)
   336  
   337  	switch filter := filter.(type) {
   338  	case *U32:
   339  		sel := filter.Sel
   340  		if sel == nil {
   341  			// match all
   342  			sel = &nl.TcU32Sel{
   343  				Nkeys: 1,
   344  				Flags: nl.TC_U32_TERMINAL,
   345  			}
   346  			sel.Keys = append(sel.Keys, nl.TcU32Key{})
   347  		}
   348  
   349  		if native != networkOrder {
   350  			// Copy TcU32Sel.
   351  			cSel := *sel
   352  			keys := make([]nl.TcU32Key, cap(sel.Keys))
   353  			copy(keys, sel.Keys)
   354  			cSel.Keys = keys
   355  			sel = &cSel
   356  
   357  			// Handle the endianness of attributes
   358  			sel.Offmask = native.Uint16(htons(sel.Offmask))
   359  			sel.Hmask = native.Uint32(htonl(sel.Hmask))
   360  			for i, key := range sel.Keys {
   361  				sel.Keys[i].Mask = native.Uint32(htonl(key.Mask))
   362  				sel.Keys[i].Val = native.Uint32(htonl(key.Val))
   363  			}
   364  		}
   365  		sel.Nkeys = uint8(len(sel.Keys))
   366  		options.AddRtAttr(nl.TCA_U32_SEL, sel.Serialize())
   367  		if filter.ClassId != 0 {
   368  			options.AddRtAttr(nl.TCA_U32_CLASSID, nl.Uint32Attr(filter.ClassId))
   369  		}
   370  		if filter.Divisor != 0 {
   371  			if (filter.Divisor-1)&filter.Divisor != 0 {
   372  				return fmt.Errorf("illegal divisor %d. Must be a power of 2", filter.Divisor)
   373  			}
   374  			options.AddRtAttr(nl.TCA_U32_DIVISOR, nl.Uint32Attr(filter.Divisor))
   375  		}
   376  		if filter.Hash != 0 {
   377  			options.AddRtAttr(nl.TCA_U32_HASH, nl.Uint32Attr(filter.Hash))
   378  		}
   379  		if filter.Link != 0 {
   380  			options.AddRtAttr(nl.TCA_U32_LINK, nl.Uint32Attr(filter.Link))
   381  		}
   382  		if filter.Police != nil {
   383  			police := options.AddRtAttr(nl.TCA_U32_POLICE, nil)
   384  			if err := encodePolice(police, filter.Police); err != nil {
   385  				return err
   386  			}
   387  		}
   388  		actionsAttr := options.AddRtAttr(nl.TCA_U32_ACT, nil)
   389  		// backwards compatibility
   390  		if filter.RedirIndex != 0 {
   391  			filter.Actions = append([]Action{NewMirredAction(filter.RedirIndex)}, filter.Actions...)
   392  		}
   393  		if err := EncodeActions(actionsAttr, filter.Actions); err != nil {
   394  			return err
   395  		}
   396  	case *FwFilter:
   397  		if filter.Mask != 0 {
   398  			b := make([]byte, 4)
   399  			native.PutUint32(b, filter.Mask)
   400  			options.AddRtAttr(nl.TCA_FW_MASK, b)
   401  		}
   402  		if filter.InDev != "" {
   403  			options.AddRtAttr(nl.TCA_FW_INDEV, nl.ZeroTerminated(filter.InDev))
   404  		}
   405  		if filter.Police != nil {
   406  			police := options.AddRtAttr(nl.TCA_FW_POLICE, nil)
   407  			if err := encodePolice(police, filter.Police); err != nil {
   408  				return err
   409  			}
   410  		}
   411  		if filter.ClassId != 0 {
   412  			b := make([]byte, 4)
   413  			native.PutUint32(b, filter.ClassId)
   414  			options.AddRtAttr(nl.TCA_FW_CLASSID, b)
   415  		}
   416  		actionsAttr := options.AddRtAttr(nl.TCA_FW_ACT, nil)
   417  		if err := EncodeActions(actionsAttr, filter.Actions); err != nil {
   418  			return err
   419  		}
   420  	case *BpfFilter:
   421  		var bpfFlags uint32
   422  		if filter.ClassId != 0 {
   423  			options.AddRtAttr(nl.TCA_BPF_CLASSID, nl.Uint32Attr(filter.ClassId))
   424  		}
   425  		if filter.Fd >= 0 {
   426  			options.AddRtAttr(nl.TCA_BPF_FD, nl.Uint32Attr((uint32(filter.Fd))))
   427  		}
   428  		if filter.Name != "" {
   429  			options.AddRtAttr(nl.TCA_BPF_NAME, nl.ZeroTerminated(filter.Name))
   430  		}
   431  		if filter.DirectAction {
   432  			bpfFlags |= nl.TCA_BPF_FLAG_ACT_DIRECT
   433  		}
   434  		options.AddRtAttr(nl.TCA_BPF_FLAGS, nl.Uint32Attr(bpfFlags))
   435  	case *MatchAll:
   436  		actionsAttr := options.AddRtAttr(nl.TCA_MATCHALL_ACT, nil)
   437  		if err := EncodeActions(actionsAttr, filter.Actions); err != nil {
   438  			return err
   439  		}
   440  		if filter.ClassId != 0 {
   441  			options.AddRtAttr(nl.TCA_MATCHALL_CLASSID, nl.Uint32Attr(filter.ClassId))
   442  		}
   443  	case *Flower:
   444  		if err := filter.encode(options); err != nil {
   445  			return err
   446  		}
   447  	}
   448  	req.AddData(options)
   449  	_, err := req.Execute(unix.NETLINK_ROUTE, 0)
   450  	return err
   451  }
   452  
   453  // FilterList gets a list of filters in the system.
   454  // Equivalent to: `tc filter show`.
   455  //
   456  // Generally returns nothing if link and parent are not specified.
   457  // If the returned error is [ErrDumpInterrupted], results may be inconsistent
   458  // or incomplete.
   459  func FilterList(link Link, parent uint32) ([]Filter, error) {
   460  	return pkgHandle.FilterList(link, parent)
   461  }
   462  
   463  // FilterList gets a list of filters in the system.
   464  // Equivalent to: `tc filter show`.
   465  //
   466  // Generally returns nothing if link and parent are not specified.
   467  // If the returned error is [ErrDumpInterrupted], results may be inconsistent
   468  // or incomplete.
   469  func (h *Handle) FilterList(link Link, parent uint32) ([]Filter, error) {
   470  	req := h.newNetlinkRequest(unix.RTM_GETTFILTER, unix.NLM_F_DUMP)
   471  	msg := &nl.TcMsg{
   472  		Family: nl.FAMILY_ALL,
   473  		Parent: parent,
   474  	}
   475  	if link != nil {
   476  		base := link.Attrs()
   477  		h.ensureIndex(base)
   478  		msg.Ifindex = int32(base.Index)
   479  	}
   480  	req.AddData(msg)
   481  
   482  	msgs, executeErr := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWTFILTER)
   483  	if executeErr != nil && !errors.Is(executeErr, ErrDumpInterrupted) {
   484  		return nil, executeErr
   485  	}
   486  
   487  	var res []Filter
   488  	for _, m := range msgs {
   489  		msg := nl.DeserializeTcMsg(m)
   490  
   491  		attrs, err := nl.ParseRouteAttr(m[msg.Len():])
   492  		if err != nil {
   493  			return nil, err
   494  		}
   495  
   496  		base := FilterAttrs{
   497  			LinkIndex: int(msg.Ifindex),
   498  			Handle:    msg.Handle,
   499  			Parent:    msg.Parent,
   500  		}
   501  		base.Priority, base.Protocol = MajorMinor(msg.Info)
   502  		base.Protocol = nl.Swap16(base.Protocol)
   503  
   504  		var filter Filter
   505  		filterType := ""
   506  		detailed := false
   507  		for _, attr := range attrs {
   508  			switch attr.Attr.Type {
   509  			case nl.TCA_KIND:
   510  				filterType = string(attr.Value[:len(attr.Value)-1])
   511  				switch filterType {
   512  				case "u32":
   513  					filter = &U32{}
   514  				case "fw":
   515  					filter = &FwFilter{}
   516  				case "bpf":
   517  					filter = &BpfFilter{}
   518  				case "matchall":
   519  					filter = &MatchAll{}
   520  				case "flower":
   521  					filter = &Flower{}
   522  				default:
   523  					filter = &GenericFilter{FilterType: filterType}
   524  				}
   525  			case nl.TCA_OPTIONS:
   526  				data, err := nl.ParseRouteAttr(attr.Value)
   527  				if err != nil {
   528  					return nil, err
   529  				}
   530  				switch filterType {
   531  				case "u32":
   532  					detailed, err = parseU32Data(filter, data)
   533  					if err != nil {
   534  						return nil, err
   535  					}
   536  				case "fw":
   537  					detailed, err = parseFwData(filter, data)
   538  					if err != nil {
   539  						return nil, err
   540  					}
   541  				case "bpf":
   542  					detailed, err = parseBpfData(filter, data)
   543  					if err != nil {
   544  						return nil, err
   545  					}
   546  				case "matchall":
   547  					detailed, err = parseMatchAllData(filter, data)
   548  					if err != nil {
   549  						return nil, err
   550  					}
   551  				case "flower":
   552  					detailed, err = parseFlowerData(filter, data)
   553  					if err != nil {
   554  						return nil, err
   555  					}
   556  				default:
   557  					detailed = true
   558  				}
   559  			case nl.TCA_CHAIN:
   560  				val := new(uint32)
   561  				*val = native.Uint32(attr.Value)
   562  				base.Chain = val
   563  			}
   564  		}
   565  		// only return the detailed version of the filter
   566  		if detailed {
   567  			*filter.Attrs() = base
   568  			res = append(res, filter)
   569  		}
   570  	}
   571  
   572  	return res, executeErr
   573  }
   574  
   575  func toTcGen(attrs *ActionAttrs, tcgen *nl.TcGen) {
   576  	tcgen.Index = uint32(attrs.Index)
   577  	tcgen.Capab = uint32(attrs.Capab)
   578  	tcgen.Action = int32(attrs.Action)
   579  	tcgen.Refcnt = int32(attrs.Refcnt)
   580  	tcgen.Bindcnt = int32(attrs.Bindcnt)
   581  }
   582  
   583  func toAttrs(tcgen *nl.TcGen, attrs *ActionAttrs) {
   584  	attrs.Index = int(tcgen.Index)
   585  	attrs.Capab = int(tcgen.Capab)
   586  	attrs.Action = TcAct(tcgen.Action)
   587  	attrs.Refcnt = int(tcgen.Refcnt)
   588  	attrs.Bindcnt = int(tcgen.Bindcnt)
   589  }
   590  
   591  func toTimeStamp(tcf *nl.Tcf) *ActionTimestamp {
   592  	return &ActionTimestamp{
   593  		Installed: tcf.Install,
   594  		LastUsed:  tcf.LastUse,
   595  		Expires:   tcf.Expires,
   596  		FirstUsed: tcf.FirstUse}
   597  }
   598  
   599  func encodePolice(attr *nl.RtAttr, action *PoliceAction) error {
   600  	var rtab [256]uint32
   601  	var ptab [256]uint32
   602  	police := nl.TcPolice{}
   603  	police.Index = uint32(action.Attrs().Index)
   604  	police.Bindcnt = int32(action.Attrs().Bindcnt)
   605  	police.Capab = uint32(action.Attrs().Capab)
   606  	police.Refcnt = int32(action.Attrs().Refcnt)
   607  	police.Rate.Rate = action.Rate
   608  	police.PeakRate.Rate = action.PeakRate
   609  	police.Action = int32(action.ExceedAction)
   610  
   611  	if police.Rate.Rate != 0 {
   612  		police.Rate.Mpu = action.Mpu
   613  		police.Rate.Overhead = action.Overhead
   614  		if CalcRtable(&police.Rate, rtab[:], action.RCellLog, action.Mtu, action.LinkLayer) < 0 {
   615  			return errors.New("TBF: failed to calculate rate table")
   616  		}
   617  		police.Burst = Xmittime(uint64(police.Rate.Rate), action.Burst)
   618  	}
   619  
   620  	police.Mtu = action.Mtu
   621  	if police.PeakRate.Rate != 0 {
   622  		police.PeakRate.Mpu = action.Mpu
   623  		police.PeakRate.Overhead = action.Overhead
   624  		if CalcRtable(&police.PeakRate, ptab[:], action.PCellLog, action.Mtu, action.LinkLayer) < 0 {
   625  			return errors.New("POLICE: failed to calculate peak rate table")
   626  		}
   627  	}
   628  
   629  	attr.AddRtAttr(nl.TCA_POLICE_TBF, police.Serialize())
   630  	if police.Rate.Rate != 0 {
   631  		attr.AddRtAttr(nl.TCA_POLICE_RATE, SerializeRtab(rtab))
   632  	}
   633  	if police.PeakRate.Rate != 0 {
   634  		attr.AddRtAttr(nl.TCA_POLICE_PEAKRATE, SerializeRtab(ptab))
   635  	}
   636  	if action.AvRate != 0 {
   637  		attr.AddRtAttr(nl.TCA_POLICE_AVRATE, nl.Uint32Attr(action.AvRate))
   638  	}
   639  	if action.NotExceedAction != 0 {
   640  		attr.AddRtAttr(nl.TCA_POLICE_RESULT, nl.Uint32Attr(uint32(action.NotExceedAction)))
   641  	}
   642  
   643  	return nil
   644  }
   645  
   646  func EncodeActions(attr *nl.RtAttr, actions []Action) error {
   647  	tabIndex := int(nl.TCA_ACT_TAB)
   648  
   649  	for _, action := range actions {
   650  		switch action := action.(type) {
   651  		default:
   652  			return fmt.Errorf("unknown action type %s", action.Type())
   653  		case *PoliceAction:
   654  			table := attr.AddRtAttr(tabIndex, nil)
   655  			tabIndex++
   656  			table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("police"))
   657  			aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
   658  			if err := encodePolice(aopts, action); err != nil {
   659  				return err
   660  			}
   661  		case *MirredAction:
   662  			table := attr.AddRtAttr(tabIndex, nil)
   663  			tabIndex++
   664  			table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("mirred"))
   665  			aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
   666  			mirred := nl.TcMirred{
   667  				Eaction: int32(action.MirredAction),
   668  				Ifindex: uint32(action.Ifindex),
   669  			}
   670  			toTcGen(action.Attrs(), &mirred.TcGen)
   671  			aopts.AddRtAttr(nl.TCA_MIRRED_PARMS, mirred.Serialize())
   672  		case *VlanAction:
   673  			table := attr.AddRtAttr(tabIndex, nil)
   674  			tabIndex++
   675  			table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("vlan"))
   676  			aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
   677  			vlan := nl.TcVlan{
   678  				Action: int32(action.Action),
   679  			}
   680  			toTcGen(action.Attrs(), &vlan.TcGen)
   681  			aopts.AddRtAttr(nl.TCA_VLAN_PARMS, vlan.Serialize())
   682  			if action.Action == TCA_VLAN_ACT_PUSH && action.VlanID == 0 {
   683  				return fmt.Errorf("vlan id is required for push action")
   684  			}
   685  			if action.VlanID != 0 {
   686  				aopts.AddRtAttr(nl.TCA_VLAN_PUSH_VLAN_ID, nl.Uint16Attr(action.VlanID))
   687  			}
   688  		case *TunnelKeyAction:
   689  			table := attr.AddRtAttr(tabIndex, nil)
   690  			tabIndex++
   691  			table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("tunnel_key"))
   692  			aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
   693  			tun := nl.TcTunnelKey{
   694  				Action: int32(action.Action),
   695  			}
   696  			toTcGen(action.Attrs(), &tun.TcGen)
   697  			aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_PARMS, tun.Serialize())
   698  			if action.Action == TCA_TUNNEL_KEY_SET {
   699  				aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_ENC_KEY_ID, htonl(action.KeyID))
   700  				if v4 := action.SrcAddr.To4(); v4 != nil {
   701  					aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_ENC_IPV4_SRC, v4[:])
   702  				} else if v6 := action.SrcAddr.To16(); v6 != nil {
   703  					aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_ENC_IPV6_SRC, v6[:])
   704  				} else {
   705  					return fmt.Errorf("invalid src addr %s for tunnel_key action", action.SrcAddr)
   706  				}
   707  				if v4 := action.DstAddr.To4(); v4 != nil {
   708  					aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_ENC_IPV4_DST, v4[:])
   709  				} else if v6 := action.DstAddr.To16(); v6 != nil {
   710  					aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_ENC_IPV6_DST, v6[:])
   711  				} else {
   712  					return fmt.Errorf("invalid dst addr %s for tunnel_key action", action.DstAddr)
   713  				}
   714  				if action.DestPort != 0 {
   715  					aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_ENC_DST_PORT, htons(action.DestPort))
   716  				}
   717  			}
   718  		case *SkbEditAction:
   719  			table := attr.AddRtAttr(tabIndex, nil)
   720  			tabIndex++
   721  			table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("skbedit"))
   722  			aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
   723  			skbedit := nl.TcSkbEdit{}
   724  			toTcGen(action.Attrs(), &skbedit.TcGen)
   725  			aopts.AddRtAttr(nl.TCA_SKBEDIT_PARMS, skbedit.Serialize())
   726  			if action.QueueMapping != nil {
   727  				aopts.AddRtAttr(nl.TCA_SKBEDIT_QUEUE_MAPPING, nl.Uint16Attr(*action.QueueMapping))
   728  			}
   729  			if action.Priority != nil {
   730  				aopts.AddRtAttr(nl.TCA_SKBEDIT_PRIORITY, nl.Uint32Attr(*action.Priority))
   731  			}
   732  			if action.PType != nil {
   733  				aopts.AddRtAttr(nl.TCA_SKBEDIT_PTYPE, nl.Uint16Attr(*action.PType))
   734  			}
   735  			if action.Mark != nil {
   736  				aopts.AddRtAttr(nl.TCA_SKBEDIT_MARK, nl.Uint32Attr(*action.Mark))
   737  			}
   738  			if action.Mask != nil {
   739  				aopts.AddRtAttr(nl.TCA_SKBEDIT_MASK, nl.Uint32Attr(*action.Mask))
   740  			}
   741  		case *ConnmarkAction:
   742  			table := attr.AddRtAttr(tabIndex, nil)
   743  			tabIndex++
   744  			table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("connmark"))
   745  			aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
   746  			connmark := nl.TcConnmark{
   747  				Zone: action.Zone,
   748  			}
   749  			toTcGen(action.Attrs(), &connmark.TcGen)
   750  			aopts.AddRtAttr(nl.TCA_CONNMARK_PARMS, connmark.Serialize())
   751  		case *CsumAction:
   752  			table := attr.AddRtAttr(tabIndex, nil)
   753  			tabIndex++
   754  			table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("csum"))
   755  			aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
   756  			csum := nl.TcCsum{
   757  				UpdateFlags: uint32(action.UpdateFlags),
   758  			}
   759  			toTcGen(action.Attrs(), &csum.TcGen)
   760  			aopts.AddRtAttr(nl.TCA_CSUM_PARMS, csum.Serialize())
   761  		case *BpfAction:
   762  			table := attr.AddRtAttr(tabIndex, nil)
   763  			tabIndex++
   764  			table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("bpf"))
   765  			aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
   766  			gen := nl.TcGen{}
   767  			toTcGen(action.Attrs(), &gen)
   768  			aopts.AddRtAttr(nl.TCA_ACT_BPF_PARMS, gen.Serialize())
   769  			aopts.AddRtAttr(nl.TCA_ACT_BPF_FD, nl.Uint32Attr(uint32(action.Fd)))
   770  			aopts.AddRtAttr(nl.TCA_ACT_BPF_NAME, nl.ZeroTerminated(action.Name))
   771  		case *SampleAction:
   772  			table := attr.AddRtAttr(tabIndex, nil)
   773  			tabIndex++
   774  			table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("sample"))
   775  			aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
   776  			gen := nl.TcGen{}
   777  			toTcGen(action.Attrs(), &gen)
   778  			aopts.AddRtAttr(nl.TCA_ACT_SAMPLE_PARMS, gen.Serialize())
   779  			aopts.AddRtAttr(nl.TCA_ACT_SAMPLE_RATE, nl.Uint32Attr(action.Rate))
   780  			aopts.AddRtAttr(nl.TCA_ACT_SAMPLE_PSAMPLE_GROUP, nl.Uint32Attr(action.Group))
   781  			aopts.AddRtAttr(nl.TCA_ACT_SAMPLE_TRUNC_SIZE, nl.Uint32Attr(action.TruncSize))
   782  		case *GenericAction:
   783  			table := attr.AddRtAttr(tabIndex, nil)
   784  			tabIndex++
   785  			table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("gact"))
   786  			aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
   787  			gen := nl.TcGen{}
   788  			toTcGen(action.Attrs(), &gen)
   789  			aopts.AddRtAttr(nl.TCA_GACT_PARMS, gen.Serialize())
   790  		case *PeditAction:
   791  			table := attr.AddRtAttr(tabIndex, nil)
   792  			tabIndex++
   793  			pedit := nl.TcPedit{}
   794  			toTcGen(action.Attrs(), &pedit.Sel.TcGen)
   795  			if action.SrcMacAddr != nil {
   796  				pedit.SetEthSrc(action.SrcMacAddr)
   797  			}
   798  			if action.DstMacAddr != nil {
   799  				pedit.SetEthDst(action.DstMacAddr)
   800  			}
   801  			if action.SrcIP != nil {
   802  				pedit.SetSrcIP(action.SrcIP)
   803  			}
   804  			if action.DstIP != nil {
   805  				pedit.SetDstIP(action.DstIP)
   806  			}
   807  			if action.SrcPort != 0 {
   808  				pedit.SetSrcPort(action.SrcPort, action.Proto)
   809  			}
   810  			if action.DstPort != 0 {
   811  				pedit.SetDstPort(action.DstPort, action.Proto)
   812  			}
   813  			pedit.Encode(table)
   814  		}
   815  	}
   816  	return nil
   817  }
   818  
   819  func parsePolice(data syscall.NetlinkRouteAttr, police *PoliceAction) {
   820  	switch data.Attr.Type {
   821  	case nl.TCA_POLICE_RESULT:
   822  		police.NotExceedAction = TcPolAct(native.Uint32(data.Value[0:4]))
   823  	case nl.TCA_POLICE_AVRATE:
   824  		police.AvRate = native.Uint32(data.Value[0:4])
   825  	case nl.TCA_POLICE_TBF:
   826  		p := *nl.DeserializeTcPolice(data.Value)
   827  		police.ActionAttrs = ActionAttrs{}
   828  		police.Attrs().Index = int(p.Index)
   829  		police.Attrs().Bindcnt = int(p.Bindcnt)
   830  		police.Attrs().Capab = int(p.Capab)
   831  		police.Attrs().Refcnt = int(p.Refcnt)
   832  		police.ExceedAction = TcPolAct(p.Action)
   833  		police.Rate = p.Rate.Rate
   834  		police.PeakRate = p.PeakRate.Rate
   835  		police.Burst = Xmitsize(uint64(p.Rate.Rate), p.Burst)
   836  		police.Mtu = p.Mtu
   837  		police.LinkLayer = int(p.Rate.Linklayer) & nl.TC_LINKLAYER_MASK
   838  		police.Overhead = p.Rate.Overhead
   839  	}
   840  }
   841  
   842  func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
   843  	var actions []Action
   844  	for _, table := range tables {
   845  		var action Action
   846  		var actionType string
   847  		var actionnStatistic *ActionStatistic
   848  		var actionTimestamp *ActionTimestamp
   849  		aattrs, err := nl.ParseRouteAttr(table.Value)
   850  		if err != nil {
   851  			return nil, err
   852  		}
   853  	nextattr:
   854  		for _, aattr := range aattrs {
   855  			switch aattr.Attr.Type {
   856  			case nl.TCA_KIND:
   857  				actionType = string(aattr.Value[:len(aattr.Value)-1])
   858  				// only parse if the action is mirred or bpf
   859  				switch actionType {
   860  				case "mirred":
   861  					action = &MirredAction{}
   862  				case "bpf":
   863  					action = &BpfAction{}
   864  				case "connmark":
   865  					action = &ConnmarkAction{}
   866  				case "csum":
   867  					action = &CsumAction{}
   868  				case "sample":
   869  					action = &SampleAction{}
   870  				case "gact":
   871  					action = &GenericAction{}
   872  				case "vlan":
   873  					action = &VlanAction{}
   874  				case "tunnel_key":
   875  					action = &TunnelKeyAction{}
   876  				case "skbedit":
   877  					action = &SkbEditAction{}
   878  				case "police":
   879  					action = &PoliceAction{}
   880  				case "pedit":
   881  					action = &PeditAction{}
   882  				default:
   883  					break nextattr
   884  				}
   885  			case nl.TCA_OPTIONS:
   886  				adata, err := nl.ParseRouteAttr(aattr.Value)
   887  				if err != nil {
   888  					return nil, err
   889  				}
   890  				for _, adatum := range adata {
   891  					switch actionType {
   892  					case "mirred":
   893  						switch adatum.Attr.Type {
   894  						case nl.TCA_MIRRED_PARMS:
   895  							mirred := *nl.DeserializeTcMirred(adatum.Value)
   896  							action.(*MirredAction).ActionAttrs = ActionAttrs{}
   897  							toAttrs(&mirred.TcGen, action.Attrs())
   898  							action.(*MirredAction).Ifindex = int(mirred.Ifindex)
   899  							action.(*MirredAction).MirredAction = MirredAct(mirred.Eaction)
   900  						case nl.TCA_MIRRED_TM:
   901  							tcTs := nl.DeserializeTcf(adatum.Value)
   902  							actionTimestamp = toTimeStamp(tcTs)
   903  						}
   904  					case "vlan":
   905  						switch adatum.Attr.Type {
   906  						case nl.TCA_VLAN_PARMS:
   907  							vlan := *nl.DeserializeTcVlan(adatum.Value)
   908  							action.(*VlanAction).ActionAttrs = ActionAttrs{}
   909  							toAttrs(&vlan.TcGen, action.Attrs())
   910  							action.(*VlanAction).Action = VlanAct(vlan.Action)
   911  						case nl.TCA_VLAN_PUSH_VLAN_ID:
   912  							vlanId := native.Uint16(adatum.Value[0:2])
   913  							action.(*VlanAction).VlanID = vlanId
   914  						}
   915  					case "tunnel_key":
   916  						switch adatum.Attr.Type {
   917  						case nl.TCA_TUNNEL_KEY_PARMS:
   918  							tun := *nl.DeserializeTunnelKey(adatum.Value)
   919  							action.(*TunnelKeyAction).ActionAttrs = ActionAttrs{}
   920  							toAttrs(&tun.TcGen, action.Attrs())
   921  							action.(*TunnelKeyAction).Action = TunnelKeyAct(tun.Action)
   922  						case nl.TCA_TUNNEL_KEY_ENC_KEY_ID:
   923  							action.(*TunnelKeyAction).KeyID = networkOrder.Uint32(adatum.Value[0:4])
   924  						case nl.TCA_TUNNEL_KEY_ENC_IPV6_SRC, nl.TCA_TUNNEL_KEY_ENC_IPV4_SRC:
   925  							action.(*TunnelKeyAction).SrcAddr = adatum.Value[:]
   926  						case nl.TCA_TUNNEL_KEY_ENC_IPV6_DST, nl.TCA_TUNNEL_KEY_ENC_IPV4_DST:
   927  							action.(*TunnelKeyAction).DstAddr = adatum.Value[:]
   928  						case nl.TCA_TUNNEL_KEY_ENC_DST_PORT:
   929  							action.(*TunnelKeyAction).DestPort = ntohs(adatum.Value)
   930  						case nl.TCA_TUNNEL_KEY_TM:
   931  							tcTs := nl.DeserializeTcf(adatum.Value)
   932  							actionTimestamp = toTimeStamp(tcTs)
   933  						}
   934  					case "skbedit":
   935  						switch adatum.Attr.Type {
   936  						case nl.TCA_SKBEDIT_PARMS:
   937  							skbedit := *nl.DeserializeSkbEdit(adatum.Value)
   938  							action.(*SkbEditAction).ActionAttrs = ActionAttrs{}
   939  							toAttrs(&skbedit.TcGen, action.Attrs())
   940  						case nl.TCA_SKBEDIT_MARK:
   941  							mark := native.Uint32(adatum.Value[0:4])
   942  							action.(*SkbEditAction).Mark = &mark
   943  						case nl.TCA_SKBEDIT_MASK:
   944  							mask := native.Uint32(adatum.Value[0:4])
   945  							action.(*SkbEditAction).Mask = &mask
   946  						case nl.TCA_SKBEDIT_PRIORITY:
   947  							priority := native.Uint32(adatum.Value[0:4])
   948  							action.(*SkbEditAction).Priority = &priority
   949  						case nl.TCA_SKBEDIT_PTYPE:
   950  							ptype := native.Uint16(adatum.Value[0:2])
   951  							action.(*SkbEditAction).PType = &ptype
   952  						case nl.TCA_SKBEDIT_QUEUE_MAPPING:
   953  							mapping := native.Uint16(adatum.Value[0:2])
   954  							action.(*SkbEditAction).QueueMapping = &mapping
   955  						case nl.TCA_SKBEDIT_TM:
   956  							tcTs := nl.DeserializeTcf(adatum.Value)
   957  							actionTimestamp = toTimeStamp(tcTs)
   958  						}
   959  					case "bpf":
   960  						switch adatum.Attr.Type {
   961  						case nl.TCA_ACT_BPF_PARMS:
   962  							gen := *nl.DeserializeTcGen(adatum.Value)
   963  							toAttrs(&gen, action.Attrs())
   964  						case nl.TCA_ACT_BPF_FD:
   965  							action.(*BpfAction).Fd = int(native.Uint32(adatum.Value[0:4]))
   966  						case nl.TCA_ACT_BPF_NAME:
   967  							action.(*BpfAction).Name = string(adatum.Value[:len(adatum.Value)-1])
   968  						case nl.TCA_ACT_BPF_TM:
   969  							tcTs := nl.DeserializeTcf(adatum.Value)
   970  							actionTimestamp = toTimeStamp(tcTs)
   971  						}
   972  					case "connmark":
   973  						switch adatum.Attr.Type {
   974  						case nl.TCA_CONNMARK_PARMS:
   975  							connmark := *nl.DeserializeTcConnmark(adatum.Value)
   976  							action.(*ConnmarkAction).ActionAttrs = ActionAttrs{}
   977  							toAttrs(&connmark.TcGen, action.Attrs())
   978  							action.(*ConnmarkAction).Zone = connmark.Zone
   979  						case nl.TCA_CONNMARK_TM:
   980  							tcTs := nl.DeserializeTcf(adatum.Value)
   981  							actionTimestamp = toTimeStamp(tcTs)
   982  						}
   983  					case "csum":
   984  						switch adatum.Attr.Type {
   985  						case nl.TCA_CSUM_PARMS:
   986  							csum := *nl.DeserializeTcCsum(adatum.Value)
   987  							action.(*CsumAction).ActionAttrs = ActionAttrs{}
   988  							toAttrs(&csum.TcGen, action.Attrs())
   989  							action.(*CsumAction).UpdateFlags = CsumUpdateFlags(csum.UpdateFlags)
   990  						case nl.TCA_CSUM_TM:
   991  							tcTs := nl.DeserializeTcf(adatum.Value)
   992  							actionTimestamp = toTimeStamp(tcTs)
   993  						}
   994  					case "sample":
   995  						switch adatum.Attr.Type {
   996  						case nl.TCA_ACT_SAMPLE_PARMS:
   997  							gen := *nl.DeserializeTcGen(adatum.Value)
   998  							toAttrs(&gen, action.Attrs())
   999  						case nl.TCA_ACT_SAMPLE_RATE:
  1000  							action.(*SampleAction).Rate = native.Uint32(adatum.Value[0:4])
  1001  						case nl.TCA_ACT_SAMPLE_PSAMPLE_GROUP:
  1002  							action.(*SampleAction).Group = native.Uint32(adatum.Value[0:4])
  1003  						case nl.TCA_ACT_SAMPLE_TRUNC_SIZE:
  1004  							action.(*SampleAction).TruncSize = native.Uint32(adatum.Value[0:4])
  1005  						}
  1006  					case "gact":
  1007  						switch adatum.Attr.Type {
  1008  						case nl.TCA_GACT_PARMS:
  1009  							gen := *nl.DeserializeTcGen(adatum.Value)
  1010  							toAttrs(&gen, action.Attrs())
  1011  							if action.Attrs().Action.String() == "goto" {
  1012  								action.(*GenericAction).Chain = TC_ACT_EXT_VAL_MASK & gen.Action
  1013  							}
  1014  						case nl.TCA_GACT_TM:
  1015  							tcTs := nl.DeserializeTcf(adatum.Value)
  1016  							actionTimestamp = toTimeStamp(tcTs)
  1017  						}
  1018  					case "police":
  1019  						parsePolice(adatum, action.(*PoliceAction))
  1020  					}
  1021  				}
  1022  			case nl.TCA_ACT_STATS:
  1023  				s, err := parseTcStats2(aattr.Value)
  1024  				if err != nil {
  1025  					return nil, err
  1026  				}
  1027  				actionnStatistic = (*ActionStatistic)(s)
  1028  			}
  1029  		}
  1030  		if action != nil {
  1031  			action.Attrs().Statistics = actionnStatistic
  1032  			action.Attrs().Timestamp = actionTimestamp
  1033  			actions = append(actions, action)
  1034  		}
  1035  	}
  1036  	return actions, nil
  1037  }
  1038  
  1039  func parseU32Data(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
  1040  	u32 := filter.(*U32)
  1041  	detailed := false
  1042  	for _, datum := range data {
  1043  		switch datum.Attr.Type {
  1044  		case nl.TCA_U32_SEL:
  1045  			detailed = true
  1046  			sel := nl.DeserializeTcU32Sel(datum.Value)
  1047  			u32.Sel = sel
  1048  			if native != networkOrder {
  1049  				// Handle the endianness of attributes
  1050  				u32.Sel.Offmask = native.Uint16(htons(sel.Offmask))
  1051  				u32.Sel.Hmask = native.Uint32(htonl(sel.Hmask))
  1052  				for i, key := range u32.Sel.Keys {
  1053  					u32.Sel.Keys[i].Mask = native.Uint32(htonl(key.Mask))
  1054  					u32.Sel.Keys[i].Val = native.Uint32(htonl(key.Val))
  1055  				}
  1056  			}
  1057  		case nl.TCA_U32_ACT:
  1058  			tables, err := nl.ParseRouteAttr(datum.Value)
  1059  			if err != nil {
  1060  				return detailed, err
  1061  			}
  1062  			u32.Actions, err = parseActions(tables)
  1063  			if err != nil {
  1064  				return detailed, err
  1065  			}
  1066  			for _, action := range u32.Actions {
  1067  				if action, ok := action.(*MirredAction); ok {
  1068  					u32.RedirIndex = int(action.Ifindex)
  1069  				}
  1070  			}
  1071  		case nl.TCA_U32_POLICE:
  1072  			var police PoliceAction
  1073  			adata, _ := nl.ParseRouteAttr(datum.Value)
  1074  			for _, aattr := range adata {
  1075  				parsePolice(aattr, &police)
  1076  			}
  1077  			u32.Police = &police
  1078  		case nl.TCA_U32_CLASSID:
  1079  			u32.ClassId = native.Uint32(datum.Value)
  1080  		case nl.TCA_U32_DIVISOR:
  1081  			u32.Divisor = native.Uint32(datum.Value)
  1082  		case nl.TCA_U32_HASH:
  1083  			u32.Hash = native.Uint32(datum.Value)
  1084  		case nl.TCA_U32_LINK:
  1085  			u32.Link = native.Uint32(datum.Value)
  1086  		}
  1087  	}
  1088  	return detailed, nil
  1089  }
  1090  
  1091  func parseFwData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
  1092  	fw := filter.(*FwFilter)
  1093  	detailed := true
  1094  	for _, datum := range data {
  1095  		switch datum.Attr.Type {
  1096  		case nl.TCA_FW_MASK:
  1097  			fw.Mask = native.Uint32(datum.Value[0:4])
  1098  		case nl.TCA_FW_CLASSID:
  1099  			fw.ClassId = native.Uint32(datum.Value[0:4])
  1100  		case nl.TCA_FW_INDEV:
  1101  			fw.InDev = string(datum.Value[:len(datum.Value)-1])
  1102  		case nl.TCA_FW_POLICE:
  1103  			var police PoliceAction
  1104  			adata, _ := nl.ParseRouteAttr(datum.Value)
  1105  			for _, aattr := range adata {
  1106  				parsePolice(aattr, &police)
  1107  			}
  1108  			fw.Police = &police
  1109  		case nl.TCA_FW_ACT:
  1110  			tables, err := nl.ParseRouteAttr(datum.Value)
  1111  			if err != nil {
  1112  				return detailed, err
  1113  			}
  1114  			fw.Actions, err = parseActions(tables)
  1115  			if err != nil {
  1116  				return detailed, err
  1117  			}
  1118  		}
  1119  	}
  1120  	return detailed, nil
  1121  }
  1122  
  1123  func parseBpfData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
  1124  	bpf := filter.(*BpfFilter)
  1125  	detailed := true
  1126  	for _, datum := range data {
  1127  		switch datum.Attr.Type {
  1128  		case nl.TCA_BPF_FD:
  1129  			bpf.Fd = int(native.Uint32(datum.Value[0:4]))
  1130  		case nl.TCA_BPF_NAME:
  1131  			bpf.Name = string(datum.Value[:len(datum.Value)-1])
  1132  		case nl.TCA_BPF_CLASSID:
  1133  			bpf.ClassId = native.Uint32(datum.Value[0:4])
  1134  		case nl.TCA_BPF_FLAGS:
  1135  			flags := native.Uint32(datum.Value[0:4])
  1136  			if (flags & nl.TCA_BPF_FLAG_ACT_DIRECT) != 0 {
  1137  				bpf.DirectAction = true
  1138  			}
  1139  		case nl.TCA_BPF_ID:
  1140  			bpf.Id = int(native.Uint32(datum.Value[0:4]))
  1141  		case nl.TCA_BPF_TAG:
  1142  			bpf.Tag = hex.EncodeToString(datum.Value)
  1143  		}
  1144  	}
  1145  	return detailed, nil
  1146  }
  1147  
  1148  func parseMatchAllData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
  1149  	matchall := filter.(*MatchAll)
  1150  	detailed := true
  1151  	for _, datum := range data {
  1152  		switch datum.Attr.Type {
  1153  		case nl.TCA_MATCHALL_CLASSID:
  1154  			matchall.ClassId = native.Uint32(datum.Value[0:4])
  1155  		case nl.TCA_MATCHALL_ACT:
  1156  			tables, err := nl.ParseRouteAttr(datum.Value)
  1157  			if err != nil {
  1158  				return detailed, err
  1159  			}
  1160  			matchall.Actions, err = parseActions(tables)
  1161  			if err != nil {
  1162  				return detailed, err
  1163  			}
  1164  		}
  1165  	}
  1166  	return detailed, nil
  1167  }
  1168  
  1169  func parseFlowerData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
  1170  	return true, filter.(*Flower).decode(data)
  1171  }
  1172  
  1173  func AlignToAtm(size uint) uint {
  1174  	var linksize, cells int
  1175  	cells = int(size / nl.ATM_CELL_PAYLOAD)
  1176  	if (size % nl.ATM_CELL_PAYLOAD) > 0 {
  1177  		cells++
  1178  	}
  1179  	linksize = cells * nl.ATM_CELL_SIZE
  1180  	return uint(linksize)
  1181  }
  1182  
  1183  func AdjustSize(sz uint, mpu uint, linklayer int) uint {
  1184  	if sz < mpu {
  1185  		sz = mpu
  1186  	}
  1187  	switch linklayer {
  1188  	case nl.LINKLAYER_ATM:
  1189  		return AlignToAtm(sz)
  1190  	default:
  1191  		return sz
  1192  	}
  1193  }
  1194  
  1195  func CalcRtable(rate *nl.TcRateSpec, rtab []uint32, cellLog int, mtu uint32, linklayer int) int {
  1196  	bps := rate.Rate
  1197  	mpu := rate.Mpu
  1198  	var sz uint
  1199  	if mtu == 0 {
  1200  		mtu = 2047
  1201  	}
  1202  	if cellLog < 0 {
  1203  		cellLog = 0
  1204  		for (mtu >> uint(cellLog)) > 255 {
  1205  			cellLog++
  1206  		}
  1207  	}
  1208  	for i := 0; i < 256; i++ {
  1209  		sz = AdjustSize(uint((i+1)<<uint32(cellLog)), uint(mpu), linklayer)
  1210  		rtab[i] = Xmittime(uint64(bps), uint32(sz))
  1211  	}
  1212  	rate.CellAlign = -1
  1213  	rate.CellLog = uint8(cellLog)
  1214  	rate.Linklayer = uint8(linklayer & nl.TC_LINKLAYER_MASK)
  1215  	return cellLog
  1216  }
  1217  
  1218  func DeserializeRtab(b []byte) [256]uint32 {
  1219  	var rtab [256]uint32
  1220  	r := bytes.NewReader(b)
  1221  	_ = binary.Read(r, native, &rtab)
  1222  	return rtab
  1223  }
  1224  
  1225  func SerializeRtab(rtab [256]uint32) []byte {
  1226  	var w bytes.Buffer
  1227  	_ = binary.Write(&w, native, rtab)
  1228  	return w.Bytes()
  1229  }