mirror of
https://github.com/vishvananda/netlink
synced 2025-02-10 09:06:57 +00:00
dc00cf9d5c
This patch adds "Hash" attribute that represents the ID of the hash table with which the filter is associated to U32 struct. If the hash table is not created yet, a new hash table is created with the specified ID. Signed-off-by: Taku Fukushima <taku@soracom.jp>
763 lines
16 KiB
Go
763 lines
16 KiB
Go
// +build linux
|
|
|
|
package netlink
|
|
|
|
import (
|
|
"reflect"
|
|
"testing"
|
|
|
|
"golang.org/x/sys/unix"
|
|
)
|
|
|
|
func TestFilterAddDel(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)
|
|
}
|
|
if len(qdiscs) != 1 {
|
|
t.Fatal("Failed to add qdisc")
|
|
}
|
|
_, ok := qdiscs[0].(*Ingress)
|
|
if !ok {
|
|
t.Fatal("Qdisc is the wrong type")
|
|
}
|
|
classId := MakeHandle(1, 1)
|
|
filter := &U32{
|
|
FilterAttrs: FilterAttrs{
|
|
LinkIndex: link.Attrs().Index,
|
|
Parent: MakeHandle(0xffff, 0),
|
|
Priority: 1,
|
|
Protocol: unix.ETH_P_IP,
|
|
},
|
|
RedirIndex: redir.Attrs().Index,
|
|
ClassId: classId,
|
|
}
|
|
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 u32.ClassId != classId {
|
|
t.Fatalf("ClassId of the filter is the wrong value")
|
|
}
|
|
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)
|
|
}
|
|
if len(qdiscs) != 0 {
|
|
t.Fatal("Failed to remove qdisc")
|
|
}
|
|
}
|
|
|
|
func TestAdvancedFilterAddDel(t *testing.T) {
|
|
tearDown := setUpNetlinkTest(t)
|
|
defer tearDown()
|
|
if err := LinkAdd(&Ifb{LinkAttrs{Name: "baz"}}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
link, err := LinkByName("baz")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := LinkSetUp(link); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
index := link.Attrs().Index
|
|
|
|
qdiscHandle := MakeHandle(0x1, 0x0)
|
|
qdiscAttrs := QdiscAttrs{
|
|
LinkIndex: index,
|
|
Handle: qdiscHandle,
|
|
Parent: HANDLE_ROOT,
|
|
}
|
|
|
|
qdisc := NewHtb(qdiscAttrs)
|
|
if err := QdiscAdd(qdisc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
qdiscs, err := SafeQdiscList(link)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(qdiscs) != 1 {
|
|
t.Fatal("Failed to add qdisc")
|
|
}
|
|
_, ok := qdiscs[0].(*Htb)
|
|
if !ok {
|
|
t.Fatal("Qdisc is the wrong type")
|
|
}
|
|
|
|
classId := MakeHandle(0x1, 0x46cb)
|
|
classAttrs := ClassAttrs{
|
|
LinkIndex: index,
|
|
Parent: qdiscHandle,
|
|
Handle: classId,
|
|
}
|
|
htbClassAttrs := HtbClassAttrs{
|
|
Rate: 512 * 1024,
|
|
Buffer: 32 * 1024,
|
|
}
|
|
htbClass := NewHtbClass(classAttrs, htbClassAttrs)
|
|
if err = ClassReplace(htbClass); err != nil {
|
|
t.Fatalf("Failed to add a HTB class: %v", err)
|
|
}
|
|
classes, err := ClassList(link, qdiscHandle)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(classes) != 1 {
|
|
t.Fatal("Failed to add class")
|
|
}
|
|
_, ok = classes[0].(*HtbClass)
|
|
if !ok {
|
|
t.Fatal("Class is the wrong type")
|
|
}
|
|
|
|
htid := MakeHandle(0x0010, 0000)
|
|
divisor := uint32(1)
|
|
hashTable := &U32{
|
|
FilterAttrs: FilterAttrs{
|
|
LinkIndex: index,
|
|
Handle: htid,
|
|
Parent: qdiscHandle,
|
|
Priority: 1,
|
|
Protocol: unix.ETH_P_ALL,
|
|
},
|
|
Divisor: divisor,
|
|
}
|
|
cHashTable := *hashTable
|
|
if err := FilterAdd(hashTable); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
// Check if the hash table is identical before and after FilterAdd.
|
|
if !reflect.DeepEqual(cHashTable, *hashTable) {
|
|
t.Fatalf("Hash table %v and %v are not equal", cHashTable, *hashTable)
|
|
}
|
|
|
|
u32SelKeys := []TcU32Key{
|
|
{
|
|
Mask: 0xff,
|
|
Val: 80,
|
|
Off: 20,
|
|
OffMask: 0,
|
|
},
|
|
{
|
|
Mask: 0xffff,
|
|
Val: 0x146ca,
|
|
Off: 32,
|
|
OffMask: 0,
|
|
},
|
|
}
|
|
|
|
handle := MakeHandle(0x0000, 0001)
|
|
filter := &U32{
|
|
FilterAttrs: FilterAttrs{
|
|
LinkIndex: index,
|
|
Handle: handle,
|
|
Parent: qdiscHandle,
|
|
Priority: 1,
|
|
Protocol: unix.ETH_P_ALL,
|
|
},
|
|
Sel: &TcU32Sel{
|
|
Keys: u32SelKeys,
|
|
Flags: TC_U32_TERMINAL,
|
|
},
|
|
ClassId: classId,
|
|
Hash: htid,
|
|
Actions: []Action{},
|
|
}
|
|
// Copy filter.
|
|
cFilter := *filter
|
|
if err := FilterAdd(filter); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
// Check if the filter is identical before and after FilterAdd.
|
|
if !reflect.DeepEqual(cFilter, *filter) {
|
|
t.Fatalf("U32 %v and %v are not equal", cFilter, *filter)
|
|
}
|
|
|
|
filters, err := FilterList(link, qdiscHandle)
|
|
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")
|
|
}
|
|
// Endianness checks
|
|
if u32.Sel.Offmask != filter.Sel.Offmask {
|
|
t.Fatal("The endianness of TcU32Key.Sel.Offmask is wrong")
|
|
}
|
|
if u32.Sel.Hmask != filter.Sel.Hmask {
|
|
t.Fatal("The endianness of TcU32Key.Sel.Hmask is wrong")
|
|
}
|
|
for i, key := range u32.Sel.Keys {
|
|
if key.Mask != filter.Sel.Keys[i].Mask {
|
|
t.Fatal("The endianness of TcU32Key.Mask is wrong")
|
|
}
|
|
if key.Val != filter.Sel.Keys[i].Val {
|
|
t.Fatal("The endianness of TcU32Key.Val is wrong")
|
|
}
|
|
}
|
|
if u32.Handle != (handle | htid) {
|
|
t.Fatalf("The handle is wrong. expected %v but actually %v",
|
|
(handle | htid), u32.Handle)
|
|
}
|
|
if u32.Hash != htid {
|
|
t.Fatal("The hash table ID is wrong")
|
|
}
|
|
|
|
if err := FilterDel(u32); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
filters, err = FilterList(link, qdiscHandle)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(filters) != 0 {
|
|
t.Fatal("Failed to remove filter")
|
|
}
|
|
|
|
if err = ClassDel(htbClass); err != nil {
|
|
t.Fatalf("Failed to delete a HTP class: %v", err)
|
|
}
|
|
classes, err = ClassList(link, qdiscHandle)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(classes) != 0 {
|
|
t.Fatal("Failed to remove class")
|
|
}
|
|
|
|
if err := QdiscDel(qdisc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
qdiscs, err = SafeQdiscList(link)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(qdiscs) != 0 {
|
|
t.Fatal("Failed to remove qdisc")
|
|
}
|
|
}
|
|
|
|
func TestFilterFwAddDel(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)
|
|
}
|
|
attrs := QdiscAttrs{
|
|
LinkIndex: link.Attrs().Index,
|
|
Handle: MakeHandle(0xffff, 0),
|
|
Parent: HANDLE_ROOT,
|
|
}
|
|
qdisc := NewHtb(attrs)
|
|
if err := QdiscAdd(qdisc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
qdiscs, err := SafeQdiscList(link)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(qdiscs) != 1 {
|
|
t.Fatal("Failed to add qdisc")
|
|
}
|
|
_, ok := qdiscs[0].(*Htb)
|
|
if !ok {
|
|
t.Fatal("Qdisc is the wrong type")
|
|
}
|
|
|
|
classattrs := ClassAttrs{
|
|
LinkIndex: link.Attrs().Index,
|
|
Parent: MakeHandle(0xffff, 0),
|
|
Handle: MakeHandle(0xffff, 2),
|
|
}
|
|
|
|
htbclassattrs := HtbClassAttrs{
|
|
Rate: 1234000,
|
|
Cbuffer: 1690,
|
|
}
|
|
class := NewHtbClass(classattrs, htbclassattrs)
|
|
if err := ClassAdd(class); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
classes, err := ClassList(link, MakeHandle(0xffff, 2))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(classes) != 1 {
|
|
t.Fatal("Failed to add class")
|
|
}
|
|
|
|
filterattrs := FilterAttrs{
|
|
LinkIndex: link.Attrs().Index,
|
|
Parent: MakeHandle(0xffff, 0),
|
|
Handle: MakeHandle(0, 0x6),
|
|
Priority: 1,
|
|
Protocol: unix.ETH_P_IP,
|
|
}
|
|
fwattrs := FilterFwAttrs{
|
|
Buffer: 12345,
|
|
Rate: 1234,
|
|
PeakRate: 2345,
|
|
Action: TC_POLICE_SHOT,
|
|
ClassId: MakeHandle(0xffff, 2),
|
|
}
|
|
|
|
filter, err := NewFw(filterattrs, fwattrs)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
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")
|
|
}
|
|
fw, ok := filters[0].(*Fw)
|
|
if !ok {
|
|
t.Fatal("Filter is the wrong type")
|
|
}
|
|
if fw.Police.Rate.Rate != filter.Police.Rate.Rate {
|
|
t.Fatal("Police Rate doesn't match")
|
|
}
|
|
if fw.ClassId != filter.ClassId {
|
|
t.Fatal("ClassId doesn't match")
|
|
}
|
|
if fw.InDev != filter.InDev {
|
|
t.Fatal("InDev doesn't match")
|
|
}
|
|
if fw.AvRate != filter.AvRate {
|
|
t.Fatal("AvRate doesn't match")
|
|
}
|
|
|
|
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 := ClassDel(class); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
classes, err = ClassList(link, MakeHandle(0xffff, 0))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(classes) != 0 {
|
|
t.Fatal("Failed to remove class")
|
|
}
|
|
|
|
if err := QdiscDel(qdisc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
qdiscs, err = SafeQdiscList(link)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(qdiscs) != 0 {
|
|
t.Fatal("Failed to remove qdisc")
|
|
}
|
|
}
|
|
|
|
func TestFilterU32BpfAddDel(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)
|
|
}
|
|
if len(qdiscs) != 1 {
|
|
t.Fatal("Failed to add qdisc")
|
|
}
|
|
_, ok := qdiscs[0].(*Ingress)
|
|
if !ok {
|
|
t.Fatal("Qdisc is the wrong type")
|
|
}
|
|
|
|
fd, err := loadSimpleBpf(BPF_PROG_TYPE_SCHED_ACT, 1)
|
|
if err != nil {
|
|
t.Skipf("Loading bpf program failed: %s", err)
|
|
}
|
|
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{
|
|
&BpfAction{Fd: fd, Name: "simple"},
|
|
&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
|
|
bpfAction, ok := u32.Actions[0].(*BpfAction)
|
|
if !ok {
|
|
bpfAction, ok = u32.Actions[1].(*BpfAction)
|
|
if !ok {
|
|
t.Fatal("Action is the wrong type")
|
|
}
|
|
}
|
|
if bpfAction.Fd != fd {
|
|
t.Fatal("Action Fd does not match")
|
|
}
|
|
if _, ok := u32.Actions[0].(*MirredAction); !ok {
|
|
if _, ok := u32.Actions[1].(*MirredAction); !ok {
|
|
t.Fatal("Action is the wrong type")
|
|
}
|
|
}
|
|
|
|
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)
|
|
}
|
|
if len(qdiscs) != 0 {
|
|
t.Fatal("Failed to remove qdisc")
|
|
}
|
|
}
|
|
|
|
func setupLinkForTestWithQdisc(t *testing.T, linkName string) (Qdisc, Link) {
|
|
if err := LinkAdd(&Ifb{LinkAttrs{Name: linkName}}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
link, err := LinkByName(linkName)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := LinkSetUp(link); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
attrs := QdiscAttrs{
|
|
LinkIndex: link.Attrs().Index,
|
|
Handle: MakeHandle(0xffff, 0),
|
|
Parent: HANDLE_CLSACT,
|
|
}
|
|
qdisc := &GenericQdisc{
|
|
QdiscAttrs: attrs,
|
|
QdiscType: "clsact",
|
|
}
|
|
|
|
if err := QdiscAdd(qdisc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
qdiscs, err := SafeQdiscList(link)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(qdiscs) != 1 {
|
|
t.Fatal("Failed to add qdisc", len(qdiscs))
|
|
}
|
|
if q, ok := qdiscs[0].(*GenericQdisc); !ok || q.Type() != "clsact" {
|
|
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{
|
|
LinkIndex: link.Attrs().Index,
|
|
Parent: HANDLE_MIN_EGRESS,
|
|
Handle: MakeHandle(0, 1),
|
|
Protocol: unix.ETH_P_ALL,
|
|
Priority: 1,
|
|
}
|
|
fd, err := loadSimpleBpf(BPF_PROG_TYPE_SCHED_CLS, 1)
|
|
if err != nil {
|
|
t.Skipf("Loading bpf program failed: %s", err)
|
|
}
|
|
filter := &BpfFilter{
|
|
FilterAttrs: filterattrs,
|
|
Fd: fd,
|
|
Name: "simple",
|
|
DirectAction: true,
|
|
}
|
|
if filter.Fd < 0 {
|
|
t.Skipf("Failed to load bpf program")
|
|
}
|
|
|
|
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")
|
|
}
|
|
bpf, ok := filters[0].(*BpfFilter)
|
|
if !ok {
|
|
t.Fatal("Filter is the wrong type")
|
|
}
|
|
|
|
if bpf.Fd != filter.Fd {
|
|
t.Fatal("Filter Fd does not match")
|
|
}
|
|
if bpf.DirectAction != filter.DirectAction {
|
|
t.Fatal("Filter DirectAction 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")
|
|
}
|
|
|
|
if err := QdiscDel(qdisc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
qdiscs, err := SafeQdiscList(link)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(qdiscs) != 0 {
|
|
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")
|
|
}
|
|
|
|
}
|