svinota / pyroute2

Python Netlink and PF_ROUTE library — network configuration and monitoring
https://pyroute2.org/
Other
948 stars 243 forks source link

Adding secondary ip address fails if in the same subnet as primary #27

Closed thardie closed 10 years ago

thardie commented 10 years ago

Given an interface with his config (from ip ad ls):

5: virbr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP link/ether fe:54:00:64:ee:54 brd ff:ff:ff:ff:ff:ff inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0

from pyroute2 import IPRoute ip = IPRoute() dev = ip.link_lookup(ifname='virbr0')[0] ip.addr('add', dev, address='192.168.122.2', mask=24) Traceback (most recent call last): File "", line 1, in File "/usr/local/lib/python2.7/dist-packages/pyroute2/netlink/iproute.py", line 450, in addr return self.nlm_request(msg, msg_type=command, msg_flags=flags) File "/usr/local/lib/python2.7/dist-packages/pyroute2/netlink/init.py", line 1135, in nlm_request result = self.get(nonce) File "/usr/local/lib/python2.7/dist-packages/pyroute2/netlink/init.py", line 1096, in get raise msg['header']['error'] pyroute2.netlink.NetlinkError: (22, 'Invalid argument')

For different subnet it works:

ip.addr('add', dev, address='192.168.123.2', mask=24) [{'index': 5, 'family': 2, 'flags': 128, 'attrs': [('IFA_ADDRESS', '192.168.123.2'), ('IFA_LOCAL', '192.168.123.2'), ('IFA_LABEL', 'virbr0')], 'prefixlen': 24, 'scope': 254, 'event': 'RTM_NEWADDR'}]

I suspect the first case fails because it must be added with the secondary flag. Here's the state after the above is run:

5: virbr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP link/ether fe:54:00:64:ee:54 brd ff:ff:ff:ff:ff:ff inet 192.168.123.2/24 scope host virbr0 inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0

If I add the address using "ip" command line:

ip add add 192.168.122.2/24 dev virbr0

Then "ip add ls":

5: virbr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP link/ether fe:54:00:64:ee:54 brd ff:ff:ff:ff:ff:ff inet 192.168.123.2/24 scope host virbr0 inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0 inet 192.168.122.2/24 scope global secondary virbr0

Note the "secondary" on the 192.168.122.2/24

Interestingly, if all addresses are added through pyroute2, the problem does not occur:

ip.addr('add', dev, address='192.168.123.3', mask=24) [{'index': 5, 'family': 2, 'flags': 129, 'attrs': [('IFA_ADDRESS', '192.168.123.3'), ('IFA_LOCAL', '192.168.123.3'), ('IFA_LABEL', 'virbr0')], 'prefixlen': 24, 'scope': 254, 'event': 'RTM_NEWADDR'}]

I think pyroute2 assumes that the first ip.addr call is primary, and subsequent ones are secondary, when this is not the case if you are adding addresses to an interface with existing addresses in the same subnet.

svinota commented 10 years ago

Thanks for reporting, I'm fixing it.

thardie commented 10 years ago

Wow, fantastic! Thanks for the awesomely fast response. I look forward to trying out a fix :D

svinota commented 10 years ago

Fixed in 5900aeb545e5105e68bec382e128d7c138c56de7

The root cause was that pyroute2 used different scope for IP addresses — 0xfe (host), while iproute2 and other utilities used 0x0 (global). I do not remember, why 0xfe was taken, maybe I just forgot to remove it :) So from now on pyroute2 uses 0x0 too, and should work along other utilities as well. Please check, and thanks for pointing the issue.

thardie commented 10 years ago

Works perfectly! Thank you SO much! Where do I send $$? :)

svinota commented 10 years ago

You're welcome!

In the case of bugs, just file them, I will try to react asap, but sometimes it is not so fast ;)