|
|
@@ -6,6 +6,7 @@ import (
|
|
|
"encoding/hex"
|
|
|
"errors"
|
|
|
"fmt"
|
|
|
+ "net"
|
|
|
"syscall"
|
|
|
|
|
|
"github.com/vishvananda/netlink/nl"
|
|
|
@@ -40,6 +41,7 @@ type U32 struct {
|
|
|
RedirIndex int
|
|
|
Sel *TcU32Sel
|
|
|
Actions []Action
|
|
|
+ Police *PoliceAction
|
|
|
}
|
|
|
|
|
|
func (filter *U32) Attrs() *FilterAttrs {
|
|
|
@@ -50,74 +52,232 @@ func (filter *U32) Type() string {
|
|
|
return "u32"
|
|
|
}
|
|
|
|
|
|
-// Fw filter filters on firewall marks
|
|
|
-// NOTE: this is in filter_linux because it refers to nl.TcPolice which
|
|
|
-// is defined in nl/tc_linux.go
|
|
|
-type Fw struct {
|
|
|
+type Flower struct {
|
|
|
FilterAttrs
|
|
|
- ClassId uint32
|
|
|
- // TODO remove nl type from interface
|
|
|
- Police nl.TcPolice
|
|
|
- InDev string
|
|
|
- // TODO Action
|
|
|
- Mask uint32
|
|
|
- AvRate uint32
|
|
|
- Rtab [256]uint32
|
|
|
- Ptab [256]uint32
|
|
|
-}
|
|
|
-
|
|
|
-func NewFw(attrs FilterAttrs, fattrs FilterFwAttrs) (*Fw, error) {
|
|
|
- var rtab [256]uint32
|
|
|
- var ptab [256]uint32
|
|
|
- rcellLog := -1
|
|
|
- pcellLog := -1
|
|
|
- avrate := fattrs.AvRate / 8
|
|
|
- police := nl.TcPolice{}
|
|
|
- police.Rate.Rate = fattrs.Rate / 8
|
|
|
- police.PeakRate.Rate = fattrs.PeakRate / 8
|
|
|
- buffer := fattrs.Buffer
|
|
|
- linklayer := nl.LINKLAYER_ETHERNET
|
|
|
+ ClassId uint32
|
|
|
+ DestIP net.IP
|
|
|
+ DestIPMask net.IPMask
|
|
|
+ SrcIP net.IP
|
|
|
+ SrcIPMask net.IPMask
|
|
|
+ EthType uint16
|
|
|
+ EncDestIP net.IP
|
|
|
+ EncDestIPMask net.IPMask
|
|
|
+ EncSrcIP net.IP
|
|
|
+ EncSrcIPMask net.IPMask
|
|
|
+ EncDestPort uint16
|
|
|
+ EncKeyId uint32
|
|
|
+ SrcMac net.HardwareAddr
|
|
|
+ DestMac net.HardwareAddr
|
|
|
+ VlanId uint16
|
|
|
+ SkipHw bool
|
|
|
+ SkipSw bool
|
|
|
+ IPProto *nl.IPProto
|
|
|
+ DestPort uint16
|
|
|
+ SrcPort uint16
|
|
|
+ SrcPortRangeMin uint16
|
|
|
+ SrcPortRangeMax uint16
|
|
|
+ DstPortRangeMin uint16
|
|
|
+ DstPortRangeMax uint16
|
|
|
|
|
|
- if fattrs.LinkLayer != nl.LINKLAYER_UNSPEC {
|
|
|
- linklayer = fattrs.LinkLayer
|
|
|
- }
|
|
|
+ Actions []Action
|
|
|
+}
|
|
|
|
|
|
- police.Action = int32(fattrs.Action)
|
|
|
- if police.Rate.Rate != 0 {
|
|
|
- police.Rate.Mpu = fattrs.Mpu
|
|
|
- police.Rate.Overhead = fattrs.Overhead
|
|
|
- if CalcRtable(&police.Rate, rtab[:], rcellLog, fattrs.Mtu, linklayer) < 0 {
|
|
|
- return nil, errors.New("TBF: failed to calculate rate table")
|
|
|
- }
|
|
|
- police.Burst = Xmittime(uint64(police.Rate.Rate), uint32(buffer))
|
|
|
+func (filter *Flower) Attrs() *FilterAttrs {
|
|
|
+ return &filter.FilterAttrs
|
|
|
+}
|
|
|
+
|
|
|
+func (filter *Flower) Type() string {
|
|
|
+ return "flower"
|
|
|
+}
|
|
|
+
|
|
|
+func (filter *Flower) encodeIP(parent *nl.RtAttr, ip net.IP, mask net.IPMask, v4Type, v6Type int, v4MaskType, v6MaskType int) {
|
|
|
+ ipType := v4Type
|
|
|
+ maskType := v4MaskType
|
|
|
+
|
|
|
+ encodeMask := mask
|
|
|
+ if mask == nil {
|
|
|
+ encodeMask = net.CIDRMask(32, 32)
|
|
|
}
|
|
|
- police.Mtu = fattrs.Mtu
|
|
|
- if police.PeakRate.Rate != 0 {
|
|
|
- police.PeakRate.Mpu = fattrs.Mpu
|
|
|
- police.PeakRate.Overhead = fattrs.Overhead
|
|
|
- if CalcRtable(&police.PeakRate, ptab[:], pcellLog, fattrs.Mtu, linklayer) < 0 {
|
|
|
- return nil, errors.New("POLICE: failed to calculate peak rate table")
|
|
|
+ v4IP := ip.To4()
|
|
|
+ if v4IP == nil {
|
|
|
+ ipType = v6Type
|
|
|
+ maskType = v6MaskType
|
|
|
+ if mask == nil {
|
|
|
+ encodeMask = net.CIDRMask(128, 128)
|
|
|
}
|
|
|
+ } else {
|
|
|
+ ip = v4IP
|
|
|
}
|
|
|
|
|
|
- return &Fw{
|
|
|
- FilterAttrs: attrs,
|
|
|
- ClassId: fattrs.ClassId,
|
|
|
- InDev: fattrs.InDev,
|
|
|
- Mask: fattrs.Mask,
|
|
|
- Police: police,
|
|
|
- AvRate: avrate,
|
|
|
- Rtab: rtab,
|
|
|
- Ptab: ptab,
|
|
|
- }, nil
|
|
|
+ parent.AddRtAttr(ipType, ip)
|
|
|
+ parent.AddRtAttr(maskType, encodeMask)
|
|
|
}
|
|
|
|
|
|
-func (filter *Fw) Attrs() *FilterAttrs {
|
|
|
- return &filter.FilterAttrs
|
|
|
+func (filter *Flower) encode(parent *nl.RtAttr) error {
|
|
|
+ if filter.EthType != 0 {
|
|
|
+ parent.AddRtAttr(nl.TCA_FLOWER_KEY_ETH_TYPE, htons(filter.EthType))
|
|
|
+ }
|
|
|
+ if filter.SrcIP != nil {
|
|
|
+ filter.encodeIP(parent, filter.SrcIP, filter.SrcIPMask,
|
|
|
+ nl.TCA_FLOWER_KEY_IPV4_SRC, nl.TCA_FLOWER_KEY_IPV6_SRC,
|
|
|
+ nl.TCA_FLOWER_KEY_IPV4_SRC_MASK, nl.TCA_FLOWER_KEY_IPV6_SRC_MASK)
|
|
|
+ }
|
|
|
+ if filter.DestIP != nil {
|
|
|
+ filter.encodeIP(parent, filter.DestIP, filter.DestIPMask,
|
|
|
+ nl.TCA_FLOWER_KEY_IPV4_DST, nl.TCA_FLOWER_KEY_IPV6_DST,
|
|
|
+ nl.TCA_FLOWER_KEY_IPV4_DST_MASK, nl.TCA_FLOWER_KEY_IPV6_DST_MASK)
|
|
|
+ }
|
|
|
+ if filter.EncSrcIP != nil {
|
|
|
+ filter.encodeIP(parent, filter.EncSrcIP, filter.EncSrcIPMask,
|
|
|
+ nl.TCA_FLOWER_KEY_ENC_IPV4_SRC, nl.TCA_FLOWER_KEY_ENC_IPV6_SRC,
|
|
|
+ nl.TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK, nl.TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK)
|
|
|
+ }
|
|
|
+ if filter.EncDestIP != nil {
|
|
|
+ filter.encodeIP(parent, filter.EncDestIP, filter.EncSrcIPMask,
|
|
|
+ nl.TCA_FLOWER_KEY_ENC_IPV4_DST, nl.TCA_FLOWER_KEY_ENC_IPV6_DST,
|
|
|
+ nl.TCA_FLOWER_KEY_ENC_IPV4_DST_MASK, nl.TCA_FLOWER_KEY_ENC_IPV6_DST_MASK)
|
|
|
+ }
|
|
|
+ if filter.EncDestPort != 0 {
|
|
|
+ parent.AddRtAttr(nl.TCA_FLOWER_KEY_ENC_UDP_DST_PORT, htons(filter.EncDestPort))
|
|
|
+ }
|
|
|
+ if filter.EncKeyId != 0 {
|
|
|
+ parent.AddRtAttr(nl.TCA_FLOWER_KEY_ENC_KEY_ID, htonl(filter.EncKeyId))
|
|
|
+ }
|
|
|
+ if filter.SrcMac != nil {
|
|
|
+ parent.AddRtAttr(nl.TCA_FLOWER_KEY_ETH_SRC, filter.SrcMac)
|
|
|
+ }
|
|
|
+ if filter.DestMac != nil {
|
|
|
+ parent.AddRtAttr(nl.TCA_FLOWER_KEY_ETH_DST, filter.DestMac)
|
|
|
+ }
|
|
|
+ if filter.VlanId != 0 {
|
|
|
+ parent.AddRtAttr(nl.TCA_FLOWER_KEY_VLAN_ID, nl.Uint16Attr(filter.VlanId))
|
|
|
+ }
|
|
|
+ if filter.IPProto != nil {
|
|
|
+ ipproto := *filter.IPProto
|
|
|
+ parent.AddRtAttr(nl.TCA_FLOWER_KEY_IP_PROTO, ipproto.Serialize())
|
|
|
+ if filter.SrcPort != 0 {
|
|
|
+ switch ipproto {
|
|
|
+ case nl.IPPROTO_TCP:
|
|
|
+ parent.AddRtAttr(nl.TCA_FLOWER_KEY_TCP_SRC, htons(filter.SrcPort))
|
|
|
+ case nl.IPPROTO_UDP:
|
|
|
+ parent.AddRtAttr(nl.TCA_FLOWER_KEY_UDP_SRC, htons(filter.SrcPort))
|
|
|
+ case nl.IPPROTO_SCTP:
|
|
|
+ parent.AddRtAttr(nl.TCA_FLOWER_KEY_SCTP_SRC, htons(filter.SrcPort))
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if filter.DestPort != 0 {
|
|
|
+ switch ipproto {
|
|
|
+ case nl.IPPROTO_TCP:
|
|
|
+ parent.AddRtAttr(nl.TCA_FLOWER_KEY_TCP_DST, htons(filter.DestPort))
|
|
|
+ case nl.IPPROTO_UDP:
|
|
|
+ parent.AddRtAttr(nl.TCA_FLOWER_KEY_UDP_DST, htons(filter.DestPort))
|
|
|
+ case nl.IPPROTO_SCTP:
|
|
|
+ parent.AddRtAttr(nl.TCA_FLOWER_KEY_SCTP_DST, htons(filter.DestPort))
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if filter.SrcPortRangeMin != 0 && filter.SrcPortRangeMax != 0 {
|
|
|
+ parent.AddRtAttr(nl.TCA_FLOWER_KEY_PORT_SRC_MIN, htons(filter.SrcPortRangeMin))
|
|
|
+ parent.AddRtAttr(nl.TCA_FLOWER_KEY_PORT_SRC_MAX, htons(filter.SrcPortRangeMax))
|
|
|
+ }
|
|
|
+
|
|
|
+ if filter.DstPortRangeMin != 0 && filter.DstPortRangeMax != 0 {
|
|
|
+ parent.AddRtAttr(nl.TCA_FLOWER_KEY_PORT_DST_MIN, htons(filter.DstPortRangeMin))
|
|
|
+ parent.AddRtAttr(nl.TCA_FLOWER_KEY_PORT_DST_MAX, htons(filter.DstPortRangeMax))
|
|
|
+ }
|
|
|
+
|
|
|
+ if filter.ClassId != 0 {
|
|
|
+ parent.AddRtAttr(nl.TCA_FLOWER_CLASSID, nl.Uint32Attr(filter.ClassId))
|
|
|
+ }
|
|
|
+
|
|
|
+ var flags uint32 = 0
|
|
|
+ if filter.SkipHw {
|
|
|
+ flags |= nl.TCA_CLS_FLAGS_SKIP_HW
|
|
|
+ }
|
|
|
+ if filter.SkipSw {
|
|
|
+ flags |= nl.TCA_CLS_FLAGS_SKIP_SW
|
|
|
+ }
|
|
|
+ parent.AddRtAttr(nl.TCA_FLOWER_FLAGS, htonl(flags))
|
|
|
+
|
|
|
+ actionsAttr := parent.AddRtAttr(nl.TCA_FLOWER_ACT, nil)
|
|
|
+ if err := EncodeActions(actionsAttr, filter.Actions); err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ return nil
|
|
|
}
|
|
|
|
|
|
-func (filter *Fw) Type() string {
|
|
|
- return "fw"
|
|
|
+func (filter *Flower) decode(data []syscall.NetlinkRouteAttr) error {
|
|
|
+ for _, datum := range data {
|
|
|
+ switch datum.Attr.Type {
|
|
|
+ case nl.TCA_FLOWER_KEY_ETH_TYPE:
|
|
|
+ filter.EthType = ntohs(datum.Value)
|
|
|
+ case nl.TCA_FLOWER_KEY_IPV4_SRC, nl.TCA_FLOWER_KEY_IPV6_SRC:
|
|
|
+ filter.SrcIP = datum.Value
|
|
|
+ case nl.TCA_FLOWER_KEY_IPV4_SRC_MASK, nl.TCA_FLOWER_KEY_IPV6_SRC_MASK:
|
|
|
+ filter.SrcIPMask = datum.Value
|
|
|
+ case nl.TCA_FLOWER_KEY_IPV4_DST, nl.TCA_FLOWER_KEY_IPV6_DST:
|
|
|
+ filter.DestIP = datum.Value
|
|
|
+ case nl.TCA_FLOWER_KEY_IPV4_DST_MASK, nl.TCA_FLOWER_KEY_IPV6_DST_MASK:
|
|
|
+ filter.DestIPMask = datum.Value
|
|
|
+ case nl.TCA_FLOWER_KEY_ENC_IPV4_SRC, nl.TCA_FLOWER_KEY_ENC_IPV6_SRC:
|
|
|
+ filter.EncSrcIP = datum.Value
|
|
|
+ case nl.TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK, nl.TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK:
|
|
|
+ filter.EncSrcIPMask = datum.Value
|
|
|
+ case nl.TCA_FLOWER_KEY_ENC_IPV4_DST, nl.TCA_FLOWER_KEY_ENC_IPV6_DST:
|
|
|
+ filter.EncDestIP = datum.Value
|
|
|
+ case nl.TCA_FLOWER_KEY_ENC_IPV4_DST_MASK, nl.TCA_FLOWER_KEY_ENC_IPV6_DST_MASK:
|
|
|
+ filter.EncDestIPMask = datum.Value
|
|
|
+ case nl.TCA_FLOWER_KEY_ENC_UDP_DST_PORT:
|
|
|
+ filter.EncDestPort = ntohs(datum.Value)
|
|
|
+ case nl.TCA_FLOWER_KEY_ENC_KEY_ID:
|
|
|
+ filter.EncKeyId = ntohl(datum.Value)
|
|
|
+ case nl.TCA_FLOWER_KEY_ETH_SRC:
|
|
|
+ filter.SrcMac = datum.Value
|
|
|
+ case nl.TCA_FLOWER_KEY_ETH_DST:
|
|
|
+ filter.DestMac = datum.Value
|
|
|
+ case nl.TCA_FLOWER_KEY_VLAN_ID:
|
|
|
+ filter.VlanId = native.Uint16(datum.Value[0:2])
|
|
|
+ filter.EthType = unix.ETH_P_8021Q
|
|
|
+ case nl.TCA_FLOWER_KEY_IP_PROTO:
|
|
|
+ val := new(nl.IPProto)
|
|
|
+ *val = nl.IPProto(datum.Value[0])
|
|
|
+ filter.IPProto = val
|
|
|
+ case nl.TCA_FLOWER_KEY_TCP_SRC, nl.TCA_FLOWER_KEY_UDP_SRC, nl.TCA_FLOWER_KEY_SCTP_SRC:
|
|
|
+ filter.SrcPort = ntohs(datum.Value)
|
|
|
+ case nl.TCA_FLOWER_KEY_TCP_DST, nl.TCA_FLOWER_KEY_UDP_DST, nl.TCA_FLOWER_KEY_SCTP_DST:
|
|
|
+ filter.DestPort = ntohs(datum.Value)
|
|
|
+ case nl.TCA_FLOWER_ACT:
|
|
|
+ tables, err := nl.ParseRouteAttr(datum.Value)
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ filter.Actions, err = parseActions(tables)
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ case nl.TCA_FLOWER_FLAGS:
|
|
|
+ attr := nl.DeserializeUint32Bitfield(datum.Value)
|
|
|
+ skipSw := attr.Value & nl.TCA_CLS_FLAGS_SKIP_HW
|
|
|
+ skipHw := attr.Value & nl.TCA_CLS_FLAGS_SKIP_SW
|
|
|
+ if skipSw != 0 {
|
|
|
+ filter.SkipSw = true
|
|
|
+ }
|
|
|
+ if skipHw != 0 {
|
|
|
+ filter.SkipHw = true
|
|
|
+ }
|
|
|
+ case nl.TCA_FLOWER_KEY_PORT_SRC_MIN:
|
|
|
+ filter.SrcPortRangeMin = ntohs(datum.Value)
|
|
|
+ case nl.TCA_FLOWER_KEY_PORT_SRC_MAX:
|
|
|
+ filter.SrcPortRangeMax = ntohs(datum.Value)
|
|
|
+ case nl.TCA_FLOWER_KEY_PORT_DST_MIN:
|
|
|
+ filter.DstPortRangeMin = ntohs(datum.Value)
|
|
|
+ case nl.TCA_FLOWER_KEY_PORT_DST_MAX:
|
|
|
+ filter.DstPortRangeMax = ntohs(datum.Value)
|
|
|
+ case nl.TCA_FLOWER_CLASSID:
|
|
|
+ filter.ClassId = native.Uint32(datum.Value)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return nil
|
|
|
}
|
|
|
|
|
|
// FilterDel will delete a filter from the system.
|
|
|
@@ -129,19 +289,7 @@ func FilterDel(filter Filter) error {
|
|
|
// FilterDel will delete a filter from the system.
|
|
|
// Equivalent to: `tc filter del $filter`
|
|
|
func (h *Handle) FilterDel(filter Filter) error {
|
|
|
- req := h.newNetlinkRequest(unix.RTM_DELTFILTER, unix.NLM_F_ACK)
|
|
|
- base := filter.Attrs()
|
|
|
- msg := &nl.TcMsg{
|
|
|
- Family: nl.FAMILY_ALL,
|
|
|
- Ifindex: int32(base.LinkIndex),
|
|
|
- Handle: base.Handle,
|
|
|
- Parent: base.Parent,
|
|
|
- Info: MakeHandle(base.Priority, nl.Swap16(base.Protocol)),
|
|
|
- }
|
|
|
- req.AddData(msg)
|
|
|
-
|
|
|
- _, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
|
|
- return err
|
|
|
+ return h.filterModify(filter, unix.RTM_DELTFILTER, 0)
|
|
|
}
|
|
|
|
|
|
// FilterAdd will add a filter to the system.
|
|
|
@@ -153,7 +301,7 @@ func FilterAdd(filter Filter) error {
|
|
|
// FilterAdd will add a filter to the system.
|
|
|
// Equivalent to: `tc filter add $filter`
|
|
|
func (h *Handle) FilterAdd(filter Filter) error {
|
|
|
- return h.filterModify(filter, unix.NLM_F_CREATE|unix.NLM_F_EXCL)
|
|
|
+ return h.filterModify(filter, unix.RTM_NEWTFILTER, unix.NLM_F_CREATE|unix.NLM_F_EXCL)
|
|
|
}
|
|
|
|
|
|
// FilterReplace will replace a filter.
|
|
|
@@ -165,12 +313,11 @@ func FilterReplace(filter Filter) error {
|
|
|
// FilterReplace will replace a filter.
|
|
|
// Equivalent to: `tc filter replace $filter`
|
|
|
func (h *Handle) FilterReplace(filter Filter) error {
|
|
|
- return h.filterModify(filter, unix.NLM_F_CREATE)
|
|
|
+ return h.filterModify(filter, unix.RTM_NEWTFILTER, unix.NLM_F_CREATE)
|
|
|
}
|
|
|
|
|
|
-func (h *Handle) filterModify(filter Filter, flags int) error {
|
|
|
- native = nl.NativeEndian()
|
|
|
- req := h.newNetlinkRequest(unix.RTM_NEWTFILTER, flags|unix.NLM_F_ACK)
|
|
|
+func (h *Handle) filterModify(filter Filter, proto, flags int) error {
|
|
|
+ req := h.newNetlinkRequest(proto, flags|unix.NLM_F_ACK)
|
|
|
base := filter.Attrs()
|
|
|
msg := &nl.TcMsg{
|
|
|
Family: nl.FAMILY_ALL,
|
|
|
@@ -180,6 +327,9 @@ func (h *Handle) filterModify(filter Filter, flags int) error {
|
|
|
Info: MakeHandle(base.Priority, nl.Swap16(base.Protocol)),
|
|
|
}
|
|
|
req.AddData(msg)
|
|
|
+ if filter.Attrs().Chain != nil {
|
|
|
+ req.AddData(nl.NewRtAttr(nl.TCA_CHAIN, nl.Uint32Attr(*filter.Attrs().Chain)))
|
|
|
+ }
|
|
|
req.AddData(nl.NewRtAttr(nl.TCA_KIND, nl.ZeroTerminated(filter.Type())))
|
|
|
|
|
|
options := nl.NewRtAttr(nl.TCA_OPTIONS, nil)
|
|
|
@@ -229,6 +379,12 @@ func (h *Handle) filterModify(filter Filter, flags int) error {
|
|
|
if filter.Link != 0 {
|
|
|
options.AddRtAttr(nl.TCA_U32_LINK, nl.Uint32Attr(filter.Link))
|
|
|
}
|
|
|
+ if filter.Police != nil {
|
|
|
+ police := options.AddRtAttr(nl.TCA_U32_POLICE, nil)
|
|
|
+ if err := encodePolice(police, filter.Police); err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ }
|
|
|
actionsAttr := options.AddRtAttr(nl.TCA_U32_ACT, nil)
|
|
|
// backwards compatibility
|
|
|
if filter.RedirIndex != 0 {
|
|
|
@@ -237,7 +393,7 @@ func (h *Handle) filterModify(filter Filter, flags int) error {
|
|
|
if err := EncodeActions(actionsAttr, filter.Actions); err != nil {
|
|
|
return err
|
|
|
}
|
|
|
- case *Fw:
|
|
|
+ case *FwFilter:
|
|
|
if filter.Mask != 0 {
|
|
|
b := make([]byte, 4)
|
|
|
native.PutUint32(b, filter.Mask)
|
|
|
@@ -246,17 +402,10 @@ func (h *Handle) filterModify(filter Filter, flags int) error {
|
|
|
if filter.InDev != "" {
|
|
|
options.AddRtAttr(nl.TCA_FW_INDEV, nl.ZeroTerminated(filter.InDev))
|
|
|
}
|
|
|
- if (filter.Police != nl.TcPolice{}) {
|
|
|
-
|
|
|
+ if filter.Police != nil {
|
|
|
police := options.AddRtAttr(nl.TCA_FW_POLICE, nil)
|
|
|
- police.AddRtAttr(nl.TCA_POLICE_TBF, filter.Police.Serialize())
|
|
|
- if (filter.Police.Rate != nl.TcRateSpec{}) {
|
|
|
- payload := SerializeRtab(filter.Rtab)
|
|
|
- police.AddRtAttr(nl.TCA_POLICE_RATE, payload)
|
|
|
- }
|
|
|
- if (filter.Police.PeakRate != nl.TcRateSpec{}) {
|
|
|
- payload := SerializeRtab(filter.Ptab)
|
|
|
- police.AddRtAttr(nl.TCA_POLICE_PEAKRATE, payload)
|
|
|
+ if err := encodePolice(police, filter.Police); err != nil {
|
|
|
+ return err
|
|
|
}
|
|
|
}
|
|
|
if filter.ClassId != 0 {
|
|
|
@@ -264,6 +413,10 @@ func (h *Handle) filterModify(filter Filter, flags int) error {
|
|
|
native.PutUint32(b, filter.ClassId)
|
|
|
options.AddRtAttr(nl.TCA_FW_CLASSID, b)
|
|
|
}
|
|
|
+ actionsAttr := options.AddRtAttr(nl.TCA_FW_ACT, nil)
|
|
|
+ if err := EncodeActions(actionsAttr, filter.Actions); err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
case *BpfFilter:
|
|
|
var bpfFlags uint32
|
|
|
if filter.ClassId != 0 {
|
|
|
@@ -287,8 +440,11 @@ func (h *Handle) filterModify(filter Filter, flags int) error {
|
|
|
if filter.ClassId != 0 {
|
|
|
options.AddRtAttr(nl.TCA_MATCHALL_CLASSID, nl.Uint32Attr(filter.ClassId))
|
|
|
}
|
|
|
+ case *Flower:
|
|
|
+ if err := filter.encode(options); err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
}
|
|
|
-
|
|
|
req.AddData(options)
|
|
|
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
|
|
|
return err
|
|
|
@@ -296,14 +452,20 @@ func (h *Handle) filterModify(filter Filter, flags int) error {
|
|
|
|
|
|
// FilterList gets a list of filters in the system.
|
|
|
// Equivalent to: `tc filter show`.
|
|
|
+//
|
|
|
// Generally returns nothing if link and parent are not specified.
|
|
|
+// If the returned error is [ErrDumpInterrupted], results may be inconsistent
|
|
|
+// or incomplete.
|
|
|
func FilterList(link Link, parent uint32) ([]Filter, error) {
|
|
|
return pkgHandle.FilterList(link, parent)
|
|
|
}
|
|
|
|
|
|
// FilterList gets a list of filters in the system.
|
|
|
// Equivalent to: `tc filter show`.
|
|
|
+//
|
|
|
// Generally returns nothing if link and parent are not specified.
|
|
|
+// If the returned error is [ErrDumpInterrupted], results may be inconsistent
|
|
|
+// or incomplete.
|
|
|
func (h *Handle) FilterList(link Link, parent uint32) ([]Filter, error) {
|
|
|
req := h.newNetlinkRequest(unix.RTM_GETTFILTER, unix.NLM_F_DUMP)
|
|
|
msg := &nl.TcMsg{
|
|
|
@@ -317,9 +479,9 @@ func (h *Handle) FilterList(link Link, parent uint32) ([]Filter, error) {
|
|
|
}
|
|
|
req.AddData(msg)
|
|
|
|
|
|
- msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWTFILTER)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
+ msgs, executeErr := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWTFILTER)
|
|
|
+ if executeErr != nil && !errors.Is(executeErr, ErrDumpInterrupted) {
|
|
|
+ return nil, executeErr
|
|
|
}
|
|
|
|
|
|
var res []Filter
|
|
|
@@ -350,11 +512,13 @@ func (h *Handle) FilterList(link Link, parent uint32) ([]Filter, error) {
|
|
|
case "u32":
|
|
|
filter = &U32{}
|
|
|
case "fw":
|
|
|
- filter = &Fw{}
|
|
|
+ filter = &FwFilter{}
|
|
|
case "bpf":
|
|
|
filter = &BpfFilter{}
|
|
|
case "matchall":
|
|
|
filter = &MatchAll{}
|
|
|
+ case "flower":
|
|
|
+ filter = &Flower{}
|
|
|
default:
|
|
|
filter = &GenericFilter{FilterType: filterType}
|
|
|
}
|
|
|
@@ -384,9 +548,18 @@ func (h *Handle) FilterList(link Link, parent uint32) ([]Filter, error) {
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
+ case "flower":
|
|
|
+ detailed, err = parseFlowerData(filter, data)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
default:
|
|
|
detailed = true
|
|
|
}
|
|
|
+ case nl.TCA_CHAIN:
|
|
|
+ val := new(uint32)
|
|
|
+ *val = native.Uint32(attr.Value)
|
|
|
+ base.Chain = val
|
|
|
}
|
|
|
}
|
|
|
// only return the detailed version of the filter
|
|
|
@@ -396,7 +569,7 @@ func (h *Handle) FilterList(link Link, parent uint32) ([]Filter, error) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- return res, nil
|
|
|
+ return res, executeErr
|
|
|
}
|
|
|
|
|
|
func toTcGen(attrs *ActionAttrs, tcgen *nl.TcGen) {
|
|
|
@@ -415,6 +588,61 @@ func toAttrs(tcgen *nl.TcGen, attrs *ActionAttrs) {
|
|
|
attrs.Bindcnt = int(tcgen.Bindcnt)
|
|
|
}
|
|
|
|
|
|
+func toTimeStamp(tcf *nl.Tcf) *ActionTimestamp {
|
|
|
+ return &ActionTimestamp{
|
|
|
+ Installed: tcf.Install,
|
|
|
+ LastUsed: tcf.LastUse,
|
|
|
+ Expires: tcf.Expires,
|
|
|
+ FirstUsed: tcf.FirstUse}
|
|
|
+}
|
|
|
+
|
|
|
+func encodePolice(attr *nl.RtAttr, action *PoliceAction) error {
|
|
|
+ var rtab [256]uint32
|
|
|
+ var ptab [256]uint32
|
|
|
+ police := nl.TcPolice{}
|
|
|
+ police.Index = uint32(action.Attrs().Index)
|
|
|
+ police.Bindcnt = int32(action.Attrs().Bindcnt)
|
|
|
+ police.Capab = uint32(action.Attrs().Capab)
|
|
|
+ police.Refcnt = int32(action.Attrs().Refcnt)
|
|
|
+ police.Rate.Rate = action.Rate
|
|
|
+ police.PeakRate.Rate = action.PeakRate
|
|
|
+ police.Action = int32(action.ExceedAction)
|
|
|
+
|
|
|
+ if police.Rate.Rate != 0 {
|
|
|
+ police.Rate.Mpu = action.Mpu
|
|
|
+ police.Rate.Overhead = action.Overhead
|
|
|
+ if CalcRtable(&police.Rate, rtab[:], action.RCellLog, action.Mtu, action.LinkLayer) < 0 {
|
|
|
+ return errors.New("TBF: failed to calculate rate table")
|
|
|
+ }
|
|
|
+ police.Burst = Xmittime(uint64(police.Rate.Rate), action.Burst)
|
|
|
+ }
|
|
|
+
|
|
|
+ police.Mtu = action.Mtu
|
|
|
+ if police.PeakRate.Rate != 0 {
|
|
|
+ police.PeakRate.Mpu = action.Mpu
|
|
|
+ police.PeakRate.Overhead = action.Overhead
|
|
|
+ if CalcRtable(&police.PeakRate, ptab[:], action.PCellLog, action.Mtu, action.LinkLayer) < 0 {
|
|
|
+ return errors.New("POLICE: failed to calculate peak rate table")
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ attr.AddRtAttr(nl.TCA_POLICE_TBF, police.Serialize())
|
|
|
+ if police.Rate.Rate != 0 {
|
|
|
+ attr.AddRtAttr(nl.TCA_POLICE_RATE, SerializeRtab(rtab))
|
|
|
+ }
|
|
|
+ if police.PeakRate.Rate != 0 {
|
|
|
+ attr.AddRtAttr(nl.TCA_POLICE_PEAKRATE, SerializeRtab(ptab))
|
|
|
+ }
|
|
|
+ if action.AvRate != 0 {
|
|
|
+ attr.AddRtAttr(nl.TCA_POLICE_AVRATE, nl.Uint32Attr(action.AvRate))
|
|
|
+ }
|
|
|
+ if action.NotExceedAction != 0 {
|
|
|
+ attr.AddRtAttr(nl.TCA_POLICE_RESULT, nl.Uint32Attr(uint32(action.NotExceedAction)))
|
|
|
+ }
|
|
|
+
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
func EncodeActions(attr *nl.RtAttr, actions []Action) error {
|
|
|
tabIndex := int(nl.TCA_ACT_TAB)
|
|
|
|
|
|
@@ -422,6 +650,14 @@ func EncodeActions(attr *nl.RtAttr, actions []Action) error {
|
|
|
switch action := action.(type) {
|
|
|
default:
|
|
|
return fmt.Errorf("unknown action type %s", action.Type())
|
|
|
+ case *PoliceAction:
|
|
|
+ table := attr.AddRtAttr(tabIndex, nil)
|
|
|
+ tabIndex++
|
|
|
+ table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("police"))
|
|
|
+ aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
|
|
|
+ if err := encodePolice(aopts, action); err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
case *MirredAction:
|
|
|
table := attr.AddRtAttr(tabIndex, nil)
|
|
|
tabIndex++
|
|
|
@@ -433,6 +669,22 @@ func EncodeActions(attr *nl.RtAttr, actions []Action) error {
|
|
|
}
|
|
|
toTcGen(action.Attrs(), &mirred.TcGen)
|
|
|
aopts.AddRtAttr(nl.TCA_MIRRED_PARMS, mirred.Serialize())
|
|
|
+ case *VlanAction:
|
|
|
+ table := attr.AddRtAttr(tabIndex, nil)
|
|
|
+ tabIndex++
|
|
|
+ table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("vlan"))
|
|
|
+ aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
|
|
|
+ vlan := nl.TcVlan{
|
|
|
+ Action: int32(action.Action),
|
|
|
+ }
|
|
|
+ toTcGen(action.Attrs(), &vlan.TcGen)
|
|
|
+ aopts.AddRtAttr(nl.TCA_VLAN_PARMS, vlan.Serialize())
|
|
|
+ if action.Action == TCA_VLAN_ACT_PUSH && action.VlanID == 0 {
|
|
|
+ return fmt.Errorf("vlan id is required for push action")
|
|
|
+ }
|
|
|
+ if action.VlanID != 0 {
|
|
|
+ aopts.AddRtAttr(nl.TCA_VLAN_PUSH_VLAN_ID, nl.Uint16Attr(action.VlanID))
|
|
|
+ }
|
|
|
case *TunnelKeyAction:
|
|
|
table := attr.AddRtAttr(tabIndex, nil)
|
|
|
tabIndex++
|
|
|
@@ -483,6 +735,9 @@ func EncodeActions(attr *nl.RtAttr, actions []Action) error {
|
|
|
if action.Mark != nil {
|
|
|
aopts.AddRtAttr(nl.TCA_SKBEDIT_MARK, nl.Uint32Attr(*action.Mark))
|
|
|
}
|
|
|
+ if action.Mask != nil {
|
|
|
+ aopts.AddRtAttr(nl.TCA_SKBEDIT_MASK, nl.Uint32Attr(*action.Mask))
|
|
|
+ }
|
|
|
case *ConnmarkAction:
|
|
|
table := attr.AddRtAttr(tabIndex, nil)
|
|
|
tabIndex++
|
|
|
@@ -493,6 +748,16 @@ func EncodeActions(attr *nl.RtAttr, actions []Action) error {
|
|
|
}
|
|
|
toTcGen(action.Attrs(), &connmark.TcGen)
|
|
|
aopts.AddRtAttr(nl.TCA_CONNMARK_PARMS, connmark.Serialize())
|
|
|
+ case *CsumAction:
|
|
|
+ table := attr.AddRtAttr(tabIndex, nil)
|
|
|
+ tabIndex++
|
|
|
+ table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("csum"))
|
|
|
+ aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
|
|
|
+ csum := nl.TcCsum{
|
|
|
+ UpdateFlags: uint32(action.UpdateFlags),
|
|
|
+ }
|
|
|
+ toTcGen(action.Attrs(), &csum.TcGen)
|
|
|
+ aopts.AddRtAttr(nl.TCA_CSUM_PARMS, csum.Serialize())
|
|
|
case *BpfAction:
|
|
|
table := attr.AddRtAttr(tabIndex, nil)
|
|
|
tabIndex++
|
|
|
@@ -503,6 +768,17 @@ func EncodeActions(attr *nl.RtAttr, actions []Action) error {
|
|
|
aopts.AddRtAttr(nl.TCA_ACT_BPF_PARMS, gen.Serialize())
|
|
|
aopts.AddRtAttr(nl.TCA_ACT_BPF_FD, nl.Uint32Attr(uint32(action.Fd)))
|
|
|
aopts.AddRtAttr(nl.TCA_ACT_BPF_NAME, nl.ZeroTerminated(action.Name))
|
|
|
+ case *SampleAction:
|
|
|
+ table := attr.AddRtAttr(tabIndex, nil)
|
|
|
+ tabIndex++
|
|
|
+ table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("sample"))
|
|
|
+ aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
|
|
|
+ gen := nl.TcGen{}
|
|
|
+ toTcGen(action.Attrs(), &gen)
|
|
|
+ aopts.AddRtAttr(nl.TCA_ACT_SAMPLE_PARMS, gen.Serialize())
|
|
|
+ aopts.AddRtAttr(nl.TCA_ACT_SAMPLE_RATE, nl.Uint32Attr(action.Rate))
|
|
|
+ aopts.AddRtAttr(nl.TCA_ACT_SAMPLE_PSAMPLE_GROUP, nl.Uint32Attr(action.Group))
|
|
|
+ aopts.AddRtAttr(nl.TCA_ACT_SAMPLE_TRUNC_SIZE, nl.Uint32Attr(action.TruncSize))
|
|
|
case *GenericAction:
|
|
|
table := attr.AddRtAttr(tabIndex, nil)
|
|
|
tabIndex++
|
|
|
@@ -511,16 +787,65 @@ func EncodeActions(attr *nl.RtAttr, actions []Action) error {
|
|
|
gen := nl.TcGen{}
|
|
|
toTcGen(action.Attrs(), &gen)
|
|
|
aopts.AddRtAttr(nl.TCA_GACT_PARMS, gen.Serialize())
|
|
|
+ case *PeditAction:
|
|
|
+ table := attr.AddRtAttr(tabIndex, nil)
|
|
|
+ tabIndex++
|
|
|
+ pedit := nl.TcPedit{}
|
|
|
+ toTcGen(action.Attrs(), &pedit.Sel.TcGen)
|
|
|
+ if action.SrcMacAddr != nil {
|
|
|
+ pedit.SetEthSrc(action.SrcMacAddr)
|
|
|
+ }
|
|
|
+ if action.DstMacAddr != nil {
|
|
|
+ pedit.SetEthDst(action.DstMacAddr)
|
|
|
+ }
|
|
|
+ if action.SrcIP != nil {
|
|
|
+ pedit.SetSrcIP(action.SrcIP)
|
|
|
+ }
|
|
|
+ if action.DstIP != nil {
|
|
|
+ pedit.SetDstIP(action.DstIP)
|
|
|
+ }
|
|
|
+ if action.SrcPort != 0 {
|
|
|
+ pedit.SetSrcPort(action.SrcPort, action.Proto)
|
|
|
+ }
|
|
|
+ if action.DstPort != 0 {
|
|
|
+ pedit.SetDstPort(action.DstPort, action.Proto)
|
|
|
+ }
|
|
|
+ pedit.Encode(table)
|
|
|
}
|
|
|
}
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
+func parsePolice(data syscall.NetlinkRouteAttr, police *PoliceAction) {
|
|
|
+ switch data.Attr.Type {
|
|
|
+ case nl.TCA_POLICE_RESULT:
|
|
|
+ police.NotExceedAction = TcPolAct(native.Uint32(data.Value[0:4]))
|
|
|
+ case nl.TCA_POLICE_AVRATE:
|
|
|
+ police.AvRate = native.Uint32(data.Value[0:4])
|
|
|
+ case nl.TCA_POLICE_TBF:
|
|
|
+ p := *nl.DeserializeTcPolice(data.Value)
|
|
|
+ police.ActionAttrs = ActionAttrs{}
|
|
|
+ police.Attrs().Index = int(p.Index)
|
|
|
+ police.Attrs().Bindcnt = int(p.Bindcnt)
|
|
|
+ police.Attrs().Capab = int(p.Capab)
|
|
|
+ police.Attrs().Refcnt = int(p.Refcnt)
|
|
|
+ police.ExceedAction = TcPolAct(p.Action)
|
|
|
+ police.Rate = p.Rate.Rate
|
|
|
+ police.PeakRate = p.PeakRate.Rate
|
|
|
+ police.Burst = Xmitsize(uint64(p.Rate.Rate), p.Burst)
|
|
|
+ police.Mtu = p.Mtu
|
|
|
+ police.LinkLayer = int(p.Rate.Linklayer) & nl.TC_LINKLAYER_MASK
|
|
|
+ police.Overhead = p.Rate.Overhead
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
|
|
|
var actions []Action
|
|
|
for _, table := range tables {
|
|
|
var action Action
|
|
|
var actionType string
|
|
|
+ var actionnStatistic *ActionStatistic
|
|
|
+ var actionTimestamp *ActionTimestamp
|
|
|
aattrs, err := nl.ParseRouteAttr(table.Value)
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
@@ -538,12 +863,22 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
|
|
|
action = &BpfAction{}
|
|
|
case "connmark":
|
|
|
action = &ConnmarkAction{}
|
|
|
+ case "csum":
|
|
|
+ action = &CsumAction{}
|
|
|
+ case "sample":
|
|
|
+ action = &SampleAction{}
|
|
|
case "gact":
|
|
|
action = &GenericAction{}
|
|
|
+ case "vlan":
|
|
|
+ action = &VlanAction{}
|
|
|
case "tunnel_key":
|
|
|
action = &TunnelKeyAction{}
|
|
|
case "skbedit":
|
|
|
action = &SkbEditAction{}
|
|
|
+ case "police":
|
|
|
+ action = &PoliceAction{}
|
|
|
+ case "pedit":
|
|
|
+ action = &PeditAction{}
|
|
|
default:
|
|
|
break nextattr
|
|
|
}
|
|
|
@@ -562,6 +897,20 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
|
|
|
toAttrs(&mirred.TcGen, action.Attrs())
|
|
|
action.(*MirredAction).Ifindex = int(mirred.Ifindex)
|
|
|
action.(*MirredAction).MirredAction = MirredAct(mirred.Eaction)
|
|
|
+ case nl.TCA_MIRRED_TM:
|
|
|
+ tcTs := nl.DeserializeTcf(adatum.Value)
|
|
|
+ actionTimestamp = toTimeStamp(tcTs)
|
|
|
+ }
|
|
|
+ case "vlan":
|
|
|
+ switch adatum.Attr.Type {
|
|
|
+ case nl.TCA_VLAN_PARMS:
|
|
|
+ vlan := *nl.DeserializeTcVlan(adatum.Value)
|
|
|
+ action.(*VlanAction).ActionAttrs = ActionAttrs{}
|
|
|
+ toAttrs(&vlan.TcGen, action.Attrs())
|
|
|
+ action.(*VlanAction).Action = VlanAct(vlan.Action)
|
|
|
+ case nl.TCA_VLAN_PUSH_VLAN_ID:
|
|
|
+ vlanId := native.Uint16(adatum.Value[0:2])
|
|
|
+ action.(*VlanAction).VlanID = vlanId
|
|
|
}
|
|
|
case "tunnel_key":
|
|
|
switch adatum.Attr.Type {
|
|
|
@@ -578,6 +927,9 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
|
|
|
action.(*TunnelKeyAction).DstAddr = adatum.Value[:]
|
|
|
case nl.TCA_TUNNEL_KEY_ENC_DST_PORT:
|
|
|
action.(*TunnelKeyAction).DestPort = ntohs(adatum.Value)
|
|
|
+ case nl.TCA_TUNNEL_KEY_TM:
|
|
|
+ tcTs := nl.DeserializeTcf(adatum.Value)
|
|
|
+ actionTimestamp = toTimeStamp(tcTs)
|
|
|
}
|
|
|
case "skbedit":
|
|
|
switch adatum.Attr.Type {
|
|
|
@@ -588,6 +940,9 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
|
|
|
case nl.TCA_SKBEDIT_MARK:
|
|
|
mark := native.Uint32(adatum.Value[0:4])
|
|
|
action.(*SkbEditAction).Mark = &mark
|
|
|
+ case nl.TCA_SKBEDIT_MASK:
|
|
|
+ mask := native.Uint32(adatum.Value[0:4])
|
|
|
+ action.(*SkbEditAction).Mask = &mask
|
|
|
case nl.TCA_SKBEDIT_PRIORITY:
|
|
|
priority := native.Uint32(adatum.Value[0:4])
|
|
|
action.(*SkbEditAction).Priority = &priority
|
|
|
@@ -597,6 +952,9 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
|
|
|
case nl.TCA_SKBEDIT_QUEUE_MAPPING:
|
|
|
mapping := native.Uint16(adatum.Value[0:2])
|
|
|
action.(*SkbEditAction).QueueMapping = &mapping
|
|
|
+ case nl.TCA_SKBEDIT_TM:
|
|
|
+ tcTs := nl.DeserializeTcf(adatum.Value)
|
|
|
+ actionTimestamp = toTimeStamp(tcTs)
|
|
|
}
|
|
|
case "bpf":
|
|
|
switch adatum.Attr.Type {
|
|
|
@@ -607,6 +965,9 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
|
|
|
action.(*BpfAction).Fd = int(native.Uint32(adatum.Value[0:4]))
|
|
|
case nl.TCA_ACT_BPF_NAME:
|
|
|
action.(*BpfAction).Name = string(adatum.Value[:len(adatum.Value)-1])
|
|
|
+ case nl.TCA_ACT_BPF_TM:
|
|
|
+ tcTs := nl.DeserializeTcf(adatum.Value)
|
|
|
+ actionTimestamp = toTimeStamp(tcTs)
|
|
|
}
|
|
|
case "connmark":
|
|
|
switch adatum.Attr.Type {
|
|
|
@@ -615,24 +976,67 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
|
|
|
action.(*ConnmarkAction).ActionAttrs = ActionAttrs{}
|
|
|
toAttrs(&connmark.TcGen, action.Attrs())
|
|
|
action.(*ConnmarkAction).Zone = connmark.Zone
|
|
|
+ case nl.TCA_CONNMARK_TM:
|
|
|
+ tcTs := nl.DeserializeTcf(adatum.Value)
|
|
|
+ actionTimestamp = toTimeStamp(tcTs)
|
|
|
+ }
|
|
|
+ case "csum":
|
|
|
+ switch adatum.Attr.Type {
|
|
|
+ case nl.TCA_CSUM_PARMS:
|
|
|
+ csum := *nl.DeserializeTcCsum(adatum.Value)
|
|
|
+ action.(*CsumAction).ActionAttrs = ActionAttrs{}
|
|
|
+ toAttrs(&csum.TcGen, action.Attrs())
|
|
|
+ action.(*CsumAction).UpdateFlags = CsumUpdateFlags(csum.UpdateFlags)
|
|
|
+ case nl.TCA_CSUM_TM:
|
|
|
+ tcTs := nl.DeserializeTcf(adatum.Value)
|
|
|
+ actionTimestamp = toTimeStamp(tcTs)
|
|
|
+ }
|
|
|
+ case "sample":
|
|
|
+ switch adatum.Attr.Type {
|
|
|
+ case nl.TCA_ACT_SAMPLE_PARMS:
|
|
|
+ gen := *nl.DeserializeTcGen(adatum.Value)
|
|
|
+ toAttrs(&gen, action.Attrs())
|
|
|
+ case nl.TCA_ACT_SAMPLE_RATE:
|
|
|
+ action.(*SampleAction).Rate = native.Uint32(adatum.Value[0:4])
|
|
|
+ case nl.TCA_ACT_SAMPLE_PSAMPLE_GROUP:
|
|
|
+ action.(*SampleAction).Group = native.Uint32(adatum.Value[0:4])
|
|
|
+ case nl.TCA_ACT_SAMPLE_TRUNC_SIZE:
|
|
|
+ action.(*SampleAction).TruncSize = native.Uint32(adatum.Value[0:4])
|
|
|
}
|
|
|
case "gact":
|
|
|
switch adatum.Attr.Type {
|
|
|
case nl.TCA_GACT_PARMS:
|
|
|
gen := *nl.DeserializeTcGen(adatum.Value)
|
|
|
toAttrs(&gen, action.Attrs())
|
|
|
+ if action.Attrs().Action.String() == "goto" {
|
|
|
+ action.(*GenericAction).Chain = TC_ACT_EXT_VAL_MASK & gen.Action
|
|
|
+ }
|
|
|
+ case nl.TCA_GACT_TM:
|
|
|
+ tcTs := nl.DeserializeTcf(adatum.Value)
|
|
|
+ actionTimestamp = toTimeStamp(tcTs)
|
|
|
}
|
|
|
+ case "police":
|
|
|
+ parsePolice(adatum, action.(*PoliceAction))
|
|
|
}
|
|
|
}
|
|
|
+ case nl.TCA_ACT_STATS:
|
|
|
+ s, err := parseTcStats2(aattr.Value)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ actionnStatistic = (*ActionStatistic)(s)
|
|
|
}
|
|
|
}
|
|
|
- actions = append(actions, action)
|
|
|
+ if action != nil {
|
|
|
+ action.Attrs().Statistics = actionnStatistic
|
|
|
+ action.Attrs().Timestamp = actionTimestamp
|
|
|
+ actions = append(actions, action)
|
|
|
+ }
|
|
|
}
|
|
|
return actions, nil
|
|
|
}
|
|
|
|
|
|
func parseU32Data(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
|
|
|
- native = nl.NativeEndian()
|
|
|
u32 := filter.(*U32)
|
|
|
detailed := false
|
|
|
for _, datum := range data {
|
|
|
@@ -664,6 +1068,13 @@ func parseU32Data(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error)
|
|
|
u32.RedirIndex = int(action.Ifindex)
|
|
|
}
|
|
|
}
|
|
|
+ case nl.TCA_U32_POLICE:
|
|
|
+ var police PoliceAction
|
|
|
+ adata, _ := nl.ParseRouteAttr(datum.Value)
|
|
|
+ for _, aattr := range adata {
|
|
|
+ parsePolice(aattr, &police)
|
|
|
+ }
|
|
|
+ u32.Police = &police
|
|
|
case nl.TCA_U32_CLASSID:
|
|
|
u32.ClassId = native.Uint32(datum.Value)
|
|
|
case nl.TCA_U32_DIVISOR:
|
|
|
@@ -678,8 +1089,7 @@ func parseU32Data(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error)
|
|
|
}
|
|
|
|
|
|
func parseFwData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
|
|
|
- native = nl.NativeEndian()
|
|
|
- fw := filter.(*Fw)
|
|
|
+ fw := filter.(*FwFilter)
|
|
|
detailed := true
|
|
|
for _, datum := range data {
|
|
|
switch datum.Attr.Type {
|
|
|
@@ -690,16 +1100,20 @@ func parseFwData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
|
|
|
case nl.TCA_FW_INDEV:
|
|
|
fw.InDev = string(datum.Value[:len(datum.Value)-1])
|
|
|
case nl.TCA_FW_POLICE:
|
|
|
+ var police PoliceAction
|
|
|
adata, _ := nl.ParseRouteAttr(datum.Value)
|
|
|
for _, aattr := range adata {
|
|
|
- switch aattr.Attr.Type {
|
|
|
- case nl.TCA_POLICE_TBF:
|
|
|
- fw.Police = *nl.DeserializeTcPolice(aattr.Value)
|
|
|
- case nl.TCA_POLICE_RATE:
|
|
|
- fw.Rtab = DeserializeRtab(aattr.Value)
|
|
|
- case nl.TCA_POLICE_PEAKRATE:
|
|
|
- fw.Ptab = DeserializeRtab(aattr.Value)
|
|
|
- }
|
|
|
+ parsePolice(aattr, &police)
|
|
|
+ }
|
|
|
+ fw.Police = &police
|
|
|
+ case nl.TCA_FW_ACT:
|
|
|
+ tables, err := nl.ParseRouteAttr(datum.Value)
|
|
|
+ if err != nil {
|
|
|
+ return detailed, err
|
|
|
+ }
|
|
|
+ fw.Actions, err = parseActions(tables)
|
|
|
+ if err != nil {
|
|
|
+ return detailed, err
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -707,7 +1121,6 @@ func parseFwData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
|
|
|
}
|
|
|
|
|
|
func parseBpfData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
|
|
|
- native = nl.NativeEndian()
|
|
|
bpf := filter.(*BpfFilter)
|
|
|
detailed := true
|
|
|
for _, datum := range data {
|
|
|
@@ -726,14 +1139,13 @@ func parseBpfData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error)
|
|
|
case nl.TCA_BPF_ID:
|
|
|
bpf.Id = int(native.Uint32(datum.Value[0:4]))
|
|
|
case nl.TCA_BPF_TAG:
|
|
|
- bpf.Tag = hex.EncodeToString(datum.Value[:len(datum.Value)-1])
|
|
|
+ bpf.Tag = hex.EncodeToString(datum.Value)
|
|
|
}
|
|
|
}
|
|
|
return detailed, nil
|
|
|
}
|
|
|
|
|
|
func parseMatchAllData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
|
|
|
- native = nl.NativeEndian()
|
|
|
matchall := filter.(*MatchAll)
|
|
|
detailed := true
|
|
|
for _, datum := range data {
|
|
|
@@ -754,6 +1166,10 @@ func parseMatchAllData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, er
|
|
|
return detailed, nil
|
|
|
}
|
|
|
|
|
|
+func parseFlowerData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
|
|
|
+ return true, filter.(*Flower).decode(data)
|
|
|
+}
|
|
|
+
|
|
|
func AlignToAtm(size uint) uint {
|
|
|
var linksize, cells int
|
|
|
cells = int(size / nl.ATM_CELL_PAYLOAD)
|
|
|
@@ -801,14 +1217,12 @@ func CalcRtable(rate *nl.TcRateSpec, rtab []uint32, cellLog int, mtu uint32, lin
|
|
|
|
|
|
func DeserializeRtab(b []byte) [256]uint32 {
|
|
|
var rtab [256]uint32
|
|
|
- native := nl.NativeEndian()
|
|
|
r := bytes.NewReader(b)
|
|
|
_ = binary.Read(r, native, &rtab)
|
|
|
return rtab
|
|
|
}
|
|
|
|
|
|
func SerializeRtab(rtab [256]uint32) []byte {
|
|
|
- native := nl.NativeEndian()
|
|
|
var w bytes.Buffer
|
|
|
_ = binary.Write(&w, native, rtab)
|
|
|
return w.Bytes()
|