github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/test/packetimpact/netdevs/netdevs_test.go (about)

     1  // Copyright 2020 The gVisor Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //   http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  package netdevs
    15  
    16  import (
    17  	"fmt"
    18  	"net"
    19  	"testing"
    20  
    21  	"github.com/google/go-cmp/cmp"
    22  )
    23  
    24  func mustParseMAC(s string) net.HardwareAddr {
    25  	mac, err := net.ParseMAC(s)
    26  	if err != nil {
    27  		panic(fmt.Sprintf("failed to parse test MAC %q: %s", s, err))
    28  	}
    29  	return mac
    30  }
    31  
    32  func TestParseDevices(t *testing.T) {
    33  	for _, v := range []struct {
    34  		desc      string
    35  		cmdOutput string
    36  		want      map[string]DeviceInfo
    37  	}{
    38  		{
    39  			desc: "v4 and v6",
    40  			cmdOutput: `
    41  1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    42    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    43    inet 127.0.0.1/8 scope host lo
    44      valid_lft forever preferred_lft forever
    45    inet6 ::1/128 scope host
    46      valid_lft forever preferred_lft forever
    47  2613: eth0@if2614: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    48    link/ether 02:42:c0:a8:09:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    49    inet 192.168.9.2/24 brd 192.168.9.255 scope global eth0
    50      valid_lft forever preferred_lft forever
    51    inet6 fe80::42:c0ff:fea8:902/64 scope link tentative
    52      valid_lft forever preferred_lft forever
    53  2615: eth2@if2616: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    54    link/ether 02:42:df:f5:e1:0a brd ff:ff:ff:ff:ff:ff link-netnsid 0
    55    inet 223.245.225.10/24 brd 223.245.225.255 scope global eth2
    56      valid_lft forever preferred_lft forever
    57    inet6 fe80::42:dfff:fef5:e10a/64 scope link tentative
    58      valid_lft forever preferred_lft forever
    59  2617: eth1@if2618: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    60    link/ether 02:42:da:33:13:0a brd ff:ff:ff:ff:ff:ff link-netnsid 0
    61    inet 218.51.19.10/24 brd 218.51.19.255 scope global eth1
    62      valid_lft forever preferred_lft forever
    63    inet6 fe80::42:daff:fe33:130a/64 scope link tentative
    64      valid_lft forever preferred_lft forever`,
    65  			want: map[string]DeviceInfo{
    66  				"lo": {
    67  					ID:       1,
    68  					MAC:      mustParseMAC("00:00:00:00:00:00"),
    69  					IPv4Addr: net.IPv4(127, 0, 0, 1),
    70  					IPv4Net: &net.IPNet{
    71  						IP:   net.IPv4(127, 0, 0, 0),
    72  						Mask: net.CIDRMask(8, 32),
    73  					},
    74  					IPv6Addr: net.ParseIP("::1"),
    75  					IPv6Net: &net.IPNet{
    76  						IP:   net.ParseIP("::1"),
    77  						Mask: net.CIDRMask(128, 128),
    78  					},
    79  				},
    80  				"eth0": {
    81  					ID:       2613,
    82  					MAC:      mustParseMAC("02:42:c0:a8:09:02"),
    83  					IPv4Addr: net.IPv4(192, 168, 9, 2),
    84  					IPv4Net: &net.IPNet{
    85  						IP:   net.IPv4(192, 168, 9, 0),
    86  						Mask: net.CIDRMask(24, 32),
    87  					},
    88  					IPv6Addr: net.ParseIP("fe80::42:c0ff:fea8:902"),
    89  					IPv6Net: &net.IPNet{
    90  						IP:   net.ParseIP("fe80::"),
    91  						Mask: net.CIDRMask(64, 128),
    92  					},
    93  				},
    94  				"eth1": {
    95  					ID:       2617,
    96  					MAC:      mustParseMAC("02:42:da:33:13:0a"),
    97  					IPv4Addr: net.IPv4(218, 51, 19, 10),
    98  					IPv4Net: &net.IPNet{
    99  						IP:   net.IPv4(218, 51, 19, 0),
   100  						Mask: net.CIDRMask(24, 32),
   101  					},
   102  					IPv6Addr: net.ParseIP("fe80::42:daff:fe33:130a"),
   103  					IPv6Net: &net.IPNet{
   104  						IP:   net.ParseIP("fe80::"),
   105  						Mask: net.CIDRMask(64, 128),
   106  					},
   107  				},
   108  				"eth2": {
   109  					ID:       2615,
   110  					MAC:      mustParseMAC("02:42:df:f5:e1:0a"),
   111  					IPv4Addr: net.IPv4(223, 245, 225, 10),
   112  					IPv4Net: &net.IPNet{
   113  						IP:   net.IPv4(223, 245, 225, 0),
   114  						Mask: net.CIDRMask(24, 32),
   115  					},
   116  					IPv6Addr: net.ParseIP("fe80::42:dfff:fef5:e10a"),
   117  					IPv6Net: &net.IPNet{
   118  						IP:   net.ParseIP("fe80::"),
   119  						Mask: net.CIDRMask(64, 128),
   120  					},
   121  				},
   122  			},
   123  		},
   124  		{
   125  			desc: "v4 only",
   126  			cmdOutput: `
   127  2613: eth0@if2614: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
   128    link/ether 02:42:c0:a8:09:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
   129    inet 192.168.9.2/24 brd 192.168.9.255 scope global eth0
   130      valid_lft forever preferred_lft forever`,
   131  			want: map[string]DeviceInfo{
   132  				"eth0": {
   133  					ID:       2613,
   134  					MAC:      mustParseMAC("02:42:c0:a8:09:02"),
   135  					IPv4Addr: net.IPv4(192, 168, 9, 2),
   136  					IPv4Net: &net.IPNet{
   137  						IP:   net.IPv4(192, 168, 9, 0),
   138  						Mask: net.CIDRMask(24, 32),
   139  					},
   140  				},
   141  			},
   142  		},
   143  		{
   144  			desc: "v6 only",
   145  			cmdOutput: `
   146  2615: eth2@if2616: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
   147    link/ether 02:42:df:f5:e1:0a brd ff:ff:ff:ff:ff:ff link-netnsid 0
   148    inet6 fe80::42:dfff:fef5:e10a/64 scope link tentative
   149      valid_lft forever preferred_lft forever`,
   150  			want: map[string]DeviceInfo{
   151  				"eth2": {
   152  					ID:       2615,
   153  					MAC:      mustParseMAC("02:42:df:f5:e1:0a"),
   154  					IPv6Addr: net.ParseIP("fe80::42:dfff:fef5:e10a"),
   155  					IPv6Net: &net.IPNet{
   156  						IP:   net.ParseIP("fe80::"),
   157  						Mask: net.CIDRMask(64, 128),
   158  					},
   159  				},
   160  			},
   161  		},
   162  	} {
   163  		t.Run(v.desc, func(t *testing.T) {
   164  			got, err := ParseDevices(v.cmdOutput)
   165  			if err != nil {
   166  				t.Errorf("ParseDevices(\n%s\n) got unexpected error: %s", v.cmdOutput, err)
   167  			}
   168  			if diff := cmp.Diff(v.want, got); diff != "" {
   169  				t.Errorf("ParseDevices(\n%s\n) got output diff (-want, +got):\n%s", v.cmdOutput, diff)
   170  			}
   171  		})
   172  	}
   173  }
   174  
   175  func TestParseDevicesErrors(t *testing.T) {
   176  	for _, v := range []struct {
   177  		desc      string
   178  		cmdOutput string
   179  	}{
   180  		{
   181  			desc: "invalid MAC addr",
   182  			cmdOutput: `
   183  2617: eth1@if2618: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
   184  	link/ether 02:42:da:33:13:0a:ffffffff brd ff:ff:ff:ff:ff:ff link-netnsid 0
   185    inet 218.51.19.10/24 brd 218.51.19.255 scope global eth1
   186      valid_lft forever preferred_lft forever
   187    inet6 fe80::42:daff:fe33:130a/64 scope link tentative
   188      valid_lft forever preferred_lft forever`,
   189  		},
   190  		{
   191  			desc: "invalid v4 addr",
   192  			cmdOutput: `
   193  2617: eth1@if2618: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
   194    link/ether 02:42:da:33:13:0a brd ff:ff:ff:ff:ff:ff link-netnsid 0
   195    inet 1234.4321.424242.0/24 brd 218.51.19.255 scope global eth1
   196      valid_lft forever preferred_lft forever
   197    inet6 fe80::42:daff:fe33:130a/64 scope link tentative
   198      valid_lft forever preferred_lft forever`,
   199  		},
   200  		{
   201  			desc: "invalid v6 addr",
   202  			cmdOutput: `
   203  2617: eth1@if2618: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
   204    link/ether 02:42:da:33:13:0a brd ff:ff:ff:ff:ff:ff link-netnsid 0
   205    inet 218.51.19.10/24 brd 218.51.19.255 scope global eth1
   206      valid_lft forever preferred_lft forever
   207  		inet6 fe80:ffffffff::42:daff:fe33:130a/64 scope link tentative
   208      valid_lft forever preferred_lft forever`,
   209  		},
   210  		{
   211  			desc: "invalid CIDR missing prefixlen",
   212  			cmdOutput: `
   213  2617: eth1@if2618: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
   214    link/ether 02:42:da:33:13:0a brd ff:ff:ff:ff:ff:ff link-netnsid 0
   215    inet 218.51.19.10 brd 218.51.19.255 scope global eth1
   216      valid_lft forever preferred_lft forever
   217    inet6 fe80::42:daff:fe33:130a scope link tentative
   218      valid_lft forever preferred_lft forever`,
   219  		},
   220  	} {
   221  		t.Run(v.desc, func(t *testing.T) {
   222  			if _, err := ParseDevices(v.cmdOutput); err == nil {
   223  				t.Errorf("ParseDevices(\n%s\n) succeeded unexpectedly, want error", v.cmdOutput)
   224  			}
   225  		})
   226  	}
   227  }