2015-08-19 23:02:04 +00:00
|
|
|
package netlink
|
|
|
|
|
|
|
|
import (
|
|
|
|
"syscall"
|
|
|
|
"testing"
|
2015-10-05 05:34:02 +00:00
|
|
|
|
|
|
|
"github.com/vishvananda/netlink/nl"
|
2015-08-19 23:02:04 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
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 := QdiscList(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")
|
|
|
|
}
|
|
|
|
filter := &U32{
|
|
|
|
FilterAttrs: FilterAttrs{
|
|
|
|
LinkIndex: link.Attrs().Index,
|
|
|
|
Parent: MakeHandle(0xffff, 0),
|
|
|
|
Priority: 1,
|
|
|
|
Protocol: syscall.ETH_P_IP,
|
|
|
|
},
|
|
|
|
RedirIndex: 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")
|
|
|
|
}
|
|
|
|
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 = QdiscList(link)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if len(qdiscs) != 0 {
|
|
|
|
t.Fatal("Failed to remove qdisc")
|
|
|
|
}
|
|
|
|
}
|
2015-09-12 06:24:22 +00:00
|
|
|
|
|
|
|
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 := QdiscList(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: syscall.ETH_P_IP,
|
|
|
|
}
|
|
|
|
fwattrs := FilterFwAttrs{
|
|
|
|
Buffer: 12345,
|
|
|
|
Rate: 1234,
|
|
|
|
PeakRate: 2345,
|
|
|
|
Action: nl.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")
|
|
|
|
}
|
|
|
|
for i := range fw.Rtab {
|
|
|
|
if fw.Rtab[i] != filter.Rtab[i] {
|
|
|
|
t.Fatal("Rtab doesn't match")
|
|
|
|
}
|
|
|
|
if fw.Ptab[i] != filter.Ptab[i] {
|
|
|
|
t.Fatal("Ptab 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 = QdiscList(link)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if len(qdiscs) != 0 {
|
|
|
|
t.Fatal("Failed to remove qdisc")
|
|
|
|
}
|
|
|
|
}
|
2016-02-29 07:12:34 +00:00
|
|
|
|
|
|
|
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 := QdiscList(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)
|
|
|
|
if err != nil {
|
2016-02-29 07:52:26 +00:00
|
|
|
t.Skipf("Loading bpf program failed: %s", err)
|
2016-02-29 07:12:34 +00:00
|
|
|
}
|
|
|
|
filter := &U32{
|
|
|
|
FilterAttrs: FilterAttrs{
|
|
|
|
LinkIndex: link.Attrs().Index,
|
|
|
|
Parent: MakeHandle(0xffff, 0),
|
|
|
|
Priority: 1,
|
|
|
|
Protocol: syscall.ETH_P_ALL,
|
|
|
|
},
|
|
|
|
ClassId: MakeHandle(1, 1),
|
|
|
|
Actions: []Action{
|
|
|
|
&BpfAction{Fd: fd, Name: "simple"},
|
|
|
|
&MirredAction{
|
|
|
|
TcMirred: nl.TcMirred{
|
|
|
|
TcGen: nl.TcGen{Action: nl.TC_ACT_STOLEN},
|
|
|
|
Eaction: nl.TCA_EGRESS_REDIR,
|
|
|
|
Ifindex: uint32(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")
|
|
|
|
}
|
|
|
|
bpfAction, ok := u32.Actions[0].(*BpfAction)
|
|
|
|
if !ok {
|
|
|
|
t.Fatal("Action[0] is the wrong type")
|
|
|
|
}
|
|
|
|
if bpfAction.Fd != fd {
|
|
|
|
t.Fatal("Action Fd does not match")
|
|
|
|
}
|
|
|
|
if _, ok := u32.Actions[1].(*MirredAction); !ok {
|
|
|
|
t.Fatal("Action[1] 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 = QdiscList(link)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if len(qdiscs) != 0 {
|
|
|
|
t.Fatal("Failed to remove qdisc")
|
|
|
|
}
|
|
|
|
}
|
2016-02-29 07:20:29 +00:00
|
|
|
|
|
|
|
func TestFilterClsActBpfAddDel(t *testing.T) {
|
|
|
|
tearDown := setUpNetlinkTest(t)
|
|
|
|
defer tearDown()
|
|
|
|
if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
link, err := LinkByName("foo")
|
|
|
|
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",
|
|
|
|
}
|
|
|
|
// This feature was added in kernel 4.5
|
|
|
|
if err := QdiscAdd(qdisc); err != nil {
|
|
|
|
t.Skipf("Failed adding clsact qdisc, unsupported kernel")
|
|
|
|
}
|
|
|
|
qdiscs, err := QdiscList(link)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if len(qdiscs) != 1 {
|
|
|
|
t.Fatal("Failed to add qdisc")
|
|
|
|
}
|
|
|
|
if q, ok := qdiscs[0].(*GenericQdisc); !ok || q.Type() != "clsact" {
|
|
|
|
t.Fatal("qdisc is the wrong type")
|
|
|
|
}
|
|
|
|
|
|
|
|
filterattrs := FilterAttrs{
|
|
|
|
LinkIndex: link.Attrs().Index,
|
|
|
|
Parent: HANDLE_MIN_EGRESS,
|
|
|
|
Handle: MakeHandle(0, 1),
|
|
|
|
Protocol: syscall.ETH_P_ALL,
|
|
|
|
Priority: 1,
|
|
|
|
}
|
|
|
|
fd, err := loadSimpleBpf(BPF_PROG_TYPE_SCHED_CLS)
|
|
|
|
if err != nil {
|
2016-02-29 07:52:26 +00:00
|
|
|
t.Skipf("Loading bpf program failed: %s", err)
|
2016-02-29 07:20:29 +00:00
|
|
|
}
|
|
|
|
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 = QdiscList(link)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if len(qdiscs) != 0 {
|
|
|
|
t.Fatal("Failed to remove qdisc")
|
|
|
|
}
|
|
|
|
}
|