Physical interface MAC rather than macvlan MAC is sent as ARP response [closed]

On Arch Linux ARM (Raspberry Pi) Kernel 4.4.37, I created a macvlan e.g.

ip link add link eth0 mac0 type macvlan

The macvlan virtual NIC then appears in the list so I assign it an IP address, and set the link state to up. (By the way, I have tried with modes bridge, vepa and private.)

I can then ping the IP from my Windows clients, but when I check the ARP cache (arp -a) in Windows, they are showing the same MAC address as the main (physical) network adapter, not the newly created macvlan MAC address.

I made sure to clear the ARP cache try an IP address that the clients had not seen before, etc. but it always shows the wrong MAC.

When I created a static ARP entry to the Windows client for the macvlan MAC address, and ping the relevant IP address, tcpdump shows the echo request coming in on the macvlan interface, and it doesn't show anything on the main (physical) interface, and I get a ping response on my windows client (once I remembered to set up the iptables rule to allow the traffic!)

As soon as I clear the ARP cache on the client and ping again, I still get a ping response, but this time the ARP entry has reverted to that of the main physical network adapter on the Linux box.

Just wondered what I might be doing wrong?


Solution 1:

For this to work for me I had to add one step to the accepted answer and set the following additional variable:

net.ipv4.conf.all.rp_filter=2

I did not need to set arp_ignore to 2, 1 seemed to work. I also didn't need to set arp_filter to 1 for my network.

So the complete solution for me was:

net.ipv4.conf.all.arp_ignore=1
net.ipv4.conf.all.arp_announce=2
net.ipv4.conf.all.rp_filter=2

Found the solution to my issue here

Solution 2:

Basically, nothing is wrong here. This is how Linux kernel works in regard to ARP resolution - by default it will reply to ARP requests for any of its local addresses regardless of interface they are coming in, even if requested address is on a different interface.

To work around this, you need to adjust two sysctl variables:

net.ipv4.conf.all.arp_ignore=1
net.ipv4.conf.all.arp_announce=2

You may need to change arp_ignore value to 2 and also set arp_filter to 1 depending on your IP addresses/subnetting scenario.

For a full description of available options for these variables, please have a look at kernel.org documentation.