github.com/vishvananda/netlink@v1.3.0/filter_test.go (about)

     1  //go:build linux
     2  // +build linux
     3  
     4  package netlink
     5  
     6  import (
     7  	"net"
     8  	"reflect"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/vishvananda/netlink/nl"
    13  	"golang.org/x/sys/unix"
    14  )
    15  
    16  func TestFilterAddDel(t *testing.T) {
    17  	tearDown := setUpNetlinkTest(t)
    18  	defer tearDown()
    19  	if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
    20  		t.Fatal(err)
    21  	}
    22  	if err := LinkAdd(&Ifb{LinkAttrs{Name: "bar"}}); err != nil {
    23  		t.Fatal(err)
    24  	}
    25  	link, err := LinkByName("foo")
    26  	if err != nil {
    27  		t.Fatal(err)
    28  	}
    29  	if err := LinkSetUp(link); err != nil {
    30  		t.Fatal(err)
    31  	}
    32  	redir, err := LinkByName("bar")
    33  	if err != nil {
    34  		t.Fatal(err)
    35  	}
    36  	if err := LinkSetUp(redir); err != nil {
    37  		t.Fatal(err)
    38  	}
    39  	qdisc := &Ingress{
    40  		QdiscAttrs: QdiscAttrs{
    41  			LinkIndex: link.Attrs().Index,
    42  			Handle:    MakeHandle(0xffff, 0),
    43  			Parent:    HANDLE_INGRESS,
    44  		},
    45  	}
    46  	if err := QdiscAdd(qdisc); err != nil {
    47  		t.Fatal(err)
    48  	}
    49  	qdiscs, err := SafeQdiscList(link)
    50  	if err != nil {
    51  		t.Fatal(err)
    52  	}
    53  	if len(qdiscs) != 1 {
    54  		t.Fatal("Failed to add qdisc")
    55  	}
    56  	_, ok := qdiscs[0].(*Ingress)
    57  	if !ok {
    58  		t.Fatal("Qdisc is the wrong type")
    59  	}
    60  	classId := MakeHandle(1, 1)
    61  	filter := &U32{
    62  		FilterAttrs: FilterAttrs{
    63  			LinkIndex: link.Attrs().Index,
    64  			Parent:    MakeHandle(0xffff, 0),
    65  			Priority:  1,
    66  			Protocol:  unix.ETH_P_IP,
    67  		},
    68  		RedirIndex: redir.Attrs().Index,
    69  		ClassId:    classId,
    70  	}
    71  	if err := FilterAdd(filter); err != nil {
    72  		t.Fatal(err)
    73  	}
    74  	filters, err := FilterList(link, MakeHandle(0xffff, 0))
    75  	if err != nil {
    76  		t.Fatal(err)
    77  	}
    78  	if len(filters) != 1 {
    79  		t.Fatal("Failed to add filter")
    80  	}
    81  	u32, ok := filters[0].(*U32)
    82  	if !ok {
    83  		t.Fatal("Filter is the wrong type")
    84  	}
    85  	if u32.ClassId != classId {
    86  		t.Fatalf("ClassId of the filter is the wrong value")
    87  	}
    88  	if err := FilterDel(filter); err != nil {
    89  		t.Fatal(err)
    90  	}
    91  	filters, err = FilterList(link, MakeHandle(0xffff, 0))
    92  	if err != nil {
    93  		t.Fatal(err)
    94  	}
    95  	if len(filters) != 0 {
    96  		t.Fatal("Failed to remove filter")
    97  	}
    98  	if err := QdiscDel(qdisc); err != nil {
    99  		t.Fatal(err)
   100  	}
   101  	qdiscs, err = SafeQdiscList(link)
   102  	if err != nil {
   103  		t.Fatal(err)
   104  	}
   105  	if len(qdiscs) != 0 {
   106  		t.Fatal("Failed to remove qdisc")
   107  	}
   108  }
   109  
   110  func TestFilterReplace(t *testing.T) {
   111  	tearDown := setUpNetlinkTest(t)
   112  	defer tearDown()
   113  	if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
   114  		t.Fatal(err)
   115  	}
   116  	if err := LinkAdd(&Ifb{LinkAttrs{Name: "bar"}}); err != nil {
   117  		t.Fatal(err)
   118  	}
   119  	link, err := LinkByName("foo")
   120  	if err != nil {
   121  		t.Fatal(err)
   122  	}
   123  	if err := LinkSetUp(link); err != nil {
   124  		t.Fatal(err)
   125  	}
   126  	redir, err := LinkByName("bar")
   127  	if err != nil {
   128  		t.Fatal(err)
   129  	}
   130  	if err := LinkSetUp(redir); err != nil {
   131  		t.Fatal(err)
   132  	}
   133  	qdisc := &Ingress{
   134  		QdiscAttrs: QdiscAttrs{
   135  			LinkIndex: link.Attrs().Index,
   136  			Handle:    MakeHandle(0xffff, 0),
   137  			Parent:    HANDLE_INGRESS,
   138  		},
   139  	}
   140  	if err := QdiscAdd(qdisc); err != nil {
   141  		t.Fatal(err)
   142  	}
   143  
   144  	filter := &U32{
   145  		FilterAttrs: FilterAttrs{
   146  			LinkIndex: link.Attrs().Index,
   147  			Parent:    MakeHandle(0xffff, 0),
   148  			Priority:  1,
   149  			Protocol:  unix.ETH_P_IP,
   150  		},
   151  		RedirIndex: redir.Attrs().Index,
   152  		ClassId:    MakeHandle(1, 1),
   153  	}
   154  
   155  	if err := FilterReplace(filter); err != nil {
   156  		t.Fatal(err)
   157  	}
   158  	filters, err := FilterList(link, MakeHandle(0xffff, 0))
   159  	if err != nil {
   160  		t.Fatal(err)
   161  	}
   162  	if len(filters) != 1 {
   163  		t.Fatal("Failed replace filter")
   164  	}
   165  
   166  	if err := FilterReplace(filter); err != nil {
   167  		t.Fatal(err)
   168  	}
   169  }
   170  
   171  func TestAdvancedFilterAddDel(t *testing.T) {
   172  	tearDown := setUpNetlinkTest(t)
   173  	defer tearDown()
   174  	if err := LinkAdd(&Ifb{LinkAttrs{Name: "baz"}}); err != nil {
   175  		t.Fatal(err)
   176  	}
   177  	link, err := LinkByName("baz")
   178  	if err != nil {
   179  		t.Fatal(err)
   180  	}
   181  	if err := LinkSetUp(link); err != nil {
   182  		t.Fatal(err)
   183  	}
   184  	index := link.Attrs().Index
   185  
   186  	qdiscHandle := MakeHandle(0x1, 0x0)
   187  	qdiscAttrs := QdiscAttrs{
   188  		LinkIndex: index,
   189  		Handle:    qdiscHandle,
   190  		Parent:    HANDLE_ROOT,
   191  	}
   192  
   193  	qdisc := NewHtb(qdiscAttrs)
   194  	if err := QdiscAdd(qdisc); err != nil {
   195  		t.Fatal(err)
   196  	}
   197  	qdiscs, err := SafeQdiscList(link)
   198  	if err != nil {
   199  		t.Fatal(err)
   200  	}
   201  	if len(qdiscs) != 1 {
   202  		t.Fatal("Failed to add qdisc")
   203  	}
   204  	_, ok := qdiscs[0].(*Htb)
   205  	if !ok {
   206  		t.Fatal("Qdisc is the wrong type")
   207  	}
   208  
   209  	classId := MakeHandle(0x1, 0x46cb)
   210  	classAttrs := ClassAttrs{
   211  		LinkIndex: index,
   212  		Parent:    qdiscHandle,
   213  		Handle:    classId,
   214  	}
   215  	htbClassAttrs := HtbClassAttrs{
   216  		Rate:   512 * 1024,
   217  		Buffer: 32 * 1024,
   218  	}
   219  	htbClass := NewHtbClass(classAttrs, htbClassAttrs)
   220  	if err = ClassReplace(htbClass); err != nil {
   221  		t.Fatalf("Failed to add a HTB class: %v", err)
   222  	}
   223  	classes, err := SafeClassList(link, qdiscHandle)
   224  	if err != nil {
   225  		t.Fatal(err)
   226  	}
   227  	if len(classes) != 1 {
   228  		t.Fatal("Failed to add class")
   229  	}
   230  	_, ok = classes[0].(*HtbClass)
   231  	if !ok {
   232  		t.Fatal("Class is the wrong type")
   233  	}
   234  
   235  	htid := MakeHandle(0x0010, 0000)
   236  	divisor := uint32(1)
   237  	hashTable := &U32{
   238  		FilterAttrs: FilterAttrs{
   239  			LinkIndex: index,
   240  			Handle:    htid,
   241  			Parent:    qdiscHandle,
   242  			Priority:  1,
   243  			Protocol:  unix.ETH_P_ALL,
   244  		},
   245  		Divisor: divisor,
   246  	}
   247  	cHashTable := *hashTable
   248  	if err := FilterAdd(hashTable); err != nil {
   249  		t.Fatal(err)
   250  	}
   251  	// Check if the hash table is identical before and after FilterAdd.
   252  	if !reflect.DeepEqual(cHashTable, *hashTable) {
   253  		t.Fatalf("Hash table %v and %v are not equal", cHashTable, *hashTable)
   254  	}
   255  
   256  	u32SelKeys := []TcU32Key{
   257  		{
   258  			Mask:    0xff,
   259  			Val:     80,
   260  			Off:     20,
   261  			OffMask: 0,
   262  		},
   263  		{
   264  			Mask:    0xffff,
   265  			Val:     0x146ca,
   266  			Off:     32,
   267  			OffMask: 0,
   268  		},
   269  	}
   270  
   271  	handle := MakeHandle(0x0000, 0001)
   272  	filter := &U32{
   273  		FilterAttrs: FilterAttrs{
   274  			LinkIndex: index,
   275  			Handle:    handle,
   276  			Parent:    qdiscHandle,
   277  			Priority:  1,
   278  			Protocol:  unix.ETH_P_ALL,
   279  		},
   280  		Sel: &TcU32Sel{
   281  			Keys:  u32SelKeys,
   282  			Flags: TC_U32_TERMINAL,
   283  		},
   284  		ClassId: classId,
   285  		Hash:    htid,
   286  		Actions: []Action{},
   287  	}
   288  	// Copy filter.
   289  	cFilter := *filter
   290  	if err := FilterAdd(filter); err != nil {
   291  		t.Fatal(err)
   292  	}
   293  	// Check if the filter is identical before and after FilterAdd.
   294  	if !reflect.DeepEqual(cFilter, *filter) {
   295  		t.Fatalf("U32 %v and %v are not equal", cFilter, *filter)
   296  	}
   297  
   298  	filters, err := FilterList(link, qdiscHandle)
   299  	if err != nil {
   300  		t.Fatal(err)
   301  	}
   302  	if len(filters) != 1 {
   303  		t.Fatal("Failed to add filter")
   304  	}
   305  
   306  	u32, ok := filters[0].(*U32)
   307  	if !ok {
   308  		t.Fatal("Filter is the wrong type")
   309  	}
   310  	// Endianness checks
   311  	if u32.Sel.Offmask != filter.Sel.Offmask {
   312  		t.Fatal("The endianness of TcU32Key.Sel.Offmask is wrong")
   313  	}
   314  	if u32.Sel.Hmask != filter.Sel.Hmask {
   315  		t.Fatal("The endianness of TcU32Key.Sel.Hmask is wrong")
   316  	}
   317  	for i, key := range u32.Sel.Keys {
   318  		if key.Mask != filter.Sel.Keys[i].Mask {
   319  			t.Fatal("The endianness of TcU32Key.Mask is wrong")
   320  		}
   321  		if key.Val != filter.Sel.Keys[i].Val {
   322  			t.Fatal("The endianness of TcU32Key.Val is wrong")
   323  		}
   324  	}
   325  	if u32.Handle != (handle | htid) {
   326  		t.Fatalf("The handle is wrong. expected %v but actually %v",
   327  			(handle | htid), u32.Handle)
   328  	}
   329  	if u32.Hash != htid {
   330  		t.Fatal("The hash table ID is wrong")
   331  	}
   332  
   333  	if err := FilterDel(u32); err != nil {
   334  		t.Fatal(err)
   335  	}
   336  	filters, err = FilterList(link, qdiscHandle)
   337  	if err != nil {
   338  		t.Fatal(err)
   339  	}
   340  	if len(filters) != 0 {
   341  		t.Fatal("Failed to remove filter")
   342  	}
   343  
   344  	if err = ClassDel(htbClass); err != nil {
   345  		t.Fatalf("Failed to delete a HTP class: %v", err)
   346  	}
   347  	classes, err = SafeClassList(link, qdiscHandle)
   348  	if err != nil {
   349  		t.Fatal(err)
   350  	}
   351  	if len(classes) != 0 {
   352  		t.Fatal("Failed to remove class")
   353  	}
   354  
   355  	if err := QdiscDel(qdisc); err != nil {
   356  		t.Fatal(err)
   357  	}
   358  	qdiscs, err = SafeQdiscList(link)
   359  	if err != nil {
   360  		t.Fatal(err)
   361  	}
   362  	if len(qdiscs) != 0 {
   363  		t.Fatal("Failed to remove qdisc")
   364  	}
   365  }
   366  
   367  func TestFilterFwAddDel(t *testing.T) {
   368  	tearDown := setUpNetlinkTest(t)
   369  	defer tearDown()
   370  	if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
   371  		t.Fatal(err)
   372  	}
   373  	if err := LinkAdd(&Ifb{LinkAttrs{Name: "bar"}}); err != nil {
   374  		t.Fatal(err)
   375  	}
   376  	link, err := LinkByName("foo")
   377  	if err != nil {
   378  		t.Fatal(err)
   379  	}
   380  	if err := LinkSetUp(link); err != nil {
   381  		t.Fatal(err)
   382  	}
   383  	redir, err := LinkByName("bar")
   384  	if err != nil {
   385  		t.Fatal(err)
   386  	}
   387  	if err := LinkSetUp(redir); err != nil {
   388  		t.Fatal(err)
   389  	}
   390  	attrs := QdiscAttrs{
   391  		LinkIndex: link.Attrs().Index,
   392  		Handle:    MakeHandle(0xffff, 0),
   393  		Parent:    HANDLE_ROOT,
   394  	}
   395  	qdisc := NewHtb(attrs)
   396  	if err := QdiscAdd(qdisc); err != nil {
   397  		t.Fatal(err)
   398  	}
   399  	qdiscs, err := SafeQdiscList(link)
   400  	if err != nil {
   401  		t.Fatal(err)
   402  	}
   403  	if len(qdiscs) != 1 {
   404  		t.Fatal("Failed to add qdisc")
   405  	}
   406  	_, ok := qdiscs[0].(*Htb)
   407  	if !ok {
   408  		t.Fatal("Qdisc is the wrong type")
   409  	}
   410  
   411  	classattrs := ClassAttrs{
   412  		LinkIndex: link.Attrs().Index,
   413  		Parent:    MakeHandle(0xffff, 0),
   414  		Handle:    MakeHandle(0xffff, 2),
   415  	}
   416  
   417  	htbclassattrs := HtbClassAttrs{
   418  		Rate:    1234000,
   419  		Cbuffer: 1690,
   420  	}
   421  	class := NewHtbClass(classattrs, htbclassattrs)
   422  	if err := ClassAdd(class); err != nil {
   423  		t.Fatal(err)
   424  	}
   425  	classes, err := SafeClassList(link, MakeHandle(0xffff, 2))
   426  	if err != nil {
   427  		t.Fatal(err)
   428  	}
   429  	if len(classes) != 1 {
   430  		t.Fatal("Failed to add class")
   431  	}
   432  
   433  	police := NewPoliceAction()
   434  	police.Burst = 12345
   435  	police.Rate = 1234
   436  	police.PeakRate = 2345
   437  	police.Action = TcAct(TC_POLICE_SHOT)
   438  
   439  	filterattrs := FilterAttrs{
   440  		LinkIndex: link.Attrs().Index,
   441  		Parent:    MakeHandle(0xffff, 0),
   442  		Handle:    MakeHandle(0, 0x6),
   443  		Priority:  1,
   444  		Protocol:  unix.ETH_P_IP,
   445  	}
   446  
   447  	filter := FwFilter{
   448  		FilterAttrs: filterattrs,
   449  		ClassId:     MakeHandle(0xffff, 2),
   450  		Police:      police,
   451  	}
   452  
   453  	if err := FilterAdd(&filter); err != nil {
   454  		t.Fatal(err)
   455  	}
   456  
   457  	filters, err := FilterList(link, MakeHandle(0xffff, 0))
   458  	if err != nil {
   459  		t.Fatal(err)
   460  	}
   461  	if len(filters) != 1 {
   462  		t.Fatal("Failed to add filter")
   463  	}
   464  	fw, ok := filters[0].(*FwFilter)
   465  	if !ok {
   466  		t.Fatal("Filter is the wrong type")
   467  	}
   468  	if fw.Police.Rate != filter.Police.Rate {
   469  		t.Fatal("Police Rate doesn't match")
   470  	}
   471  	if fw.ClassId != filter.ClassId {
   472  		t.Fatal("ClassId doesn't match")
   473  	}
   474  	if fw.InDev != filter.InDev {
   475  		t.Fatal("InDev doesn't match")
   476  	}
   477  	if fw.Police.AvRate != filter.Police.AvRate {
   478  		t.Fatal("AvRate doesn't match")
   479  	}
   480  
   481  	if err := FilterDel(&filter); err != nil {
   482  		t.Fatal(err)
   483  	}
   484  	filters, err = FilterList(link, MakeHandle(0xffff, 0))
   485  	if err != nil {
   486  		t.Fatal(err)
   487  	}
   488  	if len(filters) != 0 {
   489  		t.Fatal("Failed to remove filter")
   490  	}
   491  	if err := ClassDel(class); err != nil {
   492  		t.Fatal(err)
   493  	}
   494  	classes, err = SafeClassList(link, MakeHandle(0xffff, 0))
   495  	if err != nil {
   496  		t.Fatal(err)
   497  	}
   498  	if len(classes) != 0 {
   499  		t.Fatal("Failed to remove class")
   500  	}
   501  
   502  	if err := QdiscDel(qdisc); err != nil {
   503  		t.Fatal(err)
   504  	}
   505  	qdiscs, err = SafeQdiscList(link)
   506  	if err != nil {
   507  		t.Fatal(err)
   508  	}
   509  	if len(qdiscs) != 0 {
   510  		t.Fatal("Failed to remove qdisc")
   511  	}
   512  }
   513  
   514  func TestFilterFwActAddDel(t *testing.T) {
   515  	tearDown := setUpNetlinkTest(t)
   516  	defer tearDown()
   517  	if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
   518  		t.Fatal(err)
   519  	}
   520  	if err := LinkAdd(&Ifb{LinkAttrs{Name: "bar"}}); err != nil {
   521  		t.Fatal(err)
   522  	}
   523  	link, err := LinkByName("foo")
   524  	if err != nil {
   525  		t.Fatal(err)
   526  	}
   527  	if err := LinkSetUp(link); err != nil {
   528  		t.Fatal(err)
   529  	}
   530  	redir, err := LinkByName("bar")
   531  	if err != nil {
   532  		t.Fatal(err)
   533  	}
   534  	if err := LinkSetUp(redir); err != nil {
   535  		t.Fatal(err)
   536  	}
   537  	qdisc := &Ingress{
   538  		QdiscAttrs: QdiscAttrs{
   539  			LinkIndex: link.Attrs().Index,
   540  			Handle:    MakeHandle(0xffff, 0),
   541  			Parent:    HANDLE_INGRESS,
   542  		},
   543  	}
   544  	if err := QdiscAdd(qdisc); err != nil {
   545  		t.Fatal(err)
   546  	}
   547  	qdiscs, err := SafeQdiscList(link)
   548  	if err != nil {
   549  		t.Fatal(err)
   550  	}
   551  	if len(qdiscs) != 1 {
   552  		t.Fatal("Failed to add qdisc")
   553  	}
   554  	_, ok := qdiscs[0].(*Ingress)
   555  	if !ok {
   556  		t.Fatal("Qdisc is the wrong type")
   557  	}
   558  
   559  	classId := MakeHandle(1, 1)
   560  	filter := &FwFilter{
   561  		FilterAttrs: FilterAttrs{
   562  			LinkIndex: link.Attrs().Index,
   563  			Parent:    MakeHandle(0xffff, 0),
   564  			Priority:  1,
   565  			Protocol:  unix.ETH_P_ALL,
   566  			Handle:    MakeHandle(0, 0x6),
   567  		},
   568  		ClassId: classId,
   569  		Actions: []Action{
   570  			&MirredAction{
   571  				ActionAttrs: ActionAttrs{
   572  					Action: TC_ACT_STOLEN,
   573  				},
   574  				MirredAction: TCA_EGRESS_REDIR,
   575  				Ifindex:      redir.Attrs().Index,
   576  			},
   577  		},
   578  	}
   579  
   580  	if err := FilterAdd(filter); err != nil {
   581  		t.Fatal(err)
   582  	}
   583  
   584  	filters, err := FilterList(link, MakeHandle(0xffff, 0))
   585  	if err != nil {
   586  		t.Fatal(err)
   587  	}
   588  	if len(filters) != 1 {
   589  		t.Fatal("Failed to add filter")
   590  	}
   591  	fw, ok := filters[0].(*FwFilter)
   592  	if !ok {
   593  		t.Fatal("Filter is the wrong type")
   594  	}
   595  
   596  	if len(fw.Actions) != 1 {
   597  		t.Fatalf("Too few Actions in filter")
   598  	}
   599  	if fw.ClassId != classId {
   600  		t.Fatalf("ClassId of the filter is the wrong value")
   601  	}
   602  
   603  	mia, ok := fw.Actions[0].(*MirredAction)
   604  	if !ok {
   605  		t.Fatal("Unable to find mirred action")
   606  	}
   607  
   608  	if mia.Attrs().Action != TC_ACT_STOLEN {
   609  		t.Fatal("Mirred action isn't TC_ACT_STOLEN")
   610  	}
   611  
   612  	if mia.MirredAction != TCA_EGRESS_REDIR {
   613  		t.Fatal("MirredAction isn't TCA_EGRESS_REDIR")
   614  	}
   615  
   616  	if mia.Ifindex != redir.Attrs().Index {
   617  		t.Fatal("Unmatched redirect index")
   618  	}
   619  
   620  	if err := FilterDel(filter); err != nil {
   621  		t.Fatal(err)
   622  	}
   623  	filters, err = FilterList(link, MakeHandle(0xffff, 0))
   624  	if err != nil {
   625  		t.Fatal(err)
   626  	}
   627  	if len(filters) != 0 {
   628  		t.Fatal("Failed to remove filter")
   629  	}
   630  
   631  	if err := QdiscDel(qdisc); err != nil {
   632  		t.Fatal(err)
   633  	}
   634  	qdiscs, err = SafeQdiscList(link)
   635  	if err != nil {
   636  		t.Fatal(err)
   637  	}
   638  	if len(qdiscs) != 0 {
   639  		t.Fatal("Failed to remove qdisc")
   640  	}
   641  }
   642  
   643  func TestFilterU32BpfAddDel(t *testing.T) {
   644  	t.Skipf("Fd does not match in ci")
   645  	tearDown := setUpNetlinkTest(t)
   646  	defer tearDown()
   647  	if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
   648  		t.Fatal(err)
   649  	}
   650  	if err := LinkAdd(&Ifb{LinkAttrs{Name: "bar"}}); err != nil {
   651  		t.Fatal(err)
   652  	}
   653  	link, err := LinkByName("foo")
   654  	if err != nil {
   655  		t.Fatal(err)
   656  	}
   657  	if err := LinkSetUp(link); err != nil {
   658  		t.Fatal(err)
   659  	}
   660  	redir, err := LinkByName("bar")
   661  	if err != nil {
   662  		t.Fatal(err)
   663  	}
   664  	if err := LinkSetUp(redir); err != nil {
   665  		t.Fatal(err)
   666  	}
   667  	qdisc := &Ingress{
   668  		QdiscAttrs: QdiscAttrs{
   669  			LinkIndex: link.Attrs().Index,
   670  			Handle:    MakeHandle(0xffff, 0),
   671  			Parent:    HANDLE_INGRESS,
   672  		},
   673  	}
   674  	if err := QdiscAdd(qdisc); err != nil {
   675  		t.Fatal(err)
   676  	}
   677  	qdiscs, err := SafeQdiscList(link)
   678  	if err != nil {
   679  		t.Fatal(err)
   680  	}
   681  	if len(qdiscs) != 1 {
   682  		t.Fatal("Failed to add qdisc")
   683  	}
   684  	_, ok := qdiscs[0].(*Ingress)
   685  	if !ok {
   686  		t.Fatal("Qdisc is the wrong type")
   687  	}
   688  
   689  	fd, err := loadSimpleBpf(BPF_PROG_TYPE_SCHED_ACT, 1)
   690  	if err != nil {
   691  		t.Skipf("Loading bpf program failed: %s", err)
   692  	}
   693  	classId := MakeHandle(1, 1)
   694  	filter := &U32{
   695  		FilterAttrs: FilterAttrs{
   696  			LinkIndex: link.Attrs().Index,
   697  			Parent:    MakeHandle(0xffff, 0),
   698  			Priority:  1,
   699  			Protocol:  unix.ETH_P_ALL,
   700  		},
   701  		ClassId: classId,
   702  		Actions: []Action{
   703  			&BpfAction{Fd: fd, Name: "simple"},
   704  			&MirredAction{
   705  				ActionAttrs: ActionAttrs{
   706  					Action: TC_ACT_STOLEN,
   707  				},
   708  				MirredAction: TCA_EGRESS_REDIR,
   709  				Ifindex:      redir.Attrs().Index,
   710  			},
   711  		},
   712  	}
   713  
   714  	if err := FilterAdd(filter); err != nil {
   715  		t.Fatal(err)
   716  	}
   717  
   718  	filters, err := FilterList(link, MakeHandle(0xffff, 0))
   719  	if err != nil {
   720  		t.Fatal(err)
   721  	}
   722  	if len(filters) != 1 {
   723  		t.Fatal("Failed to add filter")
   724  	}
   725  	u32, ok := filters[0].(*U32)
   726  	if !ok {
   727  		t.Fatal("Filter is the wrong type")
   728  	}
   729  
   730  	if len(u32.Actions) != 2 {
   731  		t.Fatalf("Too few Actions in filter")
   732  	}
   733  	if u32.ClassId != classId {
   734  		t.Fatalf("ClassId of the filter is the wrong value")
   735  	}
   736  
   737  	// actions can be returned in reverse order
   738  	bpfAction, ok := u32.Actions[0].(*BpfAction)
   739  	if !ok {
   740  		bpfAction, ok = u32.Actions[1].(*BpfAction)
   741  		if !ok {
   742  			t.Fatal("Action is the wrong type")
   743  		}
   744  	}
   745  	if bpfAction.Fd != fd {
   746  		t.Fatalf("Action Fd does not match %d != %d", bpfAction.Fd, fd)
   747  	}
   748  	if _, ok := u32.Actions[0].(*MirredAction); !ok {
   749  		if _, ok := u32.Actions[1].(*MirredAction); !ok {
   750  			t.Fatal("Action is the wrong type")
   751  		}
   752  	}
   753  
   754  	if err := FilterDel(filter); err != nil {
   755  		t.Fatal(err)
   756  	}
   757  	filters, err = FilterList(link, MakeHandle(0xffff, 0))
   758  	if err != nil {
   759  		t.Fatal(err)
   760  	}
   761  	if len(filters) != 0 {
   762  		t.Fatal("Failed to remove filter")
   763  	}
   764  
   765  	if err := QdiscDel(qdisc); err != nil {
   766  		t.Fatal(err)
   767  	}
   768  	qdiscs, err = SafeQdiscList(link)
   769  	if err != nil {
   770  		t.Fatal(err)
   771  	}
   772  	if len(qdiscs) != 0 {
   773  		t.Fatal("Failed to remove qdisc")
   774  	}
   775  }
   776  
   777  func TestFilterU32ConnmarkAddDel(t *testing.T) {
   778  	tearDown := setUpNetlinkTest(t)
   779  	defer tearDown()
   780  	if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
   781  		t.Fatal(err)
   782  	}
   783  	if err := LinkAdd(&Ifb{LinkAttrs{Name: "bar"}}); err != nil {
   784  		t.Fatal(err)
   785  	}
   786  	link, err := LinkByName("foo")
   787  	if err != nil {
   788  		t.Fatal(err)
   789  	}
   790  	if err := LinkSetUp(link); err != nil {
   791  		t.Fatal(err)
   792  	}
   793  	redir, err := LinkByName("bar")
   794  	if err != nil {
   795  		t.Fatal(err)
   796  	}
   797  	if err := LinkSetUp(redir); err != nil {
   798  		t.Fatal(err)
   799  	}
   800  	qdisc := &Ingress{
   801  		QdiscAttrs: QdiscAttrs{
   802  			LinkIndex: link.Attrs().Index,
   803  			Handle:    MakeHandle(0xffff, 0),
   804  			Parent:    HANDLE_INGRESS,
   805  		},
   806  	}
   807  	if err := QdiscAdd(qdisc); err != nil {
   808  		t.Fatal(err)
   809  	}
   810  	qdiscs, err := SafeQdiscList(link)
   811  	if err != nil {
   812  		t.Fatal(err)
   813  	}
   814  	if len(qdiscs) != 1 {
   815  		t.Fatal("Failed to add qdisc")
   816  	}
   817  	_, ok := qdiscs[0].(*Ingress)
   818  	if !ok {
   819  		t.Fatal("Qdisc is the wrong type")
   820  	}
   821  
   822  	classId := MakeHandle(1, 1)
   823  	filter := &U32{
   824  		FilterAttrs: FilterAttrs{
   825  			LinkIndex: link.Attrs().Index,
   826  			Parent:    MakeHandle(0xffff, 0),
   827  			Priority:  1,
   828  			Protocol:  unix.ETH_P_ALL,
   829  		},
   830  		ClassId: classId,
   831  		Actions: []Action{
   832  			&ConnmarkAction{
   833  				ActionAttrs: ActionAttrs{
   834  					Action: TC_ACT_PIPE,
   835  				},
   836  			},
   837  			&MirredAction{
   838  				ActionAttrs: ActionAttrs{
   839  					Action: TC_ACT_STOLEN,
   840  				},
   841  				MirredAction: TCA_EGRESS_REDIR,
   842  				Ifindex:      redir.Attrs().Index,
   843  			},
   844  		},
   845  	}
   846  
   847  	if err := FilterAdd(filter); err != nil {
   848  		t.Fatal(err)
   849  	}
   850  
   851  	filters, err := FilterList(link, MakeHandle(0xffff, 0))
   852  	if err != nil {
   853  		t.Fatal(err)
   854  	}
   855  	if len(filters) != 1 {
   856  		t.Fatal("Failed to add filter")
   857  	}
   858  	u32, ok := filters[0].(*U32)
   859  	if !ok {
   860  		t.Fatal("Filter is the wrong type")
   861  	}
   862  
   863  	if len(u32.Actions) != 2 {
   864  		t.Fatalf("Too few Actions in filter")
   865  	}
   866  	if u32.ClassId != classId {
   867  		t.Fatalf("ClassId of the filter is the wrong value")
   868  	}
   869  
   870  	// actions can be returned in reverse order
   871  	cma, ok := u32.Actions[0].(*ConnmarkAction)
   872  	if !ok {
   873  		cma, ok = u32.Actions[1].(*ConnmarkAction)
   874  		if !ok {
   875  			t.Fatal("Unable to find connmark action")
   876  		}
   877  	}
   878  
   879  	if cma.Attrs().Action != TC_ACT_PIPE {
   880  		t.Fatal("Connmark action isn't TC_ACT_PIPE")
   881  	}
   882  
   883  	mia, ok := u32.Actions[0].(*MirredAction)
   884  	if !ok {
   885  		mia, ok = u32.Actions[1].(*MirredAction)
   886  		if !ok {
   887  			t.Fatal("Unable to find mirred action")
   888  		}
   889  	}
   890  
   891  	if mia.Attrs().Action != TC_ACT_STOLEN {
   892  		t.Fatal("Mirred action isn't TC_ACT_STOLEN")
   893  	}
   894  
   895  	if err := FilterDel(filter); err != nil {
   896  		t.Fatal(err)
   897  	}
   898  	filters, err = FilterList(link, MakeHandle(0xffff, 0))
   899  	if err != nil {
   900  		t.Fatal(err)
   901  	}
   902  	if len(filters) != 0 {
   903  		t.Fatal("Failed to remove filter")
   904  	}
   905  
   906  	if err := QdiscDel(qdisc); err != nil {
   907  		t.Fatal(err)
   908  	}
   909  	qdiscs, err = SafeQdiscList(link)
   910  	if err != nil {
   911  		t.Fatal(err)
   912  	}
   913  	if len(qdiscs) != 0 {
   914  		t.Fatal("Failed to remove qdisc")
   915  	}
   916  }
   917  
   918  func TestFilterU32CsumAddDel(t *testing.T) {
   919  	tearDown := setUpNetlinkTest(t)
   920  	defer tearDown()
   921  	if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
   922  		t.Fatalf("add link foo error: %v", err)
   923  	}
   924  	link, err := LinkByName("foo")
   925  	if err != nil {
   926  		t.Fatalf("add link foo error: %v", err)
   927  	}
   928  	if err := LinkSetUp(link); err != nil {
   929  		t.Fatalf("set foo link up error: %v", err)
   930  	}
   931  
   932  	qdisc := &Ingress{
   933  		QdiscAttrs: QdiscAttrs{
   934  			LinkIndex: link.Attrs().Index,
   935  			Handle:    MakeHandle(0xffff, 0),
   936  			Parent:    HANDLE_INGRESS,
   937  		},
   938  	}
   939  	if err := QdiscAdd(qdisc); err != nil {
   940  		t.Fatal(err)
   941  	}
   942  	qdiscs, err := SafeQdiscList(link)
   943  	if err != nil {
   944  		t.Fatalf("get qdisc error: %v", err)
   945  	}
   946  
   947  	found := false
   948  	for _, v := range qdiscs {
   949  		if _, ok := v.(*Ingress); ok {
   950  			found = true
   951  			break
   952  		}
   953  	}
   954  	if !found {
   955  		t.Fatal("Qdisc is the wrong type")
   956  	}
   957  
   958  	classId := MakeHandle(1, 1)
   959  	filter := &U32{
   960  		FilterAttrs: FilterAttrs{
   961  			LinkIndex: link.Attrs().Index,
   962  			Parent:    MakeHandle(0xffff, 0),
   963  			Priority:  1,
   964  			Protocol:  unix.ETH_P_ALL,
   965  		},
   966  		ClassId: classId,
   967  		Actions: []Action{
   968  			&CsumAction{
   969  				ActionAttrs: ActionAttrs{
   970  					Action: TC_ACT_PIPE,
   971  				},
   972  				UpdateFlags: TCA_CSUM_UPDATE_FLAG_TCP,
   973  			},
   974  		},
   975  	}
   976  
   977  	if err := FilterAdd(filter); err != nil {
   978  		t.Fatal(err)
   979  	}
   980  
   981  	filters, err := FilterList(link, MakeHandle(0xffff, 0))
   982  	if err != nil {
   983  		t.Fatalf("get filter error: %v", err)
   984  	}
   985  
   986  	if len(filters) != 1 {
   987  		t.Fatalf("the count filters error, expect: 1, acutal: %d", len(filters))
   988  	}
   989  
   990  	ft, ok := filters[0].(*U32)
   991  	if !ok {
   992  		t.Fatal("Filter is the wrong type")
   993  	}
   994  
   995  	if ft.LinkIndex != link.Attrs().Index {
   996  		t.Fatal("link index error")
   997  	}
   998  
   999  	if len(ft.Actions) != 1 {
  1000  		t.Fatalf("filter has wrong number of actions, expect: 1, acutal: %d", len(filters))
  1001  	}
  1002  
  1003  	csum, ok := ft.Actions[0].(*CsumAction)
  1004  	if !ok {
  1005  		t.Fatal("action is the wrong type")
  1006  	}
  1007  
  1008  	if csum.Attrs().Action != TC_ACT_PIPE {
  1009  		t.Fatal("Csum action isn't TC_ACT_PIPE")
  1010  	}
  1011  
  1012  	if csum.UpdateFlags != TCA_CSUM_UPDATE_FLAG_TCP {
  1013  		t.Fatalf("Csum action isn't TCA_CSUM_UPDATE_FLAG_TCP, got %d", csum.UpdateFlags)
  1014  	}
  1015  
  1016  	if err := FilterDel(ft); err != nil {
  1017  		t.Fatal(err)
  1018  	}
  1019  	filters, err = FilterList(link, MakeHandle(0xffff, 0))
  1020  	if err != nil {
  1021  		t.Fatal(err)
  1022  	}
  1023  	if len(filters) != 0 {
  1024  		t.Fatal("Failed to remove filter")
  1025  	}
  1026  
  1027  	if err := QdiscDel(qdisc); err != nil {
  1028  		t.Fatal(err)
  1029  	}
  1030  	qdiscs, err = SafeQdiscList(link)
  1031  	if err != nil {
  1032  		t.Fatal(err)
  1033  	}
  1034  
  1035  	found = false
  1036  	for _, v := range qdiscs {
  1037  		if _, ok := v.(*Ingress); ok {
  1038  			found = true
  1039  			break
  1040  		}
  1041  	}
  1042  	if found {
  1043  		t.Fatal("Failed to remove qdisc")
  1044  	}
  1045  }
  1046  
  1047  func setupLinkForTestWithQdisc(t *testing.T, linkName string) (Qdisc, Link) {
  1048  	if err := LinkAdd(&Ifb{LinkAttrs{Name: linkName}}); err != nil {
  1049  		t.Fatal(err)
  1050  	}
  1051  	link, err := LinkByName(linkName)
  1052  	if err != nil {
  1053  		t.Fatal(err)
  1054  	}
  1055  	if err := LinkSetUp(link); err != nil {
  1056  		t.Fatal(err)
  1057  	}
  1058  	qdisc := &Clsact{
  1059  		QdiscAttrs: QdiscAttrs{
  1060  			LinkIndex: link.Attrs().Index,
  1061  			Handle:    MakeHandle(0xffff, 0),
  1062  			Parent:    HANDLE_CLSACT,
  1063  		},
  1064  	}
  1065  
  1066  	if err := QdiscAdd(qdisc); err != nil {
  1067  		t.Fatal(err)
  1068  	}
  1069  	qdiscs, err := SafeQdiscList(link)
  1070  	if err != nil {
  1071  		t.Fatal(err)
  1072  	}
  1073  	if len(qdiscs) != 1 {
  1074  		t.Fatal("Failed to add qdisc", len(qdiscs))
  1075  	}
  1076  	if q, ok := qdiscs[0].(*Clsact); !ok || q.Type() != "clsact" {
  1077  		t.Fatal("qdisc is the wrong type")
  1078  	}
  1079  	return qdiscs[0], link
  1080  }
  1081  
  1082  func TestFilterClsActBpfAddDel(t *testing.T) {
  1083  	t.Skipf("Fd does not match in ci")
  1084  	// This feature was added in kernel 4.5
  1085  	minKernelRequired(t, 4, 5)
  1086  
  1087  	tearDown := setUpNetlinkTest(t)
  1088  	defer tearDown()
  1089  
  1090  	qdisc, link := setupLinkForTestWithQdisc(t, "foo")
  1091  	filterattrs := FilterAttrs{
  1092  		LinkIndex: link.Attrs().Index,
  1093  		Parent:    HANDLE_MIN_EGRESS,
  1094  		Handle:    MakeHandle(0, 1),
  1095  		Protocol:  unix.ETH_P_ALL,
  1096  		Priority:  1,
  1097  	}
  1098  	fd, err := loadSimpleBpf(BPF_PROG_TYPE_SCHED_CLS, 1)
  1099  	if err != nil {
  1100  		t.Skipf("Loading bpf program failed: %s", err)
  1101  	}
  1102  	filter := &BpfFilter{
  1103  		FilterAttrs:  filterattrs,
  1104  		Fd:           fd,
  1105  		Name:         "simple",
  1106  		DirectAction: true,
  1107  	}
  1108  	if filter.Fd < 0 {
  1109  		t.Skipf("Failed to load bpf program")
  1110  	}
  1111  
  1112  	if err := FilterAdd(filter); err != nil {
  1113  		t.Fatal(err)
  1114  	}
  1115  
  1116  	filters, err := FilterList(link, HANDLE_MIN_EGRESS)
  1117  	if err != nil {
  1118  		t.Fatal(err)
  1119  	}
  1120  	if len(filters) != 1 {
  1121  		t.Fatal("Failed to add filter")
  1122  	}
  1123  	bpf, ok := filters[0].(*BpfFilter)
  1124  	if !ok {
  1125  		t.Fatal("Filter is the wrong type")
  1126  	}
  1127  
  1128  	if bpf.Fd != filter.Fd {
  1129  		t.Fatal("Filter Fd does not match")
  1130  	}
  1131  	if bpf.DirectAction != filter.DirectAction {
  1132  		t.Fatal("Filter DirectAction does not match")
  1133  	}
  1134  
  1135  	if err := FilterDel(filter); err != nil {
  1136  		t.Fatal(err)
  1137  	}
  1138  	filters, err = FilterList(link, HANDLE_MIN_EGRESS)
  1139  	if err != nil {
  1140  		t.Fatal(err)
  1141  	}
  1142  	if len(filters) != 0 {
  1143  		t.Fatal("Failed to remove filter")
  1144  	}
  1145  
  1146  	if err := QdiscDel(qdisc); err != nil {
  1147  		t.Fatal(err)
  1148  	}
  1149  	qdiscs, err := SafeQdiscList(link)
  1150  	if err != nil {
  1151  		t.Fatal(err)
  1152  	}
  1153  	if len(qdiscs) != 0 {
  1154  		t.Fatal("Failed to remove qdisc")
  1155  	}
  1156  }
  1157  
  1158  func TestFilterMatchAllAddDel(t *testing.T) {
  1159  	// This classifier was added in kernel 4.7
  1160  	minKernelRequired(t, 4, 7)
  1161  
  1162  	tearDown := setUpNetlinkTest(t)
  1163  	defer tearDown()
  1164  	_, link := setupLinkForTestWithQdisc(t, "foo")
  1165  	_, link2 := setupLinkForTestWithQdisc(t, "bar")
  1166  	filter := &MatchAll{
  1167  		FilterAttrs: FilterAttrs{
  1168  			LinkIndex: link.Attrs().Index,
  1169  			Parent:    HANDLE_MIN_EGRESS,
  1170  			Priority:  32000,
  1171  			Protocol:  unix.ETH_P_ALL,
  1172  		},
  1173  		Actions: []Action{
  1174  			&MirredAction{
  1175  				ActionAttrs: ActionAttrs{
  1176  					Action: TC_ACT_STOLEN,
  1177  				},
  1178  				MirredAction: TCA_EGRESS_REDIR,
  1179  				Ifindex:      link2.Attrs().Index,
  1180  			},
  1181  		},
  1182  	}
  1183  	if err := FilterAdd(filter); err != nil {
  1184  		t.Fatal(err)
  1185  	}
  1186  
  1187  	filters, err := FilterList(link, HANDLE_MIN_EGRESS)
  1188  	if err != nil {
  1189  		t.Fatal(err)
  1190  	}
  1191  	if len(filters) != 1 {
  1192  		t.Fatal("Failed to add filter")
  1193  	}
  1194  	matchall, ok := filters[0].(*MatchAll)
  1195  	if !ok {
  1196  		t.Fatal("Filter is the wrong type")
  1197  	}
  1198  
  1199  	if matchall.Priority != 32000 {
  1200  		t.Fatal("Filter priority does not match")
  1201  	}
  1202  
  1203  	if len(matchall.Actions) != 1 {
  1204  		t.Fatal("Filter has no actions")
  1205  	}
  1206  
  1207  	mirredAction, ok := matchall.Actions[0].(*MirredAction)
  1208  	if !ok {
  1209  		t.Fatal("Action does not match")
  1210  	}
  1211  
  1212  	if mirredAction.Ifindex != link2.Attrs().Index {
  1213  		t.Fatal("Action ifindex does not match")
  1214  	}
  1215  
  1216  	if err := FilterDel(filter); err != nil {
  1217  		t.Fatal(err)
  1218  	}
  1219  	filters, err = FilterList(link, HANDLE_MIN_EGRESS)
  1220  	if err != nil {
  1221  		t.Fatal(err)
  1222  	}
  1223  	if len(filters) != 0 {
  1224  		t.Fatal("Failed to remove filter")
  1225  	}
  1226  
  1227  }
  1228  
  1229  func TestFilterU32TunnelKeyAddDel(t *testing.T) {
  1230  	tearDown := setUpNetlinkTest(t)
  1231  	defer tearDown()
  1232  	if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
  1233  		t.Fatal(err)
  1234  	}
  1235  	if err := LinkAdd(&Ifb{LinkAttrs{Name: "bar"}}); err != nil {
  1236  		t.Fatal(err)
  1237  	}
  1238  	link, err := LinkByName("foo")
  1239  	if err != nil {
  1240  		t.Fatal(err)
  1241  	}
  1242  	if err := LinkSetUp(link); err != nil {
  1243  		t.Fatal(err)
  1244  	}
  1245  	redir, err := LinkByName("bar")
  1246  	if err != nil {
  1247  		t.Fatal(err)
  1248  	}
  1249  	if err := LinkSetUp(redir); err != nil {
  1250  		t.Fatal(err)
  1251  	}
  1252  
  1253  	qdisc := &Ingress{
  1254  		QdiscAttrs: QdiscAttrs{
  1255  			LinkIndex: link.Attrs().Index,
  1256  			Handle:    MakeHandle(0xffff, 0),
  1257  			Parent:    HANDLE_INGRESS,
  1258  		},
  1259  	}
  1260  	if err := QdiscAdd(qdisc); err != nil {
  1261  		t.Fatal(err)
  1262  	}
  1263  	qdiscs, err := SafeQdiscList(link)
  1264  	if err != nil {
  1265  		t.Fatal(err)
  1266  	}
  1267  
  1268  	found := false
  1269  	for _, v := range qdiscs {
  1270  		if _, ok := v.(*Ingress); ok {
  1271  			found = true
  1272  			break
  1273  		}
  1274  	}
  1275  	if !found {
  1276  		t.Fatal("Qdisc is the wrong type")
  1277  	}
  1278  
  1279  	tunnelAct := NewTunnelKeyAction()
  1280  	tunnelAct.SrcAddr = net.IPv4(10, 10, 10, 1)
  1281  	tunnelAct.DstAddr = net.IPv4(10, 10, 10, 2)
  1282  	tunnelAct.KeyID = 0x01
  1283  	tunnelAct.Action = TCA_TUNNEL_KEY_SET
  1284  	tunnelAct.DestPort = 8472
  1285  
  1286  	classId := MakeHandle(1, 1)
  1287  	filter := &U32{
  1288  		FilterAttrs: FilterAttrs{
  1289  			LinkIndex: link.Attrs().Index,
  1290  			Parent:    MakeHandle(0xffff, 0),
  1291  			Priority:  1,
  1292  			Protocol:  unix.ETH_P_ALL,
  1293  		},
  1294  		ClassId: classId,
  1295  		Actions: []Action{
  1296  			tunnelAct,
  1297  			&MirredAction{
  1298  				ActionAttrs: ActionAttrs{
  1299  					Action: TC_ACT_STOLEN,
  1300  				},
  1301  				MirredAction: TCA_EGRESS_REDIR,
  1302  				Ifindex:      redir.Attrs().Index,
  1303  			},
  1304  		},
  1305  	}
  1306  
  1307  	if err := FilterAdd(filter); err != nil {
  1308  		t.Fatal(err)
  1309  	}
  1310  
  1311  	filters, err := FilterList(link, MakeHandle(0xffff, 0))
  1312  	if err != nil {
  1313  		t.Fatal(err)
  1314  	}
  1315  	if len(filters) != 1 {
  1316  		t.Fatal("Failed to add filter")
  1317  	}
  1318  	u32, ok := filters[0].(*U32)
  1319  	if !ok {
  1320  		t.Fatal("Filter is the wrong type")
  1321  	}
  1322  
  1323  	if len(u32.Actions) != 2 {
  1324  		t.Fatalf("Too few Actions in filter")
  1325  	}
  1326  	if u32.ClassId != classId {
  1327  		t.Fatalf("ClassId of the filter is the wrong value")
  1328  	}
  1329  
  1330  	// actions can be returned in reverse order
  1331  	tun, ok := u32.Actions[0].(*TunnelKeyAction)
  1332  	if !ok {
  1333  		tun, ok = u32.Actions[1].(*TunnelKeyAction)
  1334  		if !ok {
  1335  			t.Fatal("Unable to find tunnel action")
  1336  		}
  1337  	}
  1338  
  1339  	if tun.Attrs().Action != TC_ACT_PIPE {
  1340  		t.Fatal("TunnelKey action isn't TC_ACT_PIPE")
  1341  	}
  1342  	if !tun.SrcAddr.Equal(tunnelAct.SrcAddr) {
  1343  		t.Fatal("Action SrcAddr doesn't match")
  1344  	}
  1345  	if !tun.DstAddr.Equal(tunnelAct.DstAddr) {
  1346  		t.Fatal("Action DstAddr doesn't match")
  1347  	}
  1348  	if tun.KeyID != tunnelAct.KeyID {
  1349  		t.Fatal("Action KeyID doesn't match")
  1350  	}
  1351  	if tun.DestPort != tunnelAct.DestPort {
  1352  		t.Fatal("Action DestPort doesn't match")
  1353  	}
  1354  	if tun.Action != tunnelAct.Action {
  1355  		t.Fatal("Action doesn't match")
  1356  	}
  1357  
  1358  	mia, ok := u32.Actions[0].(*MirredAction)
  1359  	if !ok {
  1360  		mia, ok = u32.Actions[1].(*MirredAction)
  1361  		if !ok {
  1362  			t.Fatal("Unable to find mirred action")
  1363  		}
  1364  	}
  1365  
  1366  	if mia.Attrs().Action != TC_ACT_STOLEN {
  1367  		t.Fatal("Mirred action isn't TC_ACT_STOLEN")
  1368  	}
  1369  
  1370  	if err := FilterDel(filter); err != nil {
  1371  		t.Fatal(err)
  1372  	}
  1373  	filters, err = FilterList(link, MakeHandle(0xffff, 0))
  1374  	if err != nil {
  1375  		t.Fatal(err)
  1376  	}
  1377  	if len(filters) != 0 {
  1378  		t.Fatal("Failed to remove filter")
  1379  	}
  1380  
  1381  	if err := QdiscDel(qdisc); err != nil {
  1382  		t.Fatal(err)
  1383  	}
  1384  	qdiscs, err = SafeQdiscList(link)
  1385  	if err != nil {
  1386  		t.Fatal(err)
  1387  	}
  1388  
  1389  	found = false
  1390  	for _, v := range qdiscs {
  1391  		if _, ok := v.(*Ingress); ok {
  1392  			found = true
  1393  			break
  1394  		}
  1395  	}
  1396  	if found {
  1397  		t.Fatal("Failed to remove qdisc")
  1398  	}
  1399  }
  1400  
  1401  func TestFilterU32SkbEditAddDel(t *testing.T) {
  1402  	tearDown := setUpNetlinkTest(t)
  1403  	defer tearDown()
  1404  	if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
  1405  		t.Fatal(err)
  1406  	}
  1407  	if err := LinkAdd(&Ifb{LinkAttrs{Name: "bar"}}); err != nil {
  1408  		t.Fatal(err)
  1409  	}
  1410  	link, err := LinkByName("foo")
  1411  	if err != nil {
  1412  		t.Fatal(err)
  1413  	}
  1414  	if err := LinkSetUp(link); err != nil {
  1415  		t.Fatal(err)
  1416  	}
  1417  	redir, err := LinkByName("bar")
  1418  	if err != nil {
  1419  		t.Fatal(err)
  1420  	}
  1421  	if err := LinkSetUp(redir); err != nil {
  1422  		t.Fatal(err)
  1423  	}
  1424  
  1425  	qdisc := &Ingress{
  1426  		QdiscAttrs: QdiscAttrs{
  1427  			LinkIndex: link.Attrs().Index,
  1428  			Handle:    MakeHandle(0xffff, 0),
  1429  			Parent:    HANDLE_INGRESS,
  1430  		},
  1431  	}
  1432  	if err := QdiscAdd(qdisc); err != nil {
  1433  		t.Fatal(err)
  1434  	}
  1435  	qdiscs, err := SafeQdiscList(link)
  1436  	if err != nil {
  1437  		t.Fatal(err)
  1438  	}
  1439  
  1440  	found := false
  1441  	for _, v := range qdiscs {
  1442  		if _, ok := v.(*Ingress); ok {
  1443  			found = true
  1444  			break
  1445  		}
  1446  	}
  1447  	if !found {
  1448  		t.Fatal("Qdisc is the wrong type")
  1449  	}
  1450  
  1451  	skbedit := NewSkbEditAction()
  1452  	ptype := uint16(unix.PACKET_HOST)
  1453  	skbedit.PType = &ptype
  1454  	priority := uint32(0xff)
  1455  	skbedit.Priority = &priority
  1456  	mark := uint32(0xfe)
  1457  	skbedit.Mark = &mark
  1458  	mask := uint32(0xff)
  1459  	skbedit.Mask = &mask
  1460  	mapping := uint16(0xf)
  1461  	skbedit.QueueMapping = &mapping
  1462  
  1463  	classId := MakeHandle(1, 1)
  1464  	filter := &U32{
  1465  		FilterAttrs: FilterAttrs{
  1466  			LinkIndex: link.Attrs().Index,
  1467  			Parent:    MakeHandle(0xffff, 0),
  1468  			Priority:  1,
  1469  			Protocol:  unix.ETH_P_ALL,
  1470  		},
  1471  		ClassId: classId,
  1472  		Actions: []Action{
  1473  			skbedit,
  1474  			&MirredAction{
  1475  				ActionAttrs: ActionAttrs{
  1476  					Action: TC_ACT_STOLEN,
  1477  				},
  1478  				MirredAction: TCA_EGRESS_REDIR,
  1479  				Ifindex:      redir.Attrs().Index,
  1480  			},
  1481  		},
  1482  	}
  1483  
  1484  	if err := FilterAdd(filter); err != nil {
  1485  		t.Fatal(err)
  1486  	}
  1487  
  1488  	filters, err := FilterList(link, MakeHandle(0xffff, 0))
  1489  	if err != nil {
  1490  		t.Fatal(err)
  1491  	}
  1492  	if len(filters) != 1 {
  1493  		t.Fatal("Failed to add filter")
  1494  	}
  1495  	u32, ok := filters[0].(*U32)
  1496  	if !ok {
  1497  		t.Fatal("Filter is the wrong type")
  1498  	}
  1499  
  1500  	if len(u32.Actions) != 2 {
  1501  		t.Fatalf("Too few Actions in filter")
  1502  	}
  1503  	if u32.ClassId != classId {
  1504  		t.Fatalf("ClassId of the filter is the wrong value")
  1505  	}
  1506  
  1507  	// actions can be returned in reverse order
  1508  	edit, ok := u32.Actions[0].(*SkbEditAction)
  1509  	if !ok {
  1510  		edit, ok = u32.Actions[1].(*SkbEditAction)
  1511  		if !ok {
  1512  			t.Fatal("Unable to find tunnel action")
  1513  		}
  1514  	}
  1515  
  1516  	if edit.Attrs().Action != TC_ACT_PIPE {
  1517  		t.Fatal("SkbEdit action isn't TC_ACT_PIPE")
  1518  	}
  1519  	if edit.PType == nil || *edit.PType != *skbedit.PType {
  1520  		t.Fatal("Action PType doesn't match")
  1521  	}
  1522  	if edit.QueueMapping == nil || *edit.QueueMapping != *skbedit.QueueMapping {
  1523  		t.Fatal("Action QueueMapping doesn't match")
  1524  	}
  1525  	if edit.Mark == nil || *edit.Mark != *skbedit.Mark {
  1526  		t.Fatal("Action Mark doesn't match")
  1527  	}
  1528  	if edit.Mask == nil || *edit.Mask != *skbedit.Mask {
  1529  		t.Fatal("Action Mask doesn't match")
  1530  	}
  1531  	if edit.Priority == nil || *edit.Priority != *skbedit.Priority {
  1532  		t.Fatal("Action Priority doesn't match")
  1533  	}
  1534  
  1535  	mia, ok := u32.Actions[0].(*MirredAction)
  1536  	if !ok {
  1537  		mia, ok = u32.Actions[1].(*MirredAction)
  1538  		if !ok {
  1539  			t.Fatal("Unable to find mirred action")
  1540  		}
  1541  	}
  1542  
  1543  	if mia.Attrs().Action != TC_ACT_STOLEN {
  1544  		t.Fatal("Mirred action isn't TC_ACT_STOLEN")
  1545  	}
  1546  
  1547  	if err := FilterDel(filter); err != nil {
  1548  		t.Fatal(err)
  1549  	}
  1550  	filters, err = FilterList(link, MakeHandle(0xffff, 0))
  1551  	if err != nil {
  1552  		t.Fatal(err)
  1553  	}
  1554  	if len(filters) != 0 {
  1555  		t.Fatal("Failed to remove filter")
  1556  	}
  1557  
  1558  	if err := QdiscDel(qdisc); err != nil {
  1559  		t.Fatal(err)
  1560  	}
  1561  	qdiscs, err = SafeQdiscList(link)
  1562  	if err != nil {
  1563  		t.Fatal(err)
  1564  	}
  1565  
  1566  	found = false
  1567  	for _, v := range qdiscs {
  1568  		if _, ok := v.(*Ingress); ok {
  1569  			found = true
  1570  			break
  1571  		}
  1572  	}
  1573  	if found {
  1574  		t.Fatal("Failed to remove qdisc")
  1575  	}
  1576  }
  1577  
  1578  func TestFilterU32LinkOption(t *testing.T) {
  1579  	tearDown := setUpNetlinkTest(t)
  1580  	defer tearDown()
  1581  	if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
  1582  		t.Fatalf("add link foo error: %v", err)
  1583  	}
  1584  	link, err := LinkByName("foo")
  1585  	if err != nil {
  1586  		t.Fatalf("add link foo error: %v", err)
  1587  	}
  1588  	if err := LinkSetUp(link); err != nil {
  1589  		t.Fatalf("set foo link up error: %v", err)
  1590  	}
  1591  
  1592  	qdisc := &Ingress{
  1593  		QdiscAttrs: QdiscAttrs{
  1594  			LinkIndex: link.Attrs().Index,
  1595  			Handle:    MakeHandle(0xffff, 0),
  1596  			Parent:    HANDLE_INGRESS,
  1597  		},
  1598  	}
  1599  	if err := QdiscAdd(qdisc); err != nil {
  1600  		t.Fatal(err)
  1601  	}
  1602  	qdiscs, err := SafeQdiscList(link)
  1603  	if err != nil {
  1604  		t.Fatalf("get qdisc error: %v", err)
  1605  	}
  1606  
  1607  	found := false
  1608  	for _, v := range qdiscs {
  1609  		if _, ok := v.(*Ingress); ok {
  1610  			found = true
  1611  			break
  1612  		}
  1613  	}
  1614  	if !found {
  1615  		t.Fatal("Qdisc is the wrong type")
  1616  	}
  1617  
  1618  	htid := uint32(10)
  1619  	size := uint32(8)
  1620  	priority := uint16(200)
  1621  	u32Table := &U32{
  1622  		FilterAttrs: FilterAttrs{
  1623  			LinkIndex: link.Attrs().Index,
  1624  			Handle:    htid << 20,
  1625  			Parent:    MakeHandle(0xffff, 0),
  1626  			Priority:  priority,
  1627  			Protocol:  unix.ETH_P_ALL,
  1628  		},
  1629  		Divisor: size,
  1630  	}
  1631  	if err := FilterAdd(u32Table); err != nil {
  1632  		t.Fatal(err)
  1633  	}
  1634  
  1635  	u32 := &U32{
  1636  		FilterAttrs: FilterAttrs{
  1637  			LinkIndex: link.Attrs().Index,
  1638  			Parent:    MakeHandle(0xffff, 0),
  1639  			Handle:    1,
  1640  			Priority:  priority,
  1641  			Protocol:  unix.ETH_P_ALL,
  1642  		},
  1643  		Link: uint32(htid << 20),
  1644  		Sel: &TcU32Sel{
  1645  			Nkeys:    1,
  1646  			Flags:    TC_U32_TERMINAL | TC_U32_VAROFFSET,
  1647  			Hmask:    0x0000ff00,
  1648  			Hoff:     0,
  1649  			Offshift: 8,
  1650  			Keys: []TcU32Key{
  1651  				{
  1652  					Mask: 0,
  1653  					Val:  0,
  1654  					Off:  0,
  1655  				},
  1656  			},
  1657  		},
  1658  	}
  1659  	if err := FilterAdd(u32); err != nil {
  1660  		t.Fatal(err)
  1661  	}
  1662  
  1663  	filters, err := FilterList(link, MakeHandle(0xffff, 0))
  1664  	if err != nil {
  1665  		t.Fatalf("get filter error: %v", err)
  1666  	}
  1667  
  1668  	if len(filters) != 1 {
  1669  		t.Fatalf("the count filters error, expect: 1, acutal: %d", len(filters))
  1670  	}
  1671  
  1672  	ft, ok := filters[0].(*U32)
  1673  	if !ok {
  1674  		t.Fatal("Filter is the wrong type")
  1675  	}
  1676  
  1677  	if ft.LinkIndex != link.Attrs().Index {
  1678  		t.Fatal("link index error")
  1679  	}
  1680  
  1681  	if ft.Link != htid<<20 {
  1682  		t.Fatal("hash table id error")
  1683  	}
  1684  
  1685  	if ft.Priority != priority {
  1686  		t.Fatal("priority error")
  1687  	}
  1688  
  1689  	if err := FilterDel(ft); err != nil {
  1690  		t.Fatal(err)
  1691  	}
  1692  	filters, err = FilterList(link, MakeHandle(0xffff, 0))
  1693  	if err != nil {
  1694  		t.Fatal(err)
  1695  	}
  1696  	if len(filters) != 0 {
  1697  		t.Fatal("Failed to remove filter")
  1698  	}
  1699  
  1700  	if err := QdiscDel(qdisc); err != nil {
  1701  		t.Fatal(err)
  1702  	}
  1703  	qdiscs, err = SafeQdiscList(link)
  1704  	if err != nil {
  1705  		t.Fatal(err)
  1706  	}
  1707  
  1708  	found = false
  1709  	for _, v := range qdiscs {
  1710  		if _, ok := v.(*Ingress); ok {
  1711  			found = true
  1712  			break
  1713  		}
  1714  	}
  1715  	if found {
  1716  		t.Fatal("Failed to remove qdisc")
  1717  	}
  1718  }
  1719  
  1720  func TestFilterFlowerAddDel(t *testing.T) {
  1721  	tearDown := setUpNetlinkTest(t)
  1722  	defer tearDown()
  1723  	if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
  1724  		t.Fatal(err)
  1725  	}
  1726  	if err := LinkAdd(&Ifb{LinkAttrs{Name: "bar"}}); err != nil {
  1727  		t.Fatal(err)
  1728  	}
  1729  	link, err := LinkByName("foo")
  1730  	if err != nil {
  1731  		t.Fatal(err)
  1732  	}
  1733  	if err := LinkSetUp(link); err != nil {
  1734  		t.Fatal(err)
  1735  	}
  1736  	redir, err := LinkByName("bar")
  1737  	if err != nil {
  1738  		t.Fatal(err)
  1739  	}
  1740  	if err := LinkSetUp(redir); err != nil {
  1741  		t.Fatal(err)
  1742  	}
  1743  
  1744  	qdisc := &Ingress{
  1745  		QdiscAttrs: QdiscAttrs{
  1746  			LinkIndex: link.Attrs().Index,
  1747  			Handle:    MakeHandle(0xffff, 0),
  1748  			Parent:    HANDLE_INGRESS,
  1749  		},
  1750  	}
  1751  	if err := QdiscAdd(qdisc); err != nil {
  1752  		t.Fatal(err)
  1753  	}
  1754  	qdiscs, err := SafeQdiscList(link)
  1755  	if err != nil {
  1756  		t.Fatal(err)
  1757  	}
  1758  
  1759  	found := false
  1760  	for _, v := range qdiscs {
  1761  		if _, ok := v.(*Ingress); ok {
  1762  			found = true
  1763  			break
  1764  		}
  1765  	}
  1766  	if !found {
  1767  		t.Fatal("Qdisc is the wrong type")
  1768  	}
  1769  
  1770  	testMask := net.CIDRMask(24, 32)
  1771  
  1772  	ipproto := new(nl.IPProto)
  1773  	*ipproto = nl.IPPROTO_TCP
  1774  
  1775  	filter := &Flower{
  1776  		FilterAttrs: FilterAttrs{
  1777  			LinkIndex: link.Attrs().Index,
  1778  			Parent:    MakeHandle(0xffff, 0),
  1779  			Priority:  1,
  1780  			Protocol:  unix.ETH_P_ALL,
  1781  		},
  1782  		DestIP:        net.ParseIP("1.0.0.1"),
  1783  		DestIPMask:    testMask,
  1784  		SrcIP:         net.ParseIP("2.0.0.1"),
  1785  		SrcIPMask:     testMask,
  1786  		EthType:       unix.ETH_P_IP,
  1787  		EncDestIP:     net.ParseIP("3.0.0.1"),
  1788  		EncDestIPMask: testMask,
  1789  		EncSrcIP:      net.ParseIP("4.0.0.1"),
  1790  		EncSrcIPMask:  testMask,
  1791  		EncDestPort:   8472,
  1792  		EncKeyId:      1234,
  1793  		IPProto:       ipproto,
  1794  		DestPort:      1111,
  1795  		SrcPort:       1111,
  1796  		Actions: []Action{
  1797  			&MirredAction{
  1798  				ActionAttrs: ActionAttrs{
  1799  					Action: TC_ACT_STOLEN,
  1800  				},
  1801  				MirredAction: TCA_EGRESS_REDIR,
  1802  				Ifindex:      redir.Attrs().Index,
  1803  			},
  1804  			&GenericAction{
  1805  				ActionAttrs: ActionAttrs{
  1806  					Action: getTcActGotoChain(),
  1807  				},
  1808  				Chain: 20,
  1809  			},
  1810  		},
  1811  	}
  1812  
  1813  	if err := FilterAdd(filter); err != nil {
  1814  		t.Fatal(err)
  1815  	}
  1816  
  1817  	time.Sleep(time.Second)
  1818  	filters, err := FilterList(link, MakeHandle(0xffff, 0))
  1819  	if err != nil {
  1820  		t.Fatal(err)
  1821  	}
  1822  	if len(filters) != 1 {
  1823  		t.Fatal("Failed to add filter")
  1824  	}
  1825  	flower, ok := filters[0].(*Flower)
  1826  	if !ok {
  1827  		t.Fatal("Filter is the wrong type")
  1828  	}
  1829  
  1830  	if filter.EthType != flower.EthType {
  1831  		t.Fatalf("Flower EthType doesn't match")
  1832  	}
  1833  	if !filter.DestIP.Equal(flower.DestIP) {
  1834  		t.Fatalf("Flower DestIP doesn't match")
  1835  	}
  1836  	if !filter.SrcIP.Equal(flower.SrcIP) {
  1837  		t.Fatalf("Flower SrcIP doesn't match")
  1838  	}
  1839  
  1840  	if !reflect.DeepEqual(filter.DestIPMask, testMask) {
  1841  		t.Fatalf("Flower DestIPMask doesn't match")
  1842  	}
  1843  	if !reflect.DeepEqual(filter.SrcIPMask, testMask) {
  1844  		t.Fatalf("Flower SrcIPMask doesn't match")
  1845  	}
  1846  
  1847  	if !filter.EncDestIP.Equal(flower.EncDestIP) {
  1848  		t.Fatalf("Flower EncDestIP doesn't match")
  1849  	}
  1850  	if !filter.EncSrcIP.Equal(flower.EncSrcIP) {
  1851  		t.Fatalf("Flower EncSrcIP doesn't match")
  1852  	}
  1853  	if !reflect.DeepEqual(filter.EncDestIPMask, testMask) {
  1854  		t.Fatalf("Flower EncDestIPMask doesn't match")
  1855  	}
  1856  	if !reflect.DeepEqual(filter.EncSrcIPMask, testMask) {
  1857  		t.Fatalf("Flower EncSrcIPMask doesn't match")
  1858  	}
  1859  	if filter.EncKeyId != flower.EncKeyId {
  1860  		t.Fatalf("Flower EncKeyId doesn't match")
  1861  	}
  1862  	if filter.EncDestPort != flower.EncDestPort {
  1863  		t.Fatalf("Flower EncDestPort doesn't match")
  1864  	}
  1865  	if flower.IPProto == nil || *filter.IPProto != *flower.IPProto {
  1866  		t.Fatalf("Flower IPProto doesn't match")
  1867  	}
  1868  	if filter.DestPort != flower.DestPort {
  1869  		t.Fatalf("Flower DestPort doesn't match")
  1870  	}
  1871  	if filter.SrcPort != flower.SrcPort {
  1872  		t.Fatalf("Flower SrcPort doesn't match")
  1873  	}
  1874  
  1875  	mia, ok := flower.Actions[0].(*MirredAction)
  1876  	if !ok {
  1877  		t.Fatal("Unable to find mirred action")
  1878  	}
  1879  
  1880  	if mia.Attrs().Action != TC_ACT_STOLEN {
  1881  		t.Fatal("Mirred action isn't TC_ACT_STOLEN")
  1882  	}
  1883  
  1884  	if mia.Timestamp == nil || mia.Timestamp.Installed == 0 {
  1885  		t.Fatal("Incorrect mirred action timestamp")
  1886  	}
  1887  
  1888  	if mia.Statistics == nil {
  1889  		t.Fatal("Incorrect mirred action stats")
  1890  	}
  1891  
  1892  	ga, ok := flower.Actions[1].(*GenericAction)
  1893  	if !ok {
  1894  		t.Fatal("Unable to find generic action")
  1895  	}
  1896  
  1897  	if ga.Attrs().Action != getTcActGotoChain() {
  1898  		t.Fatal("Generic action isn't TC_ACT_GOTO_CHAIN")
  1899  	}
  1900  
  1901  	if ga.Timestamp == nil || ga.Timestamp.Installed == 0 {
  1902  		t.Fatal("Incorrect generic action timestamp")
  1903  	}
  1904  
  1905  	if ga.Statistics == nil {
  1906  		t.Fatal("Incorrect generic action stats")
  1907  	}
  1908  
  1909  	if err := FilterDel(filter); err != nil {
  1910  		t.Fatal(err)
  1911  	}
  1912  	filters, err = FilterList(link, MakeHandle(0xffff, 0))
  1913  	if err != nil {
  1914  		t.Fatal(err)
  1915  	}
  1916  	if len(filters) != 0 {
  1917  		t.Fatal("Failed to remove filter")
  1918  	}
  1919  
  1920  	if err := QdiscDel(qdisc); err != nil {
  1921  		t.Fatal(err)
  1922  	}
  1923  	qdiscs, err = SafeQdiscList(link)
  1924  	if err != nil {
  1925  		t.Fatal(err)
  1926  	}
  1927  
  1928  	found = false
  1929  	for _, v := range qdiscs {
  1930  		if _, ok := v.(*Ingress); ok {
  1931  			found = true
  1932  			break
  1933  		}
  1934  	}
  1935  	if found {
  1936  		t.Fatal("Failed to remove qdisc")
  1937  	}
  1938  }
  1939  
  1940  func TestFilterIPv6FlowerPedit(t *testing.T) {
  1941  	tearDown := setUpNetlinkTest(t)
  1942  	defer tearDown()
  1943  	if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
  1944  		t.Fatal(err)
  1945  	}
  1946  	if err := LinkAdd(&Ifb{LinkAttrs{Name: "bar"}}); err != nil {
  1947  		t.Fatal(err)
  1948  	}
  1949  	link, err := LinkByName("foo")
  1950  	if err != nil {
  1951  		t.Fatal(err)
  1952  	}
  1953  	if err := LinkSetUp(link); err != nil {
  1954  		t.Fatal(err)
  1955  	}
  1956  	redir, err := LinkByName("bar")
  1957  	if err != nil {
  1958  		t.Fatal(err)
  1959  	}
  1960  	if err := LinkSetUp(redir); err != nil {
  1961  		t.Fatal(err)
  1962  	}
  1963  
  1964  	qdisc := &Ingress{
  1965  		QdiscAttrs: QdiscAttrs{
  1966  			LinkIndex: link.Attrs().Index,
  1967  			Handle:    MakeHandle(0xffff, 0),
  1968  			Parent:    HANDLE_INGRESS,
  1969  		},
  1970  	}
  1971  	if err := QdiscAdd(qdisc); err != nil {
  1972  		t.Fatal(err)
  1973  	}
  1974  	qdiscs, err := SafeQdiscList(link)
  1975  	if err != nil {
  1976  		t.Fatal(err)
  1977  	}
  1978  
  1979  	found := false
  1980  	for _, v := range qdiscs {
  1981  		if _, ok := v.(*Ingress); ok {
  1982  			found = true
  1983  			break
  1984  		}
  1985  	}
  1986  	if !found {
  1987  		t.Fatal("Qdisc is the wrong type")
  1988  	}
  1989  
  1990  	testMask := net.CIDRMask(64, 128)
  1991  
  1992  	ipproto := new(nl.IPProto)
  1993  	*ipproto = nl.IPPROTO_TCP
  1994  
  1995  	filter := &Flower{
  1996  		FilterAttrs: FilterAttrs{
  1997  			LinkIndex: link.Attrs().Index,
  1998  			Parent:    MakeHandle(0xffff, 0),
  1999  			Priority:  1,
  2000  			Protocol:  unix.ETH_P_ALL,
  2001  		},
  2002  		DestIP:     net.ParseIP("ffff::fff1"),
  2003  		DestIPMask: testMask,
  2004  		EthType:    unix.ETH_P_IPV6,
  2005  		IPProto:    ipproto,
  2006  		DestPort:   6666,
  2007  		Actions:    []Action{},
  2008  	}
  2009  
  2010  	peditAction := NewPeditAction()
  2011  	peditAction.Proto = uint8(nl.IPPROTO_TCP)
  2012  	peditAction.SrcPort = 7777
  2013  	peditAction.SrcIP = net.ParseIP("ffff::fff2")
  2014  	filter.Actions = append(filter.Actions, peditAction)
  2015  
  2016  	miaAction := &MirredAction{
  2017  		ActionAttrs: ActionAttrs{
  2018  			Action: TC_ACT_REDIRECT,
  2019  		},
  2020  		MirredAction: TCA_EGRESS_REDIR,
  2021  		Ifindex:      redir.Attrs().Index,
  2022  	}
  2023  	filter.Actions = append(filter.Actions, miaAction)
  2024  
  2025  	if err := FilterAdd(filter); err != nil {
  2026  		t.Fatal(err)
  2027  	}
  2028  
  2029  	filters, err := FilterList(link, MakeHandle(0xffff, 0))
  2030  	if err != nil {
  2031  		t.Fatal(err)
  2032  	}
  2033  	if len(filters) != 1 {
  2034  		t.Fatal("Failed to add filter")
  2035  	}
  2036  	flower, ok := filters[0].(*Flower)
  2037  	if !ok {
  2038  		t.Fatal("Filter is the wrong type")
  2039  	}
  2040  
  2041  	if filter.EthType != flower.EthType {
  2042  		t.Fatalf("Flower EthType doesn't match")
  2043  	}
  2044  	if !filter.DestIP.Equal(flower.DestIP) {
  2045  		t.Fatalf("Flower DestIP doesn't match")
  2046  	}
  2047  
  2048  	if !reflect.DeepEqual(filter.DestIPMask, testMask) {
  2049  		t.Fatalf("Flower DestIPMask doesn't match")
  2050  	}
  2051  
  2052  	if flower.IPProto == nil || *filter.IPProto != *flower.IPProto {
  2053  		t.Fatalf("Flower IPProto doesn't match")
  2054  	}
  2055  	if filter.DestPort != flower.DestPort {
  2056  		t.Fatalf("Flower DestPort doesn't match")
  2057  	}
  2058  
  2059  	_, ok = flower.Actions[0].(*PeditAction)
  2060  	if !ok {
  2061  		t.Fatal("Unable to find pedit action")
  2062  	}
  2063  
  2064  	_, ok = flower.Actions[1].(*MirredAction)
  2065  	if !ok {
  2066  		t.Fatal("Unable to find mirred action")
  2067  	}
  2068  
  2069  	if err := FilterDel(filter); err != nil {
  2070  		t.Fatal(err)
  2071  	}
  2072  	filters, err = FilterList(link, MakeHandle(0xffff, 0))
  2073  	if err != nil {
  2074  		t.Fatal(err)
  2075  	}
  2076  	if len(filters) != 0 {
  2077  		t.Fatal("Failed to remove filter")
  2078  	}
  2079  
  2080  	if err := QdiscDel(qdisc); err != nil {
  2081  		t.Fatal(err)
  2082  	}
  2083  	qdiscs, err = SafeQdiscList(link)
  2084  	if err != nil {
  2085  		t.Fatal(err)
  2086  	}
  2087  
  2088  	found = false
  2089  	for _, v := range qdiscs {
  2090  		if _, ok := v.(*Ingress); ok {
  2091  			found = true
  2092  			break
  2093  		}
  2094  	}
  2095  	if found {
  2096  		t.Fatal("Failed to remove qdisc")
  2097  	}
  2098  }
  2099  
  2100  func TestFilterU32PoliceAddDel(t *testing.T) {
  2101  	tearDown := setUpNetlinkTest(t)
  2102  	defer tearDown()
  2103  	if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
  2104  		t.Fatal(err)
  2105  	}
  2106  	if err := LinkAdd(&Ifb{LinkAttrs{Name: "bar"}}); err != nil {
  2107  		t.Fatal(err)
  2108  	}
  2109  	link, err := LinkByName("foo")
  2110  	if err != nil {
  2111  		t.Fatal(err)
  2112  	}
  2113  	if err := LinkSetUp(link); err != nil {
  2114  		t.Fatal(err)
  2115  	}
  2116  	redir, err := LinkByName("bar")
  2117  	if err != nil {
  2118  		t.Fatal(err)
  2119  	}
  2120  	if err := LinkSetUp(redir); err != nil {
  2121  		t.Fatal(err)
  2122  	}
  2123  
  2124  	qdisc := &Ingress{
  2125  		QdiscAttrs: QdiscAttrs{
  2126  			LinkIndex: link.Attrs().Index,
  2127  			Handle:    MakeHandle(0xffff, 0),
  2128  			Parent:    HANDLE_INGRESS,
  2129  		},
  2130  	}
  2131  	if err := QdiscAdd(qdisc); err != nil {
  2132  		t.Fatal(err)
  2133  	}
  2134  	qdiscs, err := SafeQdiscList(link)
  2135  	if err != nil {
  2136  		t.Fatal(err)
  2137  	}
  2138  
  2139  	found := false
  2140  	for _, v := range qdiscs {
  2141  		if _, ok := v.(*Ingress); ok {
  2142  			found = true
  2143  			break
  2144  		}
  2145  	}
  2146  	if !found {
  2147  		t.Fatal("Qdisc is the wrong type")
  2148  	}
  2149  
  2150  	const (
  2151  		policeRate     = 0x40000000 // 1 Gbps
  2152  		policeBurst    = 0x19000    // 100 KB
  2153  		policePeakRate = 0x4000     // 16 Kbps
  2154  	)
  2155  
  2156  	police := NewPoliceAction()
  2157  	police.Rate = policeRate
  2158  	police.PeakRate = policePeakRate
  2159  	police.Burst = policeBurst
  2160  	police.ExceedAction = TC_POLICE_SHOT
  2161  	police.NotExceedAction = TC_POLICE_UNSPEC
  2162  
  2163  	classId := MakeHandle(1, 1)
  2164  	filter := &U32{
  2165  		FilterAttrs: FilterAttrs{
  2166  			LinkIndex: link.Attrs().Index,
  2167  			Parent:    MakeHandle(0xffff, 0),
  2168  			Priority:  1,
  2169  			Protocol:  unix.ETH_P_ALL,
  2170  		},
  2171  		ClassId: classId,
  2172  		Actions: []Action{
  2173  			police,
  2174  			&MirredAction{
  2175  				ActionAttrs: ActionAttrs{
  2176  					Action: TC_ACT_STOLEN,
  2177  				},
  2178  				MirredAction: TCA_EGRESS_REDIR,
  2179  				Ifindex:      redir.Attrs().Index,
  2180  			},
  2181  		},
  2182  	}
  2183  
  2184  	if err := FilterAdd(filter); err != nil {
  2185  		t.Fatal(err)
  2186  	}
  2187  
  2188  	filters, err := FilterList(link, MakeHandle(0xffff, 0))
  2189  	if err != nil {
  2190  		t.Fatal(err)
  2191  	}
  2192  	if len(filters) != 1 {
  2193  		t.Fatal("Failed to add filter")
  2194  	}
  2195  	u32, ok := filters[0].(*U32)
  2196  	if !ok {
  2197  		t.Fatal("Filter is the wrong type")
  2198  	}
  2199  
  2200  	if len(u32.Actions) != 2 {
  2201  		t.Fatalf("Too few Actions in filter")
  2202  	}
  2203  	if u32.ClassId != classId {
  2204  		t.Fatalf("ClassId of the filter is the wrong value")
  2205  	}
  2206  
  2207  	// actions can be returned in reverse order
  2208  	p, ok := u32.Actions[0].(*PoliceAction)
  2209  	if !ok {
  2210  		p, ok = u32.Actions[1].(*PoliceAction)
  2211  		if !ok {
  2212  			t.Fatal("Unable to find police action")
  2213  		}
  2214  	}
  2215  
  2216  	if p.ExceedAction != TC_POLICE_SHOT {
  2217  		t.Fatal("Police ExceedAction isn't TC_POLICE_SHOT")
  2218  	}
  2219  
  2220  	if p.NotExceedAction != TC_POLICE_UNSPEC {
  2221  		t.Fatal("Police NotExceedAction isn't TC_POLICE_UNSPEC")
  2222  	}
  2223  
  2224  	if p.Rate != policeRate {
  2225  		t.Fatal("Action Rate doesn't match")
  2226  	}
  2227  
  2228  	if p.PeakRate != policePeakRate {
  2229  		t.Fatal("Action PeakRate doesn't match")
  2230  	}
  2231  
  2232  	if p.LinkLayer != nl.LINKLAYER_ETHERNET {
  2233  		t.Fatal("Action LinkLayer doesn't match")
  2234  	}
  2235  
  2236  	mia, ok := u32.Actions[0].(*MirredAction)
  2237  	if !ok {
  2238  		mia, ok = u32.Actions[1].(*MirredAction)
  2239  		if !ok {
  2240  			t.Fatal("Unable to find mirred action")
  2241  		}
  2242  	}
  2243  
  2244  	if mia.Attrs().Action != TC_ACT_STOLEN {
  2245  		t.Fatal("Mirred action isn't TC_ACT_STOLEN")
  2246  	}
  2247  
  2248  	if err := FilterDel(filter); err != nil {
  2249  		t.Fatal(err)
  2250  	}
  2251  	filters, err = FilterList(link, MakeHandle(0xffff, 0))
  2252  	if err != nil {
  2253  		t.Fatal(err)
  2254  	}
  2255  	if len(filters) != 0 {
  2256  		t.Fatal("Failed to remove filter")
  2257  	}
  2258  
  2259  	if err := QdiscDel(qdisc); err != nil {
  2260  		t.Fatal(err)
  2261  	}
  2262  	qdiscs, err = SafeQdiscList(link)
  2263  	if err != nil {
  2264  		t.Fatal(err)
  2265  	}
  2266  
  2267  	found = false
  2268  	for _, v := range qdiscs {
  2269  		if _, ok := v.(*Ingress); ok {
  2270  			found = true
  2271  			break
  2272  		}
  2273  	}
  2274  	if found {
  2275  		t.Fatal("Failed to remove qdisc")
  2276  	}
  2277  }
  2278  
  2279  func TestFilterU32DirectPoliceAddDel(t *testing.T) {
  2280  	tearDown := setUpNetlinkTest(t)
  2281  	defer tearDown()
  2282  	if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
  2283  		t.Fatal(err)
  2284  	}
  2285  	link, err := LinkByName("foo")
  2286  	if err != nil {
  2287  		t.Fatal(err)
  2288  	}
  2289  	if err := LinkSetUp(link); err != nil {
  2290  		t.Fatal(err)
  2291  	}
  2292  
  2293  	qdisc := &Ingress{
  2294  		QdiscAttrs: QdiscAttrs{
  2295  			LinkIndex: link.Attrs().Index,
  2296  			Handle:    MakeHandle(0xffff, 0),
  2297  			Parent:    HANDLE_INGRESS,
  2298  		},
  2299  	}
  2300  	if err := QdiscAdd(qdisc); err != nil {
  2301  		t.Fatal(err)
  2302  	}
  2303  
  2304  	const (
  2305  		policeRate     = 0x40000000 // 1 Gbps
  2306  		policeBurst    = 0x19000    // 100 KB
  2307  		policePeakRate = 0x4000     // 16 Kbps
  2308  	)
  2309  
  2310  	police := NewPoliceAction()
  2311  	police.Rate = policeRate
  2312  	police.PeakRate = policePeakRate
  2313  	police.Burst = policeBurst
  2314  	police.ExceedAction = TC_POLICE_SHOT
  2315  	police.NotExceedAction = TC_POLICE_UNSPEC
  2316  
  2317  	classId := MakeHandle(1, 1)
  2318  	filter := &U32{
  2319  		FilterAttrs: FilterAttrs{
  2320  			LinkIndex: link.Attrs().Index,
  2321  			Parent:    MakeHandle(0xffff, 0),
  2322  			Priority:  1,
  2323  			Protocol:  unix.ETH_P_ALL,
  2324  		},
  2325  		ClassId: classId,
  2326  		Police:  police,
  2327  	}
  2328  
  2329  	if err := FilterAdd(filter); err != nil {
  2330  		t.Fatal(err)
  2331  	}
  2332  
  2333  	filters, err := FilterList(link, MakeHandle(0xffff, 0))
  2334  	if err != nil {
  2335  		t.Fatal(err)
  2336  	}
  2337  	if len(filters) != 1 {
  2338  		t.Fatal("Failed to add filter")
  2339  	}
  2340  	u32, ok := filters[0].(*U32)
  2341  	if !ok {
  2342  		t.Fatal("Filter is the wrong type")
  2343  	}
  2344  
  2345  	if u32.Police == nil {
  2346  		t.Fatalf("No police in filter")
  2347  	}
  2348  
  2349  	if u32.Police.Rate != policeRate {
  2350  		t.Fatal("Filter Rate doesn't match")
  2351  	}
  2352  
  2353  	if u32.Police.PeakRate != policePeakRate {
  2354  		t.Fatal("Filter PeakRate doesn't match")
  2355  	}
  2356  
  2357  	if u32.Police.LinkLayer != nl.LINKLAYER_ETHERNET {
  2358  		t.Fatal("Filter LinkLayer doesn't match")
  2359  	}
  2360  
  2361  	if err := QdiscDel(qdisc); err != nil {
  2362  		t.Fatal(err)
  2363  	}
  2364  	qdiscs, err := SafeQdiscList(link)
  2365  	if err != nil {
  2366  		t.Fatal(err)
  2367  	}
  2368  
  2369  	found := false
  2370  	for _, v := range qdiscs {
  2371  		if _, ok := v.(*Ingress); ok {
  2372  			found = true
  2373  			break
  2374  		}
  2375  	}
  2376  	if found {
  2377  		t.Fatal("Failed to remove qdisc")
  2378  	}
  2379  }
  2380  
  2381  func TestFilterChainAddDel(t *testing.T) {
  2382  	tearDown := setUpNetlinkTest(t)
  2383  	defer tearDown()
  2384  	if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
  2385  		t.Fatal(err)
  2386  	}
  2387  	if err := LinkAdd(&Ifb{LinkAttrs{Name: "bar"}}); err != nil {
  2388  		t.Fatal(err)
  2389  	}
  2390  	link, err := LinkByName("foo")
  2391  	if err != nil {
  2392  		t.Fatal(err)
  2393  	}
  2394  	if err := LinkSetUp(link); err != nil {
  2395  		t.Fatal(err)
  2396  	}
  2397  	redir, err := LinkByName("bar")
  2398  	if err != nil {
  2399  		t.Fatal(err)
  2400  	}
  2401  	if err := LinkSetUp(redir); err != nil {
  2402  		t.Fatal(err)
  2403  	}
  2404  	qdisc := &Ingress{
  2405  		QdiscAttrs: QdiscAttrs{
  2406  			LinkIndex: link.Attrs().Index,
  2407  			Handle:    MakeHandle(0xffff, 0),
  2408  			Parent:    HANDLE_INGRESS,
  2409  		},
  2410  	}
  2411  	if err := QdiscAdd(qdisc); err != nil {
  2412  		t.Fatal(err)
  2413  	}
  2414  	qdiscs, err := SafeQdiscList(link)
  2415  	if err != nil {
  2416  		t.Fatal(err)
  2417  	}
  2418  	if len(qdiscs) != 1 {
  2419  		t.Fatal("Failed to add qdisc")
  2420  	}
  2421  	_, ok := qdiscs[0].(*Ingress)
  2422  	if !ok {
  2423  		t.Fatal("Qdisc is the wrong type")
  2424  	}
  2425  	classId := MakeHandle(1, 1)
  2426  	chainVal := new(uint32)
  2427  	*chainVal = 20
  2428  	filter := &U32{
  2429  		FilterAttrs: FilterAttrs{
  2430  			LinkIndex: link.Attrs().Index,
  2431  			Parent:    MakeHandle(0xffff, 0),
  2432  			Priority:  1,
  2433  			Protocol:  unix.ETH_P_IP,
  2434  			Chain:     chainVal,
  2435  		},
  2436  		RedirIndex: redir.Attrs().Index,
  2437  		ClassId:    classId,
  2438  	}
  2439  	if err := FilterAdd(filter); err != nil {
  2440  		t.Fatal(err)
  2441  	}
  2442  	filters, err := FilterList(link, MakeHandle(0xffff, 0))
  2443  	if err != nil {
  2444  		t.Fatal(err)
  2445  	}
  2446  	if len(filters) != 1 {
  2447  		t.Fatal("Failed to add filter")
  2448  	}
  2449  	filterChain := filters[0].Attrs().Chain
  2450  	if filterChain != nil && *filterChain != *chainVal {
  2451  		t.Fatalf("Chain of the filter is the wrong value")
  2452  	}
  2453  	if err := FilterDel(filter); err != nil {
  2454  		t.Fatal(err)
  2455  	}
  2456  	filters, err = FilterList(link, MakeHandle(0xffff, 0))
  2457  	if err != nil {
  2458  		t.Fatal(err)
  2459  	}
  2460  	if len(filters) != 0 {
  2461  		t.Fatal("Failed to remove filter")
  2462  	}
  2463  	if err := QdiscDel(qdisc); err != nil {
  2464  		t.Fatal(err)
  2465  	}
  2466  	qdiscs, err = SafeQdiscList(link)
  2467  	if err != nil {
  2468  		t.Fatal(err)
  2469  	}
  2470  	if len(qdiscs) != 0 {
  2471  		t.Fatal("Failed to remove qdisc")
  2472  	}
  2473  }