4 Star 1 Fork 0

Gitee 极速下载/netlink

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
此仓库是为了提升国内下载速度的镜像仓库,每日同步一次。 原始仓库: https://github.com/vishvananda/netlink
克隆/下载
filter_test.go 52.81 KB
一键复制 编辑 原始数据 按行查看 历史
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601
//go:build linux
// +build linux
package netlink
import (
"net"
"reflect"
"testing"
"time"
"github.com/vishvananda/netlink/nl"
"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 TestFilterReplace(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)
}
filter := &U32{
FilterAttrs: FilterAttrs{
LinkIndex: link.Attrs().Index,
Parent: MakeHandle(0xffff, 0),
Priority: 1,
Protocol: unix.ETH_P_IP,
},
RedirIndex: redir.Attrs().Index,
ClassId: MakeHandle(1, 1),
}
if err := FilterReplace(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 replace filter")
}
if err := FilterReplace(filter); err != nil {
t.Fatal(err)
}
}
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 := SafeClassList(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 = SafeClassList(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 := SafeClassList(link, MakeHandle(0xffff, 2))
if err != nil {
t.Fatal(err)
}
if len(classes) != 1 {
t.Fatal("Failed to add class")
}
police := NewPoliceAction()
police.Burst = 12345
police.Rate = 1234
police.PeakRate = 2345
police.Action = TcAct(TC_POLICE_SHOT)
filterattrs := FilterAttrs{
LinkIndex: link.Attrs().Index,
Parent: MakeHandle(0xffff, 0),
Handle: MakeHandle(0, 0x6),
Priority: 1,
Protocol: unix.ETH_P_IP,
}
filter := FwFilter{
FilterAttrs: filterattrs,
ClassId: MakeHandle(0xffff, 2),
Police: police,
}
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].(*FwFilter)
if !ok {
t.Fatal("Filter is the wrong type")
}
if fw.Police.Rate != filter.Police.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.Police.AvRate != filter.Police.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 = SafeClassList(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 TestFilterFwActAddDel(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 := &FwFilter{
FilterAttrs: FilterAttrs{
LinkIndex: link.Attrs().Index,
Parent: MakeHandle(0xffff, 0),
Priority: 1,
Protocol: unix.ETH_P_ALL,
Handle: MakeHandle(0, 0x6),
},
ClassId: classId,
Actions: []Action{
&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")
}
fw, ok := filters[0].(*FwFilter)
if !ok {
t.Fatal("Filter is the wrong type")
}
if len(fw.Actions) != 1 {
t.Fatalf("Too few Actions in filter")
}
if fw.ClassId != classId {
t.Fatalf("ClassId of the filter is the wrong value")
}
mia, ok := fw.Actions[0].(*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 mia.MirredAction != TCA_EGRESS_REDIR {
t.Fatal("MirredAction isn't TCA_EGRESS_REDIR")
}
if mia.Ifindex != redir.Attrs().Index {
t.Fatal("Unmatched redirect index")
}
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 TestFilterU32BpfAddDel(t *testing.T) {
t.Skipf("Fd does not match in ci")
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.Fatalf("Action Fd does not match %d != %d", bpfAction.Fd, fd)
}
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 TestFilterU32ConnmarkAddDel(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_ALL,
},
ClassId: classId,
Actions: []Action{
&ConnmarkAction{
ActionAttrs: ActionAttrs{
Action: TC_ACT_PIPE,
},
},
&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
cma, ok := u32.Actions[0].(*ConnmarkAction)
if !ok {
cma, ok = u32.Actions[1].(*ConnmarkAction)
if !ok {
t.Fatal("Unable to find connmark action")
}
}
if cma.Attrs().Action != TC_ACT_PIPE {
t.Fatal("Connmark action isn't TC_ACT_PIPE")
}
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)
}
if len(qdiscs) != 0 {
t.Fatal("Failed to remove qdisc")
}
}
func TestFilterU32CsumAddDel(t *testing.T) {
tearDown := setUpNetlinkTest(t)
defer tearDown()
if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
t.Fatalf("add link foo error: %v", err)
}
link, err := LinkByName("foo")
if err != nil {
t.Fatalf("add link foo error: %v", err)
}
if err := LinkSetUp(link); err != nil {
t.Fatalf("set foo link up error: %v", 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.Fatalf("get qdisc error: %v", err)
}
found := false
for _, v := range qdiscs {
if _, ok := v.(*Ingress); ok {
found = true
break
}
}
if !found {
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_ALL,
},
ClassId: classId,
Actions: []Action{
&CsumAction{
ActionAttrs: ActionAttrs{
Action: TC_ACT_PIPE,
},
UpdateFlags: TCA_CSUM_UPDATE_FLAG_TCP,
},
},
}
if err := FilterAdd(filter); err != nil {
t.Fatal(err)
}
filters, err := FilterList(link, MakeHandle(0xffff, 0))
if err != nil {
t.Fatalf("get filter error: %v", err)
}
if len(filters) != 1 {
t.Fatalf("the count filters error, expect: 1, acutal: %d", len(filters))
}
ft, ok := filters[0].(*U32)
if !ok {
t.Fatal("Filter is the wrong type")
}
if ft.LinkIndex != link.Attrs().Index {
t.Fatal("link index error")
}
if len(ft.Actions) != 1 {
t.Fatalf("filter has wrong number of actions, expect: 1, acutal: %d", len(filters))
}
csum, ok := ft.Actions[0].(*CsumAction)
if !ok {
t.Fatal("action is the wrong type")
}
if csum.Attrs().Action != TC_ACT_PIPE {
t.Fatal("Csum action isn't TC_ACT_PIPE")
}
if csum.UpdateFlags != TCA_CSUM_UPDATE_FLAG_TCP {
t.Fatalf("Csum action isn't TCA_CSUM_UPDATE_FLAG_TCP, got %d", csum.UpdateFlags)
}
if err := FilterDel(ft); 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")
}
}
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)
}
qdisc := &Clsact{
QdiscAttrs: QdiscAttrs{
LinkIndex: link.Attrs().Index,
Handle: MakeHandle(0xffff, 0),
Parent: HANDLE_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].(*Clsact); !ok || q.Type() != "clsact" {
t.Fatal("qdisc is the wrong type")
}
return qdiscs[0], link
}
func TestFilterClsActBpfAddDel(t *testing.T) {
t.Skipf("Fd does not match in ci")
// 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")
}
}
func TestFilterU32TunnelKeyAddDel(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")
}
tunnelAct := NewTunnelKeyAction()
tunnelAct.SrcAddr = net.IPv4(10, 10, 10, 1)
tunnelAct.DstAddr = net.IPv4(10, 10, 10, 2)
tunnelAct.KeyID = 0x01
tunnelAct.Action = TCA_TUNNEL_KEY_SET
tunnelAct.DestPort = 8472
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{
tunnelAct,
&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
tun, ok := u32.Actions[0].(*TunnelKeyAction)
if !ok {
tun, ok = u32.Actions[1].(*TunnelKeyAction)
if !ok {
t.Fatal("Unable to find tunnel action")
}
}
if tun.Attrs().Action != TC_ACT_PIPE {
t.Fatal("TunnelKey action isn't TC_ACT_PIPE")
}
if !tun.SrcAddr.Equal(tunnelAct.SrcAddr) {
t.Fatal("Action SrcAddr doesn't match")
}
if !tun.DstAddr.Equal(tunnelAct.DstAddr) {
t.Fatal("Action DstAddr doesn't match")
}
if tun.KeyID != tunnelAct.KeyID {
t.Fatal("Action KeyID doesn't match")
}
if tun.DestPort != tunnelAct.DestPort {
t.Fatal("Action DestPort doesn't match")
}
if tun.Action != tunnelAct.Action {
t.Fatal("Action 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")
}
}
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
mask := uint32(0xff)
skbedit.Mask = &mask
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.Mask == nil || *edit.Mask != *skbedit.Mask {
t.Fatal("Action Mask 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")
}
}
func TestFilterU32LinkOption(t *testing.T) {
tearDown := setUpNetlinkTest(t)
defer tearDown()
if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
t.Fatalf("add link foo error: %v", err)
}
link, err := LinkByName("foo")
if err != nil {
t.Fatalf("add link foo error: %v", err)
}
if err := LinkSetUp(link); err != nil {
t.Fatalf("set foo link up error: %v", 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.Fatalf("get qdisc error: %v", err)
}
found := false
for _, v := range qdiscs {
if _, ok := v.(*Ingress); ok {
found = true
break
}
}
if !found {
t.Fatal("Qdisc is the wrong type")
}
htid := uint32(10)
size := uint32(8)
priority := uint16(200)
u32Table := &U32{
FilterAttrs: FilterAttrs{
LinkIndex: link.Attrs().Index,
Handle: htid << 20,
Parent: MakeHandle(0xffff, 0),
Priority: priority,
Protocol: unix.ETH_P_ALL,
},
Divisor: size,
}
if err := FilterAdd(u32Table); err != nil {
t.Fatal(err)
}
u32 := &U32{
FilterAttrs: FilterAttrs{
LinkIndex: link.Attrs().Index,
Parent: MakeHandle(0xffff, 0),
Handle: 1,
Priority: priority,
Protocol: unix.ETH_P_ALL,
},
Link: uint32(htid << 20),
Sel: &TcU32Sel{
Nkeys: 1,
Flags: TC_U32_TERMINAL | TC_U32_VAROFFSET,
Hmask: 0x0000ff00,
Hoff: 0,
Offshift: 8,
Keys: []TcU32Key{
{
Mask: 0,
Val: 0,
Off: 0,
},
},
},
}
if err := FilterAdd(u32); err != nil {
t.Fatal(err)
}
filters, err := FilterList(link, MakeHandle(0xffff, 0))
if err != nil {
t.Fatalf("get filter error: %v", err)
}
if len(filters) != 1 {
t.Fatalf("the count filters error, expect: 1, acutal: %d", len(filters))
}
ft, ok := filters[0].(*U32)
if !ok {
t.Fatal("Filter is the wrong type")
}
if ft.LinkIndex != link.Attrs().Index {
t.Fatal("link index error")
}
if ft.Link != htid<<20 {
t.Fatal("hash table id error")
}
if ft.Priority != priority {
t.Fatal("priority error")
}
if err := FilterDel(ft); 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")
}
}
func TestFilterFlowerAddDel(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")
}
testMask := net.CIDRMask(24, 32)
srcMac, err := net.ParseMAC("2C:54:91:88:C9:E3")
if err != nil {
t.Fatal(err)
}
destMac, err := net.ParseMAC("2C:54:91:88:C9:E5")
if err != nil {
t.Fatal(err)
}
ipproto := new(nl.IPProto)
*ipproto = nl.IPPROTO_TCP
filter := &Flower{
FilterAttrs: FilterAttrs{
LinkIndex: link.Attrs().Index,
Parent: MakeHandle(0xffff, 0),
Priority: 1,
Protocol: unix.ETH_P_ALL,
},
DestIP: net.ParseIP("1.0.0.1"),
DestIPMask: testMask,
SrcIP: net.ParseIP("2.0.0.1"),
SrcIPMask: testMask,
EthType: unix.ETH_P_IP,
EncDestIP: net.ParseIP("3.0.0.1"),
EncDestIPMask: testMask,
EncSrcIP: net.ParseIP("4.0.0.1"),
EncSrcIPMask: testMask,
EncDestPort: 8472,
EncKeyId: 1234,
SrcMac: srcMac,
DestMac: destMac,
IPProto: ipproto,
DestPort: 1111,
SrcPort: 1111,
Actions: []Action{
&VlanAction{
ActionAttrs: ActionAttrs{
Action: TC_ACT_PIPE,
},
Action: TCA_VLAN_ACT_PUSH,
VlanID: 1234,
},
&MirredAction{
ActionAttrs: ActionAttrs{
Action: TC_ACT_STOLEN,
},
MirredAction: TCA_EGRESS_REDIR,
Ifindex: redir.Attrs().Index,
},
&GenericAction{
ActionAttrs: ActionAttrs{
Action: getTcActGotoChain(),
},
Chain: 20,
},
},
}
if err := FilterAdd(filter); err != nil {
t.Fatal(err)
}
time.Sleep(time.Second)
filters, err := FilterList(link, MakeHandle(0xffff, 0))
if err != nil {
t.Fatal(err)
}
if len(filters) != 1 {
t.Fatal("Failed to add filter")
}
flower, ok := filters[0].(*Flower)
if !ok {
t.Fatal("Filter is the wrong type")
}
if filter.EthType != flower.EthType {
t.Fatalf("Flower EthType doesn't match")
}
if !filter.DestIP.Equal(flower.DestIP) {
t.Fatalf("Flower DestIP doesn't match")
}
if !filter.SrcIP.Equal(flower.SrcIP) {
t.Fatalf("Flower SrcIP doesn't match")
}
if !reflect.DeepEqual(filter.DestIPMask, testMask) {
t.Fatalf("Flower DestIPMask doesn't match")
}
if !reflect.DeepEqual(filter.SrcIPMask, testMask) {
t.Fatalf("Flower SrcIPMask doesn't match")
}
if !filter.EncDestIP.Equal(flower.EncDestIP) {
t.Fatalf("Flower EncDestIP doesn't match")
}
if !filter.EncSrcIP.Equal(flower.EncSrcIP) {
t.Fatalf("Flower EncSrcIP doesn't match")
}
if !reflect.DeepEqual(filter.EncDestIPMask, testMask) {
t.Fatalf("Flower EncDestIPMask doesn't match")
}
if !reflect.DeepEqual(filter.EncSrcIPMask, testMask) {
t.Fatalf("Flower EncSrcIPMask doesn't match")
}
if filter.EncKeyId != flower.EncKeyId {
t.Fatalf("Flower EncKeyId doesn't match")
}
if filter.EncDestPort != flower.EncDestPort {
t.Fatalf("Flower EncDestPort doesn't match")
}
if flower.IPProto == nil || *filter.IPProto != *flower.IPProto {
t.Fatalf("Flower IPProto doesn't match")
}
if filter.DestPort != flower.DestPort {
t.Fatalf("Flower DestPort doesn't match")
}
if filter.SrcPort != flower.SrcPort {
t.Fatalf("Flower SrcPort doesn't match")
}
if !(filter.SrcMac.String() == flower.SrcMac.String()) {
t.Fatalf("Flower SrcMac doesn't match")
}
if !(filter.DestMac.String() == flower.DestMac.String()) {
t.Fatalf("Flower DestMac doesn't match")
}
vla, ok := flower.Actions[0].(*VlanAction)
if !ok {
t.Fatal("Unable to find vlan action")
}
if vla.Attrs().Action != TC_ACT_PIPE {
t.Fatal("Vlan action isn't TC_ACT_PIPE")
}
if vla.Action != TCA_VLAN_ACT_PUSH {
t.Fatal("Second Vlan action isn't push")
}
if vla.VlanID != 1234 {
t.Fatal("Second Vlan action vlanId isn't correct")
}
mia, ok := flower.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 mia.Timestamp == nil || mia.Timestamp.Installed == 0 {
t.Fatal("Incorrect mirred action timestamp")
}
if mia.Statistics == nil {
t.Fatal("Incorrect mirred action stats")
}
ga, ok := flower.Actions[2].(*GenericAction)
if !ok {
t.Fatal("Unable to find generic action")
}
if ga.Attrs().Action != getTcActGotoChain() {
t.Fatal("Generic action isn't TC_ACT_GOTO_CHAIN")
}
if ga.Timestamp == nil || ga.Timestamp.Installed == 0 {
t.Fatal("Incorrect generic action timestamp")
}
if ga.Statistics == nil {
t.Fatal("Incorrect generic action stats")
}
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")
}
filter = &Flower{
FilterAttrs: FilterAttrs{
LinkIndex: link.Attrs().Index,
Parent: MakeHandle(0xffff, 0),
Priority: 1,
Protocol: unix.ETH_P_8021Q,
},
EthType: unix.ETH_P_8021Q,
VlanId: 2046,
Actions: []Action{
&VlanAction{
ActionAttrs: ActionAttrs{
Action: TC_ACT_PIPE,
},
Action: TCA_VLAN_ACT_POP,
},
&MirredAction{
ActionAttrs: ActionAttrs{
Action: TC_ACT_STOLEN,
},
MirredAction: TCA_EGRESS_REDIR,
Ifindex: redir.Attrs().Index,
},
},
}
if err := FilterAdd(filter); err != nil {
t.Fatal(err)
}
time.Sleep(time.Second)
filters, err = FilterList(link, MakeHandle(0xffff, 0))
if err != nil {
t.Fatal(err)
}
if len(filters) != 1 {
t.Fatal("Failed to add filter")
}
flower, ok = filters[0].(*Flower)
if !ok {
t.Fatal("Filter is the wrong type")
}
if filter.VlanId != flower.VlanId {
t.Fatalf("Flower VlanId doesn't match")
}
vla, ok = flower.Actions[0].(*VlanAction)
if !ok {
t.Fatal("Unable to find vlan action")
}
if vla.Attrs().Action != TC_ACT_PIPE {
t.Fatal("Vlan action isn't TC_ACT_PIPE")
}
if vla.Action != TCA_VLAN_ACT_POP {
t.Fatal("First Vlan action isn't pop")
}
mia, ok = flower.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 mia.Timestamp == nil || mia.Timestamp.Installed == 0 {
t.Fatal("Incorrect mirred action timestamp")
}
if mia.Statistics == nil {
t.Fatal("Incorrect mirred action stats")
}
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")
}
}
func TestFilterIPv6FlowerPedit(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")
}
testMask := net.CIDRMask(64, 128)
ipproto := new(nl.IPProto)
*ipproto = nl.IPPROTO_TCP
filter := &Flower{
FilterAttrs: FilterAttrs{
LinkIndex: link.Attrs().Index,
Parent: MakeHandle(0xffff, 0),
Priority: 1,
Protocol: unix.ETH_P_ALL,
},
DestIP: net.ParseIP("ffff::fff1"),
DestIPMask: testMask,
EthType: unix.ETH_P_IPV6,
IPProto: ipproto,
DestPort: 6666,
Actions: []Action{},
}
peditAction := NewPeditAction()
peditAction.Proto = uint8(nl.IPPROTO_TCP)
peditAction.SrcPort = 7777
peditAction.SrcIP = net.ParseIP("ffff::fff2")
filter.Actions = append(filter.Actions, peditAction)
miaAction := &MirredAction{
ActionAttrs: ActionAttrs{
Action: TC_ACT_REDIRECT,
},
MirredAction: TCA_EGRESS_REDIR,
Ifindex: redir.Attrs().Index,
}
filter.Actions = append(filter.Actions, miaAction)
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")
}
flower, ok := filters[0].(*Flower)
if !ok {
t.Fatal("Filter is the wrong type")
}
if filter.EthType != flower.EthType {
t.Fatalf("Flower EthType doesn't match")
}
if !filter.DestIP.Equal(flower.DestIP) {
t.Fatalf("Flower DestIP doesn't match")
}
if !reflect.DeepEqual(filter.DestIPMask, testMask) {
t.Fatalf("Flower DestIPMask doesn't match")
}
if flower.IPProto == nil || *filter.IPProto != *flower.IPProto {
t.Fatalf("Flower IPProto doesn't match")
}
if filter.DestPort != flower.DestPort {
t.Fatalf("Flower DestPort doesn't match")
}
_, ok = flower.Actions[0].(*PeditAction)
if !ok {
t.Fatal("Unable to find pedit action")
}
_, ok = flower.Actions[1].(*MirredAction)
if !ok {
t.Fatal("Unable to find mirred action")
}
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")
}
}
func TestFilterU32PoliceAddDel(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")
}
const (
policeRate = 0x40000000 // 1 Gbps
policeBurst = 0x19000 // 100 KB
policePeakRate = 0x4000 // 16 Kbps
)
police := NewPoliceAction()
police.Rate = policeRate
police.PeakRate = policePeakRate
police.Burst = policeBurst
police.ExceedAction = TC_POLICE_SHOT
police.NotExceedAction = TC_POLICE_UNSPEC
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{
police,
&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
p, ok := u32.Actions[0].(*PoliceAction)
if !ok {
p, ok = u32.Actions[1].(*PoliceAction)
if !ok {
t.Fatal("Unable to find police action")
}
}
if p.ExceedAction != TC_POLICE_SHOT {
t.Fatal("Police ExceedAction isn't TC_POLICE_SHOT")
}
if p.NotExceedAction != TC_POLICE_UNSPEC {
t.Fatal("Police NotExceedAction isn't TC_POLICE_UNSPEC")
}
if p.Rate != policeRate {
t.Fatal("Action Rate doesn't match")
}
if p.PeakRate != policePeakRate {
t.Fatal("Action PeakRate doesn't match")
}
if p.LinkLayer != nl.LINKLAYER_ETHERNET {
t.Fatal("Action LinkLayer 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")
}
}
func TestFilterU32DirectPoliceAddDel(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)
}
qdisc := &Ingress{
QdiscAttrs: QdiscAttrs{
LinkIndex: link.Attrs().Index,
Handle: MakeHandle(0xffff, 0),
Parent: HANDLE_INGRESS,
},
}
if err := QdiscAdd(qdisc); err != nil {
t.Fatal(err)
}
const (
policeRate = 0x40000000 // 1 Gbps
policeBurst = 0x19000 // 100 KB
policePeakRate = 0x4000 // 16 Kbps
)
police := NewPoliceAction()
police.Rate = policeRate
police.PeakRate = policePeakRate
police.Burst = policeBurst
police.ExceedAction = TC_POLICE_SHOT
police.NotExceedAction = TC_POLICE_UNSPEC
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,
Police: police,
}
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.Police == nil {
t.Fatalf("No police in filter")
}
if u32.Police.Rate != policeRate {
t.Fatal("Filter Rate doesn't match")
}
if u32.Police.PeakRate != policePeakRate {
t.Fatal("Filter PeakRate doesn't match")
}
if u32.Police.LinkLayer != nl.LINKLAYER_ETHERNET {
t.Fatal("Filter LinkLayer doesn't match")
}
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")
}
}
func TestFilterChainAddDel(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)
chainVal := new(uint32)
*chainVal = 20
filter := &U32{
FilterAttrs: FilterAttrs{
LinkIndex: link.Attrs().Index,
Parent: MakeHandle(0xffff, 0),
Priority: 1,
Protocol: unix.ETH_P_IP,
Chain: chainVal,
},
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")
}
filterChain := filters[0].Attrs().Chain
if filterChain != nil && *filterChain != *chainVal {
t.Fatalf("Chain 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")
}
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/mirrors/netlink.git
[email protected]:mirrors/netlink.git
mirrors
netlink
netlink
main

搜索帮助