|
@@ -3,10 +3,11 @@ package netlink
|
|
import (
|
|
import (
|
|
"bytes"
|
|
"bytes"
|
|
"encoding/binary"
|
|
"encoding/binary"
|
|
|
|
+ "encoding/hex"
|
|
"errors"
|
|
"errors"
|
|
"fmt"
|
|
"fmt"
|
|
|
|
+ "net"
|
|
"syscall"
|
|
"syscall"
|
|
- "unsafe"
|
|
|
|
|
|
|
|
"github.com/vishvananda/netlink/nl"
|
|
"github.com/vishvananda/netlink/nl"
|
|
"golang.org/x/sys/unix"
|
|
"golang.org/x/sys/unix"
|
|
@@ -20,6 +21,35 @@ const (
|
|
TC_U32_EAT = nl.TC_U32_EAT
|
|
TC_U32_EAT = nl.TC_U32_EAT
|
|
)
|
|
)
|
|
|
|
|
|
|
|
+// Sel of the U32 filters that contains multiple TcU32Key. This is the type
|
|
|
|
+// alias and the frontend representation of nl.TcU32Sel. It is serialized into
|
|
|
|
+// canonical nl.TcU32Sel with the appropriate endianness.
|
|
|
|
+type TcU32Sel = nl.TcU32Sel
|
|
|
|
+
|
|
|
|
+// TcU32Key contained of Sel in the U32 filters. This is the type alias and the
|
|
|
|
+// frontend representation of nl.TcU32Key. It is serialized into chanonical
|
|
|
|
+// nl.TcU32Sel with the appropriate endianness.
|
|
|
|
+type TcU32Key = nl.TcU32Key
|
|
|
|
+
|
|
|
|
+// U32 filters on many packet related properties
|
|
|
|
+type U32 struct {
|
|
|
|
+ FilterAttrs
|
|
|
|
+ ClassId uint32
|
|
|
|
+ Divisor uint32 // Divisor MUST be power of 2.
|
|
|
|
+ Hash uint32
|
|
|
|
+ RedirIndex int
|
|
|
|
+ Sel *TcU32Sel
|
|
|
|
+ Actions []Action
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (filter *U32) Attrs() *FilterAttrs {
|
|
|
|
+ return &filter.FilterAttrs
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (filter *U32) Type() string {
|
|
|
|
+ return "u32"
|
|
|
|
+}
|
|
|
|
+
|
|
// Fw filter filters on firewall marks
|
|
// Fw filter filters on firewall marks
|
|
// NOTE: this is in filter_linux because it refers to nl.TcPolice which
|
|
// NOTE: this is in filter_linux because it refers to nl.TcPolice which
|
|
// is defined in nl/tc_linux.go
|
|
// is defined in nl/tc_linux.go
|
|
@@ -123,8 +153,24 @@ func FilterAdd(filter Filter) error {
|
|
// FilterAdd will add a filter to the system.
|
|
// FilterAdd will add a filter to the system.
|
|
// Equivalent to: `tc filter add $filter`
|
|
// Equivalent to: `tc filter add $filter`
|
|
func (h *Handle) FilterAdd(filter Filter) error {
|
|
func (h *Handle) FilterAdd(filter Filter) error {
|
|
|
|
+ return h.filterModify(filter, unix.NLM_F_CREATE|unix.NLM_F_EXCL)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// FilterReplace will replace a filter.
|
|
|
|
+// Equivalent to: `tc filter replace $filter`
|
|
|
|
+func FilterReplace(filter Filter) error {
|
|
|
|
+ return pkgHandle.FilterReplace(filter)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// 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)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (h *Handle) filterModify(filter Filter, flags int) error {
|
|
native = nl.NativeEndian()
|
|
native = nl.NativeEndian()
|
|
- req := h.newNetlinkRequest(unix.RTM_NEWTFILTER, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK)
|
|
|
|
|
|
+ req := h.newNetlinkRequest(unix.RTM_NEWTFILTER, flags|unix.NLM_F_ACK)
|
|
base := filter.Attrs()
|
|
base := filter.Attrs()
|
|
msg := &nl.TcMsg{
|
|
msg := &nl.TcMsg{
|
|
Family: nl.FAMILY_ALL,
|
|
Family: nl.FAMILY_ALL,
|
|
@@ -140,8 +186,7 @@ func (h *Handle) FilterAdd(filter Filter) error {
|
|
|
|
|
|
switch filter := filter.(type) {
|
|
switch filter := filter.(type) {
|
|
case *U32:
|
|
case *U32:
|
|
- // Convert TcU32Sel into nl.TcU32Sel as it is without copy.
|
|
|
|
- sel := (*nl.TcU32Sel)(unsafe.Pointer(filter.Sel))
|
|
|
|
|
|
+ sel := filter.Sel
|
|
if sel == nil {
|
|
if sel == nil {
|
|
// match all
|
|
// match all
|
|
sel = &nl.TcU32Sel{
|
|
sel = &nl.TcU32Sel{
|
|
@@ -168,11 +213,20 @@ func (h *Handle) FilterAdd(filter Filter) error {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
sel.Nkeys = uint8(len(sel.Keys))
|
|
sel.Nkeys = uint8(len(sel.Keys))
|
|
- nl.NewRtAttrChild(options, nl.TCA_U32_SEL, sel.Serialize())
|
|
|
|
|
|
+ options.AddRtAttr(nl.TCA_U32_SEL, sel.Serialize())
|
|
if filter.ClassId != 0 {
|
|
if filter.ClassId != 0 {
|
|
- nl.NewRtAttrChild(options, nl.TCA_U32_CLASSID, nl.Uint32Attr(filter.ClassId))
|
|
|
|
|
|
+ options.AddRtAttr(nl.TCA_U32_CLASSID, nl.Uint32Attr(filter.ClassId))
|
|
|
|
+ }
|
|
|
|
+ if filter.Divisor != 0 {
|
|
|
|
+ if (filter.Divisor-1)&filter.Divisor != 0 {
|
|
|
|
+ return fmt.Errorf("illegal divisor %d. Must be a power of 2", filter.Divisor)
|
|
|
|
+ }
|
|
|
|
+ options.AddRtAttr(nl.TCA_U32_DIVISOR, nl.Uint32Attr(filter.Divisor))
|
|
}
|
|
}
|
|
- actionsAttr := nl.NewRtAttrChild(options, nl.TCA_U32_ACT, nil)
|
|
|
|
|
|
+ if filter.Hash != 0 {
|
|
|
|
+ options.AddRtAttr(nl.TCA_U32_HASH, nl.Uint32Attr(filter.Hash))
|
|
|
|
+ }
|
|
|
|
+ actionsAttr := options.AddRtAttr(nl.TCA_U32_ACT, nil)
|
|
// backwards compatibility
|
|
// backwards compatibility
|
|
if filter.RedirIndex != 0 {
|
|
if filter.RedirIndex != 0 {
|
|
filter.Actions = append([]Action{NewMirredAction(filter.RedirIndex)}, filter.Actions...)
|
|
filter.Actions = append([]Action{NewMirredAction(filter.RedirIndex)}, filter.Actions...)
|
|
@@ -184,51 +238,51 @@ func (h *Handle) FilterAdd(filter Filter) error {
|
|
if filter.Mask != 0 {
|
|
if filter.Mask != 0 {
|
|
b := make([]byte, 4)
|
|
b := make([]byte, 4)
|
|
native.PutUint32(b, filter.Mask)
|
|
native.PutUint32(b, filter.Mask)
|
|
- nl.NewRtAttrChild(options, nl.TCA_FW_MASK, b)
|
|
|
|
|
|
+ options.AddRtAttr(nl.TCA_FW_MASK, b)
|
|
}
|
|
}
|
|
if filter.InDev != "" {
|
|
if filter.InDev != "" {
|
|
- nl.NewRtAttrChild(options, nl.TCA_FW_INDEV, nl.ZeroTerminated(filter.InDev))
|
|
|
|
|
|
+ options.AddRtAttr(nl.TCA_FW_INDEV, nl.ZeroTerminated(filter.InDev))
|
|
}
|
|
}
|
|
if (filter.Police != nl.TcPolice{}) {
|
|
if (filter.Police != nl.TcPolice{}) {
|
|
|
|
|
|
- police := nl.NewRtAttrChild(options, nl.TCA_FW_POLICE, nil)
|
|
|
|
- nl.NewRtAttrChild(police, nl.TCA_POLICE_TBF, filter.Police.Serialize())
|
|
|
|
|
|
+ police := options.AddRtAttr(nl.TCA_FW_POLICE, nil)
|
|
|
|
+ police.AddRtAttr(nl.TCA_POLICE_TBF, filter.Police.Serialize())
|
|
if (filter.Police.Rate != nl.TcRateSpec{}) {
|
|
if (filter.Police.Rate != nl.TcRateSpec{}) {
|
|
payload := SerializeRtab(filter.Rtab)
|
|
payload := SerializeRtab(filter.Rtab)
|
|
- nl.NewRtAttrChild(police, nl.TCA_POLICE_RATE, payload)
|
|
|
|
|
|
+ police.AddRtAttr(nl.TCA_POLICE_RATE, payload)
|
|
}
|
|
}
|
|
if (filter.Police.PeakRate != nl.TcRateSpec{}) {
|
|
if (filter.Police.PeakRate != nl.TcRateSpec{}) {
|
|
payload := SerializeRtab(filter.Ptab)
|
|
payload := SerializeRtab(filter.Ptab)
|
|
- nl.NewRtAttrChild(police, nl.TCA_POLICE_PEAKRATE, payload)
|
|
|
|
|
|
+ police.AddRtAttr(nl.TCA_POLICE_PEAKRATE, payload)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if filter.ClassId != 0 {
|
|
if filter.ClassId != 0 {
|
|
b := make([]byte, 4)
|
|
b := make([]byte, 4)
|
|
native.PutUint32(b, filter.ClassId)
|
|
native.PutUint32(b, filter.ClassId)
|
|
- nl.NewRtAttrChild(options, nl.TCA_FW_CLASSID, b)
|
|
|
|
|
|
+ options.AddRtAttr(nl.TCA_FW_CLASSID, b)
|
|
}
|
|
}
|
|
case *BpfFilter:
|
|
case *BpfFilter:
|
|
var bpfFlags uint32
|
|
var bpfFlags uint32
|
|
if filter.ClassId != 0 {
|
|
if filter.ClassId != 0 {
|
|
- nl.NewRtAttrChild(options, nl.TCA_BPF_CLASSID, nl.Uint32Attr(filter.ClassId))
|
|
|
|
|
|
+ options.AddRtAttr(nl.TCA_BPF_CLASSID, nl.Uint32Attr(filter.ClassId))
|
|
}
|
|
}
|
|
if filter.Fd >= 0 {
|
|
if filter.Fd >= 0 {
|
|
- nl.NewRtAttrChild(options, nl.TCA_BPF_FD, nl.Uint32Attr((uint32(filter.Fd))))
|
|
|
|
|
|
+ options.AddRtAttr(nl.TCA_BPF_FD, nl.Uint32Attr((uint32(filter.Fd))))
|
|
}
|
|
}
|
|
if filter.Name != "" {
|
|
if filter.Name != "" {
|
|
- nl.NewRtAttrChild(options, nl.TCA_BPF_NAME, nl.ZeroTerminated(filter.Name))
|
|
|
|
|
|
+ options.AddRtAttr(nl.TCA_BPF_NAME, nl.ZeroTerminated(filter.Name))
|
|
}
|
|
}
|
|
if filter.DirectAction {
|
|
if filter.DirectAction {
|
|
bpfFlags |= nl.TCA_BPF_FLAG_ACT_DIRECT
|
|
bpfFlags |= nl.TCA_BPF_FLAG_ACT_DIRECT
|
|
}
|
|
}
|
|
- nl.NewRtAttrChild(options, nl.TCA_BPF_FLAGS, nl.Uint32Attr(bpfFlags))
|
|
|
|
|
|
+ options.AddRtAttr(nl.TCA_BPF_FLAGS, nl.Uint32Attr(bpfFlags))
|
|
case *MatchAll:
|
|
case *MatchAll:
|
|
- actionsAttr := nl.NewRtAttrChild(options, nl.TCA_MATCHALL_ACT, nil)
|
|
|
|
|
|
+ actionsAttr := options.AddRtAttr(nl.TCA_MATCHALL_ACT, nil)
|
|
if err := EncodeActions(actionsAttr, filter.Actions); err != nil {
|
|
if err := EncodeActions(actionsAttr, filter.Actions); err != nil {
|
|
return err
|
|
return err
|
|
}
|
|
}
|
|
if filter.ClassId != 0 {
|
|
if filter.ClassId != 0 {
|
|
- nl.NewRtAttrChild(options, nl.TCA_MATCHALL_CLASSID, nl.Uint32Attr(filter.ClassId))
|
|
|
|
|
|
+ options.AddRtAttr(nl.TCA_MATCHALL_CLASSID, nl.Uint32Attr(filter.ClassId))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -366,34 +420,91 @@ func EncodeActions(attr *nl.RtAttr, actions []Action) error {
|
|
default:
|
|
default:
|
|
return fmt.Errorf("unknown action type %s", action.Type())
|
|
return fmt.Errorf("unknown action type %s", action.Type())
|
|
case *MirredAction:
|
|
case *MirredAction:
|
|
- table := nl.NewRtAttrChild(attr, tabIndex, nil)
|
|
|
|
|
|
+ table := attr.AddRtAttr(tabIndex, nil)
|
|
tabIndex++
|
|
tabIndex++
|
|
- nl.NewRtAttrChild(table, nl.TCA_ACT_KIND, nl.ZeroTerminated("mirred"))
|
|
|
|
- aopts := nl.NewRtAttrChild(table, nl.TCA_ACT_OPTIONS, nil)
|
|
|
|
|
|
+ table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("mirred"))
|
|
|
|
+ aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
|
|
mirred := nl.TcMirred{
|
|
mirred := nl.TcMirred{
|
|
Eaction: int32(action.MirredAction),
|
|
Eaction: int32(action.MirredAction),
|
|
Ifindex: uint32(action.Ifindex),
|
|
Ifindex: uint32(action.Ifindex),
|
|
}
|
|
}
|
|
toTcGen(action.Attrs(), &mirred.TcGen)
|
|
toTcGen(action.Attrs(), &mirred.TcGen)
|
|
- nl.NewRtAttrChild(aopts, nl.TCA_MIRRED_PARMS, mirred.Serialize())
|
|
|
|
|
|
+ aopts.AddRtAttr(nl.TCA_MIRRED_PARMS, mirred.Serialize())
|
|
|
|
+ case *TunnelKeyAction:
|
|
|
|
+ table := attr.AddRtAttr(tabIndex, nil)
|
|
|
|
+ tabIndex++
|
|
|
|
+ table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("tunnel_key"))
|
|
|
|
+ aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
|
|
|
|
+ tun := nl.TcTunnelKey{
|
|
|
|
+ Action: int32(action.Action),
|
|
|
|
+ }
|
|
|
|
+ toTcGen(action.Attrs(), &tun.TcGen)
|
|
|
|
+ aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_PARMS, tun.Serialize())
|
|
|
|
+ if action.Action == TCA_TUNNEL_KEY_SET {
|
|
|
|
+ aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_ENC_KEY_ID, htonl(action.KeyID))
|
|
|
|
+ if v4 := action.SrcAddr.To4(); v4 != nil {
|
|
|
|
+ aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_ENC_IPV4_SRC, v4[:])
|
|
|
|
+ } else if v6 := action.SrcAddr.To16(); v6 != nil {
|
|
|
|
+ aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_ENC_IPV6_SRC, v6[:])
|
|
|
|
+ } else {
|
|
|
|
+ return fmt.Errorf("invalid src addr %s for tunnel_key action", action.SrcAddr)
|
|
|
|
+ }
|
|
|
|
+ if v4 := action.DstAddr.To4(); v4 != nil {
|
|
|
|
+ aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_ENC_IPV4_DST, v4[:])
|
|
|
|
+ } else if v6 := action.DstAddr.To16(); v6 != nil {
|
|
|
|
+ aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_ENC_IPV6_DST, v6[:])
|
|
|
|
+ } else {
|
|
|
|
+ return fmt.Errorf("invalid dst addr %s for tunnel_key action", action.DstAddr)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ case *SkbEditAction:
|
|
|
|
+ table := attr.AddRtAttr(tabIndex, nil)
|
|
|
|
+ tabIndex++
|
|
|
|
+ table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("skbedit"))
|
|
|
|
+ aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
|
|
|
|
+ skbedit := nl.TcSkbEdit{}
|
|
|
|
+ toTcGen(action.Attrs(), &skbedit.TcGen)
|
|
|
|
+ aopts.AddRtAttr(nl.TCA_SKBEDIT_PARMS, skbedit.Serialize())
|
|
|
|
+ if action.QueueMapping != nil {
|
|
|
|
+ aopts.AddRtAttr(nl.TCA_SKBEDIT_QUEUE_MAPPING, nl.Uint16Attr(*action.QueueMapping))
|
|
|
|
+ }
|
|
|
|
+ if action.Priority != nil {
|
|
|
|
+ aopts.AddRtAttr(nl.TCA_SKBEDIT_PRIORITY, nl.Uint32Attr(*action.Priority))
|
|
|
|
+ }
|
|
|
|
+ if action.PType != nil {
|
|
|
|
+ aopts.AddRtAttr(nl.TCA_SKBEDIT_PTYPE, nl.Uint16Attr(*action.PType))
|
|
|
|
+ }
|
|
|
|
+ if action.Mark != nil {
|
|
|
|
+ aopts.AddRtAttr(nl.TCA_SKBEDIT_MARK, nl.Uint32Attr(*action.Mark))
|
|
|
|
+ }
|
|
|
|
+ case *ConnmarkAction:
|
|
|
|
+ table := attr.AddRtAttr(tabIndex, nil)
|
|
|
|
+ tabIndex++
|
|
|
|
+ table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("connmark"))
|
|
|
|
+ aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
|
|
|
|
+ connmark := nl.TcConnmark{
|
|
|
|
+ Zone: action.Zone,
|
|
|
|
+ }
|
|
|
|
+ toTcGen(action.Attrs(), &connmark.TcGen)
|
|
|
|
+ aopts.AddRtAttr(nl.TCA_CONNMARK_PARMS, connmark.Serialize())
|
|
case *BpfAction:
|
|
case *BpfAction:
|
|
- table := nl.NewRtAttrChild(attr, tabIndex, nil)
|
|
|
|
|
|
+ table := attr.AddRtAttr(tabIndex, nil)
|
|
tabIndex++
|
|
tabIndex++
|
|
- nl.NewRtAttrChild(table, nl.TCA_ACT_KIND, nl.ZeroTerminated("bpf"))
|
|
|
|
- aopts := nl.NewRtAttrChild(table, nl.TCA_ACT_OPTIONS, nil)
|
|
|
|
|
|
+ table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("bpf"))
|
|
|
|
+ aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
|
|
gen := nl.TcGen{}
|
|
gen := nl.TcGen{}
|
|
toTcGen(action.Attrs(), &gen)
|
|
toTcGen(action.Attrs(), &gen)
|
|
- nl.NewRtAttrChild(aopts, nl.TCA_ACT_BPF_PARMS, gen.Serialize())
|
|
|
|
- nl.NewRtAttrChild(aopts, nl.TCA_ACT_BPF_FD, nl.Uint32Attr(uint32(action.Fd)))
|
|
|
|
- nl.NewRtAttrChild(aopts, nl.TCA_ACT_BPF_NAME, nl.ZeroTerminated(action.Name))
|
|
|
|
|
|
+ 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 *GenericAction:
|
|
case *GenericAction:
|
|
- table := nl.NewRtAttrChild(attr, tabIndex, nil)
|
|
|
|
|
|
+ table := attr.AddRtAttr(tabIndex, nil)
|
|
tabIndex++
|
|
tabIndex++
|
|
- nl.NewRtAttrChild(table, nl.TCA_ACT_KIND, nl.ZeroTerminated("gact"))
|
|
|
|
- aopts := nl.NewRtAttrChild(table, nl.TCA_ACT_OPTIONS, nil)
|
|
|
|
|
|
+ table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("gact"))
|
|
|
|
+ aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
|
|
gen := nl.TcGen{}
|
|
gen := nl.TcGen{}
|
|
toTcGen(action.Attrs(), &gen)
|
|
toTcGen(action.Attrs(), &gen)
|
|
- nl.NewRtAttrChild(aopts, nl.TCA_GACT_PARMS, gen.Serialize())
|
|
|
|
|
|
+ aopts.AddRtAttr(nl.TCA_GACT_PARMS, gen.Serialize())
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
return nil
|
|
@@ -419,8 +530,14 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
|
|
action = &MirredAction{}
|
|
action = &MirredAction{}
|
|
case "bpf":
|
|
case "bpf":
|
|
action = &BpfAction{}
|
|
action = &BpfAction{}
|
|
|
|
+ case "connmark":
|
|
|
|
+ action = &ConnmarkAction{}
|
|
case "gact":
|
|
case "gact":
|
|
action = &GenericAction{}
|
|
action = &GenericAction{}
|
|
|
|
+ case "tunnel_key":
|
|
|
|
+ action = &TunnelKeyAction{}
|
|
|
|
+ case "skbedit":
|
|
|
|
+ action = &SkbEditAction{}
|
|
default:
|
|
default:
|
|
break nextattr
|
|
break nextattr
|
|
}
|
|
}
|
|
@@ -435,11 +552,46 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
|
|
switch adatum.Attr.Type {
|
|
switch adatum.Attr.Type {
|
|
case nl.TCA_MIRRED_PARMS:
|
|
case nl.TCA_MIRRED_PARMS:
|
|
mirred := *nl.DeserializeTcMirred(adatum.Value)
|
|
mirred := *nl.DeserializeTcMirred(adatum.Value)
|
|
- toAttrs(&mirred.TcGen, action.Attrs())
|
|
|
|
action.(*MirredAction).ActionAttrs = ActionAttrs{}
|
|
action.(*MirredAction).ActionAttrs = ActionAttrs{}
|
|
|
|
+ toAttrs(&mirred.TcGen, action.Attrs())
|
|
action.(*MirredAction).Ifindex = int(mirred.Ifindex)
|
|
action.(*MirredAction).Ifindex = int(mirred.Ifindex)
|
|
action.(*MirredAction).MirredAction = MirredAct(mirred.Eaction)
|
|
action.(*MirredAction).MirredAction = MirredAct(mirred.Eaction)
|
|
}
|
|
}
|
|
|
|
+ case "tunnel_key":
|
|
|
|
+ switch adatum.Attr.Type {
|
|
|
|
+ case nl.TCA_TUNNEL_KEY_PARMS:
|
|
|
|
+ tun := *nl.DeserializeTunnelKey(adatum.Value)
|
|
|
|
+ action.(*TunnelKeyAction).ActionAttrs = ActionAttrs{}
|
|
|
|
+ toAttrs(&tun.TcGen, action.Attrs())
|
|
|
|
+ action.(*TunnelKeyAction).Action = TunnelKeyAct(tun.Action)
|
|
|
|
+ case nl.TCA_TUNNEL_KEY_ENC_KEY_ID:
|
|
|
|
+ action.(*TunnelKeyAction).KeyID = networkOrder.Uint32(adatum.Value[0:4])
|
|
|
|
+ case nl.TCA_TUNNEL_KEY_ENC_IPV6_SRC:
|
|
|
|
+ case nl.TCA_TUNNEL_KEY_ENC_IPV4_SRC:
|
|
|
|
+ action.(*TunnelKeyAction).SrcAddr = net.IP(adatum.Value[:])
|
|
|
|
+ case nl.TCA_TUNNEL_KEY_ENC_IPV6_DST:
|
|
|
|
+ case nl.TCA_TUNNEL_KEY_ENC_IPV4_DST:
|
|
|
|
+ action.(*TunnelKeyAction).DstAddr = net.IP(adatum.Value[:])
|
|
|
|
+ }
|
|
|
|
+ case "skbedit":
|
|
|
|
+ switch adatum.Attr.Type {
|
|
|
|
+ case nl.TCA_SKBEDIT_PARMS:
|
|
|
|
+ skbedit := *nl.DeserializeSkbEdit(adatum.Value)
|
|
|
|
+ action.(*SkbEditAction).ActionAttrs = ActionAttrs{}
|
|
|
|
+ toAttrs(&skbedit.TcGen, action.Attrs())
|
|
|
|
+ case nl.TCA_SKBEDIT_MARK:
|
|
|
|
+ mark := native.Uint32(adatum.Value[0:4])
|
|
|
|
+ action.(*SkbEditAction).Mark = &mark
|
|
|
|
+ case nl.TCA_SKBEDIT_PRIORITY:
|
|
|
|
+ priority := native.Uint32(adatum.Value[0:4])
|
|
|
|
+ action.(*SkbEditAction).Priority = &priority
|
|
|
|
+ case nl.TCA_SKBEDIT_PTYPE:
|
|
|
|
+ ptype := native.Uint16(adatum.Value[0:2])
|
|
|
|
+ action.(*SkbEditAction).PType = &ptype
|
|
|
|
+ case nl.TCA_SKBEDIT_QUEUE_MAPPING:
|
|
|
|
+ mapping := native.Uint16(adatum.Value[0:2])
|
|
|
|
+ action.(*SkbEditAction).QueueMapping = &mapping
|
|
|
|
+ }
|
|
case "bpf":
|
|
case "bpf":
|
|
switch adatum.Attr.Type {
|
|
switch adatum.Attr.Type {
|
|
case nl.TCA_ACT_BPF_PARMS:
|
|
case nl.TCA_ACT_BPF_PARMS:
|
|
@@ -450,6 +602,14 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
|
|
case nl.TCA_ACT_BPF_NAME:
|
|
case nl.TCA_ACT_BPF_NAME:
|
|
action.(*BpfAction).Name = string(adatum.Value[:len(adatum.Value)-1])
|
|
action.(*BpfAction).Name = string(adatum.Value[:len(adatum.Value)-1])
|
|
}
|
|
}
|
|
|
|
+ case "connmark":
|
|
|
|
+ switch adatum.Attr.Type {
|
|
|
|
+ case nl.TCA_CONNMARK_PARMS:
|
|
|
|
+ connmark := *nl.DeserializeTcConnmark(adatum.Value)
|
|
|
|
+ action.(*ConnmarkAction).ActionAttrs = ActionAttrs{}
|
|
|
|
+ toAttrs(&connmark.TcGen, action.Attrs())
|
|
|
|
+ action.(*ConnmarkAction).Zone = connmark.Zone
|
|
|
|
+ }
|
|
case "gact":
|
|
case "gact":
|
|
switch adatum.Attr.Type {
|
|
switch adatum.Attr.Type {
|
|
case nl.TCA_GACT_PARMS:
|
|
case nl.TCA_GACT_PARMS:
|
|
@@ -474,7 +634,7 @@ func parseU32Data(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error)
|
|
case nl.TCA_U32_SEL:
|
|
case nl.TCA_U32_SEL:
|
|
detailed = true
|
|
detailed = true
|
|
sel := nl.DeserializeTcU32Sel(datum.Value)
|
|
sel := nl.DeserializeTcU32Sel(datum.Value)
|
|
- u32.Sel = (*TcU32Sel)(unsafe.Pointer(sel))
|
|
|
|
|
|
+ u32.Sel = sel
|
|
if native != networkOrder {
|
|
if native != networkOrder {
|
|
// Handle the endianness of attributes
|
|
// Handle the endianness of attributes
|
|
u32.Sel.Offmask = native.Uint16(htons(sel.Offmask))
|
|
u32.Sel.Offmask = native.Uint16(htons(sel.Offmask))
|
|
@@ -500,6 +660,10 @@ func parseU32Data(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error)
|
|
}
|
|
}
|
|
case nl.TCA_U32_CLASSID:
|
|
case nl.TCA_U32_CLASSID:
|
|
u32.ClassId = native.Uint32(datum.Value)
|
|
u32.ClassId = native.Uint32(datum.Value)
|
|
|
|
+ case nl.TCA_U32_DIVISOR:
|
|
|
|
+ u32.Divisor = native.Uint32(datum.Value)
|
|
|
|
+ case nl.TCA_U32_HASH:
|
|
|
|
+ u32.Hash = native.Uint32(datum.Value)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return detailed, nil
|
|
return detailed, nil
|
|
@@ -551,6 +715,10 @@ func parseBpfData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error)
|
|
if (flags & nl.TCA_BPF_FLAG_ACT_DIRECT) != 0 {
|
|
if (flags & nl.TCA_BPF_FLAG_ACT_DIRECT) != 0 {
|
|
bpf.DirectAction = true
|
|
bpf.DirectAction = true
|
|
}
|
|
}
|
|
|
|
+ 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])
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return detailed, nil
|
|
return detailed, nil
|