mirror of https://github.com/vishvananda/netlink
filter, action: Add support for skbedit
Signed-off-by: Zhiyuan Hou <zhiyuan2048@linux.alibaba.com>
This commit is contained in:
parent
e25c252266
commit
ed8931371a
24
filter.go
24
filter.go
|
@ -235,6 +235,30 @@ func NewTunnelKeyAction() *TunnelKeyAction {
|
|||
}
|
||||
}
|
||||
|
||||
type SkbEditAction struct {
|
||||
ActionAttrs
|
||||
QueueMapping *uint16
|
||||
PType *uint16
|
||||
Priority *uint32
|
||||
Mark *uint32
|
||||
}
|
||||
|
||||
func (action *SkbEditAction) Type() string {
|
||||
return "skbedit"
|
||||
}
|
||||
|
||||
func (action *SkbEditAction) Attrs() *ActionAttrs {
|
||||
return &action.ActionAttrs
|
||||
}
|
||||
|
||||
func NewSkbEditAction() *SkbEditAction {
|
||||
return &SkbEditAction{
|
||||
ActionAttrs: ActionAttrs{
|
||||
Action: TC_ACT_PIPE,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// MatchAll filters match all packets
|
||||
type MatchAll struct {
|
||||
FilterAttrs
|
||||
|
|
|
@ -457,6 +457,26 @@ func EncodeActions(attr *nl.RtAttr, actions []Action) error {
|
|||
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++
|
||||
|
@ -516,6 +536,8 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
|
|||
action = &GenericAction{}
|
||||
case "tunnel_key":
|
||||
action = &TunnelKeyAction{}
|
||||
case "skbedit":
|
||||
action = &SkbEditAction{}
|
||||
default:
|
||||
break nextattr
|
||||
}
|
||||
|
@ -551,6 +573,25 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
|
|||
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":
|
||||
switch adatum.Attr.Type {
|
||||
case nl.TCA_ACT_BPF_PARMS:
|
||||
|
|
172
filter_test.go
172
filter_test.go
|
@ -1134,3 +1134,175 @@ func TestFilterU32TunnelKeyAddDel(t *testing.T) {
|
|||
t.Fatal("Failed to remove qdisc")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFilterU32SkbEditAddDel(t *testing.T) {
|
||||
tearDown := setUpNetlinkTest(t)
|
||||
defer tearDown()
|
||||
if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := LinkAdd(&Ifb{LinkAttrs{Name: "bar"}}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
link, err := LinkByName("foo")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := LinkSetUp(link); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
redir, err := LinkByName("bar")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := LinkSetUp(redir); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
qdisc := &Ingress{
|
||||
QdiscAttrs: QdiscAttrs{
|
||||
LinkIndex: link.Attrs().Index,
|
||||
Handle: MakeHandle(0xffff, 0),
|
||||
Parent: HANDLE_INGRESS,
|
||||
},
|
||||
}
|
||||
if err := QdiscAdd(qdisc); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
qdiscs, err := SafeQdiscList(link)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
found := false
|
||||
for _, v := range qdiscs {
|
||||
if _, ok := v.(*Ingress); ok {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatal("Qdisc is the wrong type")
|
||||
}
|
||||
|
||||
skbedit := NewSkbEditAction()
|
||||
ptype := uint16(unix.PACKET_HOST)
|
||||
skbedit.PType = &ptype
|
||||
priority := uint32(0xff)
|
||||
skbedit.Priority = &priority
|
||||
mark := uint32(0xfe)
|
||||
skbedit.Mark = &mark
|
||||
mapping := uint16(0xf)
|
||||
skbedit.QueueMapping = &mapping
|
||||
|
||||
classId := MakeHandle(1, 1)
|
||||
filter := &U32{
|
||||
FilterAttrs: FilterAttrs{
|
||||
LinkIndex: link.Attrs().Index,
|
||||
Parent: MakeHandle(0xffff, 0),
|
||||
Priority: 1,
|
||||
Protocol: unix.ETH_P_ALL,
|
||||
},
|
||||
ClassId: classId,
|
||||
Actions: []Action{
|
||||
skbedit,
|
||||
&MirredAction{
|
||||
ActionAttrs: ActionAttrs{
|
||||
Action: TC_ACT_STOLEN,
|
||||
},
|
||||
MirredAction: TCA_EGRESS_REDIR,
|
||||
Ifindex: redir.Attrs().Index,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if err := FilterAdd(filter); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
filters, err := FilterList(link, MakeHandle(0xffff, 0))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(filters) != 1 {
|
||||
t.Fatal("Failed to add filter")
|
||||
}
|
||||
u32, ok := filters[0].(*U32)
|
||||
if !ok {
|
||||
t.Fatal("Filter is the wrong type")
|
||||
}
|
||||
|
||||
if len(u32.Actions) != 2 {
|
||||
t.Fatalf("Too few Actions in filter")
|
||||
}
|
||||
if u32.ClassId != classId {
|
||||
t.Fatalf("ClassId of the filter is the wrong value")
|
||||
}
|
||||
|
||||
// actions can be returned in reverse order
|
||||
edit, ok := u32.Actions[0].(*SkbEditAction)
|
||||
if !ok {
|
||||
edit, ok = u32.Actions[1].(*SkbEditAction)
|
||||
if !ok {
|
||||
t.Fatal("Unable to find tunnel action")
|
||||
}
|
||||
}
|
||||
|
||||
if edit.Attrs().Action != TC_ACT_PIPE {
|
||||
t.Fatal("SkbEdit action isn't TC_ACT_PIPE")
|
||||
}
|
||||
if edit.PType == nil || *edit.PType != *skbedit.PType {
|
||||
t.Fatal("Action PType doesn't match")
|
||||
}
|
||||
if edit.QueueMapping == nil || *edit.QueueMapping != *skbedit.QueueMapping {
|
||||
t.Fatal("Action QueueMapping doesn't match")
|
||||
}
|
||||
if edit.Mark == nil || *edit.Mark != *skbedit.Mark {
|
||||
t.Fatal("Action Mark doesn't match")
|
||||
}
|
||||
if edit.Priority == nil || *edit.Priority != *skbedit.Priority {
|
||||
t.Fatal("Action Priority doesn't match")
|
||||
}
|
||||
|
||||
mia, ok := u32.Actions[0].(*MirredAction)
|
||||
if !ok {
|
||||
mia, ok = u32.Actions[1].(*MirredAction)
|
||||
if !ok {
|
||||
t.Fatal("Unable to find mirred action")
|
||||
}
|
||||
}
|
||||
|
||||
if mia.Attrs().Action != TC_ACT_STOLEN {
|
||||
t.Fatal("Mirred action isn't TC_ACT_STOLEN")
|
||||
}
|
||||
|
||||
if err := FilterDel(filter); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
filters, err = FilterList(link, MakeHandle(0xffff, 0))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(filters) != 0 {
|
||||
t.Fatal("Failed to remove filter")
|
||||
}
|
||||
|
||||
if err := QdiscDel(qdisc); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
qdiscs, err = SafeQdiscList(link)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
found = false
|
||||
for _, v := range qdiscs {
|
||||
if _, ok := v.(*Ingress); ok {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if found {
|
||||
t.Fatal("Failed to remove qdisc")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,6 +92,7 @@ const (
|
|||
SizeofTcConnmark = SizeofTcGen + 0x04
|
||||
SizeofTcMirred = SizeofTcGen + 0x08
|
||||
SizeofTcTunnelKey = SizeofTcGen + 0x04
|
||||
SizeofTcSkbEdit = SizeofTcGen
|
||||
SizeofTcPolice = 2*SizeofTcRateSpec + 0x20
|
||||
)
|
||||
|
||||
|
@ -754,6 +755,34 @@ func (x *TcTunnelKey) Serialize() []byte {
|
|||
return (*(*[SizeofTcTunnelKey]byte)(unsafe.Pointer(x)))[:]
|
||||
}
|
||||
|
||||
const (
|
||||
TCA_SKBEDIT_UNSPEC = iota
|
||||
TCA_SKBEDIT_TM
|
||||
TCA_SKBEDIT_PARMS
|
||||
TCA_SKBEDIT_PRIORITY
|
||||
TCA_SKBEDIT_QUEUE_MAPPING
|
||||
TCA_SKBEDIT_MARK
|
||||
TCA_SKBEDIT_PAD
|
||||
TCA_SKBEDIT_PTYPE
|
||||
TCA_SKBEDIT_MAX = TCA_SKBEDIT_MARK
|
||||
)
|
||||
|
||||
type TcSkbEdit struct {
|
||||
TcGen
|
||||
}
|
||||
|
||||
func (x *TcSkbEdit) Len() int {
|
||||
return SizeofTcSkbEdit
|
||||
}
|
||||
|
||||
func DeserializeSkbEdit(b []byte) *TcSkbEdit {
|
||||
return (*TcSkbEdit)(unsafe.Pointer(&b[0:SizeofTcSkbEdit][0]))
|
||||
}
|
||||
|
||||
func (x *TcSkbEdit) Serialize() []byte {
|
||||
return (*(*[SizeofTcSkbEdit]byte)(unsafe.Pointer(x)))[:]
|
||||
}
|
||||
|
||||
// struct tc_police {
|
||||
// __u32 index;
|
||||
// int action;
|
||||
|
|
Loading…
Reference in New Issue