Change in vdsm[master]: netinfo: improve which ipv4 addr is reported if there are mu...

asegurap at redhat.com asegurap at redhat.com
Thu Sep 25 15:22:44 UTC 2014


Antoni Segura Puimedon has uploaded a new change for review.

Change subject: netinfo: improve which ipv4 addr is reported if there are multiple primary
......................................................................

netinfo: improve which ipv4 addr is reported if there are multiple primary

The current code assumed that additional configured addresses for a
device would have the 'secondary' flag. However, this is no longer
true in recent kernels, as multiple primary addresses can be set for
a device.

The improvement is that now we will check if any of the addresses is
in the subnet of the gateway and report one of them. If there is no
default gw in the main table for the device we return the last
set primary ip and if there is a default gw but going through another
hop, we return the first set ip.

Change-Id: I8666cfef5bd8ea63edf8979e501d4785db5f4893
Signed-off-by: Antoni S. Puimedon <asegurap at redhat.com>
---
M lib/vdsm/netinfo.py
1 file changed, 35 insertions(+), 7 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/75/33375/1

diff --git a/lib/vdsm/netinfo.py b/lib/vdsm/netinfo.py
index 6491505..816810d 100644
--- a/lib/vdsm/netinfo.py
+++ b/lib/vdsm/netinfo.py
@@ -292,25 +292,49 @@
         struct.pack("!I", int('1' * prefix + '0' * (32 - prefix), 2)))
 
 
+def prefix2int(prefix):
+    if not 0 <= prefix <= 32:
+        raise ValueError('%s is not a valid prefix value. It must be between '
+                         '0 and 32')
+    return (2 ** prefix - 1) << (32 - prefix)
+
+
+def addr2int(address):
+    return struct.unpack('!I', socket.inet_aton(address))[0]
+
+
 def getDefaultGateway():
     output = routeShowGateways('main')
     return Route.fromText(output[0]) if output else None
 
 
-def getIpInfo(dev, ipaddrs=None):
+def getIpInfo(dev, ipaddrs=None, ipv4_gateway=None):
     if ipaddrs is None:
         ipaddrs = _getIpAddrs()
     ipv4addr = ipv4netmask = ''
     ipv4addrs = []
     ipv6addrs = []
+    gateway_int = addr2int(ipv4_gateway) if ipv4_gateway else None
+
     for addr in ipaddrs[dev]:
         if addr['family'] == 'inet':
             ipv4addrs.append(addr['address'])
             if 'secondary' not in addr['flags']:
-                ipv4addr, prefix = addr['address'].split('/')
-                ipv4netmask = prefix2netmask(addr['prefixlen'])
+                address, _ = addr['address'].split('/')
+                mask = prefix2int(addr['prefixlen'])
+                if (gateway_int is None or
+                        addr2int(address) & mask == gateway_int & mask):
+                    ipv4addr = address
+                    ipv4netmask = prefix2netmask(addr['prefixlen'])
         else:
             ipv6addrs.append(addr['address'])
+        if ipv4addrs and ipv4addr == '':
+            # If we didn't find an address in the gateway subnet (which is
+            # legal if there is another route that takes us to the gateway) we
+            # choose to report the first address
+            ipv4addr, prefix = ipv4addrs[0].split('/')
+            ipv4netmask = prefix2netmask(int(prefix))
+
     return ipv4addr, ipv4netmask, ipv4addrs, ipv6addrs
 
 
@@ -501,14 +525,16 @@
             # comment when the version is no longer supported.
             data['interface'] = iface
 
-        ipv4addr, ipv4netmask, ipv4addrs, ipv6addrs = getIpInfo(iface, ipaddrs)
+        gateway = _get_gateway(routes, iface)
+        ipv4addr, ipv4netmask, ipv4addrs, ipv6addrs = getIpInfo(
+            iface, ipaddrs, gateway)
         data.update({'iface': iface, 'bridged': bridged,
                      'addr': ipv4addr, 'netmask': ipv4netmask,
                      'bootproto4': ('dhcp' if ipv4addr and iface in dhcp4
                                     else 'none'),
                      'ipv4addrs': ipv4addrs,
                      'ipv6addrs': ipv6addrs,
-                     'gateway': _get_gateway(routes, iface),
+                     'gateway': gateway,
                      'ipv6gateway': _get_gateway(routes, iface, family=6),
                      'mtu': str(getMtu(iface))})
     except (IOError, OSError) as e:
@@ -549,12 +575,14 @@
 
 
 def _devinfo(link, routes, ipaddrs, dhcp4):
-    ipv4addr, ipv4netmask, ipv4addrs, ipv6addrs = getIpInfo(link.name, ipaddrs)
+    gateway = _get_gateway(routes, link.name)
+    ipv4addr, ipv4netmask, ipv4addrs, ipv6addrs = getIpInfo(
+        link.name, ipaddrs, gateway)
     info = {'addr': ipv4addr,
             'cfg': getIfaceCfg(link.name),
             'ipv4addrs': ipv4addrs,
             'ipv6addrs': ipv6addrs,
-            'gateway': _get_gateway(routes, link.name),
+            'gateway': gateway,
             'ipv6gateway': _get_gateway(routes, link.name, family=6),
             'bootproto4': ('dhcp' if ipv4addr and link.name in dhcp4
                            else 'none'),


-- 
To view, visit http://gerrit.ovirt.org/33375
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I8666cfef5bd8ea63edf8979e501d4785db5f4893
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Antoni Segura Puimedon <asegurap at redhat.com>


More information about the vdsm-patches mailing list