github.com/sagernet/netlink@v0.0.0-20240612041022-b9a21c07ac6a/route_test.go (about)

     1  //go:build linux
     2  // +build linux
     3  
     4  package netlink
     5  
     6  import (
     7  	"net"
     8  	"os"
     9  	"strconv"
    10  	"testing"
    11  	"time"
    12  
    13  	"github.com/sagernet/netlink/nl"
    14  	"github.com/vishvananda/netns"
    15  	"golang.org/x/sys/unix"
    16  )
    17  
    18  func TestRouteAddDel(t *testing.T) {
    19  	tearDown := setUpNetlinkTest(t)
    20  	defer tearDown()
    21  
    22  	// get loopback interface
    23  	link, err := LinkByName("lo")
    24  	if err != nil {
    25  		t.Fatal(err)
    26  	}
    27  
    28  	// bring the interface up
    29  	if err := LinkSetUp(link); err != nil {
    30  		t.Fatal(err)
    31  	}
    32  
    33  	// add a gateway route
    34  	dst := &net.IPNet{
    35  		IP:   net.IPv4(192, 168, 0, 0),
    36  		Mask: net.CIDRMask(24, 32),
    37  	}
    38  
    39  	ip := net.IPv4(127, 1, 1, 1)
    40  	route := Route{LinkIndex: link.Attrs().Index, Dst: dst, Src: ip}
    41  	if err := RouteAdd(&route); err != nil {
    42  		t.Fatal(err)
    43  	}
    44  	routes, err := RouteList(link, FAMILY_V4)
    45  	if err != nil {
    46  		t.Fatal(err)
    47  	}
    48  	if len(routes) != 1 {
    49  		t.Fatal("Route not added properly")
    50  	}
    51  
    52  	dstIP := net.IPv4(192, 168, 0, 42)
    53  	routeToDstIP, err := RouteGet(dstIP)
    54  	if err != nil {
    55  		t.Fatal(err)
    56  	}
    57  
    58  	if len(routeToDstIP) == 0 {
    59  		t.Fatal("Default route not present")
    60  	}
    61  	if err := RouteDel(&route); err != nil {
    62  		t.Fatal(err)
    63  	}
    64  	routes, err = RouteList(link, FAMILY_V4)
    65  	if err != nil {
    66  		t.Fatal(err)
    67  	}
    68  	if len(routes) != 0 {
    69  		t.Fatal("Route not removed properly")
    70  	}
    71  
    72  }
    73  
    74  func TestRoute6AddDel(t *testing.T) {
    75  	tearDown := setUpNetlinkTest(t)
    76  	defer tearDown()
    77  
    78  	// create dummy interface
    79  	// IPv6 route added to loopback interface will be unreachable
    80  	la := NewLinkAttrs()
    81  	la.Name = "dummy_route6"
    82  	la.TxQLen = 1500
    83  	dummy := &Dummy{LinkAttrs: la}
    84  	if err := LinkAdd(dummy); err != nil {
    85  		t.Fatal(err)
    86  	}
    87  
    88  	// get dummy interface
    89  	link, err := LinkByName("dummy_route6")
    90  	if err != nil {
    91  		t.Fatal(err)
    92  	}
    93  
    94  	// bring the interface up
    95  	if err := LinkSetUp(link); err != nil {
    96  		t.Fatal(err)
    97  	}
    98  
    99  	// remember number of routes before adding
   100  	// typically one route (fe80::/64) will be created when dummy_route6 is created
   101  	routes, err := RouteList(link, FAMILY_V6)
   102  	if err != nil {
   103  		t.Fatal(err)
   104  	}
   105  	nroutes := len(routes)
   106  
   107  	// add a gateway route
   108  	dst := &net.IPNet{
   109  		IP:   net.ParseIP("2001:db8::0"),
   110  		Mask: net.CIDRMask(64, 128),
   111  	}
   112  	route := Route{LinkIndex: link.Attrs().Index, Dst: dst}
   113  	if err := RouteAdd(&route); err != nil {
   114  		t.Fatal(err)
   115  	}
   116  	routes, err = RouteList(link, FAMILY_V6)
   117  	if err != nil {
   118  		t.Fatal(err)
   119  	}
   120  	if len(routes) != nroutes+1 {
   121  		t.Fatal("Route not added properly")
   122  	}
   123  
   124  	dstIP := net.ParseIP("2001:db8::1")
   125  	routeToDstIP, err := RouteGet(dstIP)
   126  	if err != nil {
   127  		t.Fatal(err)
   128  	}
   129  
   130  	// cleanup route and dummy interface created for the test
   131  	if len(routeToDstIP) == 0 {
   132  		t.Fatal("Route not present")
   133  	}
   134  	if err := RouteDel(&route); err != nil {
   135  		t.Fatal(err)
   136  	}
   137  	routes, err = RouteList(link, FAMILY_V6)
   138  	if err != nil {
   139  		t.Fatal(err)
   140  	}
   141  	if len(routes) != nroutes {
   142  		t.Fatal("Route not removed properly")
   143  	}
   144  	if err := LinkDel(link); err != nil {
   145  		t.Fatal(err)
   146  	}
   147  }
   148  
   149  func TestRouteReplace(t *testing.T) {
   150  	tearDown := setUpNetlinkTest(t)
   151  	defer tearDown()
   152  
   153  	// get loopback interface
   154  	link, err := LinkByName("lo")
   155  	if err != nil {
   156  		t.Fatal(err)
   157  	}
   158  
   159  	// bring the interface up
   160  	if err := LinkSetUp(link); err != nil {
   161  		t.Fatal(err)
   162  	}
   163  
   164  	// add a gateway route
   165  	dst := &net.IPNet{
   166  		IP:   net.IPv4(192, 168, 0, 0),
   167  		Mask: net.CIDRMask(24, 32),
   168  	}
   169  
   170  	ip := net.IPv4(127, 1, 1, 1)
   171  	route := Route{LinkIndex: link.Attrs().Index, Dst: dst, Src: ip}
   172  	if err := RouteAdd(&route); err != nil {
   173  		t.Fatal(err)
   174  	}
   175  	routes, err := RouteList(link, FAMILY_V4)
   176  	if err != nil {
   177  		t.Fatal(err)
   178  	}
   179  	if len(routes) != 1 {
   180  		t.Fatal("Route not added properly")
   181  	}
   182  
   183  	ip = net.IPv4(127, 1, 1, 2)
   184  	route = Route{LinkIndex: link.Attrs().Index, Dst: dst, Src: ip}
   185  	if err := RouteReplace(&route); err != nil {
   186  		t.Fatal(err)
   187  	}
   188  
   189  	routes, err = RouteList(link, FAMILY_V4)
   190  	if err != nil {
   191  		t.Fatal(err)
   192  	}
   193  
   194  	if len(routes) != 1 || !routes[0].Src.Equal(ip) {
   195  		t.Fatal("Route not replaced properly")
   196  	}
   197  
   198  	if err := RouteDel(&route); err != nil {
   199  		t.Fatal(err)
   200  	}
   201  	routes, err = RouteList(link, FAMILY_V4)
   202  	if err != nil {
   203  		t.Fatal(err)
   204  	}
   205  	if len(routes) != 0 {
   206  		t.Fatal("Route not removed properly")
   207  	}
   208  
   209  }
   210  
   211  func TestRouteAppend(t *testing.T) {
   212  	tearDown := setUpNetlinkTest(t)
   213  	defer tearDown()
   214  
   215  	// get loopback interface
   216  	link, err := LinkByName("lo")
   217  	if err != nil {
   218  		t.Fatal(err)
   219  	}
   220  
   221  	// bring the interface up
   222  	if err := LinkSetUp(link); err != nil {
   223  		t.Fatal(err)
   224  	}
   225  
   226  	// add a gateway route
   227  	dst := &net.IPNet{
   228  		IP:   net.IPv4(192, 168, 0, 0),
   229  		Mask: net.CIDRMask(24, 32),
   230  	}
   231  
   232  	ip := net.IPv4(127, 1, 1, 1)
   233  	route := Route{LinkIndex: link.Attrs().Index, Dst: dst, Src: ip}
   234  	if err := RouteAdd(&route); err != nil {
   235  		t.Fatal(err)
   236  	}
   237  	routes, err := RouteList(link, FAMILY_V4)
   238  	if err != nil {
   239  		t.Fatal(err)
   240  	}
   241  	if len(routes) != 1 {
   242  		t.Fatal("Route not added properly")
   243  	}
   244  
   245  	ip = net.IPv4(127, 1, 1, 2)
   246  	route = Route{LinkIndex: link.Attrs().Index, Dst: dst, Src: ip}
   247  	if err := RouteAppend(&route); err != nil {
   248  		t.Fatal(err)
   249  	}
   250  
   251  	routes, err = RouteList(link, FAMILY_V4)
   252  	if err != nil {
   253  		t.Fatal(err)
   254  	}
   255  
   256  	if len(routes) != 2 || !routes[1].Src.Equal(ip) {
   257  		t.Fatal("Route not append properly")
   258  	}
   259  
   260  	if err := RouteDel(&routes[0]); err != nil {
   261  		t.Fatal(err)
   262  	}
   263  	if err := RouteDel(&routes[1]); err != nil {
   264  		t.Fatal(err)
   265  	}
   266  	routes, err = RouteList(link, FAMILY_V4)
   267  	if err != nil {
   268  		t.Fatal(err)
   269  	}
   270  	if len(routes) != 0 {
   271  		t.Fatal("Route not removed properly")
   272  	}
   273  }
   274  
   275  func TestRouteAddIncomplete(t *testing.T) {
   276  	tearDown := setUpNetlinkTest(t)
   277  	defer tearDown()
   278  
   279  	// get loopback interface
   280  	link, err := LinkByName("lo")
   281  	if err != nil {
   282  		t.Fatal(err)
   283  	}
   284  
   285  	// bring the interface up
   286  	if err = LinkSetUp(link); err != nil {
   287  		t.Fatal(err)
   288  	}
   289  
   290  	route := Route{LinkIndex: link.Attrs().Index}
   291  	if err := RouteAdd(&route); err == nil {
   292  		t.Fatal("Adding incomplete route should fail")
   293  	}
   294  }
   295  
   296  // expectNeighUpdate returns whether the expected updated is received within one minute.
   297  func expectRouteUpdate(ch <-chan RouteUpdate, t uint16, dst net.IP) bool {
   298  	for {
   299  		timeout := time.After(time.Minute)
   300  		select {
   301  		case update := <-ch:
   302  			if update.Type == t &&
   303  				update.Route.Dst != nil &&
   304  				update.Route.Dst.IP.Equal(dst) {
   305  				return true
   306  			}
   307  		case <-timeout:
   308  			return false
   309  		}
   310  	}
   311  }
   312  
   313  func TestRouteSubscribe(t *testing.T) {
   314  	tearDown := setUpNetlinkTest(t)
   315  	defer tearDown()
   316  
   317  	ch := make(chan RouteUpdate)
   318  	done := make(chan struct{})
   319  	defer close(done)
   320  	if err := RouteSubscribe(ch, done); err != nil {
   321  		t.Fatal(err)
   322  	}
   323  
   324  	// get loopback interface
   325  	link, err := LinkByName("lo")
   326  	if err != nil {
   327  		t.Fatal(err)
   328  	}
   329  
   330  	// bring the interface up
   331  	if err = LinkSetUp(link); err != nil {
   332  		t.Fatal(err)
   333  	}
   334  
   335  	// add a gateway route
   336  	dst := &net.IPNet{
   337  		IP:   net.IPv4(192, 168, 0, 0),
   338  		Mask: net.CIDRMask(24, 32),
   339  	}
   340  
   341  	ip := net.IPv4(127, 1, 1, 1)
   342  	route := Route{LinkIndex: link.Attrs().Index, Dst: dst, Src: ip}
   343  	if err := RouteAdd(&route); err != nil {
   344  		t.Fatal(err)
   345  	}
   346  
   347  	if !expectRouteUpdate(ch, unix.RTM_NEWROUTE, dst.IP) {
   348  		t.Fatal("Add update not received as expected")
   349  	}
   350  	if err := RouteDel(&route); err != nil {
   351  		t.Fatal(err)
   352  	}
   353  	if !expectRouteUpdate(ch, unix.RTM_DELROUTE, dst.IP) {
   354  		t.Fatal("Del update not received as expected")
   355  	}
   356  }
   357  
   358  func TestRouteSubscribeWithOptions(t *testing.T) {
   359  	tearDown := setUpNetlinkTest(t)
   360  	defer tearDown()
   361  
   362  	ch := make(chan RouteUpdate)
   363  	done := make(chan struct{})
   364  	defer close(done)
   365  	var lastError error
   366  	defer func() {
   367  		if lastError != nil {
   368  			t.Fatalf("Fatal error received during subscription: %v", lastError)
   369  		}
   370  	}()
   371  	if err := RouteSubscribeWithOptions(ch, done, RouteSubscribeOptions{
   372  		ErrorCallback: func(err error) {
   373  			lastError = err
   374  		},
   375  	}); err != nil {
   376  		t.Fatal(err)
   377  	}
   378  
   379  	// get loopback interface
   380  	link, err := LinkByName("lo")
   381  	if err != nil {
   382  		t.Fatal(err)
   383  	}
   384  
   385  	// bring the interface up
   386  	if err = LinkSetUp(link); err != nil {
   387  		t.Fatal(err)
   388  	}
   389  
   390  	// add a gateway route
   391  	dst := &net.IPNet{
   392  		IP:   net.IPv4(192, 168, 0, 0),
   393  		Mask: net.CIDRMask(24, 32),
   394  	}
   395  
   396  	ip := net.IPv4(127, 1, 1, 1)
   397  	route := Route{LinkIndex: link.Attrs().Index, Dst: dst, Src: ip}
   398  	if err := RouteAdd(&route); err != nil {
   399  		t.Fatal(err)
   400  	}
   401  
   402  	if !expectRouteUpdate(ch, unix.RTM_NEWROUTE, dst.IP) {
   403  		t.Fatal("Add update not received as expected")
   404  	}
   405  }
   406  
   407  func TestRouteSubscribeAt(t *testing.T) {
   408  	skipUnlessRoot(t)
   409  
   410  	// Create an handle on a custom netns
   411  	newNs, err := netns.New()
   412  	if err != nil {
   413  		t.Fatal(err)
   414  	}
   415  	defer newNs.Close()
   416  
   417  	nh, err := NewHandleAt(newNs)
   418  	if err != nil {
   419  		t.Fatal(err)
   420  	}
   421  	defer nh.Close()
   422  
   423  	// Subscribe for Route events on the custom netns
   424  	ch := make(chan RouteUpdate)
   425  	done := make(chan struct{})
   426  	defer close(done)
   427  	if err := RouteSubscribeAt(newNs, ch, done); err != nil {
   428  		t.Fatal(err)
   429  	}
   430  
   431  	// get loopback interface
   432  	link, err := nh.LinkByName("lo")
   433  	if err != nil {
   434  		t.Fatal(err)
   435  	}
   436  
   437  	// bring the interface up
   438  	if err = nh.LinkSetUp(link); err != nil {
   439  		t.Fatal(err)
   440  	}
   441  
   442  	// add a gateway route
   443  	dst := &net.IPNet{
   444  		IP:   net.IPv4(192, 169, 0, 0),
   445  		Mask: net.CIDRMask(24, 32),
   446  	}
   447  
   448  	ip := net.IPv4(127, 100, 1, 1)
   449  	route := Route{LinkIndex: link.Attrs().Index, Dst: dst, Src: ip}
   450  	if err := nh.RouteAdd(&route); err != nil {
   451  		t.Fatal(err)
   452  	}
   453  
   454  	if !expectRouteUpdate(ch, unix.RTM_NEWROUTE, dst.IP) {
   455  		t.Fatal("Add update not received as expected")
   456  	}
   457  	if err := nh.RouteDel(&route); err != nil {
   458  		t.Fatal(err)
   459  	}
   460  	if !expectRouteUpdate(ch, unix.RTM_DELROUTE, dst.IP) {
   461  		t.Fatal("Del update not received as expected")
   462  	}
   463  }
   464  
   465  func TestRouteSubscribeListExisting(t *testing.T) {
   466  	skipUnlessRoot(t)
   467  
   468  	// Create an handle on a custom netns
   469  	newNs, err := netns.New()
   470  	if err != nil {
   471  		t.Fatal(err)
   472  	}
   473  	defer newNs.Close()
   474  
   475  	nh, err := NewHandleAt(newNs)
   476  	if err != nil {
   477  		t.Fatal(err)
   478  	}
   479  	defer nh.Close()
   480  
   481  	// get loopback interface
   482  	link, err := nh.LinkByName("lo")
   483  	if err != nil {
   484  		t.Fatal(err)
   485  	}
   486  
   487  	// bring the interface up
   488  	if err = nh.LinkSetUp(link); err != nil {
   489  		t.Fatal(err)
   490  	}
   491  
   492  	// add a gateway route before subscribing
   493  	dst10 := &net.IPNet{
   494  		IP:   net.IPv4(10, 10, 10, 0),
   495  		Mask: net.CIDRMask(24, 32),
   496  	}
   497  
   498  	ip := net.IPv4(127, 100, 1, 1)
   499  	route10 := Route{LinkIndex: link.Attrs().Index, Dst: dst10, Src: ip}
   500  	if err := nh.RouteAdd(&route10); err != nil {
   501  		t.Fatal(err)
   502  	}
   503  
   504  	// Subscribe for Route events including existing routes
   505  	ch := make(chan RouteUpdate)
   506  	done := make(chan struct{})
   507  	defer close(done)
   508  	if err := RouteSubscribeWithOptions(ch, done, RouteSubscribeOptions{
   509  		Namespace:    &newNs,
   510  		ListExisting: true},
   511  	); err != nil {
   512  		t.Fatal(err)
   513  	}
   514  
   515  	if !expectRouteUpdate(ch, unix.RTM_NEWROUTE, dst10.IP) {
   516  		t.Fatal("Existing add update not received as expected")
   517  	}
   518  
   519  	// add a gateway route
   520  	dst := &net.IPNet{
   521  		IP:   net.IPv4(192, 169, 0, 0),
   522  		Mask: net.CIDRMask(24, 32),
   523  	}
   524  
   525  	route := Route{LinkIndex: link.Attrs().Index, Dst: dst, Src: ip}
   526  	if err := nh.RouteAdd(&route); err != nil {
   527  		t.Fatal(err)
   528  	}
   529  
   530  	if !expectRouteUpdate(ch, unix.RTM_NEWROUTE, dst.IP) {
   531  		t.Fatal("Add update not received as expected")
   532  	}
   533  	if err := nh.RouteDel(&route); err != nil {
   534  		t.Fatal(err)
   535  	}
   536  	if !expectRouteUpdate(ch, unix.RTM_DELROUTE, dst.IP) {
   537  		t.Fatal("Del update not received as expected")
   538  	}
   539  	if err := nh.RouteDel(&route10); err != nil {
   540  		t.Fatal(err)
   541  	}
   542  	if !expectRouteUpdate(ch, unix.RTM_DELROUTE, dst10.IP) {
   543  		t.Fatal("Del update not received as expected")
   544  	}
   545  }
   546  
   547  func TestRouteFilterAllTables(t *testing.T) {
   548  	tearDown := setUpNetlinkTest(t)
   549  	defer tearDown()
   550  
   551  	// get loopback interface
   552  	link, err := LinkByName("lo")
   553  	if err != nil {
   554  		t.Fatal(err)
   555  	}
   556  	// bring the interface up
   557  	if err = LinkSetUp(link); err != nil {
   558  		t.Fatal(err)
   559  	}
   560  
   561  	// add a gateway route
   562  	dst := &net.IPNet{
   563  		IP:   net.IPv4(1, 1, 1, 1),
   564  		Mask: net.CIDRMask(32, 32),
   565  	}
   566  
   567  	tables := []int{1000, 1001, 1002}
   568  	src := net.IPv4(127, 3, 3, 3)
   569  	for _, table := range tables {
   570  		route := Route{
   571  			LinkIndex: link.Attrs().Index,
   572  			Dst:       dst,
   573  			Src:       src,
   574  			Scope:     unix.RT_SCOPE_LINK,
   575  			Priority:  13,
   576  			Table:     table,
   577  			Type:      unix.RTN_UNICAST,
   578  			Tos:       14,
   579  			Hoplimit:  100,
   580  			Realm:     328,
   581  		}
   582  		if err := RouteAdd(&route); err != nil {
   583  			t.Fatal(err)
   584  		}
   585  	}
   586  	routes, err := RouteListFiltered(FAMILY_V4, &Route{
   587  		Dst:      dst,
   588  		Src:      src,
   589  		Scope:    unix.RT_SCOPE_LINK,
   590  		Table:    unix.RT_TABLE_UNSPEC,
   591  		Type:     unix.RTN_UNICAST,
   592  		Tos:      14,
   593  		Hoplimit: 100,
   594  		Realm:    328,
   595  	}, RT_FILTER_DST|RT_FILTER_SRC|RT_FILTER_SCOPE|RT_FILTER_TABLE|RT_FILTER_TYPE|RT_FILTER_TOS|RT_FILTER_HOPLIMIT|RT_FILTER_REALM)
   596  	if err != nil {
   597  		t.Fatal(err)
   598  	}
   599  	if len(routes) != 3 {
   600  		t.Fatal("Routes not added properly")
   601  	}
   602  
   603  	for _, route := range routes {
   604  		if route.Scope != unix.RT_SCOPE_LINK {
   605  			t.Fatal("Invalid Scope. Route not added properly")
   606  		}
   607  		if route.Priority != 13 {
   608  			t.Fatal("Invalid Priority. Route not added properly")
   609  		}
   610  		if !tableIDIn(tables, route.Table) {
   611  			t.Fatalf("Invalid Table %d. Route not added properly", route.Table)
   612  		}
   613  		if route.Type != unix.RTN_UNICAST {
   614  			t.Fatal("Invalid Type. Route not added properly")
   615  		}
   616  		if route.Tos != 14 {
   617  			t.Fatal("Invalid Tos. Route not added properly")
   618  		}
   619  		if route.Hoplimit != 100 {
   620  			t.Fatal("Invalid Hoplimit. Route not added properly")
   621  		}
   622  		if route.Realm != 328 {
   623  			t.Fatal("Invalid Realm. Route not added properly")
   624  		}
   625  	}
   626  }
   627  
   628  func tableIDIn(ids []int, id int) bool {
   629  	for _, v := range ids {
   630  		if v == id {
   631  			return true
   632  		}
   633  	}
   634  	return false
   635  }
   636  
   637  func TestRouteExtraFields(t *testing.T) {
   638  	tearDown := setUpNetlinkTest(t)
   639  	defer tearDown()
   640  
   641  	// get loopback interface
   642  	link, err := LinkByName("lo")
   643  	if err != nil {
   644  		t.Fatal(err)
   645  	}
   646  	// bring the interface up
   647  	if err = LinkSetUp(link); err != nil {
   648  		t.Fatal(err)
   649  	}
   650  
   651  	// add a gateway route
   652  	dst := &net.IPNet{
   653  		IP:   net.IPv4(1, 1, 1, 1),
   654  		Mask: net.CIDRMask(32, 32),
   655  	}
   656  
   657  	src := net.IPv4(127, 3, 3, 3)
   658  	route := Route{
   659  		LinkIndex: link.Attrs().Index,
   660  		Dst:       dst,
   661  		Src:       src,
   662  		Scope:     unix.RT_SCOPE_LINK,
   663  		Priority:  13,
   664  		Table:     unix.RT_TABLE_MAIN,
   665  		Type:      unix.RTN_UNICAST,
   666  		Tos:       14,
   667  		Hoplimit:  100,
   668  		Realm:     239,
   669  	}
   670  	if err := RouteAdd(&route); err != nil {
   671  		t.Fatal(err)
   672  	}
   673  	routes, err := RouteListFiltered(FAMILY_V4, &Route{
   674  		Dst:      dst,
   675  		Src:      src,
   676  		Scope:    unix.RT_SCOPE_LINK,
   677  		Table:    unix.RT_TABLE_MAIN,
   678  		Type:     unix.RTN_UNICAST,
   679  		Tos:      14,
   680  		Hoplimit: 100,
   681  		Realm:    239,
   682  	}, RT_FILTER_DST|RT_FILTER_SRC|RT_FILTER_SCOPE|RT_FILTER_TABLE|RT_FILTER_TYPE|RT_FILTER_TOS|RT_FILTER_HOPLIMIT|RT_FILTER_REALM)
   683  	if err != nil {
   684  		t.Fatal(err)
   685  	}
   686  	if len(routes) != 1 {
   687  		t.Fatal("Route not added properly")
   688  	}
   689  
   690  	if routes[0].Scope != unix.RT_SCOPE_LINK {
   691  		t.Fatal("Invalid Scope. Route not added properly")
   692  	}
   693  	if routes[0].Priority != 13 {
   694  		t.Fatal("Invalid Priority. Route not added properly")
   695  	}
   696  	if routes[0].Table != unix.RT_TABLE_MAIN {
   697  		t.Fatal("Invalid Scope. Route not added properly")
   698  	}
   699  	if routes[0].Type != unix.RTN_UNICAST {
   700  		t.Fatal("Invalid Type. Route not added properly")
   701  	}
   702  	if routes[0].Tos != 14 {
   703  		t.Fatal("Invalid Tos. Route not added properly")
   704  	}
   705  	if routes[0].Hoplimit != 100 {
   706  		t.Fatal("Invalid Hoplimit. Route not added properly")
   707  	}
   708  	if routes[0].Realm != 239 {
   709  		t.Fatal("Invalid Realm. Route not added properly")
   710  	}
   711  }
   712  
   713  func TestRouteMultiPath(t *testing.T) {
   714  	tearDown := setUpNetlinkTest(t)
   715  	defer tearDown()
   716  
   717  	// get loopback interface
   718  	link, err := LinkByName("lo")
   719  	if err != nil {
   720  		t.Fatal(err)
   721  	}
   722  	// bring the interface up
   723  	if err = LinkSetUp(link); err != nil {
   724  		t.Fatal(err)
   725  	}
   726  
   727  	// add a gateway route
   728  	dst := &net.IPNet{
   729  		IP:   net.IPv4(192, 168, 0, 0),
   730  		Mask: net.CIDRMask(24, 32),
   731  	}
   732  
   733  	idx := link.Attrs().Index
   734  	route := Route{Dst: dst, MultiPath: []*NexthopInfo{{LinkIndex: idx}, {LinkIndex: idx}}}
   735  	if err := RouteAdd(&route); err != nil {
   736  		t.Fatal(err)
   737  	}
   738  	routes, err := RouteList(nil, FAMILY_V4)
   739  	if err != nil {
   740  		t.Fatal(err)
   741  	}
   742  	if len(routes) != 1 {
   743  		t.Fatal("MultiPath Route not added properly")
   744  	}
   745  	if len(routes[0].MultiPath) != 2 {
   746  		t.Fatal("MultiPath Route not added properly")
   747  	}
   748  }
   749  
   750  func TestRouteOifOption(t *testing.T) {
   751  	tearDown := setUpNetlinkTest(t)
   752  	defer tearDown()
   753  
   754  	// setup two interfaces: eth0, eth1
   755  	err := LinkAdd(&Dummy{LinkAttrs{Name: "eth0"}})
   756  	if err != nil {
   757  		t.Fatal(err)
   758  	}
   759  
   760  	link1, err := LinkByName("eth0")
   761  	if err != nil {
   762  		t.Fatal(err)
   763  	}
   764  
   765  	if err = LinkSetUp(link1); err != nil {
   766  		t.Fatal(err)
   767  	}
   768  
   769  	if err = LinkAdd(&Dummy{LinkAttrs{Name: "eth1"}}); err != nil {
   770  		t.Fatal(err)
   771  	}
   772  
   773  	link2, err := LinkByName("eth1")
   774  	if err != nil {
   775  		t.Fatal(err)
   776  	}
   777  
   778  	if err = LinkSetUp(link2); err != nil {
   779  		t.Fatal(err)
   780  	}
   781  
   782  	// config ip addresses on interfaces
   783  	addr1 := &Addr{
   784  		IPNet: &net.IPNet{
   785  			IP:   net.IPv4(192, 168, 1, 1),
   786  			Mask: net.CIDRMask(24, 32),
   787  		},
   788  	}
   789  
   790  	if err = AddrAdd(link1, addr1); err != nil {
   791  		t.Fatal(err)
   792  	}
   793  
   794  	addr2 := &Addr{
   795  		IPNet: &net.IPNet{
   796  			IP:   net.IPv4(192, 168, 2, 1),
   797  			Mask: net.CIDRMask(24, 32),
   798  		},
   799  	}
   800  
   801  	if err = AddrAdd(link2, addr2); err != nil {
   802  		t.Fatal(err)
   803  	}
   804  
   805  	// add default multipath route
   806  	dst := &net.IPNet{
   807  		IP:   net.IPv4(0, 0, 0, 0),
   808  		Mask: net.CIDRMask(0, 32),
   809  	}
   810  	gw1 := net.IPv4(192, 168, 1, 254)
   811  	gw2 := net.IPv4(192, 168, 2, 254)
   812  	route := Route{Dst: dst, MultiPath: []*NexthopInfo{{LinkIndex: link1.Attrs().Index,
   813  		Gw: gw1}, {LinkIndex: link2.Attrs().Index, Gw: gw2}}}
   814  	if err := RouteAdd(&route); err != nil {
   815  		t.Fatal(err)
   816  	}
   817  
   818  	// check getting route from specified Oif
   819  	dstIP := net.IPv4(10, 1, 1, 1)
   820  	routes, err := RouteGetWithOptions(dstIP, &RouteGetOptions{Oif: "eth0"})
   821  	if err != nil {
   822  		t.Fatal(err)
   823  	}
   824  
   825  	if len(routes) != 1 || routes[0].LinkIndex != link1.Attrs().Index ||
   826  		!routes[0].Gw.Equal(gw1) {
   827  		t.Fatal("Get route from unmatched interface")
   828  	}
   829  
   830  	routes, err = RouteGetWithOptions(dstIP, &RouteGetOptions{Oif: "eth1"})
   831  	if err != nil {
   832  		t.Fatal(err)
   833  	}
   834  
   835  	if len(routes) != 1 || routes[0].LinkIndex != link2.Attrs().Index ||
   836  		!routes[0].Gw.Equal(gw2) {
   837  		t.Fatal("Get route from unmatched interface")
   838  	}
   839  
   840  }
   841  
   842  func TestFilterDefaultRoute(t *testing.T) {
   843  	tearDown := setUpNetlinkTest(t)
   844  	defer tearDown()
   845  
   846  	// get loopback interface
   847  	link, err := LinkByName("lo")
   848  	if err != nil {
   849  		t.Fatal(err)
   850  	}
   851  	// bring the interface up
   852  	if err = LinkSetUp(link); err != nil {
   853  		t.Fatal(err)
   854  	}
   855  
   856  	address := &Addr{
   857  		IPNet: &net.IPNet{
   858  			IP:   net.IPv4(127, 0, 0, 2),
   859  			Mask: net.CIDRMask(24, 32),
   860  		},
   861  	}
   862  	if err = AddrAdd(link, address); err != nil {
   863  		t.Fatal(err)
   864  	}
   865  
   866  	// Add default route
   867  	gw := net.IPv4(127, 0, 0, 2)
   868  
   869  	defaultRoute := Route{
   870  		Dst: nil,
   871  		Gw:  gw,
   872  	}
   873  
   874  	if err := RouteAdd(&defaultRoute); err != nil {
   875  		t.Fatal(err)
   876  	}
   877  
   878  	// add an extra route
   879  	dst := &net.IPNet{
   880  		IP:   net.IPv4(192, 168, 0, 0),
   881  		Mask: net.CIDRMask(24, 32),
   882  	}
   883  
   884  	extraRoute := Route{
   885  		Dst: dst,
   886  		Gw:  gw,
   887  	}
   888  
   889  	if err := RouteAdd(&extraRoute); err != nil {
   890  		t.Fatal(err)
   891  	}
   892  	var filterTests = []struct {
   893  		filter   *Route
   894  		mask     uint64
   895  		expected net.IP
   896  	}{
   897  		{
   898  			&Route{Dst: nil},
   899  			RT_FILTER_DST,
   900  			gw,
   901  		},
   902  		{
   903  			&Route{Dst: dst},
   904  			RT_FILTER_DST,
   905  			gw,
   906  		},
   907  	}
   908  
   909  	for _, f := range filterTests {
   910  		routes, err := RouteListFiltered(FAMILY_V4, f.filter, f.mask)
   911  		if err != nil {
   912  			t.Fatal(err)
   913  		}
   914  		if len(routes) != 1 {
   915  			t.Fatal("Route not filtered properly")
   916  		}
   917  		if !routes[0].Gw.Equal(gw) {
   918  			t.Fatal("Unexpected Gateway")
   919  		}
   920  	}
   921  
   922  }
   923  
   924  func TestMPLSRouteAddDel(t *testing.T) {
   925  	tearDown := setUpMPLSNetlinkTest(t)
   926  	defer tearDown()
   927  
   928  	// get loopback interface
   929  	link, err := LinkByName("lo")
   930  	if err != nil {
   931  		t.Fatal(err)
   932  	}
   933  
   934  	// bring the interface up
   935  	if err := LinkSetUp(link); err != nil {
   936  		t.Fatal(err)
   937  	}
   938  
   939  	mplsDst := 100
   940  	route := Route{
   941  		LinkIndex: link.Attrs().Index,
   942  		MPLSDst:   &mplsDst,
   943  		NewDst: &MPLSDestination{
   944  			Labels: []int{200, 300},
   945  		},
   946  	}
   947  	if err := RouteAdd(&route); err != nil {
   948  		t.Fatal(err)
   949  	}
   950  	routes, err := RouteList(link, FAMILY_MPLS)
   951  	if err != nil {
   952  		t.Fatal(err)
   953  	}
   954  	if len(routes) != 1 {
   955  		t.Fatal("Route not added properly")
   956  	}
   957  
   958  	if err := RouteDel(&route); err != nil {
   959  		t.Fatal(err)
   960  	}
   961  	routes, err = RouteList(link, FAMILY_MPLS)
   962  	if err != nil {
   963  		t.Fatal(err)
   964  	}
   965  	if len(routes) != 0 {
   966  		t.Fatal("Route not removed properly")
   967  	}
   968  
   969  }
   970  
   971  func TestRouteEqual(t *testing.T) {
   972  	mplsDst := 100
   973  	seg6encap := &SEG6Encap{Mode: nl.SEG6_IPTUN_MODE_ENCAP}
   974  	seg6encap.Segments = []net.IP{net.ParseIP("fc00:a000::11")}
   975  	cases := []Route{
   976  		{
   977  			Dst: nil,
   978  			Gw:  net.IPv4(1, 1, 1, 1),
   979  		},
   980  		{
   981  			LinkIndex: 20,
   982  			Dst:       nil,
   983  			Gw:        net.IPv4(1, 1, 1, 1),
   984  		},
   985  		{
   986  			ILinkIndex: 21,
   987  			LinkIndex:  20,
   988  			Dst:        nil,
   989  			Gw:         net.IPv4(1, 1, 1, 1),
   990  		},
   991  		{
   992  			LinkIndex: 20,
   993  			Dst:       nil,
   994  			Protocol:  20,
   995  			Gw:        net.IPv4(1, 1, 1, 1),
   996  		},
   997  		{
   998  			LinkIndex: 20,
   999  			Dst:       nil,
  1000  			Priority:  20,
  1001  			Gw:        net.IPv4(1, 1, 1, 1),
  1002  		},
  1003  		{
  1004  			LinkIndex: 20,
  1005  			Dst:       nil,
  1006  			Type:      20,
  1007  			Gw:        net.IPv4(1, 1, 1, 1),
  1008  		},
  1009  		{
  1010  			LinkIndex: 20,
  1011  			Dst:       nil,
  1012  			Table:     200,
  1013  			Gw:        net.IPv4(1, 1, 1, 1),
  1014  		},
  1015  		{
  1016  			LinkIndex: 20,
  1017  			Dst:       nil,
  1018  			Tos:       1,
  1019  			Gw:        net.IPv4(1, 1, 1, 1),
  1020  		},
  1021  		{
  1022  			LinkIndex: 20,
  1023  			Dst:       nil,
  1024  			Hoplimit:  1,
  1025  			Gw:        net.IPv4(1, 1, 1, 1),
  1026  		},
  1027  		{
  1028  			LinkIndex: 20,
  1029  			Dst:       nil,
  1030  			Realm:     29,
  1031  			Gw:        net.IPv4(1, 1, 1, 1),
  1032  		},
  1033  		{
  1034  			LinkIndex: 20,
  1035  			Dst:       nil,
  1036  			Flags:     int(FLAG_ONLINK),
  1037  			Gw:        net.IPv4(1, 1, 1, 1),
  1038  		},
  1039  		{
  1040  			LinkIndex: 10,
  1041  			Dst: &net.IPNet{
  1042  				IP:   net.IPv4(192, 168, 0, 0),
  1043  				Mask: net.CIDRMask(24, 32),
  1044  			},
  1045  			Src: net.IPv4(127, 1, 1, 1),
  1046  		},
  1047  		{
  1048  			LinkIndex: 10,
  1049  			Scope:     unix.RT_SCOPE_LINK,
  1050  			Dst: &net.IPNet{
  1051  				IP:   net.IPv4(192, 168, 0, 0),
  1052  				Mask: net.CIDRMask(24, 32),
  1053  			},
  1054  			Src: net.IPv4(127, 1, 1, 1),
  1055  		},
  1056  		{
  1057  			LinkIndex: 3,
  1058  			Dst: &net.IPNet{
  1059  				IP:   net.IPv4(1, 1, 1, 1),
  1060  				Mask: net.CIDRMask(32, 32),
  1061  			},
  1062  			Src:      net.IPv4(127, 3, 3, 3),
  1063  			Scope:    unix.RT_SCOPE_LINK,
  1064  			Priority: 13,
  1065  			Table:    unix.RT_TABLE_MAIN,
  1066  			Type:     unix.RTN_UNICAST,
  1067  			Tos:      14,
  1068  		},
  1069  		{
  1070  			LinkIndex: 3,
  1071  			Dst: &net.IPNet{
  1072  				IP:   net.IPv4(1, 1, 1, 1),
  1073  				Mask: net.CIDRMask(32, 32),
  1074  			},
  1075  			Src:      net.IPv4(127, 3, 3, 3),
  1076  			Scope:    unix.RT_SCOPE_LINK,
  1077  			Priority: 13,
  1078  			Table:    unix.RT_TABLE_MAIN,
  1079  			Type:     unix.RTN_UNICAST,
  1080  			Hoplimit: 100,
  1081  		},
  1082  		{
  1083  			LinkIndex: 3,
  1084  			Dst: &net.IPNet{
  1085  				IP:   net.IPv4(1, 1, 1, 1),
  1086  				Mask: net.CIDRMask(32, 32),
  1087  			},
  1088  			Src:      net.IPv4(127, 3, 3, 3),
  1089  			Scope:    unix.RT_SCOPE_LINK,
  1090  			Priority: 13,
  1091  			Table:    unix.RT_TABLE_MAIN,
  1092  			Type:     unix.RTN_UNICAST,
  1093  			Realm:    129,
  1094  		},
  1095  		{
  1096  			LinkIndex: 10,
  1097  			MPLSDst:   &mplsDst,
  1098  			NewDst: &MPLSDestination{
  1099  				Labels: []int{200, 300},
  1100  			},
  1101  		},
  1102  		{
  1103  			Dst: nil,
  1104  			Gw:  net.IPv4(1, 1, 1, 1),
  1105  			Encap: &MPLSEncap{
  1106  				Labels: []int{100},
  1107  			},
  1108  		},
  1109  		{
  1110  			LinkIndex: 10,
  1111  			Dst: &net.IPNet{
  1112  				IP:   net.IPv4(10, 0, 0, 102),
  1113  				Mask: net.CIDRMask(32, 32),
  1114  			},
  1115  			Encap: seg6encap,
  1116  		},
  1117  		{
  1118  			Dst:       nil,
  1119  			MultiPath: []*NexthopInfo{{LinkIndex: 10}, {LinkIndex: 20}},
  1120  		},
  1121  		{
  1122  			Dst: nil,
  1123  			MultiPath: []*NexthopInfo{{
  1124  				LinkIndex: 10,
  1125  				Gw:        net.IPv4(1, 1, 1, 1),
  1126  			}, {LinkIndex: 20}},
  1127  		},
  1128  		{
  1129  			Dst: nil,
  1130  			MultiPath: []*NexthopInfo{{
  1131  				LinkIndex: 10,
  1132  				Gw:        net.IPv4(1, 1, 1, 1),
  1133  				Encap: &MPLSEncap{
  1134  					Labels: []int{100},
  1135  				},
  1136  			}, {LinkIndex: 20}},
  1137  		},
  1138  		{
  1139  			Dst: nil,
  1140  			MultiPath: []*NexthopInfo{{
  1141  				LinkIndex: 10,
  1142  				NewDst: &MPLSDestination{
  1143  					Labels: []int{200, 300},
  1144  				},
  1145  			}, {LinkIndex: 20}},
  1146  		},
  1147  		{
  1148  			Dst: nil,
  1149  			MultiPath: []*NexthopInfo{{
  1150  				LinkIndex: 10,
  1151  				Encap:     seg6encap,
  1152  			}, {LinkIndex: 20}},
  1153  		},
  1154  	}
  1155  	for i1 := range cases {
  1156  		for i2 := range cases {
  1157  			got := cases[i1].Equal(cases[i2])
  1158  			expected := i1 == i2
  1159  			if got != expected {
  1160  				t.Errorf("Equal(%q,%q) == %s but expected %s",
  1161  					cases[i1], cases[i2],
  1162  					strconv.FormatBool(got),
  1163  					strconv.FormatBool(expected))
  1164  			}
  1165  		}
  1166  	}
  1167  }
  1168  
  1169  func TestIPNetEqual(t *testing.T) {
  1170  	cases := []string{
  1171  		"1.1.1.1/24", "1.1.1.0/24", "1.1.1.1/32",
  1172  		"0.0.0.0/0", "0.0.0.0/14",
  1173  		"2001:db8::/32", "2001:db8::/128",
  1174  		"2001:db8::caff/32", "2001:db8::caff/128",
  1175  		"",
  1176  	}
  1177  	for _, c1 := range cases {
  1178  		var n1 *net.IPNet
  1179  		if c1 != "" {
  1180  			var i1 net.IP
  1181  			var err1 error
  1182  			i1, n1, err1 = net.ParseCIDR(c1)
  1183  			if err1 != nil {
  1184  				panic(err1)
  1185  			}
  1186  			n1.IP = i1
  1187  		}
  1188  		for _, c2 := range cases {
  1189  			var n2 *net.IPNet
  1190  			if c2 != "" {
  1191  				var i2 net.IP
  1192  				var err2 error
  1193  				i2, n2, err2 = net.ParseCIDR(c2)
  1194  				if err2 != nil {
  1195  					panic(err2)
  1196  				}
  1197  				n2.IP = i2
  1198  			}
  1199  
  1200  			got := ipNetEqual(n1, n2)
  1201  			expected := c1 == c2
  1202  			if got != expected {
  1203  				t.Errorf("IPNetEqual(%q,%q) == %s but expected %s",
  1204  					c1, c2,
  1205  					strconv.FormatBool(got),
  1206  					strconv.FormatBool(expected))
  1207  			}
  1208  		}
  1209  	}
  1210  }
  1211  
  1212  func TestSEG6LocalEqual(t *testing.T) {
  1213  	// Different attributes exists in different Actions. For example, Action
  1214  	// SEG6_LOCAL_ACTION_END_X has In6Addr, SEG6_LOCAL_ACTION_END_T has Table etc.
  1215  	segs := []net.IP{net.ParseIP("fc00:a000::11")}
  1216  	// set flags for each actions.
  1217  	var flags_end [nl.SEG6_LOCAL_MAX]bool
  1218  	flags_end[nl.SEG6_LOCAL_ACTION] = true
  1219  	var flags_end_x [nl.SEG6_LOCAL_MAX]bool
  1220  	flags_end_x[nl.SEG6_LOCAL_ACTION] = true
  1221  	flags_end_x[nl.SEG6_LOCAL_NH6] = true
  1222  	var flags_end_t [nl.SEG6_LOCAL_MAX]bool
  1223  	flags_end_t[nl.SEG6_LOCAL_ACTION] = true
  1224  	flags_end_t[nl.SEG6_LOCAL_TABLE] = true
  1225  	var flags_end_dx2 [nl.SEG6_LOCAL_MAX]bool
  1226  	flags_end_dx2[nl.SEG6_LOCAL_ACTION] = true
  1227  	flags_end_dx2[nl.SEG6_LOCAL_OIF] = true
  1228  	var flags_end_dx6 [nl.SEG6_LOCAL_MAX]bool
  1229  	flags_end_dx6[nl.SEG6_LOCAL_ACTION] = true
  1230  	flags_end_dx6[nl.SEG6_LOCAL_NH6] = true
  1231  	var flags_end_dx4 [nl.SEG6_LOCAL_MAX]bool
  1232  	flags_end_dx4[nl.SEG6_LOCAL_ACTION] = true
  1233  	flags_end_dx4[nl.SEG6_LOCAL_NH4] = true
  1234  	var flags_end_dt6 [nl.SEG6_LOCAL_MAX]bool
  1235  	flags_end_dt6[nl.SEG6_LOCAL_ACTION] = true
  1236  	flags_end_dt6[nl.SEG6_LOCAL_TABLE] = true
  1237  	var flags_end_dt4 [nl.SEG6_LOCAL_MAX]bool
  1238  	flags_end_dt4[nl.SEG6_LOCAL_ACTION] = true
  1239  	flags_end_dt4[nl.SEG6_LOCAL_TABLE] = true
  1240  	var flags_end_b6 [nl.SEG6_LOCAL_MAX]bool
  1241  	flags_end_b6[nl.SEG6_LOCAL_ACTION] = true
  1242  	flags_end_b6[nl.SEG6_LOCAL_SRH] = true
  1243  	var flags_end_b6_encaps [nl.SEG6_LOCAL_MAX]bool
  1244  	flags_end_b6_encaps[nl.SEG6_LOCAL_ACTION] = true
  1245  	flags_end_b6_encaps[nl.SEG6_LOCAL_SRH] = true
  1246  
  1247  	cases := []SEG6LocalEncap{
  1248  		{
  1249  			Flags:  flags_end,
  1250  			Action: nl.SEG6_LOCAL_ACTION_END,
  1251  		},
  1252  		{
  1253  			Flags:   flags_end_x,
  1254  			Action:  nl.SEG6_LOCAL_ACTION_END_X,
  1255  			In6Addr: net.ParseIP("2001:db8::1"),
  1256  		},
  1257  		{
  1258  			Flags:  flags_end_t,
  1259  			Action: nl.SEG6_LOCAL_ACTION_END_T,
  1260  			Table:  10,
  1261  		},
  1262  		{
  1263  			Flags:  flags_end_dx2,
  1264  			Action: nl.SEG6_LOCAL_ACTION_END_DX2,
  1265  			Oif:    20,
  1266  		},
  1267  		{
  1268  			Flags:   flags_end_dx6,
  1269  			Action:  nl.SEG6_LOCAL_ACTION_END_DX6,
  1270  			In6Addr: net.ParseIP("2001:db8::1"),
  1271  		},
  1272  		{
  1273  			Flags:  flags_end_dx4,
  1274  			Action: nl.SEG6_LOCAL_ACTION_END_DX4,
  1275  			InAddr: net.IPv4(192, 168, 10, 10),
  1276  		},
  1277  		{
  1278  			Flags:  flags_end_dt6,
  1279  			Action: nl.SEG6_LOCAL_ACTION_END_DT6,
  1280  			Table:  30,
  1281  		},
  1282  		{
  1283  			Flags:  flags_end_dt4,
  1284  			Action: nl.SEG6_LOCAL_ACTION_END_DT4,
  1285  			Table:  40,
  1286  		},
  1287  		{
  1288  			Flags:    flags_end_b6,
  1289  			Action:   nl.SEG6_LOCAL_ACTION_END_B6,
  1290  			Segments: segs,
  1291  		},
  1292  		{
  1293  			Flags:    flags_end_b6_encaps,
  1294  			Action:   nl.SEG6_LOCAL_ACTION_END_B6_ENCAPS,
  1295  			Segments: segs,
  1296  		},
  1297  	}
  1298  	for i1 := range cases {
  1299  		for i2 := range cases {
  1300  			got := cases[i1].Equal(&cases[i2])
  1301  			expected := i1 == i2
  1302  			if got != expected {
  1303  				t.Errorf("Equal(%v,%v) == %s but expected %s",
  1304  					cases[i1], cases[i2],
  1305  					strconv.FormatBool(got),
  1306  					strconv.FormatBool(expected))
  1307  			}
  1308  		}
  1309  	}
  1310  }
  1311  func TestSEG6RouteAddDel(t *testing.T) {
  1312  	if os.Getenv("CI") == "true" {
  1313  		t.Skipf("Fails in CI with: route_test.go:*: Invalid Type. SEG6_IPTUN_MODE_INLINE routes not added properly")
  1314  	}
  1315  	// add/del routes with LWTUNNEL_SEG6 to/from loopback interface.
  1316  	// Test both seg6 modes: encap (IPv4) & inline (IPv6).
  1317  	tearDown := setUpSEG6NetlinkTest(t)
  1318  	defer tearDown()
  1319  
  1320  	// get loopback interface and bring it up
  1321  	link, err := LinkByName("lo")
  1322  	if err != nil {
  1323  		t.Fatal(err)
  1324  	}
  1325  	if err := LinkSetUp(link); err != nil {
  1326  		t.Fatal(err)
  1327  	}
  1328  
  1329  	dst1 := &net.IPNet{ // INLINE mode must be IPv6 route
  1330  		IP:   net.ParseIP("2001:db8::1"),
  1331  		Mask: net.CIDRMask(128, 128),
  1332  	}
  1333  	dst2 := &net.IPNet{
  1334  		IP:   net.IPv4(10, 0, 0, 102),
  1335  		Mask: net.CIDRMask(32, 32),
  1336  	}
  1337  	var s1, s2 []net.IP
  1338  	s1 = append(s1, net.ParseIP("::")) // inline requires "::"
  1339  	s1 = append(s1, net.ParseIP("fc00:a000::12"))
  1340  	s1 = append(s1, net.ParseIP("fc00:a000::11"))
  1341  	s2 = append(s2, net.ParseIP("fc00:a000::22"))
  1342  	s2 = append(s2, net.ParseIP("fc00:a000::21"))
  1343  	e1 := &SEG6Encap{Mode: nl.SEG6_IPTUN_MODE_INLINE}
  1344  	e2 := &SEG6Encap{Mode: nl.SEG6_IPTUN_MODE_ENCAP}
  1345  	e1.Segments = s1
  1346  	e2.Segments = s2
  1347  	route1 := Route{LinkIndex: link.Attrs().Index, Dst: dst1, Encap: e1}
  1348  	route2 := Route{LinkIndex: link.Attrs().Index, Dst: dst2, Encap: e2}
  1349  
  1350  	// Add SEG6 routes
  1351  	if err := RouteAdd(&route1); err != nil {
  1352  		t.Fatal(err)
  1353  	}
  1354  	if err := RouteAdd(&route2); err != nil {
  1355  		t.Fatal(err)
  1356  	}
  1357  	// SEG6_IPTUN_MODE_INLINE
  1358  	routes, err := RouteList(link, FAMILY_V6)
  1359  	if err != nil {
  1360  		t.Fatal(err)
  1361  	}
  1362  	if len(routes) != 1 {
  1363  		t.Fatal("SEG6 routes not added properly")
  1364  	}
  1365  	for _, route := range routes {
  1366  		if route.Encap == nil || route.Encap.Type() != nl.LWTUNNEL_ENCAP_SEG6 {
  1367  			t.Fatal("Invalid Type. SEG6_IPTUN_MODE_INLINE routes not added properly")
  1368  		}
  1369  	}
  1370  	// SEG6_IPTUN_MODE_ENCAP
  1371  	routes, err = RouteList(link, FAMILY_V4)
  1372  	if err != nil {
  1373  		t.Fatal(err)
  1374  	}
  1375  	if len(routes) != 1 {
  1376  		t.Fatal("SEG6 routes not added properly")
  1377  	}
  1378  	for _, route := range routes {
  1379  		if route.Encap.Type() != nl.LWTUNNEL_ENCAP_SEG6 {
  1380  			t.Fatal("Invalid Type. SEG6_IPTUN_MODE_ENCAP routes not added properly")
  1381  		}
  1382  	}
  1383  
  1384  	// Del (remove) SEG6 routes
  1385  	if err := RouteDel(&route1); err != nil {
  1386  		t.Fatal(err)
  1387  	}
  1388  	if err := RouteDel(&route2); err != nil {
  1389  		t.Fatal(err)
  1390  	}
  1391  	routes, err = RouteList(link, FAMILY_V4)
  1392  	if err != nil {
  1393  		t.Fatal(err)
  1394  	}
  1395  	if len(routes) != 0 {
  1396  		t.Fatal("SEG6 routes not removed properly")
  1397  	}
  1398  }
  1399  
  1400  // add/del routes with LWTUNNEL_ENCAP_SEG6_LOCAL to/from dummy interface.
  1401  func TestSEG6LocalRoute6AddDel(t *testing.T) {
  1402  	minKernelRequired(t, 4, 14)
  1403  	tearDown := setUpSEG6NetlinkTest(t)
  1404  	defer tearDown()
  1405  
  1406  	// create dummy interface
  1407  	// IPv6 route added to loopback interface will be unreachable
  1408  	la := NewLinkAttrs()
  1409  	la.Name = "dummy_route6"
  1410  	la.TxQLen = 1500
  1411  	dummy := &Dummy{LinkAttrs: la}
  1412  	if err := LinkAdd(dummy); err != nil {
  1413  		t.Fatal(err)
  1414  	}
  1415  	// get dummy interface and bring it up
  1416  	link, err := LinkByName("dummy_route6")
  1417  	if err != nil {
  1418  		t.Fatal(err)
  1419  	}
  1420  	if err := LinkSetUp(link); err != nil {
  1421  		t.Fatal(err)
  1422  	}
  1423  
  1424  	dst1 := &net.IPNet{
  1425  		IP:   net.ParseIP("2001:db8::1"),
  1426  		Mask: net.CIDRMask(128, 128),
  1427  	}
  1428  
  1429  	// Create Route including Action SEG6_LOCAL_ACTION_END_B6.
  1430  	// Could be any Action but thought better to have seg list.
  1431  	var s1 []net.IP
  1432  	s1 = append(s1, net.ParseIP("fc00:a000::12"))
  1433  	s1 = append(s1, net.ParseIP("fc00:a000::11"))
  1434  	var flags_end_b6_encaps [nl.SEG6_LOCAL_MAX]bool
  1435  	flags_end_b6_encaps[nl.SEG6_LOCAL_ACTION] = true
  1436  	flags_end_b6_encaps[nl.SEG6_LOCAL_SRH] = true
  1437  	e1 := &SEG6LocalEncap{
  1438  		Flags:    flags_end_b6_encaps,
  1439  		Action:   nl.SEG6_LOCAL_ACTION_END_B6,
  1440  		Segments: s1,
  1441  	}
  1442  	route1 := Route{LinkIndex: link.Attrs().Index, Dst: dst1, Encap: e1}
  1443  
  1444  	// Add SEG6Local routes
  1445  	if err := RouteAdd(&route1); err != nil {
  1446  		t.Fatal(err)
  1447  	}
  1448  
  1449  	// typically one route (fe80::/64) will be created when dummy_route6 is created.
  1450  	// Thus you cannot use RouteList() to find the route entry just added.
  1451  	// Lookup route and confirm it's SEG6Local route just added.
  1452  	routesFound, err := RouteGet(dst1.IP)
  1453  	if err != nil {
  1454  		t.Fatal(err)
  1455  	}
  1456  	if len(routesFound) != 1 { // should only find 1 route entry
  1457  		t.Fatal("SEG6Local route not added correctly")
  1458  	}
  1459  	if !e1.Equal(routesFound[0].Encap) {
  1460  		t.Fatal("Encap does not match the original SEG6LocalEncap")
  1461  	}
  1462  
  1463  	// Del SEG6Local routes
  1464  	if err := RouteDel(&route1); err != nil {
  1465  		t.Fatal(err)
  1466  	}
  1467  	// Confirm route is deleted.
  1468  	if _, err = RouteGet(dst1.IP); err == nil {
  1469  		t.Fatal("SEG6Local route still exists.")
  1470  	}
  1471  
  1472  	// cleanup dummy interface created for the test
  1473  	if err := LinkDel(link); err != nil {
  1474  		t.Fatal(err)
  1475  	}
  1476  }
  1477  
  1478  func TestBpfEncap(t *testing.T) {
  1479  	tCase := &BpfEncap{}
  1480  	if err := tCase.SetProg(nl.LWT_BPF_IN, 0, "test_in"); err == nil {
  1481  		t.Fatal("BpfEncap: inserting invalid FD did not return error")
  1482  	}
  1483  	if err := tCase.SetProg(nl.LWT_BPF_XMIT_HEADROOM, 23, "test_nout"); err == nil {
  1484  		t.Fatal("BpfEncap: inserting invalid mode did not return error")
  1485  	}
  1486  	if err := tCase.SetProg(nl.LWT_BPF_XMIT, 12, "test_xmit"); err != nil {
  1487  		t.Fatal("BpfEncap: inserting valid program option returned error")
  1488  	}
  1489  	if err := tCase.SetXmitHeadroom(12); err != nil {
  1490  		t.Fatal("BpfEncap: inserting valid headroom returned error")
  1491  	}
  1492  	if err := tCase.SetXmitHeadroom(nl.LWT_BPF_MAX_HEADROOM + 1); err == nil {
  1493  		t.Fatal("BpfEncap: inserting invalid headroom did not return error")
  1494  	}
  1495  	tCase = &BpfEncap{}
  1496  
  1497  	expected := &BpfEncap{
  1498  		progs: [nl.LWT_BPF_MAX]bpfObj{
  1499  			1: {
  1500  				progName: "test_in[fd:10]",
  1501  				progFd:   10,
  1502  			},
  1503  			2: {
  1504  				progName: "test_out[fd:11]",
  1505  				progFd:   11,
  1506  			},
  1507  			3: {
  1508  				progName: "test_xmit[fd:21]",
  1509  				progFd:   21,
  1510  			},
  1511  		},
  1512  		headroom: 128,
  1513  	}
  1514  
  1515  	_ = tCase.SetProg(1, 10, "test_in")
  1516  	_ = tCase.SetProg(2, 11, "test_out")
  1517  	_ = tCase.SetProg(3, 21, "test_xmit")
  1518  	_ = tCase.SetXmitHeadroom(128)
  1519  	if !tCase.Equal(expected) {
  1520  		t.Fatal("BpfEncap: equal comparison failed")
  1521  	}
  1522  	_ = tCase.SetProg(3, 21, "test2_xmit")
  1523  	if tCase.Equal(expected) {
  1524  		t.Fatal("BpfEncap: equal comparison succeeded when attributes differ")
  1525  	}
  1526  }
  1527  
  1528  func TestMTURouteAddDel(t *testing.T) {
  1529  	_, err := RouteList(nil, FAMILY_V4)
  1530  	if err != nil {
  1531  		t.Fatal(err)
  1532  	}
  1533  
  1534  	tearDown := setUpNetlinkTest(t)
  1535  	defer tearDown()
  1536  
  1537  	// get loopback interface
  1538  	link, err := LinkByName("lo")
  1539  	if err != nil {
  1540  		t.Fatal(err)
  1541  	}
  1542  
  1543  	// bring the interface up
  1544  	if err := LinkSetUp(link); err != nil {
  1545  		t.Fatal(err)
  1546  	}
  1547  
  1548  	// add a gateway route
  1549  	dst := &net.IPNet{
  1550  		IP:   net.IPv4(192, 168, 0, 0),
  1551  		Mask: net.CIDRMask(24, 32),
  1552  	}
  1553  
  1554  	route := Route{LinkIndex: link.Attrs().Index, Dst: dst, MTU: 500}
  1555  	if err := RouteAdd(&route); err != nil {
  1556  		t.Fatal(err)
  1557  	}
  1558  	routes, err := RouteList(link, FAMILY_V4)
  1559  	if err != nil {
  1560  		t.Fatal(err)
  1561  	}
  1562  	if len(routes) != 1 {
  1563  		t.Fatal("Route not added properly")
  1564  	}
  1565  
  1566  	if route.MTU != routes[0].MTU {
  1567  		t.Fatal("Route mtu not set properly")
  1568  	}
  1569  
  1570  	if err := RouteDel(&route); err != nil {
  1571  		t.Fatal(err)
  1572  	}
  1573  	routes, err = RouteList(link, FAMILY_V4)
  1574  	if err != nil {
  1575  		t.Fatal(err)
  1576  	}
  1577  	if len(routes) != 0 {
  1578  		t.Fatal("Route not removed properly")
  1579  	}
  1580  }
  1581  
  1582  func TestRouteViaAddDel(t *testing.T) {
  1583  	minKernelRequired(t, 5, 4)
  1584  	tearDown := setUpNetlinkTest(t)
  1585  	defer tearDown()
  1586  
  1587  	_, err := RouteList(nil, FAMILY_V4)
  1588  	if err != nil {
  1589  		t.Fatal(err)
  1590  	}
  1591  
  1592  	link, err := LinkByName("lo")
  1593  	if err != nil {
  1594  		t.Fatal(err)
  1595  	}
  1596  
  1597  	if err := LinkSetUp(link); err != nil {
  1598  		t.Fatal(err)
  1599  	}
  1600  
  1601  	route := &Route{
  1602  		LinkIndex: link.Attrs().Index,
  1603  		Dst: &net.IPNet{
  1604  			IP:   net.IPv4(192, 168, 0, 0),
  1605  			Mask: net.CIDRMask(24, 32),
  1606  		},
  1607  		MultiPath: []*NexthopInfo{
  1608  			{
  1609  				LinkIndex: link.Attrs().Index,
  1610  				Via: &Via{
  1611  					AddrFamily: FAMILY_V6,
  1612  					Addr:       net.ParseIP("2001::1"),
  1613  				},
  1614  			},
  1615  		},
  1616  	}
  1617  
  1618  	if err := RouteAdd(route); err != nil {
  1619  		t.Fatalf("route: %v, err: %v", route, err)
  1620  	}
  1621  
  1622  	routes, err := RouteList(link, FAMILY_V4)
  1623  	if err != nil {
  1624  		t.Fatal(err)
  1625  	}
  1626  	if len(routes) != 1 {
  1627  		t.Fatal("Route not added properly")
  1628  	}
  1629  
  1630  	got := routes[0].Via
  1631  	want := route.MultiPath[0].Via
  1632  	if !want.Equal(got) {
  1633  		t.Fatalf("Route Via attribute does not match; got: %s, want: %s", got, want)
  1634  	}
  1635  
  1636  	if err := RouteDel(route); err != nil {
  1637  		t.Fatal(err)
  1638  	}
  1639  	routes, err = RouteList(link, FAMILY_V4)
  1640  	if err != nil {
  1641  		t.Fatal(err)
  1642  	}
  1643  	if len(routes) != 0 {
  1644  		t.Fatal("Route not removed properly")
  1645  	}
  1646  }
  1647  
  1648  func TestRouteUIDOption(t *testing.T) {
  1649  	tearDown := setUpNetlinkTest(t)
  1650  	defer tearDown()
  1651  
  1652  	// setup eth0 so that network is reachable
  1653  	err := LinkAdd(&Dummy{LinkAttrs{Name: "eth0"}})
  1654  	if err != nil {
  1655  		t.Fatal(err)
  1656  	}
  1657  	link, err := LinkByName("eth0")
  1658  	if err != nil {
  1659  		t.Fatal(err)
  1660  	}
  1661  	if err = LinkSetUp(link); err != nil {
  1662  		t.Fatal(err)
  1663  	}
  1664  	addr := &Addr{
  1665  		IPNet: &net.IPNet{
  1666  			IP:   net.IPv4(192, 168, 1, 1),
  1667  			Mask: net.CIDRMask(16, 32),
  1668  		},
  1669  	}
  1670  	if err = AddrAdd(link, addr); err != nil {
  1671  		t.Fatal(err)
  1672  	}
  1673  
  1674  	// a table different than unix.RT_TABLE_MAIN
  1675  	testtable := 1000
  1676  
  1677  	gw1 := net.IPv4(192, 168, 1, 254)
  1678  	gw2 := net.IPv4(192, 168, 2, 254)
  1679  
  1680  	// add default route via gw1 (in main route table by default)
  1681  	defaultRouteMain := Route{
  1682  		Dst: nil,
  1683  		Gw:  gw1,
  1684  	}
  1685  	if err := RouteAdd(&defaultRouteMain); err != nil {
  1686  		t.Fatal(err)
  1687  	}
  1688  
  1689  	// add default route via gw2 in test route table
  1690  	defaultRouteTest := Route{
  1691  		Dst:   nil,
  1692  		Gw:    gw2,
  1693  		Table: testtable,
  1694  	}
  1695  	if err := RouteAdd(&defaultRouteTest); err != nil {
  1696  		t.Fatal(err)
  1697  	}
  1698  
  1699  	// check the routes are in different tables
  1700  	routes, err := RouteListFiltered(FAMILY_V4, &Route{
  1701  		Dst:   nil,
  1702  		Table: unix.RT_TABLE_UNSPEC,
  1703  	}, RT_FILTER_DST|RT_FILTER_TABLE)
  1704  	if err != nil {
  1705  		t.Fatal(err)
  1706  	}
  1707  	if len(routes) != 2 || routes[0].Table == routes[1].Table {
  1708  		t.Fatal("Routes not added properly")
  1709  	}
  1710  
  1711  	// add a rule that uidrange match should result in route lookup of test table for uid other than current
  1712  	// current uid is 0 due to skipUnlessRoot()
  1713  	var uid uint32 = 1000
  1714  	rule := NewRule()
  1715  	rule.UIDRange = NewRuleUIDRange(uid, uid)
  1716  	rule.Table = testtable
  1717  	if err := RuleAdd(rule); err != nil {
  1718  		t.Fatal(err)
  1719  	}
  1720  
  1721  	dstIP := net.IPv4(10, 1, 1, 1)
  1722  
  1723  	// check getting route without UID option
  1724  	routes, err = RouteGetWithOptions(dstIP, &RouteGetOptions{UID: nil})
  1725  	if err != nil {
  1726  		t.Fatal(err)
  1727  	}
  1728  	// current uid is outside uidrange; rule does not apply; lookup main table
  1729  	if len(routes) != 1 || !routes[0].Gw.Equal(gw1) {
  1730  		t.Fatal(routes)
  1731  	}
  1732  
  1733  	// check getting route with UID option
  1734  	routes, err = RouteGetWithOptions(dstIP, &RouteGetOptions{UID: &uid})
  1735  	if err != nil {
  1736  		t.Fatal(err)
  1737  	}
  1738  	// option uid is within uidrange; rule applies; lookup test table
  1739  	if len(routes) != 1 || !routes[0].Gw.Equal(gw2) {
  1740  		t.Fatal(routes)
  1741  	}
  1742  }