github.com/gopacket/gopacket@v1.1.0/routing/routing_test.go (about)

     1  // Copyright 2012 Google, Inc. All rights reserved.
     2  //
     3  // Use of this source code is governed by a BSD-style license
     4  // that can be found in the LICENSE file in the root of the source
     5  // tree.
     6  
     7  //go:build linux
     8  // +build linux
     9  
    10  package routing
    11  
    12  import (
    13  	"fmt"
    14  	"net"
    15  	"runtime"
    16  	"sort"
    17  	"testing"
    18  
    19  	"github.com/vishvananda/netlink"
    20  	"github.com/vishvananda/netns"
    21  )
    22  
    23  func TestPrivateRoute(t *testing.T) {
    24  	tests := []struct {
    25  		name                          string
    26  		router                        router
    27  		routes                        routeSlice
    28  		input                         net.HardwareAddr
    29  		src, dst                      net.IP
    30  		wantIface                     int
    31  		wantGateway, wantPreferredSrc net.IP
    32  		wantErr                       error
    33  	}{
    34  		{
    35  			name: "only static routes",
    36  			router: router{
    37  				ifaces: map[int]*net.Interface{
    38  					1: {
    39  						Index:        1,
    40  						MTU:          1500,
    41  						Name:         "eth0",
    42  						HardwareAddr: net.HardwareAddr{0x54, 0x52, 0x00, 0x00, 0x00, 0x01},
    43  						Flags:        net.FlagUp,
    44  					},
    45  					2: {
    46  						Index:        2,
    47  						MTU:          1500,
    48  						Name:         "eth1",
    49  						HardwareAddr: net.HardwareAddr{0x54, 0x52, 0x00, 0x00, 0x00, 0x02},
    50  						Flags:        net.FlagUp,
    51  					},
    52  				},
    53  				addrs: map[int]ipAddrs{
    54  					1: {
    55  						v4: net.ParseIP("192.168.10.1/24"),
    56  					},
    57  					2: {
    58  						v4: net.ParseIP("192.168.20.1/24"),
    59  					},
    60  				},
    61  			},
    62  			routes: []*rtInfo{
    63  				{
    64  					Dst: &net.IPNet{
    65  						IP:   net.ParseIP("192.168.10.0"),
    66  						Mask: net.IPv4Mask(255, 255, 255, 0),
    67  					},
    68  					PrefSrc:     net.ParseIP("192.168.10.1"),
    69  					OutputIface: 1,
    70  				},
    71  				{
    72  					Dst: &net.IPNet{
    73  						IP:   net.ParseIP("192.168.20.0"),
    74  						Mask: net.IPv4Mask(255, 255, 255, 0),
    75  					},
    76  					PrefSrc:     net.ParseIP("192.168.20.1"),
    77  					OutputIface: 2,
    78  				},
    79  			},
    80  			input:            net.HardwareAddr{0x54, 0x52, 0x00, 0x00, 0x00, 0x01},
    81  			src:              net.ParseIP("192.168.10.1"),
    82  			dst:              net.ParseIP("192.168.20.1"),
    83  			wantIface:        2,
    84  			wantGateway:      nil,
    85  			wantPreferredSrc: net.ParseIP("192.168.20.1"),
    86  			wantErr:          nil,
    87  		},
    88  		{
    89  			name: "not exists route with default gateway",
    90  			router: router{
    91  				ifaces: map[int]*net.Interface{
    92  					1: {
    93  						Index:        1,
    94  						MTU:          1500,
    95  						Name:         "eth0",
    96  						HardwareAddr: net.HardwareAddr{0x54, 0x52, 0x00, 0x00, 0x00, 0x01},
    97  						Flags:        net.FlagUp,
    98  					},
    99  					2: {
   100  						Index:        2,
   101  						MTU:          1500,
   102  						Name:         "eth1",
   103  						HardwareAddr: net.HardwareAddr{0x54, 0x52, 0x00, 0x00, 0x00, 0x02},
   104  						Flags:        net.FlagUp,
   105  					},
   106  				},
   107  				addrs: map[int]ipAddrs{
   108  					1: {
   109  						v4: net.ParseIP("192.168.10.1/24"),
   110  					},
   111  					2: {
   112  						v4: net.ParseIP("192.168.20.1/24"),
   113  					},
   114  				},
   115  			},
   116  			routes: []*rtInfo{
   117  				{
   118  					Gateway:     net.ParseIP("192.168.20.254"),
   119  					PrefSrc:     net.ParseIP("192.168.20.1"),
   120  					OutputIface: 2,
   121  				},
   122  				{
   123  					Dst: &net.IPNet{
   124  						IP:   net.ParseIP("192.168.10.0"),
   125  						Mask: net.IPv4Mask(255, 255, 255, 0),
   126  					},
   127  					PrefSrc:     net.ParseIP("192.168.10.1"),
   128  					OutputIface: 1,
   129  				},
   130  				{
   131  					Dst: &net.IPNet{
   132  						IP:   net.ParseIP("192.168.20.0"),
   133  						Mask: net.IPv4Mask(255, 255, 255, 0),
   134  					},
   135  					PrefSrc:     net.ParseIP("192.168.20.1"),
   136  					OutputIface: 2,
   137  				},
   138  			},
   139  			input:            net.HardwareAddr{0x54, 0x52, 0x00, 0x00, 0x00, 0x01},
   140  			src:              net.ParseIP("192.168.10.1"),
   141  			dst:              net.ParseIP("192.168.30.2"),
   142  			wantIface:        2,
   143  			wantGateway:      net.ParseIP("192.168.20.254"),
   144  			wantPreferredSrc: net.ParseIP("192.168.20.1"),
   145  			wantErr:          nil,
   146  		},
   147  		{
   148  			name: "exists route with default gateway",
   149  			router: router{
   150  				ifaces: map[int]*net.Interface{
   151  					1: {
   152  						Index:        1,
   153  						MTU:          1500,
   154  						Name:         "eth0",
   155  						HardwareAddr: net.HardwareAddr{0x54, 0x52, 0x00, 0x00, 0x00, 0x01},
   156  						Flags:        net.FlagUp,
   157  					},
   158  					2: {
   159  						Index:        2,
   160  						MTU:          1500,
   161  						Name:         "eth1",
   162  						HardwareAddr: net.HardwareAddr{0x54, 0x52, 0x00, 0x00, 0x00, 0x02},
   163  						Flags:        net.FlagUp,
   164  					},
   165  				},
   166  				addrs: map[int]ipAddrs{
   167  					1: {
   168  						v4: net.ParseIP("192.168.10.1/24"),
   169  					},
   170  					2: {
   171  						v4: net.ParseIP("192.168.20.1/24"),
   172  					},
   173  				},
   174  			},
   175  			routes: []*rtInfo{
   176  				{
   177  					Gateway:     net.ParseIP("192.168.20.254"),
   178  					PrefSrc:     net.ParseIP("192.168.20.1"),
   179  					OutputIface: 2,
   180  				},
   181  				{
   182  					Dst: &net.IPNet{
   183  						IP:   net.ParseIP("192.168.10.0"),
   184  						Mask: net.IPv4Mask(255, 255, 255, 0),
   185  					},
   186  					PrefSrc:     net.ParseIP("192.168.10.1"),
   187  					OutputIface: 1,
   188  				},
   189  				{
   190  					Dst: &net.IPNet{
   191  						IP:   net.ParseIP("192.168.20.0"),
   192  						Mask: net.IPv4Mask(255, 255, 255, 0),
   193  					},
   194  					PrefSrc:     net.ParseIP("192.168.20.1"),
   195  					OutputIface: 2,
   196  				},
   197  			},
   198  			input:            net.HardwareAddr{0x54, 0x52, 0x00, 0x00, 0x00, 0x01},
   199  			src:              net.ParseIP("192.168.10.1"),
   200  			dst:              net.ParseIP("192.168.20.2"),
   201  			wantIface:        2,
   202  			wantGateway:      nil,
   203  			wantPreferredSrc: net.ParseIP("192.168.20.1"),
   204  			wantErr:          nil,
   205  		},
   206  		{
   207  			name: "not exists route without default gateway",
   208  			router: router{
   209  				ifaces: map[int]*net.Interface{
   210  					1: {
   211  						Index:        1,
   212  						MTU:          1500,
   213  						Name:         "eth0",
   214  						HardwareAddr: net.HardwareAddr{0x54, 0x52, 0x00, 0x00, 0x00, 0x01},
   215  						Flags:        net.FlagUp,
   216  					},
   217  					2: {
   218  						Index:        2,
   219  						MTU:          1500,
   220  						Name:         "eth1",
   221  						HardwareAddr: net.HardwareAddr{0x54, 0x52, 0x00, 0x00, 0x00, 0x02},
   222  						Flags:        net.FlagUp,
   223  					},
   224  				},
   225  				addrs: map[int]ipAddrs{
   226  					1: {
   227  						v4: net.ParseIP("192.168.10.1/24"),
   228  					},
   229  					2: {
   230  						v4: net.ParseIP("192.168.20.1/24"),
   231  					},
   232  				},
   233  			},
   234  			routes: []*rtInfo{
   235  				{
   236  					Dst: &net.IPNet{
   237  						IP:   net.ParseIP("192.168.10.0"),
   238  						Mask: net.IPv4Mask(255, 255, 255, 0),
   239  					},
   240  					PrefSrc:     net.ParseIP("192.168.10.1"),
   241  					OutputIface: 1,
   242  				},
   243  				{
   244  					Dst: &net.IPNet{
   245  						IP:   net.ParseIP("192.168.20.0"),
   246  						Mask: net.IPv4Mask(255, 255, 255, 0),
   247  					},
   248  					PrefSrc:     net.ParseIP("192.168.20.1"),
   249  					OutputIface: 2,
   250  				},
   251  			},
   252  			input:            net.HardwareAddr{0x54, 0x52, 0x00, 0x00, 0x00, 0x01},
   253  			src:              net.ParseIP("192.168.10.1"),
   254  			dst:              net.ParseIP("192.168.30.2"),
   255  			wantIface:        2,
   256  			wantGateway:      nil,
   257  			wantPreferredSrc: nil,
   258  			wantErr:          fmt.Errorf("no route found for 192.168.30.2"),
   259  		},
   260  	}
   261  
   262  	for _, tt := range tests {
   263  		t.Run(tt.name, func(t *testing.T) {
   264  			iface, gateway, preferredSrc, err := tt.router.route(tt.routes, tt.input, tt.src, tt.dst)
   265  			if tt.wantErr != nil {
   266  				if err != nil && tt.wantErr.Error() == err.Error() {
   267  					return
   268  				}
   269  				t.Errorf("route() illegal return value `err`:\ngot	:%#v\n\nwant:	%#v\n\n", err, tt.wantErr)
   270  
   271  			}
   272  			if err != nil {
   273  				t.Errorf("route() illegal return value `err`:\ngot	:%#v\n\nwant:	nil\n\n", err)
   274  			}
   275  
   276  			if tt.wantIface != iface {
   277  				t.Errorf("route() illegal return value `iface`:\ngot	:%d\n\nwant:	%d\n\n", iface, tt.wantIface)
   278  			}
   279  
   280  			if !tt.wantGateway.Equal(gateway) {
   281  				t.Errorf("route() illegal return value `gateway`:\ngot	:%#v\n\nwant	:%#v\n\n", gateway, tt.wantGateway)
   282  			}
   283  
   284  			if !tt.wantPreferredSrc.Equal(preferredSrc) {
   285  				t.Errorf("route() illegal return value `preferredSrc`:\ngot	:%#v\n\nwant	:%#v\n\n", preferredSrc, tt.wantPreferredSrc)
   286  			}
   287  
   288  		})
   289  	}
   290  
   291  }
   292  
   293  func TestRouting(t *testing.T) {
   294  	runtime.LockOSThread()
   295  	defer runtime.UnlockOSThread()
   296  
   297  	// parent network namespace
   298  	testNs, _ := netns.New()
   299  	defer testNs.Close()
   300  
   301  	// child network namespace
   302  	newns, _ := netns.New()
   303  	defer newns.Close()
   304  
   305  	veth0 := &netlink.Veth{
   306  		LinkAttrs: netlink.LinkAttrs{
   307  			Name: "veth0",
   308  		},
   309  		PeerName: "veth0-peer",
   310  	}
   311  
   312  	veth1 := &netlink.Veth{
   313  		LinkAttrs: netlink.LinkAttrs{
   314  			Name: "veth1",
   315  		},
   316  		PeerName: "veth1-peer",
   317  	}
   318  
   319  	// ip link add veth0 type veth peer name veth0-peer
   320  	if err := netlink.LinkAdd(veth0); err != nil {
   321  		t.Errorf("\nFailed SetUp Test Environment: link add veth0 type veth peer name veth0-peer: %#v\n\n", err)
   322  		return
   323  	}
   324  
   325  	// ip link add veth1 type veth peer name veth1-peer
   326  	if err := netlink.LinkAdd(veth1); err != nil {
   327  		t.Errorf("\nFailed SetUp Test Environment: link add veth1 type veth peer name veth1-peer: %#v\n\n", err)
   328  		return
   329  	}
   330  
   331  	// ip address add 192.168.10.1/24 dev veth0
   332  	veth0Addr, err := netlink.ParseAddr("192.168.10.1/24")
   333  	if err != nil {
   334  		t.Errorf("\nFailed SetUp Test Environment: parse addr 192.168.10.1/24: %#v\n\n", err)
   335  		return
   336  	}
   337  	if err := netlink.AddrAdd(veth0, veth0Addr); err != nil {
   338  		t.Errorf("\nFailed SetUp Test Environment: address add 192.168.10.1/24 dev veth0: %#v\n\n", err)
   339  		return
   340  	}
   341  
   342  	// ip address add 192.168.20.1/24 dev veth1
   343  	veth1Addr, err := netlink.ParseAddr("192.168.20.1/24")
   344  	if err != nil {
   345  		t.Errorf("\nFailed SetUp Test Environment: parse addr 192.168.20.1/24: %#v\n\n", err)
   346  		return
   347  	}
   348  	if err := netlink.AddrAdd(veth1, veth1Addr); err != nil {
   349  		t.Errorf("\nFailed SetUp Test Environment: parse addr 192.168.20.1/24 dev veth1: %#v\n\n", err)
   350  		return
   351  	}
   352  
   353  	// ip link set up veth0
   354  	if err := netlink.LinkSetUp(veth0); err != nil {
   355  		t.Errorf("\nFailed SetUp Test Environment: link set up veth0: %#v\n\n", err)
   356  		return
   357  	}
   358  
   359  	// ip link set up veth1
   360  	if err := netlink.LinkSetUp(veth1); err != nil {
   361  		t.Errorf("\nFailed SetUp Test Environment: link set up veth1: %#v\n\n", err)
   362  		return
   363  	}
   364  
   365  	veth0Peer, err := netlink.LinkByName("veth0-peer")
   366  	if err != nil {
   367  		t.Errorf("\nFailed SetUp Test Environment: link by name veth0-peer: %#v\n\n", err)
   368  		return
   369  	}
   370  	// ip link set up veth0-peer
   371  	if err := netlink.LinkSetUp(veth0Peer); err != nil {
   372  		t.Errorf("\nFailed SetUp Test Environment: link set up veth0-peer: %#v\n\n", err)
   373  		return
   374  	}
   375  	// ip link set dev veth0-peer netns {testNs}
   376  	if err := netlink.LinkSetNsFd(veth0Peer, int(testNs)); err != nil {
   377  		t.Errorf("\nFailed SetUp Test Environment: link set dev veth0-peer netns testNs: %#v\n\n", err)
   378  		return
   379  	}
   380  
   381  	veth1Peer, err := netlink.LinkByName("veth1-peer")
   382  	if err != nil {
   383  		t.Errorf("\nFailed SetUp Test Environment: link by name veth1-peer: %#v\n\n", err)
   384  		return
   385  	}
   386  	// ip link set up veth1-peer
   387  	if err := netlink.LinkSetUp(veth1Peer); err != nil {
   388  		t.Errorf("\nFailed SetUp Test Environment: link set up veth1-peer: %#v\n\n", err)
   389  		return
   390  	}
   391  	// ip link set dev veth1-peer netns {testNs}
   392  	if err := netlink.LinkSetNsFd(veth1Peer, int(testNs)); err != nil {
   393  		t.Errorf("\nFailed SetUp Test Environment: link set dev veth1-peer netns testNs: %#v\n\n", err)
   394  		return
   395  	}
   396  
   397  	/**
   398  	 * routing table
   399  	 * 192.168.10.0/24 dev veth0 proto kernel scope link src 192.168.10.1
   400  	 * 192.168.20.0/24 dev veth1 proto kernel scope link src 192.168.20.1
   401  	 */
   402  
   403  	t.Run("exists route without default gateway", func(t *testing.T) {
   404  		netns.Set(newns)
   405  		r, err := New()
   406  		if err != nil {
   407  			t.Errorf("\ngot:	%#v\nwant:	nil", err)
   408  			return
   409  		}
   410  
   411  		iface, _, _, err := r.Route(net.ParseIP("192.168.10.2"))
   412  		if err != nil {
   413  			t.Errorf("\ngot:	%#v\nwant:	nil", err)
   414  		}
   415  
   416  		if veth0.Index != iface.Index {
   417  			t.Errorf("\ngot:	%d\nwant:	%d\n\n", iface.Index, veth0.Index)
   418  		}
   419  
   420  		iface, _, _, err = r.Route(net.ParseIP("192.168.20.2"))
   421  		if err != nil {
   422  			t.Errorf("\ngot:	%#v\nwant:	nil", err)
   423  		}
   424  
   425  		if veth1.Index != iface.Index {
   426  			t.Errorf("\ngot:	%d\nwant:	%d\n\n", iface.Index, veth1.Index)
   427  		}
   428  	})
   429  
   430  	t.Run("not exists route without default gateway", func(t *testing.T) {
   431  		netns.Set(newns)
   432  
   433  		r, err := New()
   434  		if err != nil {
   435  			t.Errorf("\ngot:	%#v\nwant:	nil\n\n", err)
   436  			return
   437  		}
   438  
   439  		if _, _, _, err = r.Route(net.ParseIP("172.16.0.1")); err == nil && err == fmt.Errorf("no route found for 172.16.0.1") {
   440  			t.Errorf("\ngot:	%#v\nwant:	%#v\n\n", err, fmt.Errorf("no route found for 172.16.0.1"))
   441  			return
   442  		}
   443  	})
   444  
   445  	t.Run("exists route with default gateway", func(t *testing.T) {
   446  		netns.Set(newns)
   447  
   448  		netlink.RouteAdd(&netlink.Route{
   449  			Gw:        net.ParseIP("192.168.20.254"),
   450  			LinkIndex: veth1.Index,
   451  		})
   452  		defer func() {
   453  			// teardown
   454  			netlink.RouteDel(&netlink.Route{
   455  				Gw:        net.ParseIP("192.168.20.254"),
   456  				LinkIndex: veth1.Index,
   457  			})
   458  		}()
   459  
   460  		r, err := New()
   461  		if err != nil {
   462  			t.Errorf("\ngot:	%#v\nwant:	nil\n\n", err)
   463  			return
   464  		}
   465  
   466  		iface, gateway, prefSrc, err := r.Route(net.ParseIP("192.168.10.2"))
   467  		if err != nil {
   468  			t.Errorf("\ngot:	%#v\nwant:	nil\n\n", err)
   469  			return
   470  		}
   471  
   472  		if veth0.Index != iface.Index {
   473  			t.Errorf("\ngot:	%d\nwant:	%d\n\n", iface.Index, veth0.Index)
   474  		}
   475  
   476  		if gateway != nil {
   477  			t.Errorf("\ngot:	%#v\nwant:	nil\n\n", gateway)
   478  		}
   479  
   480  		if !prefSrc.Equal(net.ParseIP("192.168.10.1")) {
   481  			t.Errorf("\ngot:	%#v\nwant:	%#v\n\n", prefSrc, net.ParseIP("192.168.10.1"))
   482  		}
   483  	})
   484  
   485  	t.Run("not exists route with default gateway", func(t *testing.T) {
   486  		netns.Set(newns)
   487  
   488  		netlink.RouteAdd(&netlink.Route{
   489  			Gw:        net.ParseIP("192.168.20.254"),
   490  			LinkIndex: veth1.Index,
   491  		})
   492  		defer func() {
   493  			// teardown
   494  			netlink.RouteDel(&netlink.Route{
   495  				Gw:        net.ParseIP("192.168.20.254"),
   496  				LinkIndex: veth1.Index,
   497  			})
   498  		}()
   499  
   500  		r, err := New()
   501  		if err != nil {
   502  			t.Errorf("\ngot:	%#v\nwant:	nil\n\n", err)
   503  			return
   504  		}
   505  
   506  		iface, gateway, prefSrc, err := r.Route(net.ParseIP("172.16.0.1"))
   507  		if err != nil {
   508  			t.Errorf("\ngot:	%#v\nwant:	nil\n\n", err)
   509  			return
   510  		}
   511  
   512  		if veth1.Index != iface.Index {
   513  			t.Errorf("\ngot:	%d\nwant:	%d\n\n", iface.Index, veth1.Index)
   514  		}
   515  
   516  		if !gateway.Equal(net.ParseIP("192.168.20.254")) {
   517  			t.Errorf("\ngot:	%#v\nwant:	%#v\n\n", gateway, net.ParseIP("192.168.20.254"))
   518  		}
   519  
   520  		if !prefSrc.Equal(net.ParseIP("192.168.20.1")) {
   521  			t.Errorf("\ngot:	%#v\nwant:	%#v\n\n", prefSrc, net.ParseIP("192.168.20.1"))
   522  		}
   523  	})
   524  }
   525  
   526  var testRouter router
   527  
   528  func init() {
   529  	testRouter = router{ifaces: make(map[int]*net.Interface), addrs: make(map[int]ipAddrs)}
   530  	// Configure default route
   531  	defaultHW, _ := net.ParseMAC("01:23:45:67:89:ab")
   532  	defaultInterface := net.Interface{Index: 5, MTU: 1500, Name: "Default", HardwareAddr: defaultHW, Flags: 1}
   533  	testRouter.ifaces[2] = &defaultInterface
   534  	testRouter.addrs[2] = ipAddrs{v4: net.IPv4(192, 168, 1, 2)}
   535  	defaultRoute := &rtInfo{Gateway: net.IPv4(192, 168, 1, 1), InputIface: 0, OutputIface: 2, Priority: 600}
   536  	testRouter.v4 = append(testRouter.v4, defaultRoute)
   537  	// Configure local route
   538  	localHW, _ := net.ParseMAC("01:23:45:67:89:ac")
   539  	localInterface := net.Interface{Index: 1, MTU: 1500, Name: "Local", HardwareAddr: localHW, Flags: 1}
   540  	testRouter.ifaces[1] = &localInterface
   541  	testRouter.addrs[1] = ipAddrs{v4: net.IPv4(10, 0, 0, 2)}
   542  	localRoute := &rtInfo{Dst: &net.IPNet{IP: net.IPv4(10, 0, 0, 0), Mask: net.CIDRMask(8, 32)},
   543  		Gateway: net.IPv4(10, 0, 0, 1), InputIface: 0, OutputIface: 1, Priority: 300}
   544  	testRouter.v4 = append(testRouter.v4, localRoute)
   545  	sort.Sort(testRouter.v4)
   546  }
   547  
   548  var routeTests = []struct {
   549  	dst       net.IP
   550  	ifaceName string
   551  }{
   552  	{net.IPv4(8, 8, 8, 8), "Default"},
   553  	{net.IPv4(192, 168, 2, 3), "Default"},
   554  	{net.IPv4(10, 0, 0, 3), "Local"},
   555  }
   556  
   557  func TestRoute(t *testing.T) {
   558  	for _, tt := range routeTests {
   559  		t.Run(tt.dst.String(), func(t *testing.T) {
   560  			iface, _, _, _ := testRouter.Route(tt.dst)
   561  			if tt.ifaceName != iface.Name {
   562  				t.Fatalf("test %s\n want:%s\n got:%s\n", tt.dst.String(), tt.ifaceName, iface.Name)
   563  			}
   564  		})
   565  	}
   566  }