github.com/vishvananda/netlink@v1.3.1/route_test.go (about)

     1  //go:build linux
     2  // +build linux
     3  
     4  package netlink
     5  
     6  import (
     7  	"net"
     8  	"os"
     9  	"runtime"
    10  	"strconv"
    11  	"testing"
    12  	"time"
    13  
    14  	"github.com/vishvananda/netlink/nl"
    15  	"github.com/vishvananda/netns"
    16  	"golang.org/x/sys/unix"
    17  )
    18  
    19  func TestRouteAddDel(t *testing.T) {
    20  	tearDown := setUpNetlinkTest(t)
    21  	defer tearDown()
    22  
    23  	// get loopback interface
    24  	link, err := LinkByName("lo")
    25  	if err != nil {
    26  		t.Fatal(err)
    27  	}
    28  
    29  	// bring the interface up
    30  	if err := LinkSetUp(link); err != nil {
    31  		t.Fatal(err)
    32  	}
    33  
    34  	// add a gateway route
    35  	dst := &net.IPNet{
    36  		IP:   net.IPv4(192, 168, 0, 0),
    37  		Mask: net.CIDRMask(24, 32),
    38  	}
    39  
    40  	ip := net.IPv4(127, 1, 1, 1)
    41  	route := Route{LinkIndex: link.Attrs().Index, Dst: dst, Src: ip}
    42  	if err := RouteAdd(&route); err != nil {
    43  		t.Fatal(err)
    44  	}
    45  	routes, err := RouteList(link, FAMILY_V4)
    46  	if err != nil {
    47  		t.Fatal(err)
    48  	}
    49  	if len(routes) != 1 {
    50  		t.Fatal("Route not added properly")
    51  	}
    52  
    53  	routes, err = RouteList(nil, FAMILY_V4)
    54  	if err != nil {
    55  		t.Fatal(err)
    56  	}
    57  	if len(routes) != 1 {
    58  		t.Fatal("Route not listed properly")
    59  	}
    60  
    61  	dstIP := net.IPv4(192, 168, 0, 42)
    62  	routeToDstIP, err := RouteGet(dstIP)
    63  	if err != nil {
    64  		t.Fatal(err)
    65  	}
    66  
    67  	if len(routeToDstIP) == 0 {
    68  		t.Fatal("Default route not present")
    69  	}
    70  	if err := RouteDel(&route); err != nil {
    71  		t.Fatal(err)
    72  	}
    73  	routes, err = RouteList(link, FAMILY_V4)
    74  	if err != nil {
    75  		t.Fatal(err)
    76  	}
    77  	if len(routes) != 0 {
    78  		t.Fatal("Route not removed properly")
    79  	}
    80  
    81  	// add default route test
    82  	// equiv: default dev lo
    83  	_, defaultDst, _ := net.ParseCIDR("0.0.0.0/0")
    84  	route = Route{Dst: defaultDst, LinkIndex: link.Attrs().Index}
    85  	if err := RouteAdd(&route); err != nil {
    86  		t.Fatal(err)
    87  	}
    88  	routes, err = RouteList(link, FAMILY_V4)
    89  	if err != nil {
    90  		t.Fatal(err)
    91  	}
    92  	if len(routes) != 1 {
    93  		t.Fatal("Dev default route not listed properly")
    94  	}
    95  	if err := RouteDel(&routes[0]); err != nil {
    96  		t.Fatal(err)
    97  	}
    98  	routes, err = RouteList(link, FAMILY_V4)
    99  	if err != nil {
   100  		t.Fatal(err)
   101  	}
   102  	if len(routes) != 0 {
   103  		t.Fatal("Dev default route not removed properly")
   104  	}
   105  
   106  	// equiv: blackhole default
   107  	route = Route{Dst: defaultDst, Type: unix.RTN_BLACKHOLE, Family: FAMILY_V4}
   108  	if err := RouteAdd(&route); err != nil {
   109  		t.Fatal(err)
   110  	}
   111  	routes, err = RouteList(nil, FAMILY_V4)
   112  	if err != nil {
   113  		t.Fatal(err)
   114  	}
   115  	t.Logf("%+v", routes)
   116  
   117  	if len(routes) != 1 {
   118  		t.Fatal("Blackhole default route not listed properly")
   119  	}
   120  
   121  	if err := RouteDel(&routes[0]); err != nil {
   122  		t.Fatal(err)
   123  	}
   124  	routes, err = RouteList(nil, FAMILY_V4)
   125  	if err != nil {
   126  		t.Fatal(err)
   127  	}
   128  	if len(routes) != 0 {
   129  		t.Fatal("Blackhole default route not removed properly")
   130  	}
   131  
   132  	// equiv: prohibit default
   133  	route = Route{Dst: defaultDst, Type: unix.RTN_PROHIBIT}
   134  	if err := RouteAdd(&route); err != nil {
   135  		t.Fatal(err)
   136  	}
   137  	routes, err = RouteList(nil, FAMILY_V4)
   138  	if err != nil {
   139  		t.Fatal(err)
   140  	}
   141  	if len(routes) != 1 {
   142  		t.Fatal("Prohibit default route not listed properly")
   143  	}
   144  
   145  	if err := RouteDel(&routes[0]); err != nil {
   146  		t.Fatal(err)
   147  	}
   148  	routes, err = RouteList(nil, FAMILY_V4)
   149  	if err != nil {
   150  		t.Fatal(err)
   151  	}
   152  	if len(routes) != 0 {
   153  		t.Fatal("Prohibit default route not removed properly")
   154  	}
   155  }
   156  
   157  func TestRoute6AddDel(t *testing.T) {
   158  	tearDown := setUpNetlinkTest(t)
   159  	defer tearDown()
   160  
   161  	// create dummy interface
   162  	// IPv6 route added to loopback interface will be unreachable
   163  	la := NewLinkAttrs()
   164  	la.Name = "dummy_route6"
   165  	la.TxQLen = 1500
   166  	dummy := &Dummy{LinkAttrs: la}
   167  	if err := LinkAdd(dummy); err != nil {
   168  		t.Fatal(err)
   169  	}
   170  
   171  	// get dummy interface
   172  	link, err := LinkByName("dummy_route6")
   173  	if err != nil {
   174  		t.Fatal(err)
   175  	}
   176  
   177  	// bring the interface up
   178  	if err := LinkSetUp(link); err != nil {
   179  		t.Fatal(err)
   180  	}
   181  
   182  	// remember number of routes before adding
   183  	// typically one route (fe80::/64) will be created when dummy_route6 is created
   184  	routes, err := RouteList(link, FAMILY_V6)
   185  	if err != nil {
   186  		t.Fatal(err)
   187  	}
   188  	nroutes := len(routes)
   189  
   190  	// add a gateway route
   191  	dst := &net.IPNet{
   192  		IP:   net.ParseIP("2001:db8::0"),
   193  		Mask: net.CIDRMask(64, 128),
   194  	}
   195  	route := Route{LinkIndex: link.Attrs().Index, Dst: dst}
   196  	if err := RouteAdd(&route); err != nil {
   197  		t.Fatal(err)
   198  	}
   199  	routes, err = RouteList(link, FAMILY_V6)
   200  	if err != nil {
   201  		t.Fatal(err)
   202  	}
   203  	if len(routes) != nroutes+1 {
   204  		t.Fatal("Route not added properly")
   205  	}
   206  
   207  	dstIP := net.ParseIP("2001:db8::1")
   208  	routeToDstIP, err := RouteGet(dstIP)
   209  	if err != nil {
   210  		t.Fatal(err)
   211  	}
   212  
   213  	// cleanup route
   214  	if len(routeToDstIP) == 0 {
   215  		t.Fatal("Route not present")
   216  	}
   217  	if err := RouteDel(&route); err != nil {
   218  		t.Fatal(err)
   219  	}
   220  	routes, err = RouteList(link, FAMILY_V6)
   221  	if err != nil {
   222  		t.Fatal(err)
   223  	}
   224  	if len(routes) != nroutes {
   225  		t.Fatal("Route not removed properly")
   226  	}
   227  
   228  	// add a default link route
   229  	_, defaultDst, _ := net.ParseCIDR("::/0")
   230  	route = Route{LinkIndex: link.Attrs().Index, Dst: defaultDst}
   231  	if err := RouteAdd(&route); err != nil {
   232  		t.Fatal(err)
   233  	}
   234  	routes, err = RouteList(link, FAMILY_V6)
   235  	if err != nil {
   236  		t.Fatal(err)
   237  	}
   238  	if len(routes) != nroutes+1 {
   239  		t.Fatal("Default route not added properly")
   240  	}
   241  
   242  	// add a default link route
   243  	for _, route := range routes {
   244  		if route.Dst.String() == defaultDst.String() {
   245  			if err := RouteDel(&route); err != nil {
   246  				t.Fatal(err)
   247  			}
   248  		}
   249  	}
   250  	routes, err = RouteList(link, FAMILY_V6)
   251  	if err != nil {
   252  		t.Fatal(err)
   253  	}
   254  	if len(routes) != nroutes {
   255  		t.Fatal("Default route not removed properly")
   256  	}
   257  
   258  	// add blackhole default link route
   259  	routes, err = RouteList(nil, FAMILY_V6)
   260  	if err != nil {
   261  		t.Fatal(err)
   262  	}
   263  	nroutes = len(routes)
   264  
   265  	route = Route{Type: unix.RTN_BLACKHOLE, Dst: defaultDst}
   266  	if err := RouteAdd(&route); err != nil {
   267  		t.Fatal(err)
   268  	}
   269  	routes, err = RouteList(nil, FAMILY_V6)
   270  	if err != nil {
   271  		t.Fatal(err)
   272  	}
   273  	if len(routes) != nroutes+1 {
   274  		t.Fatal("Blackhole default route not added properly")
   275  	}
   276  
   277  	// add blackhole default link route
   278  	for _, route := range routes {
   279  		if ipNetEqual(route.Dst, defaultDst) {
   280  			if err := RouteDel(&route); err != nil {
   281  				t.Fatal(err)
   282  			}
   283  		}
   284  	}
   285  	routes, err = RouteList(nil, FAMILY_V6)
   286  	if err != nil {
   287  		t.Fatal(err)
   288  	}
   289  	if len(routes) != nroutes {
   290  		t.Fatal("Blackhole default route not removed properly")
   291  	}
   292  
   293  	// add prohibit default link route
   294  	routes, err = RouteList(nil, FAMILY_V6)
   295  	if err != nil {
   296  		t.Fatal(err)
   297  	}
   298  	nroutes = len(routes)
   299  
   300  	route = Route{Type: unix.RTN_BLACKHOLE, Dst: defaultDst}
   301  	if err := RouteAdd(&route); err != nil {
   302  		t.Fatal(err)
   303  	}
   304  	routes, err = RouteList(nil, FAMILY_V6)
   305  	if err != nil {
   306  		t.Fatal(err)
   307  	}
   308  	if len(routes) != nroutes+1 {
   309  		t.Fatal("Prohibit default route not added properly")
   310  	}
   311  
   312  	// add prohibit default link route
   313  	for _, route := range routes {
   314  		if ipNetEqual(route.Dst, defaultDst) {
   315  			if err := RouteDel(&route); err != nil {
   316  				t.Fatal(err)
   317  			}
   318  		}
   319  	}
   320  	routes, err = RouteList(nil, FAMILY_V6)
   321  	if err != nil {
   322  		t.Fatal(err)
   323  	}
   324  	if len(routes) != nroutes {
   325  		t.Fatal("Prohibit default route not removed properly")
   326  	}
   327  
   328  	// cleanup dummy interface created for the test
   329  	if err := LinkDel(link); err != nil {
   330  		t.Fatal(err)
   331  	}
   332  }
   333  
   334  func TestRouteChange(t *testing.T) {
   335  	tearDown := setUpNetlinkTest(t)
   336  	defer tearDown()
   337  
   338  	// get loopback interface
   339  	link, err := LinkByName("lo")
   340  	if err != nil {
   341  		t.Fatal(err)
   342  	}
   343  
   344  	// bring the interface up
   345  	if err := LinkSetUp(link); err != nil {
   346  		t.Fatal(err)
   347  	}
   348  
   349  	// add a gateway route
   350  	dst := &net.IPNet{
   351  		IP:   net.IPv4(192, 168, 0, 0),
   352  		Mask: net.CIDRMask(24, 32),
   353  	}
   354  
   355  	ip := net.IPv4(127, 1, 1, 1)
   356  	route := Route{LinkIndex: link.Attrs().Index, Dst: dst, Src: ip}
   357  
   358  	if err := RouteChange(&route); err == nil {
   359  		t.Fatal("Route added while it should fail")
   360  	}
   361  
   362  	if err := RouteAdd(&route); err != nil {
   363  		t.Fatal(err)
   364  	}
   365  	routes, err := RouteList(link, FAMILY_V4)
   366  	if err != nil {
   367  		t.Fatal(err)
   368  	}
   369  	if len(routes) != 1 {
   370  		t.Fatal("Route not added properly")
   371  	}
   372  
   373  	ip = net.IPv4(127, 1, 1, 2)
   374  	route = Route{LinkIndex: link.Attrs().Index, Dst: dst, Src: ip}
   375  	if err := RouteChange(&route); err != nil {
   376  		t.Fatal(err)
   377  	}
   378  
   379  	routes, err = RouteList(link, FAMILY_V4)
   380  	if err != nil {
   381  		t.Fatal(err)
   382  	}
   383  
   384  	if len(routes) != 1 || !routes[0].Src.Equal(ip) {
   385  		t.Fatal("Route not changed properly")
   386  	}
   387  
   388  	if err := RouteDel(&route); err != nil {
   389  		t.Fatal(err)
   390  	}
   391  	routes, err = RouteList(link, FAMILY_V4)
   392  	if err != nil {
   393  		t.Fatal(err)
   394  	}
   395  	if len(routes) != 0 {
   396  		t.Fatal("Route not removed properly")
   397  	}
   398  }
   399  
   400  func TestRouteReplace(t *testing.T) {
   401  	tearDown := setUpNetlinkTest(t)
   402  	defer tearDown()
   403  
   404  	// get loopback interface
   405  	link, err := LinkByName("lo")
   406  	if err != nil {
   407  		t.Fatal(err)
   408  	}
   409  
   410  	// bring the interface up
   411  	if err := LinkSetUp(link); err != nil {
   412  		t.Fatal(err)
   413  	}
   414  
   415  	// add a gateway route
   416  	dst := &net.IPNet{
   417  		IP:   net.IPv4(192, 168, 0, 0),
   418  		Mask: net.CIDRMask(24, 32),
   419  	}
   420  
   421  	ip := net.IPv4(127, 1, 1, 1)
   422  	route := Route{LinkIndex: link.Attrs().Index, Dst: dst, Src: ip}
   423  	if err := RouteAdd(&route); err != nil {
   424  		t.Fatal(err)
   425  	}
   426  	routes, err := RouteList(link, FAMILY_V4)
   427  	if err != nil {
   428  		t.Fatal(err)
   429  	}
   430  	if len(routes) != 1 {
   431  		t.Fatal("Route not added properly")
   432  	}
   433  
   434  	ip = net.IPv4(127, 1, 1, 2)
   435  	route = Route{LinkIndex: link.Attrs().Index, Dst: dst, Src: ip}
   436  	if err := RouteReplace(&route); err != nil {
   437  		t.Fatal(err)
   438  	}
   439  
   440  	routes, err = RouteList(link, FAMILY_V4)
   441  	if err != nil {
   442  		t.Fatal(err)
   443  	}
   444  
   445  	if len(routes) != 1 || !routes[0].Src.Equal(ip) {
   446  		t.Fatal("Route not replaced properly")
   447  	}
   448  
   449  	if err := RouteDel(&route); err != nil {
   450  		t.Fatal(err)
   451  	}
   452  	routes, err = RouteList(link, FAMILY_V4)
   453  	if err != nil {
   454  		t.Fatal(err)
   455  	}
   456  	if len(routes) != 0 {
   457  		t.Fatal("Route not removed properly")
   458  	}
   459  }
   460  
   461  func TestRouteAppend(t *testing.T) {
   462  	tearDown := setUpNetlinkTest(t)
   463  	defer tearDown()
   464  
   465  	// get loopback interface
   466  	link, err := LinkByName("lo")
   467  	if err != nil {
   468  		t.Fatal(err)
   469  	}
   470  
   471  	// bring the interface up
   472  	if err := LinkSetUp(link); err != nil {
   473  		t.Fatal(err)
   474  	}
   475  
   476  	// add a gateway route
   477  	dst := &net.IPNet{
   478  		IP:   net.IPv4(192, 168, 0, 0),
   479  		Mask: net.CIDRMask(24, 32),
   480  	}
   481  
   482  	ip := net.IPv4(127, 1, 1, 1)
   483  	route := Route{LinkIndex: link.Attrs().Index, Dst: dst, Src: ip}
   484  	if err := RouteAdd(&route); err != nil {
   485  		t.Fatal(err)
   486  	}
   487  	routes, err := RouteList(link, FAMILY_V4)
   488  	if err != nil {
   489  		t.Fatal(err)
   490  	}
   491  	if len(routes) != 1 {
   492  		t.Fatal("Route not added properly")
   493  	}
   494  
   495  	ip = net.IPv4(127, 1, 1, 2)
   496  	route = Route{LinkIndex: link.Attrs().Index, Dst: dst, Src: ip}
   497  	if err := RouteAppend(&route); err != nil {
   498  		t.Fatal(err)
   499  	}
   500  
   501  	routes, err = RouteList(link, FAMILY_V4)
   502  	if err != nil {
   503  		t.Fatal(err)
   504  	}
   505  
   506  	if len(routes) != 2 || !routes[1].Src.Equal(ip) {
   507  		t.Fatal("Route not append properly")
   508  	}
   509  
   510  	if err := RouteDel(&routes[0]); err != nil {
   511  		t.Fatal(err)
   512  	}
   513  	if err := RouteDel(&routes[1]); err != nil {
   514  		t.Fatal(err)
   515  	}
   516  	routes, err = RouteList(link, FAMILY_V4)
   517  	if err != nil {
   518  		t.Fatal(err)
   519  	}
   520  	if len(routes) != 0 {
   521  		t.Fatal("Route not removed properly")
   522  	}
   523  }
   524  
   525  func TestRouteAddIncomplete(t *testing.T) {
   526  	tearDown := setUpNetlinkTest(t)
   527  	defer tearDown()
   528  
   529  	// get loopback interface
   530  	link, err := LinkByName("lo")
   531  	if err != nil {
   532  		t.Fatal(err)
   533  	}
   534  
   535  	// bring the interface up
   536  	if err = LinkSetUp(link); err != nil {
   537  		t.Fatal(err)
   538  	}
   539  
   540  	route := Route{LinkIndex: link.Attrs().Index}
   541  	if err := RouteAdd(&route); err == nil {
   542  		t.Fatal("Adding incomplete route should fail")
   543  	}
   544  }
   545  
   546  // expectRouteUpdate returns whether the expected updated is received within one minute.
   547  func expectRouteUpdate(ch <-chan RouteUpdate, t, f uint16, dst net.IP) bool {
   548  	for {
   549  		timeout := time.After(time.Minute)
   550  		select {
   551  		case update := <-ch:
   552  			if update.Type == t &&
   553  				update.NlFlags == f &&
   554  				update.Route.Dst != nil &&
   555  				update.Route.Dst.IP.Equal(dst) {
   556  				return true
   557  			}
   558  		case <-timeout:
   559  			return false
   560  		}
   561  	}
   562  }
   563  
   564  func TestRouteSubscribe(t *testing.T) {
   565  	tearDown := setUpNetlinkTest(t)
   566  	defer tearDown()
   567  
   568  	ch := make(chan RouteUpdate)
   569  	done := make(chan struct{})
   570  	defer close(done)
   571  	if err := RouteSubscribe(ch, done); err != nil {
   572  		t.Fatal(err)
   573  	}
   574  
   575  	// get loopback interface
   576  	link, err := LinkByName("lo")
   577  	if err != nil {
   578  		t.Fatal(err)
   579  	}
   580  
   581  	// bring the interface up
   582  	if err = LinkSetUp(link); err != nil {
   583  		t.Fatal(err)
   584  	}
   585  
   586  	// add a gateway route
   587  	dst := &net.IPNet{
   588  		IP:   net.IPv4(192, 168, 0, 0),
   589  		Mask: net.CIDRMask(24, 32),
   590  	}
   591  
   592  	ip := net.IPv4(127, 1, 1, 1)
   593  	route := Route{LinkIndex: link.Attrs().Index, Dst: dst, Src: ip}
   594  	if err := RouteAdd(&route); err != nil {
   595  		t.Fatal(err)
   596  	}
   597  
   598  	if !expectRouteUpdate(ch, unix.RTM_NEWROUTE, unix.NLM_F_EXCL|unix.NLM_F_CREATE, dst.IP) {
   599  		t.Fatal("Add update not received as expected")
   600  	}
   601  	if err := RouteDel(&route); err != nil {
   602  		t.Fatal(err)
   603  	}
   604  	if !expectRouteUpdate(ch, unix.RTM_DELROUTE, 0, dst.IP) {
   605  		t.Fatal("Del update not received as expected")
   606  	}
   607  }
   608  
   609  func TestRouteSubscribeWithOptions(t *testing.T) {
   610  	tearDown := setUpNetlinkTest(t)
   611  	defer tearDown()
   612  
   613  	ch := make(chan RouteUpdate)
   614  	done := make(chan struct{})
   615  	defer close(done)
   616  	var lastError error
   617  	defer func() {
   618  		if lastError != nil {
   619  			t.Fatalf("Fatal error received during subscription: %v", lastError)
   620  		}
   621  	}()
   622  	if err := RouteSubscribeWithOptions(ch, done, RouteSubscribeOptions{
   623  		ErrorCallback: func(err error) {
   624  			lastError = err
   625  		},
   626  	}); err != nil {
   627  		t.Fatal(err)
   628  	}
   629  
   630  	// get loopback interface
   631  	link, err := LinkByName("lo")
   632  	if err != nil {
   633  		t.Fatal(err)
   634  	}
   635  
   636  	// bring the interface up
   637  	if err = LinkSetUp(link); err != nil {
   638  		t.Fatal(err)
   639  	}
   640  
   641  	// add a gateway route
   642  	dst := &net.IPNet{
   643  		IP:   net.IPv4(192, 168, 0, 0),
   644  		Mask: net.CIDRMask(24, 32),
   645  	}
   646  
   647  	ip := net.IPv4(127, 1, 1, 1)
   648  	route := Route{LinkIndex: link.Attrs().Index, Dst: dst, Src: ip}
   649  	if err := RouteAdd(&route); err != nil {
   650  		t.Fatal(err)
   651  	}
   652  
   653  	if !expectRouteUpdate(ch, unix.RTM_NEWROUTE, unix.NLM_F_EXCL|unix.NLM_F_CREATE, dst.IP) {
   654  		t.Fatal("Add update not received as expected")
   655  	}
   656  }
   657  
   658  func TestRouteSubscribeAt(t *testing.T) {
   659  	skipUnlessRoot(t)
   660  
   661  	// Create an handle on a custom netns
   662  	newNs, err := netns.New()
   663  	if err != nil {
   664  		t.Fatal(err)
   665  	}
   666  	defer newNs.Close()
   667  
   668  	nh, err := NewHandleAt(newNs)
   669  	if err != nil {
   670  		t.Fatal(err)
   671  	}
   672  	defer nh.Close()
   673  
   674  	// Subscribe for Route events on the custom netns
   675  	ch := make(chan RouteUpdate)
   676  	done := make(chan struct{})
   677  	defer close(done)
   678  	if err := RouteSubscribeAt(newNs, ch, done); err != nil {
   679  		t.Fatal(err)
   680  	}
   681  
   682  	// get loopback interface
   683  	link, err := nh.LinkByName("lo")
   684  	if err != nil {
   685  		t.Fatal(err)
   686  	}
   687  
   688  	// bring the interface up
   689  	if err = nh.LinkSetUp(link); err != nil {
   690  		t.Fatal(err)
   691  	}
   692  
   693  	// add a gateway route
   694  	dst := &net.IPNet{
   695  		IP:   net.IPv4(192, 169, 0, 0),
   696  		Mask: net.CIDRMask(24, 32),
   697  	}
   698  
   699  	ip := net.IPv4(127, 100, 1, 1)
   700  	route := Route{LinkIndex: link.Attrs().Index, Dst: dst, Src: ip}
   701  	if err := nh.RouteAdd(&route); err != nil {
   702  		t.Fatal(err)
   703  	}
   704  
   705  	if !expectRouteUpdate(ch, unix.RTM_NEWROUTE, unix.NLM_F_EXCL|unix.NLM_F_CREATE, dst.IP) {
   706  		t.Fatal("Add update not received as expected")
   707  	}
   708  	if err := nh.RouteDel(&route); err != nil {
   709  		t.Fatal(err)
   710  	}
   711  	if !expectRouteUpdate(ch, unix.RTM_DELROUTE, 0, dst.IP) {
   712  		t.Fatal("Del update not received as expected")
   713  	}
   714  }
   715  
   716  func TestRouteSubscribeListExisting(t *testing.T) {
   717  	skipUnlessRoot(t)
   718  
   719  	// Create an handle on a custom netns
   720  	newNs, err := netns.New()
   721  	if err != nil {
   722  		t.Fatal(err)
   723  	}
   724  	defer newNs.Close()
   725  
   726  	nh, err := NewHandleAt(newNs)
   727  	if err != nil {
   728  		t.Fatal(err)
   729  	}
   730  	defer nh.Close()
   731  
   732  	// get loopback interface
   733  	link, err := nh.LinkByName("lo")
   734  	if err != nil {
   735  		t.Fatal(err)
   736  	}
   737  
   738  	// bring the interface up
   739  	if err = nh.LinkSetUp(link); err != nil {
   740  		t.Fatal(err)
   741  	}
   742  
   743  	// add a gateway route before subscribing
   744  	dst10 := &net.IPNet{
   745  		IP:   net.IPv4(10, 10, 10, 0),
   746  		Mask: net.CIDRMask(24, 32),
   747  	}
   748  
   749  	ip := net.IPv4(127, 100, 1, 1)
   750  	route10 := Route{LinkIndex: link.Attrs().Index, Dst: dst10, Src: ip}
   751  	if err := nh.RouteAdd(&route10); err != nil {
   752  		t.Fatal(err)
   753  	}
   754  
   755  	// Subscribe for Route events including existing routes
   756  	ch := make(chan RouteUpdate)
   757  	done := make(chan struct{})
   758  	defer close(done)
   759  	if err := RouteSubscribeWithOptions(ch, done, RouteSubscribeOptions{
   760  		Namespace:    &newNs,
   761  		ListExisting: true},
   762  	); err != nil {
   763  		t.Fatal(err)
   764  	}
   765  
   766  	if !expectRouteUpdate(ch, unix.RTM_NEWROUTE, 0, dst10.IP) {
   767  		t.Fatal("Existing add update not received as expected")
   768  	}
   769  
   770  	// add a gateway route
   771  	dst := &net.IPNet{
   772  		IP:   net.IPv4(192, 169, 0, 0),
   773  		Mask: net.CIDRMask(24, 32),
   774  	}
   775  
   776  	route := Route{LinkIndex: link.Attrs().Index, Dst: dst, Src: ip}
   777  	if err := nh.RouteAdd(&route); err != nil {
   778  		t.Fatal(err)
   779  	}
   780  
   781  	if !expectRouteUpdate(ch, unix.RTM_NEWROUTE, unix.NLM_F_EXCL|unix.NLM_F_CREATE, dst.IP) {
   782  		t.Fatal("Add update not received as expected")
   783  	}
   784  	if err := nh.RouteDel(&route); err != nil {
   785  		t.Fatal(err)
   786  	}
   787  	if !expectRouteUpdate(ch, unix.RTM_DELROUTE, 0, dst.IP) {
   788  		t.Fatal("Del update not received as expected")
   789  	}
   790  	if err := nh.RouteDel(&route10); err != nil {
   791  		t.Fatal(err)
   792  	}
   793  	if !expectRouteUpdate(ch, unix.RTM_DELROUTE, 0, dst10.IP) {
   794  		t.Fatal("Del update not received as expected")
   795  	}
   796  }
   797  
   798  func TestRouteFilterAllTables(t *testing.T) {
   799  	tearDown := setUpNetlinkTest(t)
   800  	defer tearDown()
   801  
   802  	// get loopback interface
   803  	link, err := LinkByName("lo")
   804  	if err != nil {
   805  		t.Fatal(err)
   806  	}
   807  	// bring the interface up
   808  	if err = LinkSetUp(link); err != nil {
   809  		t.Fatal(err)
   810  	}
   811  
   812  	// add a gateway route
   813  	dst := &net.IPNet{
   814  		IP:   net.IPv4(1, 1, 1, 1),
   815  		Mask: net.CIDRMask(32, 32),
   816  	}
   817  
   818  	tables := []int{1000, 1001, 1002}
   819  	src := net.IPv4(127, 3, 3, 3)
   820  	for _, table := range tables {
   821  		route := Route{
   822  			LinkIndex: link.Attrs().Index,
   823  			Dst:       dst,
   824  			Src:       src,
   825  			Scope:     unix.RT_SCOPE_LINK,
   826  			Priority:  13,
   827  			Table:     table,
   828  			Type:      unix.RTN_UNICAST,
   829  			Tos:       12,
   830  			Hoplimit:  100,
   831  			Realm:     328,
   832  		}
   833  		if err := RouteAdd(&route); err != nil {
   834  			t.Fatal(err)
   835  		}
   836  	}
   837  	routes, err := RouteListFiltered(FAMILY_V4, &Route{
   838  		Dst:      dst,
   839  		Src:      src,
   840  		Scope:    unix.RT_SCOPE_LINK,
   841  		Table:    unix.RT_TABLE_UNSPEC,
   842  		Type:     unix.RTN_UNICAST,
   843  		Tos:      12,
   844  		Hoplimit: 100,
   845  		Realm:    328,
   846  	}, RT_FILTER_DST|RT_FILTER_SRC|RT_FILTER_SCOPE|RT_FILTER_TABLE|RT_FILTER_TYPE|RT_FILTER_TOS|RT_FILTER_HOPLIMIT|RT_FILTER_REALM)
   847  	if err != nil {
   848  		t.Fatal(err)
   849  	}
   850  	if len(routes) != 3 {
   851  		t.Fatal("Routes not added properly")
   852  	}
   853  
   854  	for _, route := range routes {
   855  		if route.Scope != unix.RT_SCOPE_LINK {
   856  			t.Fatal("Invalid Scope. Route not added properly")
   857  		}
   858  		if route.Priority != 13 {
   859  			t.Fatal("Invalid Priority. Route not added properly")
   860  		}
   861  		if !tableIDIn(tables, route.Table) {
   862  			t.Fatalf("Invalid Table %d. Route not added properly", route.Table)
   863  		}
   864  		if route.Type != unix.RTN_UNICAST {
   865  			t.Fatal("Invalid Type. Route not added properly")
   866  		}
   867  		if route.Tos != 12 {
   868  			t.Fatal("Invalid Tos. Route not added properly")
   869  		}
   870  		if route.Hoplimit != 100 {
   871  			t.Fatal("Invalid Hoplimit. Route not added properly")
   872  		}
   873  		if route.Realm != 328 {
   874  			t.Fatal("Invalid Realm. Route not added properly")
   875  		}
   876  	}
   877  }
   878  
   879  func TestRouteFilterByFamily(t *testing.T) {
   880  	tearDown := setUpNetlinkTest(t)
   881  	defer tearDown()
   882  
   883  	const table int = 999
   884  
   885  	// get loopback interface
   886  	link, err := LinkByName("lo")
   887  	if err != nil {
   888  		t.Fatal(err)
   889  	}
   890  	// bring the interface up
   891  	if err = LinkSetUp(link); err != nil {
   892  		t.Fatal(err)
   893  	}
   894  
   895  	// add a IPv4 gateway route
   896  	dst4 := &net.IPNet{
   897  		IP:   net.IPv4(2, 2, 0, 0),
   898  		Mask: net.CIDRMask(24, 32),
   899  	}
   900  	route4 := Route{LinkIndex: link.Attrs().Index, Dst: dst4, Table: table}
   901  	if err := RouteAdd(&route4); err != nil {
   902  		t.Fatal(err)
   903  	}
   904  
   905  	// add a IPv6 gateway route
   906  	dst6 := &net.IPNet{
   907  		IP:   net.ParseIP("2001:db9::0"),
   908  		Mask: net.CIDRMask(64, 128),
   909  	}
   910  	route6 := Route{LinkIndex: link.Attrs().Index, Dst: dst6, Table: table}
   911  	if err := RouteAdd(&route6); err != nil {
   912  		t.Fatal(err)
   913  	}
   914  
   915  	// Get routes for both families
   916  	routes_all, err := RouteListFiltered(FAMILY_ALL, &Route{Table: table}, RT_FILTER_TABLE)
   917  	if err != nil {
   918  		t.Fatal(err)
   919  	}
   920  	if len(routes_all) != 2 {
   921  		t.Fatal("Filtering by FAMILY_ALL doesn't find two routes")
   922  	}
   923  
   924  	// Get IPv4 route
   925  	routes_v4, err := RouteListFiltered(FAMILY_V4, &Route{Table: table}, RT_FILTER_TABLE)
   926  	if err != nil {
   927  		t.Fatal(err)
   928  	}
   929  	if len(routes_v4) != 1 {
   930  		t.Fatal("Filtering by FAMILY_V4 doesn't find one route")
   931  	}
   932  
   933  	// Get IPv6 route
   934  	routes_v6, err := RouteListFiltered(FAMILY_V6, &Route{Table: table}, RT_FILTER_TABLE)
   935  	if err != nil {
   936  		t.Fatal(err)
   937  	}
   938  	if len(routes_v6) != 1 {
   939  		t.Fatal("Filtering by FAMILY_V6 doesn't find one route")
   940  	}
   941  
   942  	// Get non-existent routes
   943  	routes_non_existent, err := RouteListFiltered(99, &Route{Table: table}, RT_FILTER_TABLE)
   944  	if err != nil {
   945  		t.Fatal(err)
   946  	}
   947  	if len(routes_non_existent) != 0 {
   948  		t.Fatal("Filtering by non-existent family find some route")
   949  	}
   950  }
   951  
   952  func TestRouteFilterIterCanStop(t *testing.T) {
   953  	tearDown := setUpNetlinkTest(t)
   954  	defer tearDown()
   955  
   956  	// get loopback interface
   957  	link, err := LinkByName("lo")
   958  	if err != nil {
   959  		t.Fatal(err)
   960  	}
   961  	// bring the interface up
   962  	if err = LinkSetUp(link); err != nil {
   963  		t.Fatal(err)
   964  	}
   965  
   966  	// add a gateway route
   967  	dst := &net.IPNet{
   968  		IP:   net.IPv4(1, 1, 1, 1),
   969  		Mask: net.CIDRMask(32, 32),
   970  	}
   971  
   972  	for i := 0; i < 3; i++ {
   973  		route := Route{
   974  			LinkIndex: link.Attrs().Index,
   975  			Dst:       dst,
   976  			Scope:     unix.RT_SCOPE_LINK,
   977  			Priority:  1 + i,
   978  			Table:     1000,
   979  			Type:      unix.RTN_UNICAST,
   980  		}
   981  		if err := RouteAdd(&route); err != nil {
   982  			t.Fatal(err)
   983  		}
   984  	}
   985  
   986  	var routes []Route
   987  	err = RouteListFilteredIter(FAMILY_V4, &Route{
   988  		Dst:   dst,
   989  		Scope: unix.RT_SCOPE_LINK,
   990  		Table: 1000,
   991  		Type:  unix.RTN_UNICAST,
   992  	}, RT_FILTER_TABLE, func(route Route) (cont bool) {
   993  		routes = append(routes, route)
   994  		return len(routes) < 2
   995  	})
   996  	if err != nil {
   997  		t.Fatal(err)
   998  	}
   999  	if len(routes) != 2 {
  1000  		t.Fatal("Unexpected number of iterations")
  1001  	}
  1002  	for _, route := range routes {
  1003  		if route.Scope != unix.RT_SCOPE_LINK {
  1004  			t.Fatal("Invalid Scope. Route not added properly")
  1005  		}
  1006  		if route.Priority < 1 || route.Priority > 3 {
  1007  			t.Fatal("Priority outside expected range. Route not added properly")
  1008  		}
  1009  		if route.Table != 1000 {
  1010  			t.Fatalf("Invalid Table %d. Route not added properly", route.Table)
  1011  		}
  1012  		if route.Type != unix.RTN_UNICAST {
  1013  			t.Fatal("Invalid Type. Route not added properly")
  1014  		}
  1015  	}
  1016  }
  1017  
  1018  func BenchmarkRouteListFilteredNew(b *testing.B) {
  1019  	tearDown := setUpNetlinkTest(b)
  1020  	defer tearDown()
  1021  
  1022  	link, err := setUpRoutesBench(b)
  1023  
  1024  	b.ResetTimer()
  1025  	b.ReportAllocs()
  1026  	var routes []Route
  1027  	for i := 0; i < b.N; i++ {
  1028  		routes, err = pkgHandle.RouteListFiltered(FAMILY_V4, &Route{
  1029  			LinkIndex: link.Attrs().Index,
  1030  		}, RT_FILTER_OIF)
  1031  		if err != nil {
  1032  			b.Fatal(err)
  1033  		}
  1034  		if len(routes) != 65535 {
  1035  			b.Fatal("Incorrect number of routes.", len(routes))
  1036  		}
  1037  	}
  1038  	runtime.KeepAlive(routes)
  1039  }
  1040  
  1041  func BenchmarkRouteListIter(b *testing.B) {
  1042  	tearDown := setUpNetlinkTest(b)
  1043  	defer tearDown()
  1044  
  1045  	link, err := setUpRoutesBench(b)
  1046  
  1047  	b.ResetTimer()
  1048  	b.ReportAllocs()
  1049  	for i := 0; i < b.N; i++ {
  1050  		var routes int
  1051  		err = RouteListFilteredIter(FAMILY_V4, &Route{
  1052  			LinkIndex: link.Attrs().Index,
  1053  		}, RT_FILTER_OIF, func(route Route) (cont bool) {
  1054  			routes++
  1055  			return true
  1056  		})
  1057  		if err != nil {
  1058  			b.Fatal(err)
  1059  		}
  1060  		if routes != 65535 {
  1061  			b.Fatal("Incorrect number of routes.", routes)
  1062  		}
  1063  	}
  1064  }
  1065  
  1066  func setUpRoutesBench(b *testing.B) (Link, error) {
  1067  	// get loopback interface
  1068  	link, err := LinkByName("lo")
  1069  	if err != nil {
  1070  		b.Fatal(err)
  1071  	}
  1072  	// bring the interface up
  1073  	if err = LinkSetUp(link); err != nil {
  1074  		b.Fatal(err)
  1075  	}
  1076  
  1077  	// add a gateway route
  1078  	for i := 0; i < 65535; i++ {
  1079  		dst := &net.IPNet{
  1080  			IP:   net.IPv4(1, 1, byte(i>>8), byte(i&0xff)),
  1081  			Mask: net.CIDRMask(32, 32),
  1082  		}
  1083  		route := Route{
  1084  			LinkIndex: link.Attrs().Index,
  1085  			Dst:       dst,
  1086  			Scope:     unix.RT_SCOPE_LINK,
  1087  			Priority:  10,
  1088  			Type:      unix.RTN_UNICAST,
  1089  		}
  1090  		if err := RouteAdd(&route); err != nil {
  1091  			b.Fatal(err)
  1092  		}
  1093  	}
  1094  	return link, err
  1095  }
  1096  
  1097  func tableIDIn(ids []int, id int) bool {
  1098  	for _, v := range ids {
  1099  		if v == id {
  1100  			return true
  1101  		}
  1102  	}
  1103  	return false
  1104  }
  1105  
  1106  func TestRouteExtraFields(t *testing.T) {
  1107  	tearDown := setUpNetlinkTest(t)
  1108  	defer tearDown()
  1109  
  1110  	// get loopback interface
  1111  	link, err := LinkByName("lo")
  1112  	if err != nil {
  1113  		t.Fatal(err)
  1114  	}
  1115  	// bring the interface up
  1116  	if err = LinkSetUp(link); err != nil {
  1117  		t.Fatal(err)
  1118  	}
  1119  
  1120  	// add a gateway route
  1121  	dst := &net.IPNet{
  1122  		IP:   net.IPv4(1, 1, 1, 1),
  1123  		Mask: net.CIDRMask(32, 32),
  1124  	}
  1125  
  1126  	src := net.IPv4(127, 3, 3, 3)
  1127  	route := Route{
  1128  		LinkIndex: link.Attrs().Index,
  1129  		Dst:       dst,
  1130  		Src:       src,
  1131  		Scope:     unix.RT_SCOPE_LINK,
  1132  		Priority:  13,
  1133  		Table:     unix.RT_TABLE_MAIN,
  1134  		Type:      unix.RTN_UNICAST,
  1135  		Tos:       12,
  1136  		Hoplimit:  100,
  1137  		Realm:     239,
  1138  	}
  1139  	if err := RouteAdd(&route); err != nil {
  1140  		t.Fatal(err)
  1141  	}
  1142  	routes, err := RouteListFiltered(FAMILY_V4, &Route{
  1143  		Dst:      dst,
  1144  		Src:      src,
  1145  		Scope:    unix.RT_SCOPE_LINK,
  1146  		Table:    unix.RT_TABLE_MAIN,
  1147  		Type:     unix.RTN_UNICAST,
  1148  		Tos:      12,
  1149  		Hoplimit: 100,
  1150  		Realm:    239,
  1151  	}, RT_FILTER_DST|RT_FILTER_SRC|RT_FILTER_SCOPE|RT_FILTER_TABLE|RT_FILTER_TYPE|RT_FILTER_TOS|RT_FILTER_HOPLIMIT|RT_FILTER_REALM)
  1152  	if err != nil {
  1153  		t.Fatal(err)
  1154  	}
  1155  	if len(routes) != 1 {
  1156  		t.Fatal("Route not added properly")
  1157  	}
  1158  
  1159  	if routes[0].Scope != unix.RT_SCOPE_LINK {
  1160  		t.Fatal("Invalid Scope. Route not added properly")
  1161  	}
  1162  	if routes[0].Priority != 13 {
  1163  		t.Fatal("Invalid Priority. Route not added properly")
  1164  	}
  1165  	if routes[0].Table != unix.RT_TABLE_MAIN {
  1166  		t.Fatal("Invalid Scope. Route not added properly")
  1167  	}
  1168  	if routes[0].Type != unix.RTN_UNICAST {
  1169  		t.Fatal("Invalid Type. Route not added properly")
  1170  	}
  1171  	if routes[0].Tos != 12 {
  1172  		t.Fatal("Invalid Tos. Route not added properly")
  1173  	}
  1174  	if routes[0].Hoplimit != 100 {
  1175  		t.Fatal("Invalid Hoplimit. Route not added properly")
  1176  	}
  1177  	if routes[0].Realm != 239 {
  1178  		t.Fatal("Invalid Realm. Route not added properly")
  1179  	}
  1180  }
  1181  
  1182  func TestRouteMultiPath(t *testing.T) {
  1183  	tearDown := setUpNetlinkTest(t)
  1184  	defer tearDown()
  1185  
  1186  	// get loopback interface
  1187  	link, err := LinkByName("lo")
  1188  	if err != nil {
  1189  		t.Fatal(err)
  1190  	}
  1191  	// bring the interface up
  1192  	if err = LinkSetUp(link); err != nil {
  1193  		t.Fatal(err)
  1194  	}
  1195  
  1196  	// add a gateway route
  1197  	dst := &net.IPNet{
  1198  		IP:   net.IPv4(192, 168, 0, 0),
  1199  		Mask: net.CIDRMask(24, 32),
  1200  	}
  1201  
  1202  	idx := link.Attrs().Index
  1203  	route := Route{Dst: dst, MultiPath: []*NexthopInfo{{LinkIndex: idx}, {LinkIndex: idx}}}
  1204  	if err := RouteAdd(&route); err != nil {
  1205  		t.Fatal(err)
  1206  	}
  1207  	routes, err := RouteList(nil, FAMILY_V4)
  1208  	if err != nil {
  1209  		t.Fatal(err)
  1210  	}
  1211  	if len(routes) != 1 {
  1212  		t.Fatal("MultiPath Route not added properly")
  1213  	}
  1214  	if len(routes[0].MultiPath) != 2 {
  1215  		t.Fatal("MultiPath Route not added properly")
  1216  	}
  1217  }
  1218  
  1219  func TestRouteIifOption(t *testing.T) {
  1220  	skipUnlessRoot(t)
  1221  
  1222  	runtime.LockOSThread()
  1223  	t.Cleanup(runtime.UnlockOSThread)
  1224  
  1225  	rootNs, err := netns.GetFromPid(1)
  1226  	if err != nil {
  1227  		t.Fatalf("could not get root ns: %s", err)
  1228  	}
  1229  	t.Cleanup(func() { rootNs.Close() })
  1230  
  1231  	rootHdl, err := NewHandleAt(rootNs)
  1232  	if err != nil {
  1233  		t.Fatalf("could not create handle for root ns: %s", err)
  1234  	}
  1235  	t.Cleanup(func() { rootHdl.Close() })
  1236  
  1237  	// setup a veth pair across two namespaces
  1238  	//   veth1 (2.2.2.3/24) <-> veth2 (2.2.2.4/24)
  1239  
  1240  	// peer ns for veth pair
  1241  	ns, err := netns.New()
  1242  	if err != nil {
  1243  		t.Fatalf("could not create new ns: %s", err)
  1244  	}
  1245  	t.Cleanup(func() { ns.Close() })
  1246  
  1247  	l := &Veth{
  1248  		LinkAttrs:     LinkAttrs{Name: "veth1"},
  1249  		PeerName:      "veth2",
  1250  		PeerNamespace: NsFd(ns),
  1251  	}
  1252  	if err = rootHdl.LinkAdd(l); err != nil {
  1253  		t.Fatalf("could not add veth interface: %s", err)
  1254  	}
  1255  	t.Cleanup(func() { rootHdl.LinkDel(l) })
  1256  
  1257  	ve1, err := rootHdl.LinkByName("veth1")
  1258  	if err != nil {
  1259  		t.Fatalf("could not get link veth1: %s", err)
  1260  	}
  1261  
  1262  	err = rootHdl.AddrAdd(ve1, &Addr{IPNet: &net.IPNet{IP: net.ParseIP("2.2.2.3"), Mask: net.CIDRMask(24, 32)}})
  1263  	if err != nil {
  1264  		t.Fatalf("could not set address for veth1: %s", err)
  1265  	}
  1266  
  1267  	nh, err := NewHandleAt(ns)
  1268  	if err != nil {
  1269  		t.Fatalf("could not get handle for ns %+v: %s", ns, err)
  1270  	}
  1271  	t.Cleanup(func() { nh.Close() })
  1272  
  1273  	ve2, err := nh.LinkByName("veth2")
  1274  	if err != nil {
  1275  		t.Fatalf("could not get link veth2: %s", err)
  1276  	}
  1277  
  1278  	err = nh.AddrAdd(ve2, &Addr{IPNet: &net.IPNet{IP: net.ParseIP("2.2.2.4"), Mask: net.CIDRMask(24, 32)}})
  1279  	if err != nil {
  1280  		t.Fatalf("could set address for veth2: %s", err)
  1281  	}
  1282  
  1283  	if err = rootHdl.LinkSetUp(ve1); err != nil {
  1284  		t.Fatalf("could not set veth1 up: %s", err)
  1285  	}
  1286  
  1287  	if err = nh.LinkSetUp(ve2); err != nil {
  1288  		t.Fatalf("could not set veth2 up: %s", err)
  1289  	}
  1290  
  1291  	err = nh.RouteAdd(&Route{
  1292  		Dst: &net.IPNet{
  1293  			IP:   net.IPv4zero,
  1294  			Mask: net.CIDRMask(0, 32),
  1295  		},
  1296  		Gw: net.ParseIP("2.2.2.3"),
  1297  	})
  1298  	if err != nil {
  1299  		t.Fatalf("could not add default route to ns: %s", err)
  1300  	}
  1301  
  1302  	// setup finished, now do the actual test
  1303  
  1304  	_, err = rootHdl.RouteGetWithOptions(net.ParseIP("8.8.8.8"), &RouteGetOptions{
  1305  		SrcAddr: net.ParseIP("2.2.2.4"),
  1306  	})
  1307  	if err == nil {
  1308  		t.Fatal("route get should have resulted in error but did not")
  1309  	}
  1310  
  1311  	testWithOptions := func(opts *RouteGetOptions) {
  1312  		routes, err := rootHdl.RouteGetWithOptions(net.ParseIP("8.8.8.8"), opts)
  1313  		if err != nil {
  1314  			t.Fatalf("could not get route: %s", err)
  1315  		}
  1316  		if len(routes) != 1 {
  1317  			t.Fatalf("did not get exactly one route, routes: %+v", routes)
  1318  		}
  1319  
  1320  		// should be the default route
  1321  		r, err := rootHdl.RouteGet(net.ParseIP("8.8.8.8"))
  1322  		if err != nil {
  1323  			t.Fatalf("could not get default route for 8.8.8.8: %s", err)
  1324  		}
  1325  		if len(r) != 1 {
  1326  			t.Fatalf("did not get exactly one route, routes: %+v", routes)
  1327  		}
  1328  		if !routes[0].Gw.Equal(r[0].Gw) {
  1329  			t.Fatalf("wrong gateway in route: expected: %s, got: %s", r[0].Gw, routes[0].Gw)
  1330  		}
  1331  		if routes[0].LinkIndex != r[0].LinkIndex {
  1332  			t.Fatalf("wrong link in route: expected: %d, got: %d", r[0].LinkIndex, routes[0].LinkIndex)
  1333  		}
  1334  	}
  1335  
  1336  	t.Run("with iif", func(t *testing.T) {
  1337  		testWithOptions(&RouteGetOptions{
  1338  			SrcAddr: net.ParseIP("2.2.2.4"),
  1339  			Iif:     "veth1",
  1340  		})
  1341  	})
  1342  
  1343  	t.Run("with iifIndex", func(t *testing.T) {
  1344  		testWithOptions(&RouteGetOptions{
  1345  			SrcAddr:  net.ParseIP("2.2.2.4"),
  1346  			IifIndex: ve1.Attrs().Index,
  1347  		})
  1348  	})
  1349  
  1350  	t.Run("with iif and iifIndex", func(t *testing.T) {
  1351  		testWithOptions(&RouteGetOptions{
  1352  			SrcAddr:  net.ParseIP("2.2.2.4"),
  1353  			Iif:      "veth1",
  1354  			IifIndex: ve2.Attrs().Index, // Iif will supersede here
  1355  		})
  1356  	})
  1357  }
  1358  
  1359  func TestRouteOifOption(t *testing.T) {
  1360  	tearDown := setUpNetlinkTest(t)
  1361  	defer tearDown()
  1362  
  1363  	// setup two interfaces: eth0, eth1
  1364  	err := LinkAdd(&Dummy{LinkAttrs{Name: "eth0"}})
  1365  	if err != nil {
  1366  		t.Fatal(err)
  1367  	}
  1368  
  1369  	link1, err := LinkByName("eth0")
  1370  	if err != nil {
  1371  		t.Fatal(err)
  1372  	}
  1373  
  1374  	if err = LinkSetUp(link1); err != nil {
  1375  		t.Fatal(err)
  1376  	}
  1377  
  1378  	if err = LinkAdd(&Dummy{LinkAttrs{Name: "eth1"}}); err != nil {
  1379  		t.Fatal(err)
  1380  	}
  1381  
  1382  	link2, err := LinkByName("eth1")
  1383  	if err != nil {
  1384  		t.Fatal(err)
  1385  	}
  1386  
  1387  	if err = LinkSetUp(link2); err != nil {
  1388  		t.Fatal(err)
  1389  	}
  1390  
  1391  	// config ip addresses on interfaces
  1392  	addr1 := &Addr{
  1393  		IPNet: &net.IPNet{
  1394  			IP:   net.IPv4(192, 168, 1, 1),
  1395  			Mask: net.CIDRMask(24, 32),
  1396  		},
  1397  	}
  1398  
  1399  	if err = AddrAdd(link1, addr1); err != nil {
  1400  		t.Fatal(err)
  1401  	}
  1402  
  1403  	addr2 := &Addr{
  1404  		IPNet: &net.IPNet{
  1405  			IP:   net.IPv4(192, 168, 2, 1),
  1406  			Mask: net.CIDRMask(24, 32),
  1407  		},
  1408  	}
  1409  
  1410  	if err = AddrAdd(link2, addr2); err != nil {
  1411  		t.Fatal(err)
  1412  	}
  1413  
  1414  	// add default multipath route
  1415  	dst := &net.IPNet{
  1416  		IP:   net.IPv4(0, 0, 0, 0),
  1417  		Mask: net.CIDRMask(0, 32),
  1418  	}
  1419  	gw1 := net.IPv4(192, 168, 1, 254)
  1420  	gw2 := net.IPv4(192, 168, 2, 254)
  1421  	route := Route{Dst: dst, MultiPath: []*NexthopInfo{{LinkIndex: link1.Attrs().Index,
  1422  		Gw: gw1}, {LinkIndex: link2.Attrs().Index, Gw: gw2}}}
  1423  	if err := RouteAdd(&route); err != nil {
  1424  		t.Fatal(err)
  1425  	}
  1426  
  1427  	// check getting route from specified Oif
  1428  	dstIP := net.IPv4(10, 1, 1, 1)
  1429  	routes, err := RouteGetWithOptions(dstIP, &RouteGetOptions{Oif: "eth0"})
  1430  	if err != nil {
  1431  		t.Fatal(err)
  1432  	}
  1433  
  1434  	if len(routes) != 1 || routes[0].LinkIndex != link1.Attrs().Index ||
  1435  		!routes[0].Gw.Equal(gw1) {
  1436  		t.Fatal("Get route from unmatched interface")
  1437  	}
  1438  
  1439  	// check getting route from specified Oifindex
  1440  	routes, err = RouteGetWithOptions(dstIP, &RouteGetOptions{OifIndex: link1.Attrs().Index})
  1441  	if err != nil {
  1442  		t.Fatal(err)
  1443  	}
  1444  	if len(routes) != 1 || routes[0].LinkIndex != link1.Attrs().Index ||
  1445  		!routes[0].Gw.Equal(gw1) {
  1446  		t.Fatal("Get route from unmatched interface")
  1447  	}
  1448  
  1449  	routes, err = RouteGetWithOptions(dstIP, &RouteGetOptions{Oif: "eth1"})
  1450  	if err != nil {
  1451  		t.Fatal(err)
  1452  	}
  1453  
  1454  	if len(routes) != 1 || routes[0].LinkIndex != link2.Attrs().Index ||
  1455  		!routes[0].Gw.Equal(gw2) {
  1456  		t.Fatal("Get route from unmatched interface")
  1457  	}
  1458  
  1459  	routes, err = RouteGetWithOptions(dstIP, &RouteGetOptions{OifIndex: link2.Attrs().Index})
  1460  	if err != nil {
  1461  		t.Fatal(err)
  1462  	}
  1463  	if len(routes) != 1 || routes[0].LinkIndex != link2.Attrs().Index ||
  1464  		!routes[0].Gw.Equal(gw2) {
  1465  		t.Fatal("Get route from unmatched interface")
  1466  	}
  1467  }
  1468  
  1469  func TestFilterDefaultRoute(t *testing.T) {
  1470  	tearDown := setUpNetlinkTest(t)
  1471  	defer tearDown()
  1472  
  1473  	// get loopback interface
  1474  	link, err := LinkByName("lo")
  1475  	if err != nil {
  1476  		t.Fatal(err)
  1477  	}
  1478  	// bring the interface up
  1479  	if err = LinkSetUp(link); err != nil {
  1480  		t.Fatal(err)
  1481  	}
  1482  
  1483  	address := &Addr{
  1484  		IPNet: &net.IPNet{
  1485  			IP:   net.IPv4(127, 0, 0, 2),
  1486  			Mask: net.CIDRMask(24, 32),
  1487  		},
  1488  	}
  1489  	if err = AddrAdd(link, address); err != nil {
  1490  		t.Fatal(err)
  1491  	}
  1492  
  1493  	// Add default route
  1494  	gw := net.IPv4(127, 0, 0, 2)
  1495  
  1496  	defaultRoute := Route{
  1497  		Dst: nil,
  1498  		Gw:  gw,
  1499  	}
  1500  
  1501  	if err := RouteAdd(&defaultRoute); err != nil {
  1502  		t.Fatal(err)
  1503  	}
  1504  
  1505  	// add an extra route
  1506  	dst := &net.IPNet{
  1507  		IP:   net.IPv4(192, 168, 0, 0),
  1508  		Mask: net.CIDRMask(24, 32),
  1509  	}
  1510  
  1511  	extraRoute := Route{
  1512  		Dst: dst,
  1513  		Gw:  gw,
  1514  	}
  1515  
  1516  	if err := RouteAdd(&extraRoute); err != nil {
  1517  		t.Fatal(err)
  1518  	}
  1519  	var filterTests = []struct {
  1520  		filter   *Route
  1521  		mask     uint64
  1522  		expected net.IP
  1523  	}{
  1524  		{
  1525  			&Route{Dst: nil},
  1526  			RT_FILTER_DST,
  1527  			gw,
  1528  		},
  1529  		{
  1530  			&Route{Dst: dst},
  1531  			RT_FILTER_DST,
  1532  			gw,
  1533  		},
  1534  	}
  1535  
  1536  	for _, f := range filterTests {
  1537  		routes, err := RouteListFiltered(FAMILY_V4, f.filter, f.mask)
  1538  		if err != nil {
  1539  			t.Fatal(err)
  1540  		}
  1541  		if len(routes) != 1 {
  1542  			t.Fatal("Route not filtered properly")
  1543  		}
  1544  		if !routes[0].Gw.Equal(gw) {
  1545  			t.Fatal("Unexpected Gateway")
  1546  		}
  1547  	}
  1548  
  1549  }
  1550  
  1551  func TestMPLSRouteAddDel(t *testing.T) {
  1552  	tearDown := setUpMPLSNetlinkTest(t)
  1553  	defer tearDown()
  1554  
  1555  	// get loopback interface
  1556  	link, err := LinkByName("lo")
  1557  	if err != nil {
  1558  		t.Fatal(err)
  1559  	}
  1560  
  1561  	// bring the interface up
  1562  	if err := LinkSetUp(link); err != nil {
  1563  		t.Fatal(err)
  1564  	}
  1565  
  1566  	mplsDst := 100
  1567  	route := Route{
  1568  		LinkIndex: link.Attrs().Index,
  1569  		MPLSDst:   &mplsDst,
  1570  		NewDst: &MPLSDestination{
  1571  			Labels: []int{200, 300},
  1572  		},
  1573  	}
  1574  	if err := RouteAdd(&route); err != nil {
  1575  		t.Fatal(err)
  1576  	}
  1577  	routes, err := RouteList(link, FAMILY_MPLS)
  1578  	if err != nil {
  1579  		t.Fatal(err)
  1580  	}
  1581  	if len(routes) != 1 {
  1582  		t.Fatal("Route not added properly")
  1583  	}
  1584  
  1585  	if err := RouteDel(&route); err != nil {
  1586  		t.Fatal(err)
  1587  	}
  1588  	routes, err = RouteList(link, FAMILY_MPLS)
  1589  	if err != nil {
  1590  		t.Fatal(err)
  1591  	}
  1592  	if len(routes) != 0 {
  1593  		t.Fatal("Route not removed properly")
  1594  	}
  1595  
  1596  }
  1597  
  1598  func TestIP6tnlRouteAddDel(t *testing.T) {
  1599  	_, err := RouteList(nil, FAMILY_V4)
  1600  	if err != nil {
  1601  		t.Fatal(err)
  1602  	}
  1603  
  1604  	tearDown := setUpNetlinkTest(t)
  1605  	defer tearDown()
  1606  
  1607  	// get loopback interface
  1608  	link, err := LinkByName("lo")
  1609  	if err != nil {
  1610  		t.Fatal(err)
  1611  	}
  1612  
  1613  	// bring the interface up
  1614  	if err := LinkSetUp(link); err != nil {
  1615  		t.Fatal(err)
  1616  	}
  1617  
  1618  	_, dst, err := net.ParseCIDR("192.168.99.0/24")
  1619  	if err != nil {
  1620  		t.Fatalf("cannot parse destination prefix: %v", err)
  1621  	}
  1622  
  1623  	encap := IP6tnlEncap{
  1624  		Dst: net.ParseIP("2001:db8::"),
  1625  		Src: net.ParseIP("::"),
  1626  	}
  1627  
  1628  	route := &Route{
  1629  		LinkIndex: link.Attrs().Index,
  1630  		Dst:       dst,
  1631  		Encap:     &encap,
  1632  	}
  1633  
  1634  	if err := RouteAdd(route); err != nil {
  1635  		t.Fatalf("Cannot add route: %v", err)
  1636  	}
  1637  	routes, err := RouteList(link, FAMILY_V4)
  1638  	if err != nil {
  1639  		t.Fatal(err)
  1640  	}
  1641  	if len(routes) != 1 {
  1642  		t.Fatal("Route not added properly")
  1643  	}
  1644  
  1645  	if err := RouteDel(route); err != nil {
  1646  		t.Fatal(err)
  1647  	}
  1648  	routes, err = RouteList(link, FAMILY_V4)
  1649  	if err != nil {
  1650  		t.Fatal(err)
  1651  	}
  1652  	if len(routes) != 0 {
  1653  		t.Fatal("Route not removed properly")
  1654  	}
  1655  
  1656  }
  1657  
  1658  func TestRouteEqual(t *testing.T) {
  1659  	mplsDst := 100
  1660  	seg6encap := &SEG6Encap{Mode: nl.SEG6_IPTUN_MODE_ENCAP}
  1661  	seg6encap.Segments = []net.IP{net.ParseIP("fc00:a000::11")}
  1662  	cases := []Route{
  1663  		{
  1664  			Dst: nil,
  1665  			Gw:  net.IPv4(1, 1, 1, 1),
  1666  		},
  1667  		{
  1668  			LinkIndex: 20,
  1669  			Dst:       nil,
  1670  			Gw:        net.IPv4(1, 1, 1, 1),
  1671  		},
  1672  		{
  1673  			ILinkIndex: 21,
  1674  			LinkIndex:  20,
  1675  			Dst:        nil,
  1676  			Gw:         net.IPv4(1, 1, 1, 1),
  1677  		},
  1678  		{
  1679  			LinkIndex: 20,
  1680  			Dst:       nil,
  1681  			Protocol:  20,
  1682  			Gw:        net.IPv4(1, 1, 1, 1),
  1683  		},
  1684  		{
  1685  			LinkIndex: 20,
  1686  			Dst:       nil,
  1687  			Priority:  20,
  1688  			Gw:        net.IPv4(1, 1, 1, 1),
  1689  		},
  1690  		{
  1691  			LinkIndex: 20,
  1692  			Dst:       nil,
  1693  			Type:      20,
  1694  			Gw:        net.IPv4(1, 1, 1, 1),
  1695  		},
  1696  		{
  1697  			LinkIndex: 20,
  1698  			Dst:       nil,
  1699  			Table:     200,
  1700  			Gw:        net.IPv4(1, 1, 1, 1),
  1701  		},
  1702  		{
  1703  			LinkIndex: 20,
  1704  			Dst:       nil,
  1705  			Tos:       1,
  1706  			Gw:        net.IPv4(1, 1, 1, 1),
  1707  		},
  1708  		{
  1709  			LinkIndex: 20,
  1710  			Dst:       nil,
  1711  			Hoplimit:  1,
  1712  			Gw:        net.IPv4(1, 1, 1, 1),
  1713  		},
  1714  		{
  1715  			LinkIndex: 20,
  1716  			Dst:       nil,
  1717  			Realm:     29,
  1718  			Gw:        net.IPv4(1, 1, 1, 1),
  1719  		},
  1720  		{
  1721  			LinkIndex: 20,
  1722  			Dst:       nil,
  1723  			Flags:     int(FLAG_ONLINK),
  1724  			Gw:        net.IPv4(1, 1, 1, 1),
  1725  		},
  1726  		{
  1727  			LinkIndex: 10,
  1728  			Dst: &net.IPNet{
  1729  				IP:   net.IPv4(192, 168, 0, 0),
  1730  				Mask: net.CIDRMask(24, 32),
  1731  			},
  1732  			Src: net.IPv4(127, 1, 1, 1),
  1733  		},
  1734  		{
  1735  			LinkIndex: 10,
  1736  			Scope:     unix.RT_SCOPE_LINK,
  1737  			Dst: &net.IPNet{
  1738  				IP:   net.IPv4(192, 168, 0, 0),
  1739  				Mask: net.CIDRMask(24, 32),
  1740  			},
  1741  			Src: net.IPv4(127, 1, 1, 1),
  1742  		},
  1743  		{
  1744  			LinkIndex: 3,
  1745  			Dst: &net.IPNet{
  1746  				IP:   net.IPv4(1, 1, 1, 1),
  1747  				Mask: net.CIDRMask(32, 32),
  1748  			},
  1749  			Src:      net.IPv4(127, 3, 3, 3),
  1750  			Scope:    unix.RT_SCOPE_LINK,
  1751  			Priority: 13,
  1752  			Table:    unix.RT_TABLE_MAIN,
  1753  			Type:     unix.RTN_UNICAST,
  1754  			Tos:      12,
  1755  		},
  1756  		{
  1757  			LinkIndex: 3,
  1758  			Dst: &net.IPNet{
  1759  				IP:   net.IPv4(1, 1, 1, 1),
  1760  				Mask: net.CIDRMask(32, 32),
  1761  			},
  1762  			Src:      net.IPv4(127, 3, 3, 3),
  1763  			Scope:    unix.RT_SCOPE_LINK,
  1764  			Priority: 13,
  1765  			Table:    unix.RT_TABLE_MAIN,
  1766  			Type:     unix.RTN_UNICAST,
  1767  			Hoplimit: 100,
  1768  		},
  1769  		{
  1770  			LinkIndex: 3,
  1771  			Dst: &net.IPNet{
  1772  				IP:   net.IPv4(1, 1, 1, 1),
  1773  				Mask: net.CIDRMask(32, 32),
  1774  			},
  1775  			Src:      net.IPv4(127, 3, 3, 3),
  1776  			Scope:    unix.RT_SCOPE_LINK,
  1777  			Priority: 13,
  1778  			Table:    unix.RT_TABLE_MAIN,
  1779  			Type:     unix.RTN_UNICAST,
  1780  			Realm:    129,
  1781  		},
  1782  		{
  1783  			LinkIndex: 10,
  1784  			MPLSDst:   &mplsDst,
  1785  			NewDst: &MPLSDestination{
  1786  				Labels: []int{200, 300},
  1787  			},
  1788  		},
  1789  		{
  1790  			Dst: nil,
  1791  			Gw:  net.IPv4(1, 1, 1, 1),
  1792  			Encap: &MPLSEncap{
  1793  				Labels: []int{100},
  1794  			},
  1795  		},
  1796  		{
  1797  			LinkIndex: 10,
  1798  			Dst: &net.IPNet{
  1799  				IP:   net.IPv4(10, 0, 0, 102),
  1800  				Mask: net.CIDRMask(32, 32),
  1801  			},
  1802  			Encap: seg6encap,
  1803  		},
  1804  		{
  1805  			Dst:       nil,
  1806  			MultiPath: []*NexthopInfo{{LinkIndex: 10}, {LinkIndex: 20}},
  1807  		},
  1808  		{
  1809  			Dst: nil,
  1810  			MultiPath: []*NexthopInfo{{
  1811  				LinkIndex: 10,
  1812  				Gw:        net.IPv4(1, 1, 1, 1),
  1813  			}, {LinkIndex: 20}},
  1814  		},
  1815  		{
  1816  			Dst: nil,
  1817  			MultiPath: []*NexthopInfo{{
  1818  				LinkIndex: 10,
  1819  				Gw:        net.IPv4(1, 1, 1, 1),
  1820  				Encap: &MPLSEncap{
  1821  					Labels: []int{100},
  1822  				},
  1823  			}, {LinkIndex: 20}},
  1824  		},
  1825  		{
  1826  			Dst: nil,
  1827  			MultiPath: []*NexthopInfo{{
  1828  				LinkIndex: 10,
  1829  				NewDst: &MPLSDestination{
  1830  					Labels: []int{200, 300},
  1831  				},
  1832  			}, {LinkIndex: 20}},
  1833  		},
  1834  		{
  1835  			Dst: nil,
  1836  			MultiPath: []*NexthopInfo{{
  1837  				LinkIndex: 10,
  1838  				Encap:     seg6encap,
  1839  			}, {LinkIndex: 20}},
  1840  		},
  1841  	}
  1842  	for i1 := range cases {
  1843  		for i2 := range cases {
  1844  			got := cases[i1].Equal(cases[i2])
  1845  			expected := i1 == i2
  1846  			if got != expected {
  1847  				t.Errorf("Equal(%q,%q) == %s but expected %s",
  1848  					cases[i1], cases[i2],
  1849  					strconv.FormatBool(got),
  1850  					strconv.FormatBool(expected))
  1851  			}
  1852  		}
  1853  	}
  1854  }
  1855  
  1856  func TestIPNetEqual(t *testing.T) {
  1857  	cases := []string{
  1858  		"1.1.1.1/24", "1.1.1.0/24", "1.1.1.1/32",
  1859  		"0.0.0.0/0", "0.0.0.0/14",
  1860  		"2001:db8::/32", "2001:db8::/128",
  1861  		"2001:db8::caff/32", "2001:db8::caff/128",
  1862  		"",
  1863  	}
  1864  	for _, c1 := range cases {
  1865  		var n1 *net.IPNet
  1866  		if c1 != "" {
  1867  			var i1 net.IP
  1868  			var err1 error
  1869  			i1, n1, err1 = net.ParseCIDR(c1)
  1870  			if err1 != nil {
  1871  				panic(err1)
  1872  			}
  1873  			n1.IP = i1
  1874  		}
  1875  		for _, c2 := range cases {
  1876  			var n2 *net.IPNet
  1877  			if c2 != "" {
  1878  				var i2 net.IP
  1879  				var err2 error
  1880  				i2, n2, err2 = net.ParseCIDR(c2)
  1881  				if err2 != nil {
  1882  					panic(err2)
  1883  				}
  1884  				n2.IP = i2
  1885  			}
  1886  
  1887  			got := ipNetEqual(n1, n2)
  1888  			expected := c1 == c2
  1889  			if got != expected {
  1890  				t.Errorf("IPNetEqual(%q,%q) == %s but expected %s",
  1891  					c1, c2,
  1892  					strconv.FormatBool(got),
  1893  					strconv.FormatBool(expected))
  1894  			}
  1895  		}
  1896  	}
  1897  }
  1898  
  1899  func TestSEG6LocalEqual(t *testing.T) {
  1900  	// Different attributes exists in different Actions. For example, Action
  1901  	// SEG6_LOCAL_ACTION_END_X has In6Addr, SEG6_LOCAL_ACTION_END_T has Table etc.
  1902  	segs := []net.IP{net.ParseIP("fc00:a000::11")}
  1903  	// set flags for each actions.
  1904  	var flags_end [nl.SEG6_LOCAL_MAX]bool
  1905  	flags_end[nl.SEG6_LOCAL_ACTION] = true
  1906  	var flags_end_x [nl.SEG6_LOCAL_MAX]bool
  1907  	flags_end_x[nl.SEG6_LOCAL_ACTION] = true
  1908  	flags_end_x[nl.SEG6_LOCAL_NH6] = true
  1909  	var flags_end_t [nl.SEG6_LOCAL_MAX]bool
  1910  	flags_end_t[nl.SEG6_LOCAL_ACTION] = true
  1911  	flags_end_t[nl.SEG6_LOCAL_TABLE] = true
  1912  	var flags_end_dx2 [nl.SEG6_LOCAL_MAX]bool
  1913  	flags_end_dx2[nl.SEG6_LOCAL_ACTION] = true
  1914  	flags_end_dx2[nl.SEG6_LOCAL_OIF] = true
  1915  	var flags_end_dx6 [nl.SEG6_LOCAL_MAX]bool
  1916  	flags_end_dx6[nl.SEG6_LOCAL_ACTION] = true
  1917  	flags_end_dx6[nl.SEG6_LOCAL_NH6] = true
  1918  	var flags_end_dx4 [nl.SEG6_LOCAL_MAX]bool
  1919  	flags_end_dx4[nl.SEG6_LOCAL_ACTION] = true
  1920  	flags_end_dx4[nl.SEG6_LOCAL_NH4] = true
  1921  	var flags_end_dt6 [nl.SEG6_LOCAL_MAX]bool
  1922  	flags_end_dt6[nl.SEG6_LOCAL_ACTION] = true
  1923  	flags_end_dt6[nl.SEG6_LOCAL_TABLE] = true
  1924  	var flags_end_dt4 [nl.SEG6_LOCAL_MAX]bool
  1925  	flags_end_dt4[nl.SEG6_LOCAL_ACTION] = true
  1926  	flags_end_dt4[nl.SEG6_LOCAL_TABLE] = true
  1927  	var flags_end_b6 [nl.SEG6_LOCAL_MAX]bool
  1928  	flags_end_b6[nl.SEG6_LOCAL_ACTION] = true
  1929  	flags_end_b6[nl.SEG6_LOCAL_SRH] = true
  1930  	var flags_end_b6_encaps [nl.SEG6_LOCAL_MAX]bool
  1931  	flags_end_b6_encaps[nl.SEG6_LOCAL_ACTION] = true
  1932  	flags_end_b6_encaps[nl.SEG6_LOCAL_SRH] = true
  1933  	var flags_end_bpf [nl.SEG6_LOCAL_MAX]bool
  1934  	flags_end_bpf[nl.SEG6_LOCAL_ACTION] = true
  1935  	flags_end_bpf[nl.SEG6_LOCAL_BPF] = true
  1936  
  1937  	cases := []SEG6LocalEncap{
  1938  		{
  1939  			Flags:  flags_end,
  1940  			Action: nl.SEG6_LOCAL_ACTION_END,
  1941  		},
  1942  		{
  1943  			Flags:   flags_end_x,
  1944  			Action:  nl.SEG6_LOCAL_ACTION_END_X,
  1945  			In6Addr: net.ParseIP("2001:db8::1"),
  1946  		},
  1947  		{
  1948  			Flags:  flags_end_t,
  1949  			Action: nl.SEG6_LOCAL_ACTION_END_T,
  1950  			Table:  10,
  1951  		},
  1952  		{
  1953  			Flags:  flags_end_dx2,
  1954  			Action: nl.SEG6_LOCAL_ACTION_END_DX2,
  1955  			Oif:    20,
  1956  		},
  1957  		{
  1958  			Flags:   flags_end_dx6,
  1959  			Action:  nl.SEG6_LOCAL_ACTION_END_DX6,
  1960  			In6Addr: net.ParseIP("2001:db8::1"),
  1961  		},
  1962  		{
  1963  			Flags:  flags_end_dx4,
  1964  			Action: nl.SEG6_LOCAL_ACTION_END_DX4,
  1965  			InAddr: net.IPv4(192, 168, 10, 10),
  1966  		},
  1967  		{
  1968  			Flags:  flags_end_dt6,
  1969  			Action: nl.SEG6_LOCAL_ACTION_END_DT6,
  1970  			Table:  30,
  1971  		},
  1972  		{
  1973  			Flags:  flags_end_dt4,
  1974  			Action: nl.SEG6_LOCAL_ACTION_END_DT4,
  1975  			Table:  40,
  1976  		},
  1977  		{
  1978  			Flags:    flags_end_b6,
  1979  			Action:   nl.SEG6_LOCAL_ACTION_END_B6,
  1980  			Segments: segs,
  1981  		},
  1982  		{
  1983  			Flags:    flags_end_b6_encaps,
  1984  			Action:   nl.SEG6_LOCAL_ACTION_END_B6_ENCAPS,
  1985  			Segments: segs,
  1986  		},
  1987  	}
  1988  
  1989  	// SEG6_LOCAL_ACTION_END_BPF
  1990  	endBpf := SEG6LocalEncap{
  1991  		Flags:  flags_end_bpf,
  1992  		Action: nl.SEG6_LOCAL_ACTION_END_BPF,
  1993  	}
  1994  	_ = endBpf.SetProg(1, "firewall")
  1995  	cases = append(cases, endBpf)
  1996  
  1997  	for i1 := range cases {
  1998  		for i2 := range cases {
  1999  			got := cases[i1].Equal(&cases[i2])
  2000  			expected := i1 == i2
  2001  			if got != expected {
  2002  				t.Errorf("Equal(%v,%v) == %s but expected %s",
  2003  					cases[i1], cases[i2],
  2004  					strconv.FormatBool(got),
  2005  					strconv.FormatBool(expected))
  2006  			}
  2007  		}
  2008  	}
  2009  }
  2010  func TestSEG6RouteAddDel(t *testing.T) {
  2011  	if os.Getenv("CI") == "true" {
  2012  		t.Skipf("Fails in CI with: route_test.go:*: Invalid Type. SEG6_IPTUN_MODE_INLINE routes not added properly")
  2013  	}
  2014  	// add/del routes with LWTUNNEL_SEG6 to/from loopback interface.
  2015  	// Test both seg6 modes: encap (IPv4) & inline (IPv6).
  2016  	tearDown := setUpSEG6NetlinkTest(t)
  2017  	defer tearDown()
  2018  
  2019  	// get loopback interface and bring it up
  2020  	link, err := LinkByName("lo")
  2021  	if err != nil {
  2022  		t.Fatal(err)
  2023  	}
  2024  	if err := LinkSetUp(link); err != nil {
  2025  		t.Fatal(err)
  2026  	}
  2027  
  2028  	dst1 := &net.IPNet{ // INLINE mode must be IPv6 route
  2029  		IP:   net.ParseIP("2001:db8::1"),
  2030  		Mask: net.CIDRMask(128, 128),
  2031  	}
  2032  	dst2 := &net.IPNet{
  2033  		IP:   net.IPv4(10, 0, 0, 102),
  2034  		Mask: net.CIDRMask(32, 32),
  2035  	}
  2036  	var s1, s2 []net.IP
  2037  	s1 = append(s1, net.ParseIP("::")) // inline requires "::"
  2038  	s1 = append(s1, net.ParseIP("fc00:a000::12"))
  2039  	s1 = append(s1, net.ParseIP("fc00:a000::11"))
  2040  	s2 = append(s2, net.ParseIP("fc00:a000::22"))
  2041  	s2 = append(s2, net.ParseIP("fc00:a000::21"))
  2042  	e1 := &SEG6Encap{Mode: nl.SEG6_IPTUN_MODE_INLINE}
  2043  	e2 := &SEG6Encap{Mode: nl.SEG6_IPTUN_MODE_ENCAP}
  2044  	e1.Segments = s1
  2045  	e2.Segments = s2
  2046  	route1 := Route{LinkIndex: link.Attrs().Index, Dst: dst1, Encap: e1}
  2047  	route2 := Route{LinkIndex: link.Attrs().Index, Dst: dst2, Encap: e2}
  2048  
  2049  	// Add SEG6 routes
  2050  	if err := RouteAdd(&route1); err != nil {
  2051  		t.Fatal(err)
  2052  	}
  2053  	if err := RouteAdd(&route2); err != nil {
  2054  		t.Fatal(err)
  2055  	}
  2056  	// SEG6_IPTUN_MODE_INLINE
  2057  	routes, err := RouteList(link, FAMILY_V6)
  2058  	if err != nil {
  2059  		t.Fatal(err)
  2060  	}
  2061  	if len(routes) != 1 {
  2062  		t.Fatal("SEG6 routes not added properly")
  2063  	}
  2064  	for _, route := range routes {
  2065  		if route.Encap == nil || route.Encap.Type() != nl.LWTUNNEL_ENCAP_SEG6 {
  2066  			t.Fatal("Invalid Type. SEG6_IPTUN_MODE_INLINE routes not added properly")
  2067  		}
  2068  	}
  2069  	// SEG6_IPTUN_MODE_ENCAP
  2070  	routes, err = RouteList(link, FAMILY_V4)
  2071  	if err != nil {
  2072  		t.Fatal(err)
  2073  	}
  2074  	if len(routes) != 1 {
  2075  		t.Fatal("SEG6 routes not added properly")
  2076  	}
  2077  	for _, route := range routes {
  2078  		if route.Encap.Type() != nl.LWTUNNEL_ENCAP_SEG6 {
  2079  			t.Fatal("Invalid Type. SEG6_IPTUN_MODE_ENCAP routes not added properly")
  2080  		}
  2081  	}
  2082  
  2083  	// Del (remove) SEG6 routes
  2084  	if err := RouteDel(&route1); err != nil {
  2085  		t.Fatal(err)
  2086  	}
  2087  	if err := RouteDel(&route2); err != nil {
  2088  		t.Fatal(err)
  2089  	}
  2090  	routes, err = RouteList(link, FAMILY_V4)
  2091  	if err != nil {
  2092  		t.Fatal(err)
  2093  	}
  2094  	if len(routes) != 0 {
  2095  		t.Fatal("SEG6 routes not removed properly")
  2096  	}
  2097  }
  2098  
  2099  // add/del routes with LWTUNNEL_ENCAP_SEG6_LOCAL to/from dummy interface.
  2100  func TestSEG6LocalRoute6AddDel(t *testing.T) {
  2101  	minKernelRequired(t, 4, 14)
  2102  	tearDown := setUpSEG6NetlinkTest(t)
  2103  	defer tearDown()
  2104  
  2105  	// create dummy interface
  2106  	// IPv6 route added to loopback interface will be unreachable
  2107  	la := NewLinkAttrs()
  2108  	la.Name = "dummy_route6"
  2109  	la.TxQLen = 1500
  2110  	dummy := &Dummy{LinkAttrs: la}
  2111  	if err := LinkAdd(dummy); err != nil {
  2112  		t.Fatal(err)
  2113  	}
  2114  	// get dummy interface and bring it up
  2115  	link, err := LinkByName("dummy_route6")
  2116  	if err != nil {
  2117  		t.Fatal(err)
  2118  	}
  2119  	if err := LinkSetUp(link); err != nil {
  2120  		t.Fatal(err)
  2121  	}
  2122  
  2123  	dst1 := &net.IPNet{
  2124  		IP:   net.ParseIP("2001:db8::1"),
  2125  		Mask: net.CIDRMask(128, 128),
  2126  	}
  2127  
  2128  	// Create Route including Action SEG6_LOCAL_ACTION_END_B6.
  2129  	// Could be any Action but thought better to have seg list.
  2130  	var s1 []net.IP
  2131  	s1 = append(s1, net.ParseIP("fc00:a000::12"))
  2132  	s1 = append(s1, net.ParseIP("fc00:a000::11"))
  2133  	var flags_end_b6_encaps [nl.SEG6_LOCAL_MAX]bool
  2134  	flags_end_b6_encaps[nl.SEG6_LOCAL_ACTION] = true
  2135  	flags_end_b6_encaps[nl.SEG6_LOCAL_SRH] = true
  2136  	e1 := &SEG6LocalEncap{
  2137  		Flags:    flags_end_b6_encaps,
  2138  		Action:   nl.SEG6_LOCAL_ACTION_END_B6,
  2139  		Segments: s1,
  2140  	}
  2141  	route1 := Route{LinkIndex: link.Attrs().Index, Dst: dst1, Encap: e1}
  2142  
  2143  	// Add SEG6Local routes
  2144  	if err := RouteAdd(&route1); err != nil {
  2145  		t.Fatal(err)
  2146  	}
  2147  
  2148  	// typically one route (fe80::/64) will be created when dummy_route6 is created.
  2149  	// Thus you cannot use RouteList() to find the route entry just added.
  2150  	// Lookup route and confirm it's SEG6Local route just added.
  2151  	routesFound, err := RouteGet(dst1.IP)
  2152  	if err != nil {
  2153  		t.Fatal(err)
  2154  	}
  2155  	if len(routesFound) != 1 { // should only find 1 route entry
  2156  		t.Fatal("SEG6Local route not added correctly")
  2157  	}
  2158  	if !e1.Equal(routesFound[0].Encap) {
  2159  		t.Fatal("Encap does not match the original SEG6LocalEncap")
  2160  	}
  2161  
  2162  	// Del SEG6Local routes
  2163  	if err := RouteDel(&route1); err != nil {
  2164  		t.Fatal(err)
  2165  	}
  2166  	// Confirm route is deleted.
  2167  	if _, err = RouteGet(dst1.IP); err == nil {
  2168  		t.Fatal("SEG6Local route still exists.")
  2169  	}
  2170  
  2171  	// cleanup dummy interface created for the test
  2172  	if err := LinkDel(link); err != nil {
  2173  		t.Fatal(err)
  2174  	}
  2175  }
  2176  
  2177  func TestBpfEncap(t *testing.T) {
  2178  	tCase := &BpfEncap{}
  2179  	if err := tCase.SetProg(nl.LWT_BPF_IN, 0, "test_in"); err == nil {
  2180  		t.Fatal("BpfEncap: inserting invalid FD did not return error")
  2181  	}
  2182  	if err := tCase.SetProg(nl.LWT_BPF_XMIT_HEADROOM, 23, "test_nout"); err == nil {
  2183  		t.Fatal("BpfEncap: inserting invalid mode did not return error")
  2184  	}
  2185  	if err := tCase.SetProg(nl.LWT_BPF_XMIT, 12, "test_xmit"); err != nil {
  2186  		t.Fatal("BpfEncap: inserting valid program option returned error")
  2187  	}
  2188  	if err := tCase.SetXmitHeadroom(12); err != nil {
  2189  		t.Fatal("BpfEncap: inserting valid headroom returned error")
  2190  	}
  2191  	if err := tCase.SetXmitHeadroom(nl.LWT_BPF_MAX_HEADROOM + 1); err == nil {
  2192  		t.Fatal("BpfEncap: inserting invalid headroom did not return error")
  2193  	}
  2194  	tCase = &BpfEncap{}
  2195  
  2196  	expected := &BpfEncap{
  2197  		progs: [nl.LWT_BPF_MAX]bpfObj{
  2198  			1: {
  2199  				progName: "test_in[fd:10]",
  2200  				progFd:   10,
  2201  			},
  2202  			2: {
  2203  				progName: "test_out[fd:11]",
  2204  				progFd:   11,
  2205  			},
  2206  			3: {
  2207  				progName: "test_xmit[fd:21]",
  2208  				progFd:   21,
  2209  			},
  2210  		},
  2211  		headroom: 128,
  2212  	}
  2213  
  2214  	_ = tCase.SetProg(1, 10, "test_in")
  2215  	_ = tCase.SetProg(2, 11, "test_out")
  2216  	_ = tCase.SetProg(3, 21, "test_xmit")
  2217  	_ = tCase.SetXmitHeadroom(128)
  2218  	if !tCase.Equal(expected) {
  2219  		t.Fatal("BpfEncap: equal comparison failed")
  2220  	}
  2221  	_ = tCase.SetProg(3, 21, "test2_xmit")
  2222  	if tCase.Equal(expected) {
  2223  		t.Fatal("BpfEncap: equal comparison succeeded when attributes differ")
  2224  	}
  2225  }
  2226  
  2227  func TestMTURouteAddDel(t *testing.T) {
  2228  	_, err := RouteList(nil, FAMILY_V4)
  2229  	if err != nil {
  2230  		t.Fatal(err)
  2231  	}
  2232  
  2233  	tearDown := setUpNetlinkTest(t)
  2234  	defer tearDown()
  2235  
  2236  	// get loopback interface
  2237  	link, err := LinkByName("lo")
  2238  	if err != nil {
  2239  		t.Fatal(err)
  2240  	}
  2241  
  2242  	// bring the interface up
  2243  	if err := LinkSetUp(link); err != nil {
  2244  		t.Fatal(err)
  2245  	}
  2246  
  2247  	// add a gateway route
  2248  	dst := &net.IPNet{
  2249  		IP:   net.IPv4(192, 168, 0, 0),
  2250  		Mask: net.CIDRMask(24, 32),
  2251  	}
  2252  
  2253  	route := Route{LinkIndex: link.Attrs().Index, Dst: dst, MTU: 500}
  2254  	if err := RouteAdd(&route); err != nil {
  2255  		t.Fatal(err)
  2256  	}
  2257  	routes, err := RouteList(link, FAMILY_V4)
  2258  	if err != nil {
  2259  		t.Fatal(err)
  2260  	}
  2261  	if len(routes) != 1 {
  2262  		t.Fatal("Route not added properly")
  2263  	}
  2264  
  2265  	if route.MTU != routes[0].MTU {
  2266  		t.Fatal("Route mtu not set properly")
  2267  	}
  2268  
  2269  	if err := RouteDel(&route); err != nil {
  2270  		t.Fatal(err)
  2271  	}
  2272  	routes, err = RouteList(link, FAMILY_V4)
  2273  	if err != nil {
  2274  		t.Fatal(err)
  2275  	}
  2276  	if len(routes) != 0 {
  2277  		t.Fatal("Route not removed properly")
  2278  	}
  2279  }
  2280  
  2281  func TestMTULockRouteAddDel(t *testing.T) {
  2282  	_, err := RouteList(nil, FAMILY_V4)
  2283  	if err != nil {
  2284  		t.Fatal(err)
  2285  	}
  2286  
  2287  	tearDown := setUpNetlinkTest(t)
  2288  	defer tearDown()
  2289  
  2290  	// get loopback interface
  2291  	link, err := LinkByName("lo")
  2292  	if err != nil {
  2293  		t.Fatal(err)
  2294  	}
  2295  
  2296  	// bring the interface up
  2297  	if err := LinkSetUp(link); err != nil {
  2298  		t.Fatal(err)
  2299  	}
  2300  
  2301  	// add a gateway route
  2302  	dst := &net.IPNet{
  2303  		IP:   net.IPv4(192, 168, 0, 0),
  2304  		Mask: net.CIDRMask(24, 32),
  2305  	}
  2306  
  2307  	route := Route{LinkIndex: link.Attrs().Index, Dst: dst, MTU: 500, MTULock: true}
  2308  	if err := RouteAdd(&route); err != nil {
  2309  		t.Fatal(err)
  2310  	}
  2311  	routes, err := RouteList(link, FAMILY_V4)
  2312  	if err != nil {
  2313  		t.Fatal(err)
  2314  	}
  2315  	if len(routes) != 1 {
  2316  		t.Fatal("Route not added properly")
  2317  	}
  2318  
  2319  	if route.MTU != routes[0].MTU {
  2320  		t.Fatal("Route MTU not set properly")
  2321  	}
  2322  
  2323  	if route.MTULock != routes[0].MTULock {
  2324  		t.Fatal("Route MTU lock not set properly")
  2325  	}
  2326  
  2327  	if err := RouteDel(&route); err != nil {
  2328  		t.Fatal(err)
  2329  	}
  2330  	routes, err = RouteList(link, FAMILY_V4)
  2331  	if err != nil {
  2332  		t.Fatal(err)
  2333  	}
  2334  	if len(routes) != 0 {
  2335  		t.Fatal("Route not removed properly")
  2336  	}
  2337  }
  2338  
  2339  func TestRtoMinLockRouteAddDel(t *testing.T) {
  2340  	_, err := RouteList(nil, FAMILY_V4)
  2341  	if err != nil {
  2342  		t.Fatal(err)
  2343  	}
  2344  
  2345  	tearDown := setUpNetlinkTest(t)
  2346  	defer tearDown()
  2347  
  2348  	// get loopback interface
  2349  	link, err := LinkByName("lo")
  2350  	if err != nil {
  2351  		t.Fatal(err)
  2352  	}
  2353  
  2354  	// bring the interface up
  2355  	if err := LinkSetUp(link); err != nil {
  2356  		t.Fatal(err)
  2357  	}
  2358  
  2359  	// add a gateway route
  2360  	dst := &net.IPNet{
  2361  		IP:   net.IPv4(192, 168, 0, 0),
  2362  		Mask: net.CIDRMask(24, 32),
  2363  	}
  2364  
  2365  	route := Route{LinkIndex: link.Attrs().Index, Dst: dst, RtoMin: 40, RtoMinLock: true}
  2366  	if err := RouteAdd(&route); err != nil {
  2367  		t.Fatal(err)
  2368  	}
  2369  	routes, err := RouteList(link, FAMILY_V4)
  2370  	if err != nil {
  2371  		t.Fatal(err)
  2372  	}
  2373  	if len(routes) != 1 {
  2374  		t.Fatal("Route not added properly")
  2375  	}
  2376  
  2377  	if route.RtoMin != routes[0].RtoMin {
  2378  		t.Fatal("Route RtoMin not set properly")
  2379  	}
  2380  
  2381  	if route.RtoMinLock != routes[0].RtoMinLock {
  2382  		t.Fatal("Route RtoMin lock not set properly")
  2383  	}
  2384  
  2385  	if err := RouteDel(&route); err != nil {
  2386  		t.Fatal(err)
  2387  	}
  2388  	routes, err = RouteList(link, FAMILY_V4)
  2389  	if err != nil {
  2390  		t.Fatal(err)
  2391  	}
  2392  	if len(routes) != 0 {
  2393  		t.Fatal("Route not removed properly")
  2394  	}
  2395  }
  2396  
  2397  func TestRouteViaAddDel(t *testing.T) {
  2398  	minKernelRequired(t, 5, 4)
  2399  	tearDown := setUpNetlinkTest(t)
  2400  	defer tearDown()
  2401  
  2402  	_, err := RouteList(nil, FAMILY_V4)
  2403  	if err != nil {
  2404  		t.Fatal(err)
  2405  	}
  2406  
  2407  	link, err := LinkByName("lo")
  2408  	if err != nil {
  2409  		t.Fatal(err)
  2410  	}
  2411  
  2412  	if err := LinkSetUp(link); err != nil {
  2413  		t.Fatal(err)
  2414  	}
  2415  
  2416  	route := &Route{
  2417  		LinkIndex: link.Attrs().Index,
  2418  		Dst: &net.IPNet{
  2419  			IP:   net.IPv4(192, 168, 0, 0),
  2420  			Mask: net.CIDRMask(24, 32),
  2421  		},
  2422  		MultiPath: []*NexthopInfo{
  2423  			{
  2424  				LinkIndex: link.Attrs().Index,
  2425  				Via: &Via{
  2426  					AddrFamily: FAMILY_V6,
  2427  					Addr:       net.ParseIP("2001::1"),
  2428  				},
  2429  			},
  2430  		},
  2431  	}
  2432  
  2433  	if err := RouteAdd(route); err != nil {
  2434  		t.Fatalf("route: %v, err: %v", route, err)
  2435  	}
  2436  
  2437  	routes, err := RouteList(link, FAMILY_V4)
  2438  	if err != nil {
  2439  		t.Fatal(err)
  2440  	}
  2441  	if len(routes) != 1 {
  2442  		t.Fatal("Route not added properly")
  2443  	}
  2444  
  2445  	got := routes[0].Via
  2446  	want := route.MultiPath[0].Via
  2447  	if !want.Equal(got) {
  2448  		t.Fatalf("Route Via attribute does not match; got: %s, want: %s", got, want)
  2449  	}
  2450  
  2451  	if err := RouteDel(route); err != nil {
  2452  		t.Fatal(err)
  2453  	}
  2454  	routes, err = RouteList(link, FAMILY_V4)
  2455  	if err != nil {
  2456  		t.Fatal(err)
  2457  	}
  2458  	if len(routes) != 0 {
  2459  		t.Fatal("Route not removed properly")
  2460  	}
  2461  }
  2462  
  2463  func TestRouteUIDOption(t *testing.T) {
  2464  	tearDown := setUpNetlinkTest(t)
  2465  	defer tearDown()
  2466  
  2467  	// setup eth0 so that network is reachable
  2468  	err := LinkAdd(&Dummy{LinkAttrs{Name: "eth0"}})
  2469  	if err != nil {
  2470  		t.Fatal(err)
  2471  	}
  2472  	link, err := LinkByName("eth0")
  2473  	if err != nil {
  2474  		t.Fatal(err)
  2475  	}
  2476  	if err = LinkSetUp(link); err != nil {
  2477  		t.Fatal(err)
  2478  	}
  2479  	addr := &Addr{
  2480  		IPNet: &net.IPNet{
  2481  			IP:   net.IPv4(192, 168, 1, 1),
  2482  			Mask: net.CIDRMask(16, 32),
  2483  		},
  2484  	}
  2485  	if err = AddrAdd(link, addr); err != nil {
  2486  		t.Fatal(err)
  2487  	}
  2488  
  2489  	// a table different than unix.RT_TABLE_MAIN
  2490  	testtable := 1000
  2491  
  2492  	gw1 := net.IPv4(192, 168, 1, 254)
  2493  	gw2 := net.IPv4(192, 168, 2, 254)
  2494  
  2495  	// add default route via gw1 (in main route table by default)
  2496  	defaultRouteMain := Route{
  2497  		Dst: nil,
  2498  		Gw:  gw1,
  2499  	}
  2500  	if err := RouteAdd(&defaultRouteMain); err != nil {
  2501  		t.Fatal(err)
  2502  	}
  2503  
  2504  	// add default route via gw2 in test route table
  2505  	defaultRouteTest := Route{
  2506  		Dst:   nil,
  2507  		Gw:    gw2,
  2508  		Table: testtable,
  2509  	}
  2510  	if err := RouteAdd(&defaultRouteTest); err != nil {
  2511  		t.Fatal(err)
  2512  	}
  2513  
  2514  	// check the routes are in different tables
  2515  	routes, err := RouteListFiltered(FAMILY_V4, &Route{
  2516  		Dst:   nil,
  2517  		Table: unix.RT_TABLE_UNSPEC,
  2518  	}, RT_FILTER_DST|RT_FILTER_TABLE)
  2519  	if err != nil {
  2520  		t.Fatal(err)
  2521  	}
  2522  	if len(routes) != 2 || routes[0].Table == routes[1].Table {
  2523  		t.Fatal("Routes not added properly")
  2524  	}
  2525  
  2526  	// add a rule that uidrange match should result in route lookup of test table for uid other than current
  2527  	// current uid is 0 due to skipUnlessRoot()
  2528  	var uid uint32 = 1000
  2529  	rule := NewRule()
  2530  	rule.UIDRange = NewRuleUIDRange(uid, uid)
  2531  	rule.Table = testtable
  2532  	if err := RuleAdd(rule); err != nil {
  2533  		t.Fatal(err)
  2534  	}
  2535  
  2536  	dstIP := net.IPv4(10, 1, 1, 1)
  2537  
  2538  	// check getting route without UID option
  2539  	routes, err = RouteGetWithOptions(dstIP, &RouteGetOptions{UID: nil})
  2540  	if err != nil {
  2541  		t.Fatal(err)
  2542  	}
  2543  	// current uid is outside uidrange; rule does not apply; lookup main table
  2544  	if len(routes) != 1 || !routes[0].Gw.Equal(gw1) {
  2545  		t.Fatal(routes)
  2546  	}
  2547  
  2548  	// check getting route with UID option
  2549  	routes, err = RouteGetWithOptions(dstIP, &RouteGetOptions{UID: &uid})
  2550  	if err != nil {
  2551  		t.Fatal(err)
  2552  	}
  2553  	// option uid is within uidrange; rule applies; lookup test table
  2554  	if len(routes) != 1 || !routes[0].Gw.Equal(gw2) {
  2555  		t.Fatal(routes)
  2556  	}
  2557  }
  2558  
  2559  func TestRouteFWMarkOption(t *testing.T) {
  2560  	tearDown := setUpNetlinkTest(t)
  2561  	defer tearDown()
  2562  
  2563  	// setup eth0 so that network is reachable
  2564  	err := LinkAdd(&Dummy{LinkAttrs{Name: "eth0"}})
  2565  	if err != nil {
  2566  		t.Fatal(err)
  2567  	}
  2568  	link, err := LinkByName("eth0")
  2569  	if err != nil {
  2570  		t.Fatal(err)
  2571  	}
  2572  	if err = LinkSetUp(link); err != nil {
  2573  		t.Fatal(err)
  2574  	}
  2575  	addr := &Addr{
  2576  		IPNet: &net.IPNet{
  2577  			IP:   net.IPv4(192, 168, 1, 1),
  2578  			Mask: net.CIDRMask(16, 32),
  2579  		},
  2580  	}
  2581  	if err = AddrAdd(link, addr); err != nil {
  2582  		t.Fatal(err)
  2583  	}
  2584  
  2585  	// a table different than unix.RT_TABLE_MAIN
  2586  	testTable0 := 254
  2587  	testTable1 := 1000
  2588  	testTable2 := 1001
  2589  
  2590  	gw0 := net.IPv4(192, 168, 1, 254)
  2591  	gw1 := net.IPv4(192, 168, 2, 254)
  2592  	gw2 := net.IPv4(192, 168, 3, 254)
  2593  
  2594  	// add default route via gw0 (in main route table by default)
  2595  	defaultRouteMain := Route{
  2596  		Dst:   nil,
  2597  		Gw:    gw0,
  2598  		Table: testTable0,
  2599  	}
  2600  	if err := RouteAdd(&defaultRouteMain); err != nil {
  2601  		t.Fatal(err)
  2602  	}
  2603  
  2604  	// add default route via gw1 in test route table
  2605  	defaultRouteTest1 := Route{
  2606  		Dst:   nil,
  2607  		Gw:    gw1,
  2608  		Table: testTable1,
  2609  	}
  2610  	if err := RouteAdd(&defaultRouteTest1); err != nil {
  2611  		t.Fatal(err)
  2612  	}
  2613  
  2614  	// add default route via gw2 in test route table
  2615  	defaultRouteTest2 := Route{
  2616  		Dst:   nil,
  2617  		Gw:    gw2,
  2618  		Table: testTable2,
  2619  	}
  2620  	if err := RouteAdd(&defaultRouteTest2); err != nil {
  2621  		t.Fatal(err)
  2622  	}
  2623  
  2624  	// check the routes are in different tables
  2625  	routes, err := RouteListFiltered(FAMILY_V4, &Route{
  2626  		Dst:   nil,
  2627  		Table: unix.RT_TABLE_UNSPEC,
  2628  	}, RT_FILTER_DST|RT_FILTER_TABLE)
  2629  	if err != nil {
  2630  		t.Fatal(err)
  2631  	}
  2632  	if len(routes) != 3 || routes[0].Table == routes[1].Table || routes[1].Table == routes[2].Table ||
  2633  		routes[0].Table == routes[2].Table {
  2634  		t.Fatal("Routes not added properly")
  2635  	}
  2636  
  2637  	// add a rule that fwmark match should result in route lookup of test table
  2638  	fwmark1 := uint32(0xAFFFFFFF)
  2639  	fwmark2 := uint32(0xBFFFFFFF)
  2640  
  2641  	rule := NewRule()
  2642  	rule.Mark = fwmark1
  2643  	rule.Mask = &[]uint32{0xFFFFFFFF}[0]
  2644  
  2645  	rule.Table = testTable1
  2646  	if err := RuleAdd(rule); err != nil {
  2647  		t.Fatal(err)
  2648  	}
  2649  
  2650  	rule = NewRule()
  2651  	rule.Mark = fwmark2
  2652  	rule.Mask = &[]uint32{0xFFFFFFFF}[0]
  2653  	rule.Table = testTable2
  2654  	if err := RuleAdd(rule); err != nil {
  2655  		t.Fatal(err)
  2656  	}
  2657  
  2658  	rules, err := RuleListFiltered(FAMILY_V4, &Rule{Mark: fwmark1}, RT_FILTER_MARK)
  2659  	if err != nil {
  2660  		t.Fatal(err)
  2661  	}
  2662  	if len(rules) != 1 || rules[0].Table != testTable1 || rules[0].Mark != fwmark1 {
  2663  		t.Fatal("Rules not added properly")
  2664  	}
  2665  
  2666  	rules, err = RuleListFiltered(FAMILY_V4, &Rule{Mark: fwmark2}, RT_FILTER_MARK)
  2667  	if err != nil {
  2668  		t.Fatal(err)
  2669  	}
  2670  	if len(rules) != 1 || rules[0].Table != testTable2 || rules[0].Mark != fwmark2 {
  2671  		t.Fatal("Rules not added properly")
  2672  	}
  2673  
  2674  	dstIP := net.IPv4(10, 1, 1, 1)
  2675  
  2676  	// check getting route without FWMark option
  2677  	routes, err = RouteGetWithOptions(dstIP, &RouteGetOptions{})
  2678  	if err != nil {
  2679  		t.Fatal(err)
  2680  	}
  2681  	if len(routes) != 1 || !routes[0].Gw.Equal(gw0) {
  2682  		t.Fatal(routes)
  2683  	}
  2684  
  2685  	// check getting route with FWMark option
  2686  	routes, err = RouteGetWithOptions(dstIP, &RouteGetOptions{Mark: fwmark1})
  2687  	if err != nil {
  2688  		t.Fatal(err)
  2689  	}
  2690  	if len(routes) != 1 || !routes[0].Gw.Equal(gw1) {
  2691  		t.Fatal(routes)
  2692  	}
  2693  
  2694  	// check getting route with FWMark option
  2695  	routes, err = RouteGetWithOptions(dstIP, &RouteGetOptions{Mark: fwmark2})
  2696  	if err != nil {
  2697  		t.Fatal(err)
  2698  	}
  2699  	if len(routes) != 1 || !routes[0].Gw.Equal(gw2) {
  2700  		t.Fatal(routes)
  2701  	}
  2702  }
  2703  
  2704  func TestRouteGetFIBMatchOption(t *testing.T) {
  2705  	tearDown := setUpNetlinkTest(t)
  2706  	defer tearDown()
  2707  
  2708  	err := LinkAdd(&Dummy{LinkAttrs{Name: "eth0"}})
  2709  	if err != nil {
  2710  		t.Fatal(err)
  2711  	}
  2712  	link, err := LinkByName("eth0")
  2713  	if err != nil {
  2714  		t.Fatal(err)
  2715  	}
  2716  	if err = LinkSetUp(link); err != nil {
  2717  		t.Fatal(err)
  2718  	}
  2719  	addr := &Addr{
  2720  		IPNet: &net.IPNet{
  2721  			IP:   net.IPv4(192, 168, 0, 2),
  2722  			Mask: net.CIDRMask(24, 32),
  2723  		},
  2724  	}
  2725  	if err = AddrAdd(link, addr); err != nil {
  2726  		t.Fatal(err)
  2727  	}
  2728  
  2729  	route := &Route{
  2730  		LinkIndex: link.Attrs().Index,
  2731  		Gw:        net.IPv4(192, 168, 1, 1),
  2732  		Dst: &net.IPNet{
  2733  			IP:   net.IPv4(192, 168, 2, 0),
  2734  			Mask: net.CIDRMask(24, 32),
  2735  		},
  2736  		Flags: int(FLAG_ONLINK),
  2737  	}
  2738  
  2739  	err = RouteAdd(route)
  2740  	if err != nil {
  2741  		t.Fatal(err)
  2742  	}
  2743  
  2744  	routes, err := RouteGetWithOptions(net.IPv4(192, 168, 2, 1), &RouteGetOptions{FIBMatch: true})
  2745  	if err != nil {
  2746  		t.Fatal(err)
  2747  	}
  2748  
  2749  	if len(routes) != 1 {
  2750  		t.Fatalf("More than one route matched %v", routes)
  2751  	}
  2752  
  2753  	if len(routes[0].ListFlags()) != 1 {
  2754  		t.Fatalf("More than one route flag returned %v", routes[0].ListFlags())
  2755  	}
  2756  
  2757  	flag := routes[0].ListFlags()[0]
  2758  	if flag != "onlink" {
  2759  		t.Fatalf("Unexpected flag %s returned", flag)
  2760  	}
  2761  }