github.com/rumpl/bof@v23.0.0-rc.2+incompatible/integration/network/macvlan/macvlan_test.go (about) 1 //go:build !windows 2 // +build !windows 3 4 package macvlan // import "github.com/docker/docker/integration/network/macvlan" 5 6 import ( 7 "context" 8 "strings" 9 "testing" 10 11 "github.com/docker/docker/client" 12 "github.com/docker/docker/integration/internal/container" 13 net "github.com/docker/docker/integration/internal/network" 14 n "github.com/docker/docker/integration/network" 15 "github.com/docker/docker/testutil/daemon" 16 "gotest.tools/v3/assert" 17 "gotest.tools/v3/skip" 18 ) 19 20 func TestDockerNetworkMacvlanPersistance(t *testing.T) { 21 // verify the driver automatically provisions the 802.1q link (dm-dummy0.60) 22 skip.If(t, testEnv.IsRemoteDaemon) 23 skip.If(t, testEnv.IsRootless, "rootless mode has different view of network") 24 25 d := daemon.New(t) 26 d.StartWithBusybox(t) 27 defer d.Stop(t) 28 29 master := "dm-dummy0" 30 n.CreateMasterDummy(t, master) 31 defer n.DeleteInterface(t, master) 32 33 c := d.NewClientT(t) 34 35 netName := "dm-persist" 36 net.CreateNoError(context.Background(), t, c, netName, 37 net.WithMacvlan("dm-dummy0.60"), 38 ) 39 assert.Check(t, n.IsNetworkAvailable(c, netName)) 40 d.Restart(t) 41 assert.Check(t, n.IsNetworkAvailable(c, netName)) 42 } 43 44 func TestDockerNetworkMacvlan(t *testing.T) { 45 skip.If(t, testEnv.IsRemoteDaemon) 46 skip.If(t, testEnv.IsRootless, "rootless mode has different view of network") 47 48 for _, tc := range []struct { 49 name string 50 test func(client.APIClient) func(*testing.T) 51 }{ 52 { 53 name: "Subinterface", 54 test: testMacvlanSubinterface, 55 }, { 56 name: "OverlapParent", 57 test: testMacvlanOverlapParent, 58 }, { 59 name: "NilParent", 60 test: testMacvlanNilParent, 61 }, { 62 name: "InternalMode", 63 test: testMacvlanInternalMode, 64 }, { 65 name: "MultiSubnet", 66 test: testMacvlanMultiSubnet, 67 }, { 68 name: "Addressing", 69 test: testMacvlanAddressing, 70 }, 71 } { 72 d := daemon.New(t) 73 d.StartWithBusybox(t) 74 c := d.NewClientT(t) 75 76 t.Run(tc.name, tc.test(c)) 77 78 d.Stop(t) 79 // FIXME(vdemeester) clean network 80 } 81 } 82 83 func testMacvlanOverlapParent(client client.APIClient) func(*testing.T) { 84 return func(t *testing.T) { 85 // verify the same parent interface cannot be used if already in use by an existing network 86 master := "dm-dummy0" 87 n.CreateMasterDummy(t, master) 88 defer n.DeleteInterface(t, master) 89 90 netName := "dm-subinterface" 91 parentName := "dm-dummy0.40" 92 net.CreateNoError(context.Background(), t, client, netName, 93 net.WithMacvlan(parentName), 94 ) 95 assert.Check(t, n.IsNetworkAvailable(client, netName)) 96 97 _, err := net.Create(context.Background(), client, "dm-parent-net-overlap", 98 net.WithMacvlan(parentName), 99 ) 100 assert.Check(t, err != nil) 101 102 // delete the network while preserving the parent link 103 err = client.NetworkRemove(context.Background(), netName) 104 assert.NilError(t, err) 105 106 assert.Check(t, n.IsNetworkNotAvailable(client, netName)) 107 // verify the network delete did not delete the predefined link 108 n.LinkExists(t, master) 109 } 110 } 111 112 func testMacvlanSubinterface(client client.APIClient) func(*testing.T) { 113 return func(t *testing.T) { 114 // verify the same parent interface cannot be used if already in use by an existing network 115 master := "dm-dummy0" 116 parentName := "dm-dummy0.20" 117 n.CreateMasterDummy(t, master) 118 defer n.DeleteInterface(t, master) 119 n.CreateVlanInterface(t, master, parentName, "20") 120 121 netName := "dm-subinterface" 122 net.CreateNoError(context.Background(), t, client, netName, 123 net.WithMacvlan(parentName), 124 ) 125 assert.Check(t, n.IsNetworkAvailable(client, netName)) 126 127 // delete the network while preserving the parent link 128 err := client.NetworkRemove(context.Background(), netName) 129 assert.NilError(t, err) 130 131 assert.Check(t, n.IsNetworkNotAvailable(client, netName)) 132 // verify the network delete did not delete the predefined link 133 n.LinkExists(t, parentName) 134 } 135 } 136 137 func testMacvlanNilParent(client client.APIClient) func(*testing.T) { 138 return func(t *testing.T) { 139 // macvlan bridge mode - dummy parent interface is provisioned dynamically 140 netName := "dm-nil-parent" 141 net.CreateNoError(context.Background(), t, client, netName, 142 net.WithMacvlan(""), 143 ) 144 assert.Check(t, n.IsNetworkAvailable(client, netName)) 145 146 ctx := context.Background() 147 id1 := container.Run(ctx, t, client, container.WithNetworkMode(netName)) 148 id2 := container.Run(ctx, t, client, container.WithNetworkMode(netName)) 149 150 _, err := container.Exec(ctx, client, id2, []string{"ping", "-c", "1", id1}) 151 assert.Check(t, err == nil) 152 } 153 } 154 155 func testMacvlanInternalMode(client client.APIClient) func(*testing.T) { 156 return func(t *testing.T) { 157 // macvlan bridge mode - dummy parent interface is provisioned dynamically 158 netName := "dm-internal" 159 net.CreateNoError(context.Background(), t, client, netName, 160 net.WithMacvlan(""), 161 net.WithInternal(), 162 ) 163 assert.Check(t, n.IsNetworkAvailable(client, netName)) 164 165 ctx := context.Background() 166 id1 := container.Run(ctx, t, client, container.WithNetworkMode(netName)) 167 id2 := container.Run(ctx, t, client, container.WithNetworkMode(netName)) 168 169 result, _ := container.Exec(ctx, client, id1, []string{"ping", "-c", "1", "8.8.8.8"}) 170 assert.Check(t, strings.Contains(result.Combined(), "Network is unreachable")) 171 172 _, err := container.Exec(ctx, client, id2, []string{"ping", "-c", "1", id1}) 173 assert.Check(t, err == nil) 174 } 175 } 176 177 func testMacvlanMultiSubnet(client client.APIClient) func(*testing.T) { 178 return func(t *testing.T) { 179 netName := "dualstackbridge" 180 net.CreateNoError(context.Background(), t, client, netName, 181 net.WithMacvlan(""), 182 net.WithIPv6(), 183 net.WithIPAM("172.28.100.0/24", ""), 184 net.WithIPAM("172.28.102.0/24", "172.28.102.254"), 185 net.WithIPAM("2001:db8:abc2::/64", ""), 186 net.WithIPAM("2001:db8:abc4::/64", "2001:db8:abc4::254"), 187 ) 188 189 assert.Check(t, n.IsNetworkAvailable(client, netName)) 190 191 // start dual stack containers and verify the user specified --ip and --ip6 addresses on subnets 172.28.100.0/24 and 2001:db8:abc2::/64 192 ctx := context.Background() 193 id1 := container.Run(ctx, t, client, 194 container.WithNetworkMode("dualstackbridge"), 195 container.WithIPv4("dualstackbridge", "172.28.100.20"), 196 container.WithIPv6("dualstackbridge", "2001:db8:abc2::20"), 197 ) 198 id2 := container.Run(ctx, t, client, 199 container.WithNetworkMode("dualstackbridge"), 200 container.WithIPv4("dualstackbridge", "172.28.100.21"), 201 container.WithIPv6("dualstackbridge", "2001:db8:abc2::21"), 202 ) 203 c1, err := client.ContainerInspect(ctx, id1) 204 assert.NilError(t, err) 205 206 // verify ipv4 connectivity to the explicit --ipv address second to first 207 _, err = container.Exec(ctx, client, id2, []string{"ping", "-c", "1", c1.NetworkSettings.Networks["dualstackbridge"].IPAddress}) 208 assert.NilError(t, err) 209 // verify ipv6 connectivity to the explicit --ipv6 address second to first 210 _, err = container.Exec(ctx, client, id2, []string{"ping6", "-c", "1", c1.NetworkSettings.Networks["dualstackbridge"].GlobalIPv6Address}) 211 assert.NilError(t, err) 212 213 // start dual stack containers and verify the user specified --ip and --ip6 addresses on subnets 172.28.102.0/24 and 2001:db8:abc4::/64 214 id3 := container.Run(ctx, t, client, 215 container.WithNetworkMode("dualstackbridge"), 216 container.WithIPv4("dualstackbridge", "172.28.102.20"), 217 container.WithIPv6("dualstackbridge", "2001:db8:abc4::20"), 218 ) 219 id4 := container.Run(ctx, t, client, 220 container.WithNetworkMode("dualstackbridge"), 221 container.WithIPv4("dualstackbridge", "172.28.102.21"), 222 container.WithIPv6("dualstackbridge", "2001:db8:abc4::21"), 223 ) 224 c3, err := client.ContainerInspect(ctx, id3) 225 assert.NilError(t, err) 226 227 // verify ipv4 connectivity to the explicit --ipv address from third to fourth 228 _, err = container.Exec(ctx, client, id4, []string{"ping", "-c", "1", c3.NetworkSettings.Networks["dualstackbridge"].IPAddress}) 229 assert.NilError(t, err) 230 // verify ipv6 connectivity to the explicit --ipv6 address from third to fourth 231 _, err = container.Exec(ctx, client, id4, []string{"ping6", "-c", "1", c3.NetworkSettings.Networks["dualstackbridge"].GlobalIPv6Address}) 232 assert.NilError(t, err) 233 234 // Inspect the v4 gateway to ensure the proper default GW was assigned 235 assert.Equal(t, c1.NetworkSettings.Networks["dualstackbridge"].Gateway, "172.28.100.1") 236 // Inspect the v6 gateway to ensure the proper default GW was assigned 237 assert.Equal(t, c1.NetworkSettings.Networks["dualstackbridge"].IPv6Gateway, "2001:db8:abc2::1") 238 // Inspect the v4 gateway to ensure the proper explicitly assigned default GW was assigned 239 assert.Equal(t, c3.NetworkSettings.Networks["dualstackbridge"].Gateway, "172.28.102.254") 240 // Inspect the v6 gateway to ensure the proper explicitly assigned default GW was assigned 241 assert.Equal(t, c3.NetworkSettings.Networks["dualstackbridge"].IPv6Gateway, "2001:db8:abc4::254") 242 } 243 } 244 245 func testMacvlanAddressing(client client.APIClient) func(*testing.T) { 246 return func(t *testing.T) { 247 // Ensure the default gateways, next-hops and default dev devices are properly set 248 netName := "dualstackbridge" 249 net.CreateNoError(context.Background(), t, client, netName, 250 net.WithMacvlan(""), 251 net.WithIPv6(), 252 net.WithOption("macvlan_mode", "bridge"), 253 net.WithIPAM("172.28.130.0/24", ""), 254 net.WithIPAM("2001:db8:abca::/64", "2001:db8:abca::254"), 255 ) 256 assert.Check(t, n.IsNetworkAvailable(client, netName)) 257 258 ctx := context.Background() 259 id1 := container.Run(ctx, t, client, 260 container.WithNetworkMode("dualstackbridge"), 261 ) 262 263 // Validate macvlan bridge mode defaults gateway sets the default IPAM next-hop inferred from the subnet 264 result, err := container.Exec(ctx, client, id1, []string{"ip", "route"}) 265 assert.NilError(t, err) 266 assert.Check(t, strings.Contains(result.Combined(), "default via 172.28.130.1 dev eth0")) 267 // Validate macvlan bridge mode sets the v6 gateway to the user specified default gateway/next-hop 268 result, err = container.Exec(ctx, client, id1, []string{"ip", "-6", "route"}) 269 assert.NilError(t, err) 270 assert.Check(t, strings.Contains(result.Combined(), "default via 2001:db8:abca::254 dev eth0")) 271 } 272 }