Add Matchall filter

This commit is contained in:
Sargun Dhillon 2017-12-27 02:00:08 -08:00 committed by Alessandro Boch
parent 7b4c06360e
commit 1882fa99fc
4 changed files with 146 additions and 10 deletions

View File

@ -225,6 +225,21 @@ func (filter *U32) Type() string {
return "u32" return "u32"
} }
// MatchAll filters match all packets
type MatchAll struct {
FilterAttrs
ClassId uint32
Actions []Action
}
func (filter *MatchAll) Attrs() *FilterAttrs {
return &filter.FilterAttrs
}
func (filter *MatchAll) Type() string {
return "matchall"
}
type FilterFwAttrs struct { type FilterFwAttrs struct {
ClassId uint32 ClassId uint32
InDev string InDev string

View File

@ -222,6 +222,14 @@ func (h *Handle) FilterAdd(filter Filter) error {
bpfFlags |= nl.TCA_BPF_FLAG_ACT_DIRECT bpfFlags |= nl.TCA_BPF_FLAG_ACT_DIRECT
} }
nl.NewRtAttrChild(options, nl.TCA_BPF_FLAGS, nl.Uint32Attr(bpfFlags)) nl.NewRtAttrChild(options, nl.TCA_BPF_FLAGS, nl.Uint32Attr(bpfFlags))
case *MatchAll:
actionsAttr := nl.NewRtAttrChild(options, nl.TCA_MATCHALL_ACT, nil)
if err := EncodeActions(actionsAttr, filter.Actions); err != nil {
return err
}
if filter.ClassId != 0 {
nl.NewRtAttrChild(options, nl.TCA_MATCHALL_CLASSID, nl.Uint32Attr(filter.ClassId))
}
} }
req.AddData(options) req.AddData(options)
@ -288,6 +296,8 @@ func (h *Handle) FilterList(link Link, parent uint32) ([]Filter, error) {
filter = &Fw{} filter = &Fw{}
case "bpf": case "bpf":
filter = &BpfFilter{} filter = &BpfFilter{}
case "matchall":
filter = &MatchAll{}
default: default:
filter = &GenericFilter{FilterType: filterType} filter = &GenericFilter{FilterType: filterType}
} }
@ -312,6 +322,11 @@ func (h *Handle) FilterList(link Link, parent uint32) ([]Filter, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
case "matchall":
detailed, err = parseMatchAllData(filter, data)
if err != nil {
return nil, err
}
default: default:
detailed = true detailed = true
} }
@ -541,6 +556,28 @@ func parseBpfData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error)
return detailed, nil return detailed, nil
} }
func parseMatchAllData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
native = nl.NativeEndian()
matchall := filter.(*MatchAll)
detailed := true
for _, datum := range data {
switch datum.Attr.Type {
case nl.TCA_MATCHALL_CLASSID:
matchall.ClassId = native.Uint32(datum.Value[0:4])
case nl.TCA_MATCHALL_ACT:
tables, err := nl.ParseRouteAttr(datum.Value)
if err != nil {
return detailed, err
}
matchall.Actions, err = parseActions(tables)
if err != nil {
return detailed, err
}
}
}
return detailed, nil
}
func AlignToAtm(size uint) uint { func AlignToAtm(size uint) uint {
var linksize, cells int var linksize, cells int
cells = int(size / nl.ATM_CELL_PAYLOAD) cells = int(size / nl.ATM_CELL_PAYLOAD)

View File

@ -168,13 +168,13 @@ func TestAdvancedFilterAddDel(t *testing.T) {
} }
u32SelKeys := []TcU32Key{ u32SelKeys := []TcU32Key{
TcU32Key{ {
Mask: 0xff, Mask: 0xff,
Val: 80, Val: 80,
Off: 20, Off: 20,
OffMask: 0, OffMask: 0,
}, },
TcU32Key{ {
Mask: 0xffff, Mask: 0xffff,
Val: 0x146ca, Val: 0x146ca,
Off: 32, Off: 32,
@ -546,13 +546,11 @@ func TestFilterU32BpfAddDel(t *testing.T) {
} }
} }
func TestFilterClsActBpfAddDel(t *testing.T) { func setupLinkForTestWithQdisc(t *testing.T, linkName string) (Qdisc, Link) {
tearDown := setUpNetlinkTest(t) if err := LinkAdd(&Ifb{LinkAttrs{Name: linkName}}); err != nil {
defer tearDown()
if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
t.Fatal(err) t.Fatal(err)
} }
link, err := LinkByName("foo") link, err := LinkByName(linkName)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -568,8 +566,6 @@ func TestFilterClsActBpfAddDel(t *testing.T) {
QdiscAttrs: attrs, QdiscAttrs: attrs,
QdiscType: "clsact", QdiscType: "clsact",
} }
// This feature was added in kernel 4.5
minKernelRequired(t, 4, 5)
if err := QdiscAdd(qdisc); err != nil { if err := QdiscAdd(qdisc); err != nil {
t.Fatal(err) t.Fatal(err)
@ -584,7 +580,17 @@ func TestFilterClsActBpfAddDel(t *testing.T) {
if q, ok := qdiscs[0].(*GenericQdisc); !ok || q.Type() != "clsact" { if q, ok := qdiscs[0].(*GenericQdisc); !ok || q.Type() != "clsact" {
t.Fatal("qdisc is the wrong type") t.Fatal("qdisc is the wrong type")
} }
return qdiscs[0], link
}
func TestFilterClsActBpfAddDel(t *testing.T) {
// This feature was added in kernel 4.5
minKernelRequired(t, 4, 5)
tearDown := setUpNetlinkTest(t)
defer tearDown()
qdisc, link := setupLinkForTestWithQdisc(t, "foo")
filterattrs := FilterAttrs{ filterattrs := FilterAttrs{
LinkIndex: link.Attrs().Index, LinkIndex: link.Attrs().Index,
Parent: HANDLE_MIN_EGRESS, Parent: HANDLE_MIN_EGRESS,
@ -643,7 +649,7 @@ func TestFilterClsActBpfAddDel(t *testing.T) {
if err := QdiscDel(qdisc); err != nil { if err := QdiscDel(qdisc); err != nil {
t.Fatal(err) t.Fatal(err)
} }
qdiscs, err = SafeQdiscList(link) qdiscs, err := SafeQdiscList(link)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -651,3 +657,74 @@ func TestFilterClsActBpfAddDel(t *testing.T) {
t.Fatal("Failed to remove qdisc") t.Fatal("Failed to remove qdisc")
} }
} }
func TestFilterMatchAllAddDel(t *testing.T) {
// This classifier was added in kernel 4.7
minKernelRequired(t, 4, 7)
tearDown := setUpNetlinkTest(t)
defer tearDown()
_, link := setupLinkForTestWithQdisc(t, "foo")
_, link2 := setupLinkForTestWithQdisc(t, "bar")
filter := &MatchAll{
FilterAttrs: FilterAttrs{
LinkIndex: link.Attrs().Index,
Parent: HANDLE_MIN_EGRESS,
Priority: 32000,
Protocol: unix.ETH_P_ALL,
},
Actions: []Action{
&MirredAction{
ActionAttrs: ActionAttrs{
Action: TC_ACT_STOLEN,
},
MirredAction: TCA_EGRESS_REDIR,
Ifindex: link2.Attrs().Index,
},
},
}
if err := FilterAdd(filter); err != nil {
t.Fatal(err)
}
filters, err := FilterList(link, HANDLE_MIN_EGRESS)
if err != nil {
t.Fatal(err)
}
if len(filters) != 1 {
t.Fatal("Failed to add filter")
}
matchall, ok := filters[0].(*MatchAll)
if !ok {
t.Fatal("Filter is the wrong type")
}
if matchall.Priority != 32000 {
t.Fatal("Filter priority does not match")
}
if len(matchall.Actions) != 1 {
t.Fatal("Filter has no actions")
}
mirredAction, ok := matchall.Actions[0].(*MirredAction)
if !ok {
t.Fatal("Action does not match")
}
if mirredAction.Ifindex != link2.Attrs().Index {
t.Fatal("Action ifindex does not match")
}
if err := FilterDel(filter); err != nil {
t.Fatal(err)
}
filters, err = FilterList(link, HANDLE_MIN_EGRESS)
if err != nil {
t.Fatal(err)
}
if len(filters) != 0 {
t.Fatal("Failed to remove filter")
}
}

View File

@ -673,3 +673,10 @@ const (
TCA_FW_MASK TCA_FW_MASK
TCA_FW_MAX = TCA_FW_MASK TCA_FW_MAX = TCA_FW_MASK
) )
const (
TCA_MATCHALL_UNSPEC = iota
TCA_MATCHALL_CLASSID
TCA_MATCHALL_ACT
TCA_MATCHALL_FLAGS
)