To support this, a new netlabel is added: `com.docker.network.endpoint.ifname`.
It gives the ability to specify the interface name to be set by
netdrivers when the interface is added / moved into the container's
network namespace.
All builtin netdrivers support it.
Signed-off-by: Albin Kerouanton <albinker@gmail.com>
| ... | ... |
@@ -16,6 +16,7 @@ import ( |
| 16 | 16 |
"github.com/docker/docker/internal/nlwrap" |
| 17 | 17 |
"github.com/docker/docker/internal/testutils/networking" |
| 18 | 18 |
"github.com/docker/docker/libnetwork/drivers/bridge" |
| 19 |
+ "github.com/docker/docker/libnetwork/netlabel" |
|
| 19 | 20 |
"github.com/docker/docker/testutil" |
| 20 | 21 |
"github.com/docker/docker/testutil/daemon" |
| 21 | 22 |
"github.com/vishvananda/netlink" |
| ... | ... |
@@ -404,3 +405,21 @@ func TestIsolated(t *testing.T) {
|
| 404 | 404 |
ping(t, "-4") |
| 405 | 405 |
ping(t, "-6") |
| 406 | 406 |
} |
| 407 |
+ |
|
| 408 |
+func TestEndpointWithCustomIfname(t *testing.T) {
|
|
| 409 |
+ ctx := setupTest(t) |
|
| 410 |
+ apiClient := testEnv.APIClient() |
|
| 411 |
+ |
|
| 412 |
+ ctrID := ctr.Run(ctx, t, apiClient, |
|
| 413 |
+ ctr.WithCmd("ip", "-o", "link", "show", "foobar"),
|
|
| 414 |
+ ctr.WithEndpointSettings("bridge", &networktypes.EndpointSettings{
|
|
| 415 |
+ DriverOpts: map[string]string{
|
|
| 416 |
+ netlabel.Ifname: "foobar", |
|
| 417 |
+ }, |
|
| 418 |
+ })) |
|
| 419 |
+ defer ctr.Remove(ctx, t, apiClient, ctrID, containertypes.RemoveOptions{Force: true})
|
|
| 420 |
+ |
|
| 421 |
+ out, err := ctr.Output(ctx, apiClient, ctrID) |
|
| 422 |
+ assert.NilError(t, err) |
|
| 423 |
+ assert.Assert(t, strings.Contains(out.Stdout, ": foobar@if"), "expected ': foobar@if' in 'ip link show':\n%s", out.Stdout) |
|
| 424 |
+} |
| ... | ... |
@@ -15,6 +15,7 @@ import ( |
| 15 | 15 |
"github.com/docker/docker/integration/internal/container" |
| 16 | 16 |
net "github.com/docker/docker/integration/internal/network" |
| 17 | 17 |
n "github.com/docker/docker/integration/network" |
| 18 |
+ "github.com/docker/docker/libnetwork/netlabel" |
|
| 18 | 19 |
"github.com/docker/docker/testutil" |
| 19 | 20 |
"github.com/docker/docker/testutil/daemon" |
| 20 | 21 |
"gotest.tools/v3/assert" |
| ... | ... |
@@ -682,3 +683,33 @@ func TestPointToPoint(t *testing.T) {
|
| 682 | 682 |
}) |
| 683 | 683 |
} |
| 684 | 684 |
} |
| 685 |
+ |
|
| 686 |
+func TestEndpointWithCustomIfname(t *testing.T) {
|
|
| 687 |
+ skip.If(t, testEnv.IsRemoteDaemon) |
|
| 688 |
+ skip.If(t, testEnv.IsRootless, "rootless mode has different view of network") |
|
| 689 |
+ |
|
| 690 |
+ ctx := setupTest(t) |
|
| 691 |
+ apiClient := testEnv.APIClient() |
|
| 692 |
+ |
|
| 693 |
+ // master dummy interface 'di' notation represent 'docker ipvlan' |
|
| 694 |
+ const master = "di-dummy0" |
|
| 695 |
+ n.CreateMasterDummy(ctx, t, master) |
|
| 696 |
+ defer n.DeleteInterface(ctx, t, master) |
|
| 697 |
+ |
|
| 698 |
+ // create a network specifying the desired sub-interface name |
|
| 699 |
+ const netName = "ipvlan-custom-ifname" |
|
| 700 |
+ net.CreateNoError(ctx, t, apiClient, netName, net.WithIPvlan("di-dummy0.70", ""))
|
|
| 701 |
+ |
|
| 702 |
+ ctrID := container.Run(ctx, t, apiClient, |
|
| 703 |
+ container.WithCmd("ip", "-o", "link", "show", "foobar"),
|
|
| 704 |
+ container.WithEndpointSettings(netName, &network.EndpointSettings{
|
|
| 705 |
+ DriverOpts: map[string]string{
|
|
| 706 |
+ netlabel.Ifname: "foobar", |
|
| 707 |
+ }, |
|
| 708 |
+ })) |
|
| 709 |
+ defer container.Remove(ctx, t, apiClient, ctrID, containertypes.RemoveOptions{Force: true})
|
|
| 710 |
+ |
|
| 711 |
+ out, err := container.Output(ctx, apiClient, ctrID) |
|
| 712 |
+ assert.NilError(t, err) |
|
| 713 |
+ assert.Assert(t, strings.Contains(out.Stdout, ": foobar@if"), "expected ': foobar@if' in 'ip link show':\n%s", out.Stdout) |
|
| 714 |
+} |
| ... | ... |
@@ -48,3 +48,10 @@ func TestMain(m *testing.M) {
|
| 48 | 48 |
shutdown(ctx) |
| 49 | 49 |
os.Exit(code) |
| 50 | 50 |
} |
| 51 |
+ |
|
| 52 |
+func setupTest(t *testing.T) context.Context {
|
|
| 53 |
+ ctx := testutil.StartSpan(baseContext, t) |
|
| 54 |
+ environment.ProtectAll(ctx, t, testEnv) |
|
| 55 |
+ t.Cleanup(func() { testEnv.Clean(ctx, t) })
|
|
| 56 |
+ return ctx |
|
| 57 |
+} |
| ... | ... |
@@ -14,6 +14,7 @@ import ( |
| 14 | 14 |
"github.com/docker/docker/integration/internal/container" |
| 15 | 15 |
net "github.com/docker/docker/integration/internal/network" |
| 16 | 16 |
n "github.com/docker/docker/integration/network" |
| 17 |
+ "github.com/docker/docker/libnetwork/netlabel" |
|
| 17 | 18 |
"github.com/docker/docker/testutil" |
| 18 | 19 |
"github.com/docker/docker/testutil/daemon" |
| 19 | 20 |
"gotest.tools/v3/assert" |
| ... | ... |
@@ -640,3 +641,32 @@ func TestPointToPoint(t *testing.T) {
|
| 640 | 640 |
assert.Check(t, is.Equal(res.Stderr.Len(), 0)) |
| 641 | 641 |
assert.Check(t, is.Contains(res.Stdout.String(), "1 packets transmitted, 1 packets received")) |
| 642 | 642 |
} |
| 643 |
+ |
|
| 644 |
+func TestEndpointWithCustomIfname(t *testing.T) {
|
|
| 645 |
+ skip.If(t, testEnv.IsRemoteDaemon) |
|
| 646 |
+ skip.If(t, testEnv.IsRootless, "rootless mode has different view of network") |
|
| 647 |
+ |
|
| 648 |
+ ctx := setupTest(t) |
|
| 649 |
+ apiClient := testEnv.APIClient() |
|
| 650 |
+ |
|
| 651 |
+ const master = "dm-dummy0" |
|
| 652 |
+ n.CreateMasterDummy(ctx, t, master) |
|
| 653 |
+ defer n.DeleteInterface(ctx, t, master) |
|
| 654 |
+ |
|
| 655 |
+ // create a network specifying the desired sub-interface name |
|
| 656 |
+ const netName = "macvlan-custom-ifname" |
|
| 657 |
+ net.CreateNoError(ctx, t, apiClient, netName, net.WithMacvlan("dm-dummy0.60"))
|
|
| 658 |
+ |
|
| 659 |
+ ctrID := container.Run(ctx, t, apiClient, |
|
| 660 |
+ container.WithCmd("ip", "-o", "link", "show", "foobar"),
|
|
| 661 |
+ container.WithEndpointSettings(netName, &network.EndpointSettings{
|
|
| 662 |
+ DriverOpts: map[string]string{
|
|
| 663 |
+ netlabel.Ifname: "foobar", |
|
| 664 |
+ }, |
|
| 665 |
+ })) |
|
| 666 |
+ defer container.Remove(ctx, t, apiClient, ctrID, containertypes.RemoveOptions{Force: true})
|
|
| 667 |
+ |
|
| 668 |
+ out, err := container.Output(ctx, apiClient, ctrID) |
|
| 669 |
+ assert.NilError(t, err) |
|
| 670 |
+ assert.Assert(t, strings.Contains(out.Stdout, ": foobar@if"), "expected ': foobar@if' in 'ip link show':\n%s", out.Stdout) |
|
| 671 |
+} |
| ... | ... |
@@ -52,3 +52,10 @@ func TestMain(m *testing.M) {
|
| 52 | 52 |
shutdown(ctx) |
| 53 | 53 |
os.Exit(code) |
| 54 | 54 |
} |
| 55 |
+ |
|
| 56 |
+func setupTest(t *testing.T) context.Context {
|
|
| 57 |
+ ctx := testutil.StartSpan(baseContext, t) |
|
| 58 |
+ environment.ProtectAll(ctx, t, testEnv) |
|
| 59 |
+ t.Cleanup(func() { testEnv.Clean(ctx, t) })
|
|
| 60 |
+ return ctx |
|
| 61 |
+} |
| 55 | 62 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,61 @@ |
| 0 |
+//go:build !windows |
|
| 1 |
+ |
|
| 2 |
+package overlay // import "github.com/docker/docker/integration/network/overlay" |
|
| 3 |
+ |
|
| 4 |
+import ( |
|
| 5 |
+ "context" |
|
| 6 |
+ "os" |
|
| 7 |
+ "testing" |
|
| 8 |
+ |
|
| 9 |
+ "github.com/docker/docker/testutil" |
|
| 10 |
+ "github.com/docker/docker/testutil/environment" |
|
| 11 |
+ "go.opentelemetry.io/otel" |
|
| 12 |
+ "go.opentelemetry.io/otel/attribute" |
|
| 13 |
+ "go.opentelemetry.io/otel/codes" |
|
| 14 |
+) |
|
| 15 |
+ |
|
| 16 |
+var ( |
|
| 17 |
+ testEnv *environment.Execution |
|
| 18 |
+ baseContext context.Context |
|
| 19 |
+) |
|
| 20 |
+ |
|
| 21 |
+func TestMain(m *testing.M) {
|
|
| 22 |
+ shutdown := testutil.ConfigureTracing() |
|
| 23 |
+ |
|
| 24 |
+ ctx, span := otel.Tracer("").Start(context.Background(), "integration/network/overlay/TestMain")
|
|
| 25 |
+ baseContext = ctx |
|
| 26 |
+ |
|
| 27 |
+ var err error |
|
| 28 |
+ testEnv, err = environment.New(ctx) |
|
| 29 |
+ if err != nil {
|
|
| 30 |
+ span.SetStatus(codes.Error, err.Error()) |
|
| 31 |
+ span.End() |
|
| 32 |
+ shutdown(ctx) |
|
| 33 |
+ panic(err) |
|
| 34 |
+ } |
|
| 35 |
+ |
|
| 36 |
+ err = environment.EnsureFrozenImagesLinux(ctx, testEnv) |
|
| 37 |
+ if err != nil {
|
|
| 38 |
+ span.SetStatus(codes.Error, err.Error()) |
|
| 39 |
+ span.End() |
|
| 40 |
+ shutdown(ctx) |
|
| 41 |
+ panic(err) |
|
| 42 |
+ } |
|
| 43 |
+ |
|
| 44 |
+ testEnv.Print() |
|
| 45 |
+ code := m.Run() |
|
| 46 |
+ if code != 0 {
|
|
| 47 |
+ span.SetStatus(codes.Error, "m.Run() returned non-zero exit code") |
|
| 48 |
+ } |
|
| 49 |
+ span.SetAttributes(attribute.Int("exit", code))
|
|
| 50 |
+ span.End() |
|
| 51 |
+ shutdown(ctx) |
|
| 52 |
+ os.Exit(code) |
|
| 53 |
+} |
|
| 54 |
+ |
|
| 55 |
+func setupTest(t *testing.T) context.Context {
|
|
| 56 |
+ ctx := testutil.StartSpan(baseContext, t) |
|
| 57 |
+ environment.ProtectAll(ctx, t, testEnv) |
|
| 58 |
+ t.Cleanup(func() { testEnv.Clean(ctx, t) })
|
|
| 59 |
+ return ctx |
|
| 60 |
+} |
| 0 | 1 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,49 @@ |
| 0 |
+//go:build !windows |
|
| 1 |
+ |
|
| 2 |
+package overlay // import "github.com/docker/docker/integration/network/overlay" |
|
| 3 |
+ |
|
| 4 |
+import ( |
|
| 5 |
+ "strings" |
|
| 6 |
+ "testing" |
|
| 7 |
+ |
|
| 8 |
+ containertypes "github.com/docker/docker/api/types/container" |
|
| 9 |
+ "github.com/docker/docker/api/types/network" |
|
| 10 |
+ "github.com/docker/docker/integration/internal/container" |
|
| 11 |
+ net "github.com/docker/docker/integration/internal/network" |
|
| 12 |
+ "github.com/docker/docker/libnetwork/netlabel" |
|
| 13 |
+ "github.com/docker/docker/testutil/daemon" |
|
| 14 |
+ "gotest.tools/v3/assert" |
|
| 15 |
+ "gotest.tools/v3/skip" |
|
| 16 |
+) |
|
| 17 |
+ |
|
| 18 |
+func TestEndpointWithCustomIfname(t *testing.T) {
|
|
| 19 |
+ skip.If(t, testEnv.IsRootless, "rootless mode doesn't support overlay networks") |
|
| 20 |
+ |
|
| 21 |
+ ctx := setupTest(t) |
|
| 22 |
+ |
|
| 23 |
+ d := daemon.New(t) |
|
| 24 |
+ d.StartAndSwarmInit(ctx, t) |
|
| 25 |
+ defer d.Stop(t) |
|
| 26 |
+ defer d.SwarmLeave(ctx, t, true) |
|
| 27 |
+ |
|
| 28 |
+ apiClient := d.NewClientT(t) |
|
| 29 |
+ |
|
| 30 |
+ // create a network specifying the desired sub-interface name |
|
| 31 |
+ const netName = "overlay-custom-ifname" |
|
| 32 |
+ net.CreateNoError(ctx, t, apiClient, netName, |
|
| 33 |
+ net.WithDriver("overlay"),
|
|
| 34 |
+ net.WithAttachable()) |
|
| 35 |
+ |
|
| 36 |
+ ctrID := container.Run(ctx, t, apiClient, |
|
| 37 |
+ container.WithCmd("ip", "-o", "link", "show", "foobar"),
|
|
| 38 |
+ container.WithEndpointSettings(netName, &network.EndpointSettings{
|
|
| 39 |
+ DriverOpts: map[string]string{
|
|
| 40 |
+ netlabel.Ifname: "foobar", |
|
| 41 |
+ }, |
|
| 42 |
+ })) |
|
| 43 |
+ defer container.Remove(ctx, t, apiClient, ctrID, containertypes.RemoveOptions{Force: true})
|
|
| 44 |
+ |
|
| 45 |
+ out, err := container.Output(ctx, apiClient, ctrID) |
|
| 46 |
+ assert.NilError(t, err) |
|
| 47 |
+ assert.Assert(t, strings.Contains(out.Stdout, ": foobar@if"), "expected ': foobar@if' in 'ip link show':\n%s", out.Stdout) |
|
| 48 |
+} |
| ... | ... |
@@ -2,15 +2,19 @@ package network // import "github.com/docker/docker/integration/network" |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 | 4 |
"context" |
| 5 |
+ "strings" |
|
| 5 | 6 |
"testing" |
| 6 | 7 |
"time" |
| 7 | 8 |
|
| 8 | 9 |
"github.com/docker/docker/api/types" |
| 10 |
+ containertypes "github.com/docker/docker/api/types/container" |
|
| 9 | 11 |
networktypes "github.com/docker/docker/api/types/network" |
| 10 | 12 |
swarmtypes "github.com/docker/docker/api/types/swarm" |
| 11 | 13 |
"github.com/docker/docker/client" |
| 14 |
+ "github.com/docker/docker/integration/internal/container" |
|
| 12 | 15 |
"github.com/docker/docker/integration/internal/network" |
| 13 | 16 |
"github.com/docker/docker/integration/internal/swarm" |
| 17 |
+ "github.com/docker/docker/libnetwork/netlabel" |
|
| 14 | 18 |
"github.com/docker/docker/testutil" |
| 15 | 19 |
"github.com/docker/docker/testutil/daemon" |
| 16 | 20 |
"gotest.tools/v3/assert" |
| ... | ... |
@@ -465,3 +469,66 @@ func TestServiceWithDefaultAddressPoolInit(t *testing.T) {
|
| 465 | 465 |
err = d.SwarmLeave(ctx, t, true) |
| 466 | 466 |
assert.NilError(t, err) |
| 467 | 467 |
} |
| 468 |
+ |
|
| 469 |
+func TestCustomIfnameIsPreservedOnLiveRestore(t *testing.T) {
|
|
| 470 |
+ skip.If(t, testEnv.DaemonInfo.OSType == "windows", "custom interface name is only supported by Linux netdrivers") |
|
| 471 |
+ skip.If(t, testEnv.IsRootless, "rootless mode doesn't support live-restore") |
|
| 472 |
+ |
|
| 473 |
+ ctx := setupTest(t) |
|
| 474 |
+ |
|
| 475 |
+ d := daemon.New(t) |
|
| 476 |
+ defer d.Stop(t) |
|
| 477 |
+ d.StartWithBusybox(ctx, t, "--live-restore=true") |
|
| 478 |
+ |
|
| 479 |
+ apiClient := d.NewClientT(t) |
|
| 480 |
+ defer apiClient.Close() |
|
| 481 |
+ |
|
| 482 |
+ ctrId := container.Run(ctx, t, apiClient, |
|
| 483 |
+ container.WithCmd("top"),
|
|
| 484 |
+ container.WithEndpointSettings("bridge", &networktypes.EndpointSettings{
|
|
| 485 |
+ DriverOpts: map[string]string{
|
|
| 486 |
+ netlabel.Ifname: "foobar", |
|
| 487 |
+ }, |
|
| 488 |
+ })) |
|
| 489 |
+ defer container.Remove(ctx, t, apiClient, ctrId, containertypes.RemoveOptions{Force: true})
|
|
| 490 |
+ |
|
| 491 |
+ d.Restart(t, "--live-restore=true") |
|
| 492 |
+ |
|
| 493 |
+ res, err := container.Exec(ctx, apiClient, ctrId, []string{"ip", "-o", "link", "show", "foobar"})
|
|
| 494 |
+ assert.NilError(t, err) |
|
| 495 |
+ assert.Check(t, is.Equal(res.ExitCode, 0)) |
|
| 496 |
+ assert.Check(t, strings.Contains(res.Stdout(), ": foobar@if"), "expected ': foobar@if' in 'ip link show':\n%s", res.Stdout()) |
|
| 497 |
+ |
|
| 498 |
+ // On live-restore, the daemon rebuilds the list of interfaces for all |
|
| 499 |
+ // containers. Call NetworkDisconnect here to make sure that the right |
|
| 500 |
+ // dstName is used internally. |
|
| 501 |
+ err = apiClient.NetworkDisconnect(ctx, "bridge", ctrId, true) |
|
| 502 |
+ assert.NilError(t, err) |
|
| 503 |
+} |
|
| 504 |
+ |
|
| 505 |
+func TestCustomIfnameCollidesWithExistingIface(t *testing.T) {
|
|
| 506 |
+ skip.If(t, testEnv.DaemonInfo.OSType == "windows", "custom interface name is only supported by Linux netdrivers") |
|
| 507 |
+ |
|
| 508 |
+ ctx := setupTest(t) |
|
| 509 |
+ |
|
| 510 |
+ d := daemon.New(t) |
|
| 511 |
+ defer d.Stop(t) |
|
| 512 |
+ d.StartWithBusybox(ctx, t, "--live-restore=true") |
|
| 513 |
+ |
|
| 514 |
+ apiClient := d.NewClientT(t) |
|
| 515 |
+ defer apiClient.Close() |
|
| 516 |
+ |
|
| 517 |
+ const testnet = "testnet" |
|
| 518 |
+ network.CreateNoError(ctx, t, apiClient, testnet, network.WithDriver("bridge"))
|
|
| 519 |
+ |
|
| 520 |
+ ctrId := container.Run(ctx, t, apiClient, |
|
| 521 |
+ container.WithCmd("top"),
|
|
| 522 |
+ container.WithEndpointSettings("bridge", &networktypes.EndpointSettings{}))
|
|
| 523 |
+ defer container.Remove(ctx, t, apiClient, ctrId, containertypes.RemoveOptions{Force: true})
|
|
| 524 |
+ |
|
| 525 |
+ err := apiClient.NetworkConnect(ctx, testnet, ctrId, &networktypes.EndpointSettings{DriverOpts: map[string]string{
|
|
| 526 |
+ netlabel.Ifname: "eth0", |
|
| 527 |
+ }}) |
|
| 528 |
+ assert.ErrorContains(t, err, "error renaming interface") |
|
| 529 |
+ assert.ErrorContains(t, err, "file exists") |
|
| 530 |
+} |
| ... | ... |
@@ -55,7 +55,7 @@ func (d *manager) EndpointOperInfo(nid, eid string) (map[string]interface{}, err
|
| 55 | 55 |
return nil, types.NotImplementedErrorf("not implemented")
|
| 56 | 56 |
} |
| 57 | 57 |
|
| 58 |
-func (d *manager) Join(_ context.Context, nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
|
|
| 58 |
+func (d *manager) Join(_ context.Context, nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, _, _ map[string]interface{}) error {
|
|
| 59 | 59 |
return types.NotImplementedErrorf("not implemented")
|
| 60 | 60 |
} |
| 61 | 61 |
|
| ... | ... |
@@ -51,7 +51,7 @@ type Driver interface {
|
| 51 | 51 |
EndpointOperInfo(nid, eid string) (map[string]interface{}, error)
|
| 52 | 52 |
|
| 53 | 53 |
// Join method is invoked when a Sandbox is attached to an endpoint. |
| 54 |
- Join(ctx context.Context, nid, eid string, sboxKey string, jinfo JoinInfo, options map[string]interface{}) error
|
|
| 54 |
+ Join(ctx context.Context, nid, eid string, sboxKey string, jinfo JoinInfo, epOpts, sbOpts map[string]interface{}) error
|
|
| 55 | 55 |
|
| 56 | 56 |
// Leave method is invoked when a Sandbox detaches from an endpoint. |
| 57 | 57 |
Leave(nid, eid string) error |
| ... | ... |
@@ -140,8 +140,10 @@ type InterfaceInfo interface {
|
| 140 | 140 |
// InterfaceNameInfo provides a go interface for the drivers to assign names |
| 141 | 141 |
// to interfaces. |
| 142 | 142 |
type InterfaceNameInfo interface {
|
| 143 |
- // SetNames method assigns the srcName and dstPrefix for the interface. |
|
| 144 |
- SetNames(srcName, dstPrefix string) error |
|
| 143 |
+ // SetNames method assigns the srcName, dstPrefix, and dstName for the |
|
| 144 |
+ // interface. If both dstName and dstPrefix are set, dstName takes |
|
| 145 |
+ // precedence. |
|
| 146 |
+ SetNames(srcName, dstPrefix, dstName string) error |
|
| 145 | 147 |
} |
| 146 | 148 |
|
| 147 | 149 |
// JoinInfo represents a set of resources that the driver has the ability to provide during |
| ... | ... |
@@ -1444,7 +1444,7 @@ func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, erro
|
| 1444 | 1444 |
} |
| 1445 | 1445 |
|
| 1446 | 1446 |
// Join method is invoked when a Sandbox is attached to an endpoint. |
| 1447 |
-func (d *driver) Join(ctx context.Context, nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
|
|
| 1447 |
+func (d *driver) Join(ctx context.Context, nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, epOpts, sbOpts map[string]interface{}) error {
|
|
| 1448 | 1448 |
ctx, span := otel.Tracer("").Start(ctx, "libnetwork.drivers.bridge.Join", trace.WithAttributes(
|
| 1449 | 1449 |
attribute.String("nid", nid),
|
| 1450 | 1450 |
attribute.String("eid", eid),
|
| ... | ... |
@@ -1465,7 +1465,7 @@ func (d *driver) Join(ctx context.Context, nid, eid string, sboxKey string, jinf |
| 1465 | 1465 |
return endpointNotFoundError(eid) |
| 1466 | 1466 |
} |
| 1467 | 1467 |
|
| 1468 |
- endpoint.containerConfig, err = parseContainerOptions(options) |
|
| 1468 |
+ endpoint.containerConfig, err = parseContainerOptions(sbOpts) |
|
| 1469 | 1469 |
if err != nil {
|
| 1470 | 1470 |
return err |
| 1471 | 1471 |
} |
| ... | ... |
@@ -1475,7 +1475,7 @@ func (d *driver) Join(ctx context.Context, nid, eid string, sboxKey string, jinf |
| 1475 | 1475 |
if network.config.ContainerIfacePrefix != "" {
|
| 1476 | 1476 |
containerVethPrefix = network.config.ContainerIfacePrefix |
| 1477 | 1477 |
} |
| 1478 |
- if err := iNames.SetNames(endpoint.srcName, containerVethPrefix); err != nil {
|
|
| 1478 |
+ if err := iNames.SetNames(endpoint.srcName, containerVethPrefix, netlabel.GetIfname(epOpts)); err != nil {
|
|
| 1479 | 1479 |
return err |
| 1480 | 1480 |
} |
| 1481 | 1481 |
|
| ... | ... |
@@ -642,6 +642,7 @@ type testInterface struct {
|
| 642 | 642 |
addr *net.IPNet |
| 643 | 643 |
addrv6 *net.IPNet |
| 644 | 644 |
srcName string |
| 645 |
+ dstPrefix string |
|
| 645 | 646 |
dstName string |
| 646 | 647 |
createdInContainer bool |
| 647 | 648 |
netnsPath string |
| ... | ... |
@@ -727,8 +728,9 @@ func (i *testInterface) SetCreatedInContainer(cic bool) {
|
| 727 | 727 |
i.createdInContainer = cic |
| 728 | 728 |
} |
| 729 | 729 |
|
| 730 |
-func (i *testInterface) SetNames(srcName string, dstName string) error {
|
|
| 730 |
+func (i *testInterface) SetNames(srcName, dstPrefix, dstName string) error {
|
|
| 731 | 731 |
i.srcName = srcName |
| 732 |
+ i.dstPrefix = dstPrefix |
|
| 732 | 733 |
i.dstName = dstName |
| 733 | 734 |
return nil |
| 734 | 735 |
} |
| ... | ... |
@@ -818,7 +820,7 @@ func testQueryEndpointInfo(t *testing.T, ulPxyEnabled bool) {
|
| 818 | 818 |
t.Fatalf("Failed to create an endpoint : %s", err.Error())
|
| 819 | 819 |
} |
| 820 | 820 |
|
| 821 |
- err = d.Join(context.Background(), "net1", "ep1", "sbox", te, sbOptions) |
|
| 821 |
+ err = d.Join(context.Background(), "net1", "ep1", "sbox", te, nil, sbOptions) |
|
| 822 | 822 |
if err != nil {
|
| 823 | 823 |
t.Fatalf("Failed to join the endpoint: %v", err)
|
| 824 | 824 |
} |
| ... | ... |
@@ -922,7 +924,7 @@ func TestLinkContainers(t *testing.T) {
|
| 922 | 922 |
sbOptions := make(map[string]interface{})
|
| 923 | 923 |
sbOptions[netlabel.ExposedPorts] = exposedPorts |
| 924 | 924 |
|
| 925 |
- err = d.Join(context.Background(), "net1", "ep1", "sbox", te1, sbOptions) |
|
| 925 |
+ err = d.Join(context.Background(), "net1", "ep1", "sbox", te1, nil, sbOptions) |
|
| 926 | 926 |
if err != nil {
|
| 927 | 927 |
t.Fatalf("Failed to join the endpoint: %v", err)
|
| 928 | 928 |
} |
| ... | ... |
@@ -953,7 +955,7 @@ func TestLinkContainers(t *testing.T) {
|
| 953 | 953 |
"ChildEndpoints": []string{"ep1"},
|
| 954 | 954 |
} |
| 955 | 955 |
|
| 956 |
- err = d.Join(context.Background(), "net1", "ep2", "", te2, sbOptions) |
|
| 956 |
+ err = d.Join(context.Background(), "net1", "ep2", "", te2, nil, sbOptions) |
|
| 957 | 957 |
if err != nil {
|
| 958 | 958 |
t.Fatal("Failed to link ep1 and ep2")
|
| 959 | 959 |
} |
| ... | ... |
@@ -1011,7 +1013,7 @@ func TestLinkContainers(t *testing.T) {
|
| 1011 | 1011 |
"ChildEndpoints": []string{"ep1", "ep4"},
|
| 1012 | 1012 |
} |
| 1013 | 1013 |
|
| 1014 |
- err = d.Join(context.Background(), "net1", "ep2", "", te2, sbOptions) |
|
| 1014 |
+ err = d.Join(context.Background(), "net1", "ep2", "", te2, nil, sbOptions) |
|
| 1015 | 1015 |
if err != nil {
|
| 1016 | 1016 |
t.Fatal(err) |
| 1017 | 1017 |
} |
| ... | ... |
@@ -1228,7 +1230,7 @@ func TestSetDefaultGw(t *testing.T) {
|
| 1228 | 1228 |
t.Fatalf("Failed to create endpoint: %v", err)
|
| 1229 | 1229 |
} |
| 1230 | 1230 |
|
| 1231 |
- err = d.Join(context.Background(), "dummy", "ep", "sbox", te, nil) |
|
| 1231 |
+ err = d.Join(context.Background(), "dummy", "ep", "sbox", te, nil, nil) |
|
| 1232 | 1232 |
if err != nil {
|
| 1233 | 1233 |
t.Fatalf("Failed to join endpoint: %v", err)
|
| 1234 | 1234 |
} |
| ... | ... |
@@ -55,7 +55,7 @@ func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, erro
|
| 55 | 55 |
return nil, types.NotImplementedErrorf("not implemented")
|
| 56 | 56 |
} |
| 57 | 57 |
|
| 58 |
-func (d *driver) Join(_ context.Context, nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
|
|
| 58 |
+func (d *driver) Join(_ context.Context, nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, _, _ map[string]interface{}) error {
|
|
| 59 | 59 |
return types.NotImplementedErrorf("not implemented")
|
| 60 | 60 |
} |
| 61 | 61 |
|
| ... | ... |
@@ -43,8 +43,9 @@ func TestLinkCreate(t *testing.T) {
|
| 43 | 43 |
err = d.CreateEndpoint(context.Background(), "dummy", "ep", te.Interface(), nil) |
| 44 | 44 |
assert.NilError(t, err) |
| 45 | 45 |
|
| 46 |
- err = d.Join(context.Background(), "dummy", "ep", "sbox", te, nil) |
|
| 46 |
+ err = d.Join(context.Background(), "dummy", "ep", "sbox", te, nil, nil) |
|
| 47 | 47 |
assert.NilError(t, err) |
| 48 |
+ assert.Assert(t, te.iface.dstPrefix != "", "got: %q, want: %q", te.iface.dstPrefix, "") |
|
| 48 | 49 |
|
| 49 | 50 |
// Verify sbox endpoint interface inherited MTU value from bridge config |
| 50 | 51 |
sboxLnk, err := nlwrap.LinkByName(te.iface.srcName) |
| ... | ... |
@@ -59,8 +60,6 @@ func TestLinkCreate(t *testing.T) {
|
| 59 | 59 |
assert.Check(t, is.ErrorType(err, errdefs.IsForbidden)) |
| 60 | 60 |
assert.Assert(t, is.Error(err, "Endpoint (ep) already exists (Only one endpoint allowed)"), "Failed to detect duplicate endpoint id on same network") |
| 61 | 61 |
|
| 62 |
- assert.Check(t, te.iface.dstName != "", "Invalid Dstname returned") |
|
| 63 |
- |
|
| 64 | 62 |
_, err = nlwrap.LinkByName(te.iface.srcName) |
| 65 | 63 |
assert.Check(t, err, "Could not find source link %s", te.iface.srcName) |
| 66 | 64 |
|
| ... | ... |
@@ -67,7 +67,7 @@ func TestPortMappingConfig(t *testing.T) {
|
| 67 | 67 |
t.Fatalf("Failed to create the endpoint: %s", err.Error())
|
| 68 | 68 |
} |
| 69 | 69 |
|
| 70 |
- if err = d.Join(context.Background(), "dummy", "ep1", "sbox", te, sbOptions); err != nil {
|
|
| 70 |
+ if err = d.Join(context.Background(), "dummy", "ep1", "sbox", te, nil, sbOptions); err != nil {
|
|
| 71 | 71 |
t.Fatalf("Failed to join the endpoint: %v", err)
|
| 72 | 72 |
} |
| 73 | 73 |
|
| ... | ... |
@@ -153,7 +153,7 @@ func TestPortMappingV6Config(t *testing.T) {
|
| 153 | 153 |
t.Fatalf("Failed to create the endpoint: %s", err.Error())
|
| 154 | 154 |
} |
| 155 | 155 |
|
| 156 |
- if err = d.Join(context.Background(), "dummy", "ep1", "sbox", te, sbOptions); err != nil {
|
|
| 156 |
+ if err = d.Join(context.Background(), "dummy", "ep1", "sbox", te, nil, sbOptions); err != nil {
|
|
| 157 | 157 |
t.Fatalf("Failed to join the endpoint: %v", err)
|
| 158 | 158 |
} |
| 159 | 159 |
|
| ... | ... |
@@ -68,7 +68,7 @@ func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, erro
|
| 68 | 68 |
} |
| 69 | 69 |
|
| 70 | 70 |
// Join method is invoked when a Sandbox is attached to an endpoint. |
| 71 |
-func (d *driver) Join(_ context.Context, nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
|
|
| 71 |
+func (d *driver) Join(_ context.Context, nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, _, _ map[string]interface{}) error {
|
|
| 72 | 72 |
return nil |
| 73 | 73 |
} |
| 74 | 74 |
|
| ... | ... |
@@ -9,6 +9,7 @@ import ( |
| 9 | 9 |
|
| 10 | 10 |
"github.com/containerd/log" |
| 11 | 11 |
"github.com/docker/docker/libnetwork/driverapi" |
| 12 |
+ "github.com/docker/docker/libnetwork/netlabel" |
|
| 12 | 13 |
"github.com/docker/docker/libnetwork/netutils" |
| 13 | 14 |
"github.com/docker/docker/libnetwork/ns" |
| 14 | 15 |
"github.com/docker/docker/libnetwork/types" |
| ... | ... |
@@ -29,7 +30,7 @@ const ( |
| 29 | 29 |
) |
| 30 | 30 |
|
| 31 | 31 |
// Join method is invoked when a Sandbox is attached to an endpoint. |
| 32 |
-func (d *driver) Join(ctx context.Context, nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
|
|
| 32 |
+func (d *driver) Join(ctx context.Context, nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, epOpts, _ map[string]interface{}) error {
|
|
| 33 | 33 |
ctx, span := otel.Tracer("").Start(ctx, "libnetwork.drivers.ipvlan.Join", trace.WithAttributes(
|
| 34 | 34 |
attribute.String("nid", nid),
|
| 35 | 35 |
attribute.String("eid", eid),
|
| ... | ... |
@@ -143,7 +144,7 @@ func (d *driver) Join(ctx context.Context, nid, eid string, sboxKey string, jinf |
| 143 | 143 |
jinfo.DisableGatewayService() |
| 144 | 144 |
} |
| 145 | 145 |
iNames := jinfo.InterfaceName() |
| 146 |
- err = iNames.SetNames(vethName, containerVethPrefix) |
|
| 146 |
+ err = iNames.SetNames(vethName, containerVethPrefix, netlabel.GetIfname(epOpts)) |
|
| 147 | 147 |
if err != nil {
|
| 148 | 148 |
return err |
| 149 | 149 |
} |
| ... | ... |
@@ -55,7 +55,7 @@ func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, erro
|
| 55 | 55 |
return nil, types.NotImplementedErrorf("not implemented")
|
| 56 | 56 |
} |
| 57 | 57 |
|
| 58 |
-func (d *driver) Join(_ context.Context, nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
|
|
| 58 |
+func (d *driver) Join(_ context.Context, nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, _, _ map[string]interface{}) error {
|
|
| 59 | 59 |
return types.NotImplementedErrorf("not implemented")
|
| 60 | 60 |
} |
| 61 | 61 |
|
| ... | ... |
@@ -9,6 +9,7 @@ import ( |
| 9 | 9 |
|
| 10 | 10 |
"github.com/containerd/log" |
| 11 | 11 |
"github.com/docker/docker/libnetwork/driverapi" |
| 12 |
+ "github.com/docker/docker/libnetwork/netlabel" |
|
| 12 | 13 |
"github.com/docker/docker/libnetwork/netutils" |
| 13 | 14 |
"github.com/docker/docker/libnetwork/ns" |
| 14 | 15 |
"go.opentelemetry.io/otel" |
| ... | ... |
@@ -17,7 +18,7 @@ import ( |
| 17 | 17 |
) |
| 18 | 18 |
|
| 19 | 19 |
// Join method is invoked when a Sandbox is attached to an endpoint. |
| 20 |
-func (d *driver) Join(ctx context.Context, nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
|
|
| 20 |
+func (d *driver) Join(ctx context.Context, nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, epOpts, _ map[string]interface{}) error {
|
|
| 21 | 21 |
ctx, span := otel.Tracer("").Start(ctx, "libnetwork.drivers.macvlan.Join", trace.WithAttributes(
|
| 22 | 22 |
attribute.String("nid", nid),
|
| 23 | 23 |
attribute.String("eid", eid),
|
| ... | ... |
@@ -102,7 +103,7 @@ func (d *driver) Join(ctx context.Context, nid, eid string, sboxKey string, jinf |
| 102 | 102 |
jinfo.DisableGatewayService() |
| 103 | 103 |
} |
| 104 | 104 |
iNames := jinfo.InterfaceName() |
| 105 |
- err = iNames.SetNames(vethName, containerVethPrefix) |
|
| 105 |
+ err = iNames.SetNames(vethName, containerVethPrefix, netlabel.GetIfname(epOpts)) |
|
| 106 | 106 |
if err != nil {
|
| 107 | 107 |
return err |
| 108 | 108 |
} |
| ... | ... |
@@ -55,7 +55,7 @@ func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, erro
|
| 55 | 55 |
return nil, types.NotImplementedErrorf("not implemented")
|
| 56 | 56 |
} |
| 57 | 57 |
|
| 58 |
-func (d *driver) Join(_ context.Context, nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
|
|
| 58 |
+func (d *driver) Join(_ context.Context, nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, _, _ map[string]interface{}) error {
|
|
| 59 | 59 |
return types.NotImplementedErrorf("not implemented")
|
| 60 | 60 |
} |
| 61 | 61 |
|
| ... | ... |
@@ -68,7 +68,7 @@ func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, erro
|
| 68 | 68 |
} |
| 69 | 69 |
|
| 70 | 70 |
// Join method is invoked when a Sandbox is attached to an endpoint. |
| 71 |
-func (d *driver) Join(_ context.Context, nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
|
|
| 71 |
+func (d *driver) Join(_ context.Context, nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, _, _ map[string]interface{}) error {
|
|
| 72 | 72 |
return nil |
| 73 | 73 |
} |
| 74 | 74 |
|
| ... | ... |
@@ -10,6 +10,7 @@ import ( |
| 10 | 10 |
|
| 11 | 11 |
"github.com/containerd/log" |
| 12 | 12 |
"github.com/docker/docker/libnetwork/driverapi" |
| 13 |
+ "github.com/docker/docker/libnetwork/netlabel" |
|
| 13 | 14 |
"github.com/docker/docker/libnetwork/ns" |
| 14 | 15 |
"github.com/docker/docker/libnetwork/osl" |
| 15 | 16 |
"github.com/docker/docker/libnetwork/types" |
| ... | ... |
@@ -20,7 +21,7 @@ import ( |
| 20 | 20 |
) |
| 21 | 21 |
|
| 22 | 22 |
// Join method is invoked when a Sandbox is attached to an endpoint. |
| 23 |
-func (d *driver) Join(ctx context.Context, nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
|
|
| 23 |
+func (d *driver) Join(ctx context.Context, nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, epOpts, _ map[string]interface{}) error {
|
|
| 24 | 24 |
ctx, span := otel.Tracer("").Start(ctx, "libnetwork.drivers.overlay.Join", trace.WithAttributes(
|
| 25 | 25 |
attribute.String("nid", nid),
|
| 26 | 26 |
attribute.String("eid", eid),
|
| ... | ... |
@@ -83,7 +84,7 @@ func (d *driver) Join(ctx context.Context, nid, eid string, sboxKey string, jinf |
| 83 | 83 |
return err |
| 84 | 84 |
} |
| 85 | 85 |
|
| 86 |
- if err = sbox.AddInterface(ctx, overlayIfName, "veth", osl.WithMaster(s.brName)); err != nil {
|
|
| 86 |
+ if err = sbox.AddInterface(ctx, overlayIfName, "veth", "", osl.WithMaster(s.brName)); err != nil {
|
|
| 87 | 87 |
return fmt.Errorf("could not add veth pair inside the network sandbox: %v", err)
|
| 88 | 88 |
} |
| 89 | 89 |
|
| ... | ... |
@@ -110,7 +111,7 @@ func (d *driver) Join(ctx context.Context, nid, eid string, sboxKey string, jinf |
| 110 | 110 |
} |
| 111 | 111 |
|
| 112 | 112 |
if iNames := jinfo.InterfaceName(); iNames != nil {
|
| 113 |
- err = iNames.SetNames(containerIfName, "eth") |
|
| 113 |
+ err = iNames.SetNames(containerIfName, "eth", netlabel.GetIfname(epOpts)) |
|
| 114 | 114 |
if err != nil {
|
| 115 | 115 |
return err |
| 116 | 116 |
} |
| ... | ... |
@@ -427,7 +427,7 @@ func (n *network) setupSubnetSandbox(s *subnet, brName, vxlanName string) error |
| 427 | 427 |
// create a bridge and vxlan device for this subnet and move it to the sandbox |
| 428 | 428 |
sbox := n.sbox |
| 429 | 429 |
|
| 430 |
- if err := sbox.AddInterface(context.TODO(), brName, "br", osl.WithIPv4Address(s.gwIP), osl.WithIsBridge(true)); err != nil {
|
|
| 430 |
+ if err := sbox.AddInterface(context.TODO(), brName, "br", "", osl.WithIPv4Address(s.gwIP), osl.WithIsBridge(true)); err != nil {
|
|
| 431 | 431 |
return fmt.Errorf("bridge creation in sandbox failed for subnet %q: %v", s.subnetIP.String(), err)
|
| 432 | 432 |
} |
| 433 | 433 |
|
| ... | ... |
@@ -439,7 +439,7 @@ func (n *network) setupSubnetSandbox(s *subnet, brName, vxlanName string) error |
| 439 | 439 |
return err |
| 440 | 440 |
} |
| 441 | 441 |
|
| 442 |
- if err := sbox.AddInterface(context.TODO(), vxlanName, "vxlan", osl.WithMaster(brName)); err != nil {
|
|
| 442 |
+ if err := sbox.AddInterface(context.TODO(), vxlanName, "vxlan", "", osl.WithMaster(brName)); err != nil {
|
|
| 443 | 443 |
// If adding vxlan device to the overlay namespace fails, remove the bridge interface we |
| 444 | 444 |
// already added to the namespace. This allows the caller to try the setup again. |
| 445 | 445 |
for _, iface := range sbox.Interfaces() {
|
| ... | ... |
@@ -190,7 +190,7 @@ func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, erro
|
| 190 | 190 |
} |
| 191 | 191 |
|
| 192 | 192 |
// Join method is invoked when a Sandbox is attached to an endpoint. |
| 193 |
-func (d *driver) Join(_ context.Context, nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
|
|
| 193 |
+func (d *driver) Join(_ context.Context, nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, _, _ map[string]interface{}) error {
|
|
| 194 | 194 |
return types.NotImplementedErrorf("not implemented")
|
| 195 | 195 |
} |
| 196 | 196 |
|
| ... | ... |
@@ -273,7 +273,7 @@ func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, erro
|
| 273 | 273 |
} |
| 274 | 274 |
|
| 275 | 275 |
// Join method is invoked when a Sandbox is attached to an endpoint. |
| 276 |
-func (d *driver) Join(_ context.Context, nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) (retErr error) {
|
|
| 276 |
+func (d *driver) Join(_ context.Context, nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, _, options map[string]interface{}) (retErr error) {
|
|
| 277 | 277 |
join := &api.JoinRequest{
|
| 278 | 278 |
NetworkID: nid, |
| 279 | 279 |
EndpointID: eid, |
| ... | ... |
@@ -300,7 +300,7 @@ func (d *driver) Join(_ context.Context, nid, eid string, sboxKey string, jinfo |
| 300 | 300 |
|
| 301 | 301 |
ifaceName := res.InterfaceName |
| 302 | 302 |
if iface := jinfo.InterfaceName(); iface != nil && ifaceName != nil {
|
| 303 |
- if err := iface.SetNames(ifaceName.SrcName, ifaceName.DstPrefix); err != nil {
|
|
| 303 |
+ if err := iface.SetNames(ifaceName.SrcName, ifaceName.DstPrefix, ""); err != nil {
|
|
| 304 | 304 |
return fmt.Errorf("failed to set interface name: %s", err)
|
| 305 | 305 |
} |
| 306 | 306 |
} |
| ... | ... |
@@ -21,6 +21,7 @@ import ( |
| 21 | 21 |
"github.com/docker/docker/libnetwork/scope" |
| 22 | 22 |
"github.com/docker/docker/libnetwork/types" |
| 23 | 23 |
"github.com/docker/docker/pkg/plugins" |
| 24 |
+ "gotest.tools/v3/assert" |
|
| 24 | 25 |
) |
| 25 | 26 |
|
| 26 | 27 |
func decodeToMap(r *http.Request) (res map[string]interface{}, err error) {
|
| ... | ... |
@@ -82,8 +83,9 @@ func setupPlugin(t *testing.T, name string, mux *http.ServeMux) func() {
|
| 82 | 82 |
|
| 83 | 83 |
type testEndpoint struct {
|
| 84 | 84 |
t *testing.T |
| 85 |
- src string |
|
| 86 |
- dst string |
|
| 85 |
+ srcName string |
|
| 86 |
+ dstPrefix string |
|
| 87 |
+ dstName string |
|
| 87 | 88 |
address string |
| 88 | 89 |
addressIPv6 string |
| 89 | 90 |
macAddress string |
| ... | ... |
@@ -188,13 +190,10 @@ func (test *testEndpoint) NetnsPath() string { return "" }
|
| 188 | 188 |
|
| 189 | 189 |
func (test *testEndpoint) SetCreatedInContainer(bool) {}
|
| 190 | 190 |
|
| 191 |
-func (test *testEndpoint) SetNames(src string, dst string) error {
|
|
| 192 |
- if test.src != src {
|
|
| 193 |
- test.t.Fatalf(`Wrong SrcName; expected "%s", got "%s"`, test.src, src) |
|
| 194 |
- } |
|
| 195 |
- if test.dst != dst {
|
|
| 196 |
- test.t.Fatalf(`Wrong DstPrefix; expected "%s", got "%s"`, test.dst, dst) |
|
| 197 |
- } |
|
| 191 |
+func (test *testEndpoint) SetNames(srcName, dstPrefix, dstName string) error {
|
|
| 192 |
+ assert.Equal(test.t, test.srcName, srcName) |
|
| 193 |
+ assert.Equal(test.t, test.dstPrefix, dstPrefix) |
|
| 194 |
+ assert.Equal(test.t, test.dstName, dstName) |
|
| 198 | 195 |
return nil |
| 199 | 196 |
} |
| 200 | 197 |
|
| ... | ... |
@@ -322,8 +321,8 @@ func TestRemoteDriver(t *testing.T) {
|
| 322 | 322 |
|
| 323 | 323 |
ep := &testEndpoint{
|
| 324 | 324 |
t: t, |
| 325 |
- src: "vethsrc", |
|
| 326 |
- dst: "vethdst", |
|
| 325 |
+ srcName: "vethsrc", |
|
| 326 |
+ dstPrefix: "vethdst", |
|
| 327 | 327 |
address: "192.168.5.7/16", |
| 328 | 328 |
addressIPv6: "2001:DB8::5:7/48", |
| 329 | 329 |
macAddress: "ab:cd:ef:ee:ee:ee", |
| ... | ... |
@@ -390,8 +389,9 @@ func TestRemoteDriver(t *testing.T) {
|
| 390 | 390 |
"HostsPath": ep.hostsPath, |
| 391 | 391 |
"ResolvConfPath": ep.resolvConfPath, |
| 392 | 392 |
"InterfaceName": map[string]interface{}{
|
| 393 |
- "SrcName": ep.src, |
|
| 394 |
- "DstPrefix": ep.dst, |
|
| 393 |
+ "SrcName": ep.srcName, |
|
| 394 |
+ "DstPrefix": ep.dstPrefix, |
|
| 395 |
+ "DstName": ep.dstName, |
|
| 395 | 396 |
}, |
| 396 | 397 |
"StaticRoutes": []map[string]interface{}{
|
| 397 | 398 |
{
|
| ... | ... |
@@ -478,7 +478,7 @@ func TestRemoteDriver(t *testing.T) {
|
| 478 | 478 |
} |
| 479 | 479 |
|
| 480 | 480 |
joinOpts := map[string]interface{}{"foo": "fooValue"}
|
| 481 |
- err = d.Join(context.Background(), netID, endID, "sandbox-key", ep, joinOpts) |
|
| 481 |
+ err = d.Join(context.Background(), netID, endID, "sandbox-key", ep, nil, joinOpts) |
|
| 482 | 482 |
if err != nil {
|
| 483 | 483 |
t.Fatal(err) |
| 484 | 484 |
} |
| ... | ... |
@@ -15,7 +15,7 @@ import ( |
| 15 | 15 |
) |
| 16 | 16 |
|
| 17 | 17 |
// Join method is invoked when a Sandbox is attached to an endpoint. |
| 18 |
-func (d *driver) Join(ctx context.Context, nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
|
|
| 18 |
+func (d *driver) Join(ctx context.Context, nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, _, options map[string]interface{}) error {
|
|
| 19 | 19 |
ctx, span := otel.Tracer("").Start(ctx, "libnetwork.drivers.windows_overlay.Join", trace.WithAttributes(
|
| 20 | 20 |
attribute.String("nid", nid),
|
| 21 | 21 |
attribute.String("eid", eid),
|
| ... | ... |
@@ -846,7 +846,7 @@ func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, erro
|
| 846 | 846 |
} |
| 847 | 847 |
|
| 848 | 848 |
// Join method is invoked when a Sandbox is attached to an endpoint. |
| 849 |
-func (d *driver) Join(ctx context.Context, nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
|
|
| 849 |
+func (d *driver) Join(ctx context.Context, nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, _, options map[string]interface{}) error {
|
|
| 850 | 850 |
ctx, span := otel.Tracer("").Start(ctx, fmt.Sprintf("libnetwork.drivers.windows_%s.Join", d.name), trace.WithAttributes(
|
| 851 | 851 |
attribute.String("nid", nid),
|
| 852 | 852 |
attribute.String("eid", eid),
|
| ... | ... |
@@ -536,7 +536,7 @@ func (ep *Endpoint) sbJoin(ctx context.Context, sb *Sandbox, options ...Endpoint |
| 536 | 536 |
return fmt.Errorf("failed to get driver during join: %v", err)
|
| 537 | 537 |
} |
| 538 | 538 |
|
| 539 |
- if err := d.Join(ctx, nid, epid, sb.Key(), ep, sb.Labels()); err != nil {
|
|
| 539 |
+ if err := d.Join(ctx, nid, epid, sb.Key(), ep, ep.generic, sb.Labels()); err != nil {
|
|
| 540 | 540 |
return err |
| 541 | 541 |
} |
| 542 | 542 |
defer func() {
|
| ... | ... |
@@ -43,6 +43,7 @@ type EndpointInterface struct {
|
| 43 | 43 |
llAddrs []*net.IPNet |
| 44 | 44 |
srcName string |
| 45 | 45 |
dstPrefix string |
| 46 |
+ dstName string // dstName is the name of the interface in the container namespace. It takes precedence over dstPrefix. |
|
| 46 | 47 |
routes []*net.IPNet |
| 47 | 48 |
v4PoolID string |
| 48 | 49 |
v6PoolID string |
| ... | ... |
@@ -70,6 +71,7 @@ func (epi *EndpointInterface) MarshalJSON() ([]byte, error) {
|
| 70 | 70 |
} |
| 71 | 71 |
epMap["srcName"] = epi.srcName |
| 72 | 72 |
epMap["dstPrefix"] = epi.dstPrefix |
| 73 |
+ epMap["dstName"] = epi.dstName |
|
| 73 | 74 |
var routes []string |
| 74 | 75 |
for _, route := range epi.routes {
|
| 75 | 76 |
routes = append(routes, route.String()) |
| ... | ... |
@@ -147,6 +149,7 @@ func (epi *EndpointInterface) CopyTo(dstEpi *EndpointInterface) error {
|
| 147 | 147 |
dstEpi.addrv6 = types.GetIPNetCopy(epi.addrv6) |
| 148 | 148 |
dstEpi.srcName = epi.srcName |
| 149 | 149 |
dstEpi.dstPrefix = epi.dstPrefix |
| 150 |
+ dstEpi.dstName = epi.dstName |
|
| 150 | 151 |
dstEpi.v4PoolID = epi.v4PoolID |
| 151 | 152 |
dstEpi.v6PoolID = epi.v6PoolID |
| 152 | 153 |
dstEpi.createdInContainer = epi.createdInContainer |
| ... | ... |
@@ -269,10 +272,12 @@ func (epi *EndpointInterface) SrcName() string {
|
| 269 | 269 |
return epi.srcName |
| 270 | 270 |
} |
| 271 | 271 |
|
| 272 |
-// SetNames method assigns the srcName and dstPrefix for the interface. |
|
| 273 |
-func (epi *EndpointInterface) SetNames(srcName string, dstPrefix string) error {
|
|
| 272 |
+// SetNames method assigns the srcName, dstName, and dstPrefix for the |
|
| 273 |
+// interface. If both dstName and dstPrefix are set, dstName takes precedence. |
|
| 274 |
+func (epi *EndpointInterface) SetNames(srcName, dstPrefix, dstName string) error {
|
|
| 274 | 275 |
epi.srcName = srcName |
| 275 | 276 |
epi.dstPrefix = dstPrefix |
| 277 |
+ epi.dstName = dstName |
|
| 276 | 278 |
return nil |
| 277 | 279 |
} |
| 278 | 280 |
|
| ... | ... |
@@ -239,7 +239,7 @@ func compareEndpointInterface(a, b *EndpointInterface) bool {
|
| 239 | 239 |
if a == nil || b == nil {
|
| 240 | 240 |
return false |
| 241 | 241 |
} |
| 242 |
- return a.srcName == b.srcName && a.dstPrefix == b.dstPrefix && a.v4PoolID == b.v4PoolID && a.v6PoolID == b.v6PoolID && |
|
| 242 |
+ return a.srcName == b.srcName && a.dstPrefix == b.dstPrefix && a.dstName == b.dstName && a.v4PoolID == b.v4PoolID && a.v6PoolID == b.v6PoolID && |
|
| 243 | 243 |
types.CompareIPNet(a.addr, b.addr) && types.CompareIPNet(a.addrv6, b.addrv6) && compareNwLists(a.llAddrs, b.llAddrs) |
| 244 | 244 |
} |
| 245 | 245 |
|
| ... | ... |
@@ -807,7 +807,7 @@ func (b *badDriver) EndpointOperInfo(nid, eid string) (map[string]interface{}, e
|
| 807 | 807 |
return nil, nil |
| 808 | 808 |
} |
| 809 | 809 |
|
| 810 |
-func (b *badDriver) Join(_ context.Context, nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
|
|
| 810 |
+func (b *badDriver) Join(_ context.Context, nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, _, _ map[string]interface{}) error {
|
|
| 811 | 811 |
return fmt.Errorf("I will not allow any join")
|
| 812 | 812 |
} |
| 813 | 813 |
|
| ... | ... |
@@ -30,6 +30,9 @@ const ( |
| 30 | 30 |
// where the interface name is represented by the string "IFNAME". |
| 31 | 31 |
EndpointSysctls = Prefix + ".endpoint.sysctls" |
| 32 | 32 |
|
| 33 |
+ // Ifname can be used to set the interface name used inside the container. It takes precedence over ContainerIfacePrefix. |
|
| 34 |
+ Ifname = Prefix + ".endpoint.ifname" |
|
| 35 |
+ |
|
| 33 | 36 |
// EnableIPv4 constant represents enabling IPV4 at network level |
| 34 | 37 |
EnableIPv4 = Prefix + ".enable_ipv4" |
| 35 | 38 |
|
| ... | ... |
@@ -70,3 +73,11 @@ const ( |
| 70 | 70 |
// is intended for internal use, it may be removed in a future release. |
| 71 | 71 |
NoProxy6To4 = DriverPrivatePrefix + ".no_proxy_6to4" |
| 72 | 72 |
) |
| 73 |
+ |
|
| 74 |
+// GetIfname returns the value associated to the Ifname netlabel from the |
|
| 75 |
+// provided options. If there's no Ifname netlabel, or if the value isn't a |
|
| 76 |
+// string, it returns an empty string. |
|
| 77 |
+func GetIfname(opts map[string]interface{}) string {
|
|
| 78 |
+ ifname, _ := opts[Ifname].(string) |
|
| 79 |
+ return ifname |
|
| 80 |
+} |
| 73 | 81 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,60 @@ |
| 0 |
+package netlabel |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "testing" |
|
| 4 |
+ |
|
| 5 |
+ "gotest.tools/v3/assert" |
|
| 6 |
+) |
|
| 7 |
+ |
|
| 8 |
+func TestGetIfname(t *testing.T) {
|
|
| 9 |
+ testcases := []struct {
|
|
| 10 |
+ name string |
|
| 11 |
+ opts map[string]interface{}
|
|
| 12 |
+ expIfname string |
|
| 13 |
+ }{
|
|
| 14 |
+ {
|
|
| 15 |
+ name: "nil opts", |
|
| 16 |
+ opts: nil, |
|
| 17 |
+ expIfname: "", |
|
| 18 |
+ }, |
|
| 19 |
+ {
|
|
| 20 |
+ name: "no ifname", |
|
| 21 |
+ opts: map[string]interface{}{},
|
|
| 22 |
+ expIfname: "", |
|
| 23 |
+ }, |
|
| 24 |
+ {
|
|
| 25 |
+ name: "ifname set", |
|
| 26 |
+ opts: map[string]interface{}{
|
|
| 27 |
+ Ifname: "foobar", |
|
| 28 |
+ }, |
|
| 29 |
+ expIfname: "foobar", |
|
| 30 |
+ }, |
|
| 31 |
+ {
|
|
| 32 |
+ name: "ifname set to empty string", |
|
| 33 |
+ opts: map[string]interface{}{
|
|
| 34 |
+ Ifname: "", |
|
| 35 |
+ }, |
|
| 36 |
+ expIfname: "", |
|
| 37 |
+ }, |
|
| 38 |
+ {
|
|
| 39 |
+ name: "ifname set to nil", |
|
| 40 |
+ opts: map[string]interface{}{
|
|
| 41 |
+ Ifname: nil, |
|
| 42 |
+ }, |
|
| 43 |
+ expIfname: "", |
|
| 44 |
+ }, |
|
| 45 |
+ {
|
|
| 46 |
+ name: "ifname set to int", |
|
| 47 |
+ opts: map[string]interface{}{
|
|
| 48 |
+ Ifname: 42, |
|
| 49 |
+ }, |
|
| 50 |
+ expIfname: "", |
|
| 51 |
+ }, |
|
| 52 |
+ } |
|
| 53 |
+ |
|
| 54 |
+ for _, tc := range testcases {
|
|
| 55 |
+ t.Run(tc.name, func(t *testing.T) {
|
|
| 56 |
+ assert.Equal(t, tc.expIfname, GetIfname(tc.opts)) |
|
| 57 |
+ }) |
|
| 58 |
+ } |
|
| 59 |
+} |
| ... | ... |
@@ -56,11 +56,12 @@ const ( |
| 56 | 56 |
|
| 57 | 57 |
// newInterface creates a new interface in the given namespace using the |
| 58 | 58 |
// provided options. |
| 59 |
-func newInterface(ns *Namespace, srcName, dstPrefix string, options ...IfaceOption) (*Interface, error) {
|
|
| 59 |
+func newInterface(ns *Namespace, srcName, dstPrefix, dstName string, options ...IfaceOption) (*Interface, error) {
|
|
| 60 | 60 |
i := &Interface{
|
| 61 | 61 |
stopCh: make(chan struct{}),
|
| 62 | 62 |
srcName: srcName, |
| 63 | 63 |
dstPrefix: dstPrefix, |
| 64 |
+ dstName: dstName, |
|
| 64 | 65 |
advertiseAddrNMsgs: advertiseAddrNMsgsDefault, |
| 65 | 66 |
advertiseAddrInterval: advertiseAddrIntervalDefault, |
| 66 | 67 |
ns: ns, |
| ... | ... |
@@ -116,10 +117,8 @@ func (i *Interface) SrcName() string {
|
| 116 | 116 |
return i.srcName |
| 117 | 117 |
} |
| 118 | 118 |
|
| 119 |
-// DstName returns the name that will be assigned to the interface once |
|
| 120 |
-// moved inside a network namespace. When the caller passes in a DstName, |
|
| 121 |
-// it is only expected to pass a prefix. The name will be modified with an |
|
| 122 |
-// auto-generated suffix. |
|
| 119 |
+// DstName returns the final interface name in the target network namespace. |
|
| 120 |
+// It's generated based on the prefix passed to [Namespace.AddInterface]. |
|
| 123 | 121 |
func (i *Interface) DstName() string {
|
| 124 | 122 |
return i.dstName |
| 125 | 123 |
} |
| ... | ... |
@@ -218,18 +217,19 @@ func moveLink(ctx context.Context, nlhHost nlwrap.Handle, iface netlink.Link, i |
| 218 | 218 |
return nil |
| 219 | 219 |
} |
| 220 | 220 |
|
| 221 |
-// AddInterface adds an existing Interface to the sandbox. The operation will rename |
|
| 222 |
-// from the Interface SrcName to DstName as it moves, and reconfigure the |
|
| 223 |
-// interface according to the specified settings. The caller is expected |
|
| 224 |
-// to only provide a prefix for DstName. The AddInterface api will auto-generate |
|
| 225 |
-// an appropriate suffix for the DstName to disambiguate. |
|
| 226 |
-func (n *Namespace) AddInterface(ctx context.Context, srcName, dstPrefix string, options ...IfaceOption) error {
|
|
| 221 |
+// AddInterface creates an Interface that represents an existing network |
|
| 222 |
+// interface (except for bridge interfaces, which are created here). |
|
| 223 |
+// |
|
| 224 |
+// The network interface will be reconfigured according the options passed, and |
|
| 225 |
+// it'll be renamed from srcName into an auto-generated 'dest name' that |
|
| 226 |
+// combines the provided dstPrefix and a numeric suffix. |
|
| 227 |
+func (n *Namespace) AddInterface(ctx context.Context, srcName, dstPrefix, dstName string, options ...IfaceOption) error {
|
|
| 227 | 228 |
ctx, span := otel.Tracer("").Start(ctx, "libnetwork.osl.AddInterface", trace.WithAttributes(
|
| 228 | 229 |
attribute.String("srcName", srcName),
|
| 229 | 230 |
attribute.String("dstPrefix", dstPrefix)))
|
| 230 | 231 |
defer span.End() |
| 231 | 232 |
|
| 232 |
- i, err := newInterface(n, srcName, dstPrefix, options...) |
|
| 233 |
+ i, err := newInterface(n, srcName, dstPrefix, dstName, options...) |
|
| 233 | 234 |
if err != nil {
|
| 234 | 235 |
return err |
| 235 | 236 |
} |
| ... | ... |
@@ -237,7 +237,7 @@ func (n *Namespace) AddInterface(ctx context.Context, srcName, dstPrefix string, |
| 237 | 237 |
n.mu.Lock() |
| 238 | 238 |
if n.isDefault {
|
| 239 | 239 |
i.dstName = i.srcName |
| 240 |
- } else {
|
|
| 240 |
+ } else if i.dstName == "" {
|
|
| 241 | 241 |
i.dstName = fmt.Sprintf("%s%d", dstPrefix, n.nextIfIndex[dstPrefix])
|
| 242 | 242 |
n.nextIfIndex[dstPrefix]++ |
| 243 | 243 |
} |
| ... | ... |
@@ -402,7 +402,7 @@ func (n *Namespace) Destroy() error {
|
| 402 | 402 |
func (n *Namespace) RestoreInterfaces(interfaces map[Iface][]IfaceOption) error {
|
| 403 | 403 |
// restore interfaces |
| 404 | 404 |
for iface, opts := range interfaces {
|
| 405 |
- i, err := newInterface(n, iface.SrcName, iface.DstPrefix, opts...) |
|
| 405 |
+ i, err := newInterface(n, iface.SrcName, iface.DstPrefix, iface.DstName, opts...) |
|
| 406 | 406 |
if err != nil {
|
| 407 | 407 |
return err |
| 408 | 408 |
} |
| ... | ... |
@@ -22,11 +22,11 @@ import ( |
| 22 | 22 |
) |
| 23 | 23 |
|
| 24 | 24 |
const ( |
| 25 |
- vethName1 = "wierdlongname1" |
|
| 26 |
- vethName2 = "wierdlongname2" |
|
| 27 |
- vethName3 = "wierdlongname3" |
|
| 28 |
- vethName4 = "wierdlongname4" |
|
| 29 |
- sboxIfaceName = "containername" |
|
| 25 |
+ vethName1 = "wierdlongname1" |
|
| 26 |
+ vethName2 = "wierdlongname2" |
|
| 27 |
+ vethName3 = "wierdlongname3" |
|
| 28 |
+ vethName4 = "wierdlongname4" |
|
| 29 |
+ sboxIfacePrefix = "containername" |
|
| 30 | 30 |
) |
| 31 | 31 |
|
| 32 | 32 |
func generateRandomName(prefix string, size int) (string, error) {
|
| ... | ... |
@@ -85,16 +85,16 @@ func newInfo(t *testing.T, hnd nlwrap.Handle) (*Namespace, error) {
|
| 85 | 85 |
// This is needed for cleanup on DeleteEndpoint() |
| 86 | 86 |
intf1 := &Interface{
|
| 87 | 87 |
srcName: vethName2, |
| 88 |
- dstName: sboxIfaceName, |
|
| 88 |
+ dstPrefix: sboxIfacePrefix, |
|
| 89 | 89 |
address: addr, |
| 90 | 90 |
addressIPv6: addrv6, |
| 91 | 91 |
routes: []*net.IPNet{route},
|
| 92 | 92 |
} |
| 93 | 93 |
|
| 94 | 94 |
intf2 := &Interface{
|
| 95 |
- srcName: "testbridge", |
|
| 96 |
- dstName: sboxIfaceName, |
|
| 97 |
- bridge: true, |
|
| 95 |
+ srcName: "testbridge", |
|
| 96 |
+ dstPrefix: sboxIfacePrefix, |
|
| 97 |
+ bridge: true, |
|
| 98 | 98 |
} |
| 99 | 99 |
|
| 100 | 100 |
err = hnd.LinkAdd(&netlink.Veth{
|
| ... | ... |
@@ -106,9 +106,9 @@ func newInfo(t *testing.T, hnd nlwrap.Handle) (*Namespace, error) {
|
| 106 | 106 |
} |
| 107 | 107 |
|
| 108 | 108 |
intf3 := &Interface{
|
| 109 |
- srcName: vethName4, |
|
| 110 |
- dstName: sboxIfaceName, |
|
| 111 |
- master: "testbridge", |
|
| 109 |
+ srcName: vethName4, |
|
| 110 |
+ dstPrefix: sboxIfacePrefix, |
|
| 111 |
+ master: "testbridge", |
|
| 112 | 112 |
} |
| 113 | 113 |
|
| 114 | 114 |
return &Namespace{
|
| ... | ... |
@@ -132,10 +132,10 @@ func verifySandbox(t *testing.T, ns *Namespace, ifaceSuffixes []string) {
|
| 132 | 132 |
defer nh.Close() |
| 133 | 133 |
|
| 134 | 134 |
for _, suffix := range ifaceSuffixes {
|
| 135 |
- _, err = nh.LinkByName(sboxIfaceName + suffix) |
|
| 135 |
+ _, err = nh.LinkByName(sboxIfacePrefix + suffix) |
|
| 136 | 136 |
if err != nil {
|
| 137 | 137 |
t.Fatalf("Could not find the interface %s inside the sandbox: %v",
|
| 138 |
- sboxIfaceName+suffix, err) |
|
| 138 |
+ sboxIfacePrefix+suffix, err) |
|
| 139 | 139 |
} |
| 140 | 140 |
} |
| 141 | 141 |
} |
| ... | ... |
@@ -381,7 +381,7 @@ func TestSandboxCreate(t *testing.T) {
|
| 381 | 381 |
} |
| 382 | 382 |
|
| 383 | 383 |
for _, i := range tbox.Interfaces() {
|
| 384 |
- err = s.AddInterface(context.Background(), i.SrcName(), i.DstName(), |
|
| 384 |
+ err = s.AddInterface(context.Background(), i.SrcName(), i.dstPrefix, i.DstName(), |
|
| 385 | 385 |
WithIsBridge(i.Bridge()), |
| 386 | 386 |
WithIPv4Address(i.Address()), |
| 387 | 387 |
WithIPv6Address(i.AddressIPv6()), |
| ... | ... |
@@ -480,7 +480,7 @@ func TestAddRemoveInterface(t *testing.T) {
|
| 480 | 480 |
} |
| 481 | 481 |
|
| 482 | 482 |
for _, i := range tbox.Interfaces() {
|
| 483 |
- err = s.AddInterface(context.Background(), i.SrcName(), i.DstName(), |
|
| 483 |
+ err = s.AddInterface(context.Background(), i.SrcName(), i.dstPrefix, i.DstName(), |
|
| 484 | 484 |
WithIsBridge(i.Bridge()), |
| 485 | 485 |
WithIPv4Address(i.Address()), |
| 486 | 486 |
WithIPv6Address(i.AddressIPv6()), |
| ... | ... |
@@ -501,7 +501,7 @@ func TestAddRemoveInterface(t *testing.T) {
|
| 501 | 501 |
verifySandbox(t, s, []string{"1", "2"})
|
| 502 | 502 |
|
| 503 | 503 |
i := tbox.Interfaces()[0] |
| 504 |
- err = s.AddInterface(context.Background(), i.SrcName(), i.DstName(), |
|
| 504 |
+ err = s.AddInterface(context.Background(), i.SrcName(), i.dstPrefix, i.DstName(), |
|
| 505 | 505 |
WithIsBridge(i.Bridge()), |
| 506 | 506 |
WithIPv4Address(i.Address()), |
| 507 | 507 |
WithIPv6Address(i.AddressIPv6()), |
| ... | ... |
@@ -286,7 +286,8 @@ func (sb *Sandbox) restoreOslSandbox() error {
|
| 286 | 286 |
if len(i.llAddrs) != 0 {
|
| 287 | 287 |
ifaceOptions = append(ifaceOptions, osl.WithLinkLocalAddresses(i.llAddrs)) |
| 288 | 288 |
} |
| 289 |
- interfaces[osl.Iface{SrcName: i.srcName, DstPrefix: i.dstPrefix}] = ifaceOptions
|
|
| 289 |
+ iface := osl.Iface{SrcName: i.srcName, DstPrefix: i.dstPrefix, DstName: i.dstName}
|
|
| 290 |
+ interfaces[iface] = ifaceOptions |
|
| 290 | 291 |
if joinInfo != nil {
|
| 291 | 292 |
routes = append(routes, joinInfo.StaticRoutes...) |
| 292 | 293 |
} |
| ... | ... |
@@ -362,7 +363,7 @@ func (sb *Sandbox) populateNetworkResources(ctx context.Context, ep *Endpoint) e |
| 362 | 362 |
} |
| 363 | 363 |
ifaceOptions = append(ifaceOptions, osl.WithCreatedInContainer(i.createdInContainer)) |
| 364 | 364 |
|
| 365 |
- if err := sb.osSbox.AddInterface(ctx, i.srcName, i.dstPrefix, ifaceOptions...); err != nil {
|
|
| 365 |
+ if err := sb.osSbox.AddInterface(ctx, i.srcName, i.dstPrefix, i.dstName, ifaceOptions...); err != nil {
|
|
| 366 | 366 |
return fmt.Errorf("failed to add interface %s to sandbox: %v", i.srcName, err)
|
| 367 | 367 |
} |
| 368 | 368 |
|