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 }