containers / containers/netavark

Redeploying containers with macvlan + static IP does not inform of the new mac address

Open
#1,114 4 comments 0 reactions 0 assignees View on GitHub
kind/feature
Dominant language
Rust
Stars
794
Forks
161
Avg merge
8d 17h
Merged PRs (30d)
3

Description

### Issue Description

Hello,

Let's assume that we have a macvlan network and in that network we have a container with a static IP.
When redeploying the container (rm + run), the new container has the same IP as before but a different mac address, which is the expected behavior.

The problem is that the new container does not inform the network that the mac address has changed, so the switches don't know that they need to update their routing table.
The switches still keep in memory the old couple IP/mac address which is no longer valid.
On a small setup (only one switch between the different hardware), it's not a problem because the switch quickly detects that the mac address is no longer reachable and updates its table.
On a larger setup (distributed network), this becomes a problem. All the switches have to learn the new MAC address, but since they have not been notified of the change, it takes time (on our setup we see delays of up to 30 minutes before the container becomes pingable from anywhere else on the network).

This problem can be solved by creating a Gratuitous ARP request (https://wiki.wireshark.org/Gratuitous_ARP).
Let's say my container has an IP `200.200.200.252`, if I enter it (podman exec) and run `arping -U -I eth0 200.200.200.252`, then an ARP request is sent out on the network and all the switches update their table. My container will then be directly pingable from any node on our network.

I guess that problem can also happen with ipvlan if we undeploy a container from a hardware and tries to deploy it on another hardware with the same IP.

### Steps to reproduce the issue

Steps to reproduce the issue
1. Create a macvlan network `sudo podman network create --driver=macvlan --subnet=200.200.200.0/22 --opt parent=eno1 testnetwork`
2. Start a container `sudo podman run --name=test_container --replace --rm --network=testnetwork --sdnotify=conmon -d --ip 200.200.200.252 --privileged httpd:2.4`
3. From another hardware on a distributed network, try to ping the container `ping 200.200.200.252` -> It should work as it is the first deployment
4. Redeploy the container `sudo podman run --name=test_container --replace --rm --network=testnetwork --sdnotify=conmon -d --ip 200.200.200.252 --privileged httpd:2.4`
5. From another hardware on a distributed network, try to ping the container `ping 200.200.200.252` -> it should failed in a timeout as the switches haven't updated their routing table
6. Enter the container `sudo podman exec -it test_container /bin/bash`, run `apt update && apt install arping` then generate an ARP Gratuitous request `arping -U -I eth0 200.200.200.252`
7. From another hardware on a distributed network, try to ping the container `ping 200.200.200.252` -> It should work as the switches have updated their table due to the ARP Gratuitous request

### Describe the results you received

When redeploying a container in a macvlan network with a static IP, the new container has a new MAC address associated to the same IP.
That container does not send an ARP Gratuitous request on the network (confirmed with wireshark by capturing the traffic on my ethernet interface) so the switches are not informed that they need to update their routing table.

### Describe the results you expected

I was expecting that when redeploying a container in a macvlan network, the container will generate an ARP Gratuitous request in order to inform the switches of the new couple IP / MAC address.

### podman info output

host:
arch: amd64
buildahVersion: 1.37.4
cgroupControllers:
- cpuset
- cpu
- io
- memory
- hugetlb
- pids
- rdma
- misc
cgroupManager: systemd
cgroupVersion: v2
conmon:
package: conmon_2.1.6+ds1-1_amd64
path: /usr/bin/conmon
version: 'conmon version 2.1.6, commit: unknown'
cpuUtilization:
idlePercent: 98.78
systemPercent: 0.27
userPercent: 0.95
cpus: 12
databaseBackend: boltdb
distribution:
codename: trixie
distribution: debian
version: unknown
eventLogger: journald
freeLocks: 2021
hostname: orion-docker
idMappings:
gidmap: null
uidmap: null
kernel: 6.1.0-13-rt-amd64
linkmode: dynamic
logDriver: journald
memFree: 23622979584
memTotal: 33438621696
networkBackend: netavark
networkBackendInfo:
backend: netavark
dns:
package: aardvark-dns_1.12.2-1_amd64
path: /usr/lib/podman/aardvark-dns
version: aardvark-dns 1.12.2
package: netavark_1.12.1-3_amd64
path: /usr/lib/podman/netavark
version: netavark 1.12.1
ociRuntime:
name: runc
package: runc_1.1.5+ds1-1+deb12u1_amd64
path: /usr/bin/runc
version: |-
runc version 1.1.5+ds1
commit: 1.1.5+ds1-1+deb12u1
spec: 1.0.2-dev
go: go1.19.8
libseccomp: 2.5.4
os: linux
pasta:
executable: /usr/bin/pasta
package: passt_0.0~git20240326.4988e2b-1_amd64
version: |
pasta 0.0~git20240326.4988e2b-1
Copyright Red Hat
GNU General Public License, version 2 or later

This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
remoteSocket:
exists: true
path: /run/podman/podman.sock
rootlessNetworkCmd: pasta
security:
apparmorEnabled: true
capabilities: CAP_CHOWN,CAP_DAC_OVERRIDE,CAP_FOWNER,CAP_FSETID,CAP_KILL,CAP_NET_BIND_SERVICE,CAP_SETFCAP,CAP_SETGID,CAP_SETPCAP,CAP_SETUID,CAP_SYS_CHROOT
rootless: false
seccompEnabled: true
seccompProfilePath: /usr/share/containers/seccomp.json
selinuxEnabled: false
serviceIsRemote: false
slirp4netns:
executable: /usr/bin/slirp4netns
package: slirp4netns_1.2.0-1_amd64
version: |-
slirp4netns version 1.2.0
commit: 656041d45cfca7a4176f6b7eed9e4fe6c11e8383
libslirp: 4.7.0
SLIRP_CONFIG_VERSION_MAX: 4
libseccomp: 2.5.4
swapFree: 1024454656
swapTotal: 1024454656
uptime: 5h 37m 28.00s (Approximately 0.21 days)
variant: ""
plugins:
authorization: null
log:
- k8s-file
- none
- passthrough
- journald
network:
- bridge
- macvlan
- ipvlan
volume:
- local
registries:
search:
- docker.io
store:
configFile: /usr/share/containers/storage.conf
containerStore:
number: 12
paused: 0
running: 11
stopped: 1
graphDriverName: overlay
graphOptions:
overlay.mountopt: nodev
graphRoot: /var/lib/containers/storage
graphRootAllocated: 249365385216
graphRootUsed: 70269030400
graphStatus:
Backing Filesystem: extfs
Native Overlay Diff: "true"
Supports d_type: "true"
Supports shifting: "true"
Supports volatile: "true"
Using metacopy: "false"
imageCopyTmpDir: /var/tmp
imageStore:
number: 18
runRoot: /run/containers/storage
transientStore: false
volumePath: /var/lib/containers/storage/volumes
version:
APIVersion: 5.2.4
Built: 1729434149
BuiltTime: Sun Oct 20 16:22:29 2024
GitCommit: ""
GoVersion: go1.23.2
Os: linux
OsArch: linux/amd64
Version: 5.2.4

### Podman in a container

No

### Privileged Or Rootless

Privileged

### Upstream Latest Release

No

### Additional environment details

_No response_

### Additional information

_No response_

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.