The SIOCGIFFLAGS ioctl returns a set of flags for a network interface.
Many of the classic bits there, like IFF_UP and IFF_LOOPBACK, are the same
in our internal implementation (BSD-based) and desired output (Linux),
but not all of them are the same. We already had a function to convert
the internal bitmask into a Linux bitmask, but it was incomplete.

Of particular importance is BSD's IFF_SIMPLEX flag, which does not exist
on Linux, and is set by OSv's Xen network driver. As we failed to clear
this flag, clients thought they were seeing Linux's IFF_SLAVE (which is
at the same bit position, 0x800). In particular OpenMPI did not like
seeing this flag, and refused to use this network interface.

Fixes #862

Signed-off-by: Nadav Har'El <[email protected]>
---
 bsd/sys/compat/linux/linux_ioctl.cc | 19 ++++++++++---------
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/bsd/sys/compat/linux/linux_ioctl.cc 
b/bsd/sys/compat/linux/linux_ioctl.cc
index 59f1eb3..43a50bb 100644
--- a/bsd/sys/compat/linux/linux_ioctl.cc
+++ b/bsd/sys/compat/linux/linux_ioctl.cc
@@ -143,26 +143,27 @@ linux_ifconf(struct bsd_ifconf *ifc_p)
     return (0);
 }
 
+// While many of the traditional bits returned by SIOCGIFFLAGS are the same
+// on BSD and Linux, some of the newer ones have different location, or
+// different meaning for the same bit location. So we need to convert the
+// BSD bits which we store internally to the Linux bits applications expect
+// us to return.
 static void
 linux_gifflags(struct ifnet *ifp, struct l_ifreq *ifr)
 {
     l_short flags;
 
+    // This assignment drops all the flags beyond the 16th bit.
+    // None of them have a Linux equivalent.
     flags = (ifp->if_flags | ifp->if_drv_flags);
-    /* These flags have no Linux equivalent
-     *
-     *  Notes:
-     *       - We do show IFF_SMART|IFF_DRV_OACTIVE|IFF_SIMPLEX
-     *       - IFF_LINK0 has a value of 0x1000 which conflics with the Linux
-     *         IFF_MULTICAST value.
-     */
-    flags &= ~(IFF_LINK0|IFF_LINK1|IFF_LINK2);
+    // These flags have no Linux equivalent:
+    flags &= 
~(IFF_SMART|IFF_DRV_OACTIVE|IFF_SIMPLEX|IFF_LINK0|IFF_LINK1|IFF_LINK2);
     /* Linux' multicast flag is in a different bit */
     if (flags & IFF_MULTICAST) {
         flags &= ~IFF_MULTICAST;
         flags |= 0x1000;
     }
-    ifr->ifr_flags = flags ;
+    ifr->ifr_flags = flags;
 }
 
 #define ARPHRD_ETHER   1
-- 
2.9.3

-- 
You received this message because you are subscribed to the Google Groups "OSv 
Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to