[libvirt] [PATCH] Consolidate interface related functions in interface.c

Stefan Berger stefanb at us.ibm.com
Mon Apr 12 20:21:00 UTC 2010


I am consolidating network interface related functions used in nwfilter
and macvtap code in utils/interface.c. All function names are prefixed
with 'Iface'. The following functions are now available through
interface.h:

int IfaceCtrl(const char *name, bool up);
int IfaceUp(const char *name);
int IfaceDown(const char *name);

int IfaceCheck(bool reportError, const char *ifname,
               const unsigned char *macaddr, int ifindex);

int IfaceGetIndex(bool reportError, const char *ifname, int *ifindex);

I added 'int ifindex' as parameter to IfaceCheck to the original
function and modified the code accordingly.

Signed-off-by: Stefan Berger <stefanb at us.ibm.com>

---
 src/Makefile.am                        |    1 
 src/libvirt_private.syms               |    4 
 src/nwfilter/nwfilter_gentech_driver.c |  120 -----------------
 src/nwfilter/nwfilter_gentech_driver.h |    2 
 src/nwfilter/nwfilter_learnipaddr.c    |    3 
 src/util/interface.c                   |  224 +++++++++++++++++++++++++++++++++
 src/util/interface.h                   |   31 ++++
 src/util/macvtap.c                     |  112 ----------------
 8 files changed, 269 insertions(+), 228 deletions(-)

Index: libvirt-acl/src/nwfilter/nwfilter_gentech_driver.c
===================================================================
--- libvirt-acl.orig/src/nwfilter/nwfilter_gentech_driver.c
+++ libvirt-acl/src/nwfilter/nwfilter_gentech_driver.c
@@ -23,16 +23,11 @@
 
 #include <config.h>
 
-#include <stdint.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <linux/if.h>
-
 #include "internal.h"
 
 #include "memory.h"
 #include "logging.h"
-#include "datatypes.h"
+#include "interface.h"
 #include "domain_conf.h"
 #include "virterror_internal.h"
 #include "nwfilter_gentech_driver.h"
@@ -792,117 +787,6 @@ _virNWFilterInstantiateFilter(virConnect
 }
 
 
-// FIXME: move chgIfFlags, ifUp, checkIf into common file & share w/ macvtap.c
-
-/*
- * chgIfFlags: Change flags on an interface
- * @ifname : name of the interface
- * @flagclear : the flags to clear
- * @flagset : the flags to set
- *
- * The new flags of the interface will be calculated as
- * flagmask = (~0 ^ flagclear)
- * newflags = (curflags & flagmask) | flagset;
- *
- * Returns 0 on success, errno on failure.
- */
-static int chgIfFlags(const char *ifname, short flagclear, short flagset) {
-    struct ifreq ifr;
-    int rc = 0;
-    int flags;
-    short flagmask = (~0 ^ flagclear);
-    int fd = socket(PF_PACKET, SOCK_DGRAM, 0);
-
-    if (fd < 0)
-        return errno;
-
-    if (virStrncpy(ifr.ifr_name,
-                   ifname, strlen(ifname), sizeof(ifr.ifr_name)) == NULL) {
-        rc = ENODEV;
-        goto err_exit;
-    }
-
-    if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
-        rc = errno;
-        goto err_exit;
-    }
-
-    flags = (ifr.ifr_flags & flagmask) | flagset;
-
-    if (ifr.ifr_flags != flags) {
-        ifr.ifr_flags = flags;
-
-        if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0)
-            rc = errno;
-    }
-
-err_exit:
-    close(fd);
-    return rc;
-}
-
-/*
- * ifUp
- * @name: name of the interface
- * @up: 1 for up, 0 for down
- *
- * Function to control if an interface is activated (up, 1) or not (down, 0)
- *
- * Returns 0 in case of success or an errno code in case of failure.
- */
-static int
-ifUp(const char *name, int up)
-{
-    return chgIfFlags(name,
-                      (up) ? 0      : IFF_UP,
-                      (up) ? IFF_UP : 0);
-}
-
-
-/**
- * checkIf
- *
- * @ifname: Name of the interface
- * @macaddr: expected MAC address of the interface
- *
- * FIXME: the interface's index is another good parameter to check
- *
- * Determine whether a given interface is still available. If so,
- * it must have the given MAC address.
- *
- * Returns an error code ENODEV in case the interface does not exist
- * anymore or its MAC address is different, 0 otherwise.
- */
-int
-checkIf(const char *ifname, const unsigned char *macaddr)
-{
-    struct ifreq ifr;
-    int fd = socket(PF_PACKET, SOCK_DGRAM, 0);
-    int rc = 0;
-
-    if (fd < 0)
-        return errno;
-
-    if (virStrncpy(ifr.ifr_name,
-                   ifname, strlen(ifname), sizeof(ifr.ifr_name)) == NULL) {
-        rc = ENODEV;
-        goto err_exit;
-    }
-
-    if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) {
-        rc = errno;
-        goto err_exit;
-    }
-
-    if (memcmp(&ifr.ifr_hwaddr.sa_data, macaddr, 6) != 0)
-        rc = ENODEV;
-
- err_exit:
-    close(fd);
-    return rc;
-}
-
-
 int
 virNWFilterInstantiateFilterLate(virConnectPtr conn,
                                  const char *ifname,
@@ -926,7 +810,7 @@ virNWFilterInstantiateFilterLate(virConn
                                         driver);
     if (rc) {
         //something went wrong... 'DOWN' the interface
-        if (ifUp(ifname ,0)) {
+        if (IfaceDown(ifname)) {
             // assuming interface disappeared...
             _virNWFilterTeardownFilter(ifname);
         }
Index: libvirt-acl/src/util/interface.c
===================================================================
--- /dev/null
+++ libvirt-acl/src/util/interface.c
@@ -0,0 +1,226 @@
+/*
+ * interface.c: interface support functions
+ *
+ * Copyright (C) 2010 IBM Corp.
+ * Copyright (C) 2010 Stefan Berger
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ * chgIfaceFlags originated from bridge.c
+ *
+ * Author: Stefan Berger <stefanb at us.ibm.com>
+ */
+
+#include <config.h>
+
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <linux/if.h>
+
+#include "internal.h"
+
+#include "util.h"
+#include "interface.h"
+#include "virterror_internal.h"
+
+#define ifaceError(code, ...) \
+        virReportErrorHelper(NULL, VIR_FROM_NET, code, __FILE__, \
+                             __FUNCTION__, __LINE__, __VA_ARGS__)
+
+/*
+ * chgIfFlags: Change flags on an interface
+ *
+ * @ifname : name of the interface
+ * @flagclear : the flags to clear
+ * @flagset : the flags to set
+ *
+ * The new flags of the interface will be calculated as
+ * flagmask = (~0 ^ flagclear)
+ * newflags = (curflags & flagmask) | flagset;
+ *
+ * Returns 0 on success, errno on failure.
+ */
+static int chgIfaceFlags(const char *ifname, short flagclear, short flagset) {
+    struct ifreq ifr;
+    int rc = 0;
+    int flags;
+    short flagmask = (~0 ^ flagclear);
+    int fd = socket(PF_PACKET, SOCK_DGRAM, 0);
+
+    if (fd < 0)
+        return errno;
+
+    if (virStrncpy(ifr.ifr_name,
+                   ifname, strlen(ifname), sizeof(ifr.ifr_name)) == NULL) {
+        rc = ENODEV;
+        goto err_exit;
+    }
+
+    if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
+        rc = errno;
+        goto err_exit;
+    }
+
+    flags = (ifr.ifr_flags & flagmask) | flagset;
+
+    if (ifr.ifr_flags != flags) {
+        ifr.ifr_flags = flags;
+
+        if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0)
+            rc = errno;
+    }
+
+err_exit:
+    close(fd);
+    return rc;
+}
+
+
+/*
+ * IfaceCtrl
+ * @name: name of the interface
+ * @up: true (1) for up, false (0) for down
+ *
+ * Function to control if an interface is activated (up, 1) or not (down, 0)
+ *
+ * Returns 0 in case of success or an errno code in case of failure.
+ */
+int
+IfaceCtrl(const char *name, bool up)
+{
+    return chgIfaceFlags(name,
+                         (up) ? 0      : IFF_UP,
+                         (up) ? IFF_UP : 0);
+}
+
+
+/**
+ * IfaceCheck
+ *
+ * @reportError: whether to report errors or keep silent
+ * @ifname: Name of the interface
+ * @macaddr: expected MAC address of the interface; not checked if NULL
+ * @ifindex: expected index of the interface; not checked if '-1'
+ *
+ * Determine whether a given interface is still available. If so,
+ * it must have the given MAC address and if an interface index is
+ * passed, it must also match the interface index.
+ *
+ * Returns 0 on success, an error code on failure.
+ *   ENODEV : if interface with given name does not exist or its interface
+ *            index is different than the one passed
+ *   EINVAL : if interface name is invalid (too long)
+ */
+int
+IfaceCheck(bool reportError, const char *ifname,
+           const unsigned char *macaddr, int ifindex)
+{
+    struct ifreq ifr;
+    int fd = -1;
+    int rc = 0;
+    int idx;
+
+    if (macaddr != NULL) {
+        fd = socket(PF_PACKET, SOCK_DGRAM, 0);
+        if (fd < 0)
+            return errno;
+
+        if (virStrncpy(ifr.ifr_name,
+                       ifname, strlen(ifname), sizeof(ifr.ifr_name)) == NULL) {
+            if (reportError)
+                ifaceError(VIR_ERR_INTERNAL_ERROR,
+                           _("invalid interface name %s"),
+                           ifname);
+            rc = EINVAL;
+            goto err_exit;
+        }
+
+        if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) {
+            if (reportError)
+                ifaceError(VIR_ERR_INTERNAL_ERROR,
+                           _("coud not get MAC address of interface %s"),
+                           ifname);
+            rc = errno;
+            goto err_exit;
+        }
+
+        if (memcmp(&ifr.ifr_hwaddr.sa_data, macaddr, VIR_MAC_BUFLEN) != 0) {
+            rc = ENODEV;
+            goto err_exit;
+        }
+    }
+
+    if (ifindex != -1) {
+        rc = IfaceGetIndex(reportError, ifname, &idx);
+        if (rc == 0 && idx != ifindex)
+            rc = ENODEV;
+    }
+
+ err_exit:
+    if (fd >= 0)
+        close(fd);
+
+    return rc;
+}
+
+
+/**
+ * IfaceGetIndex
+ *
+ * @reportError: whether to report errors or keep silent
+ * @ifname : Name of the interface whose index is to be found
+ * @ifindex: Pointer to int where the index will be written into
+ *
+ * Get the index of an interface given its name.
+ *
+ * Returns 0 on success, an error code on failure.
+ *   ENODEV : if interface with given name does not exist
+ *   EINVAL : if interface name is invalid (too long)
+ */
+int
+IfaceGetIndex(bool reportError, const char *ifname, int *ifindex)
+{
+    int rc = 0;
+    struct ifreq ifreq;
+    int fd = socket(PF_PACKET, SOCK_DGRAM, 0);
+
+    if (fd < 0)
+        return errno;
+
+    if (virStrncpy(ifreq.ifr_name, ifname, strlen(ifname),
+                   sizeof(ifreq.ifr_name)) == NULL) {
+        if (reportError)
+            ifaceError(VIR_ERR_INTERNAL_ERROR,
+                       _("invalid interface name %s"),
+                       ifname);
+        rc = EINVAL;
+        goto err_exit;
+    }
+
+    if (ioctl(fd, SIOCGIFINDEX, &ifreq) >= 0)
+        *ifindex = ifreq.ifr_ifindex;
+    else {
+        if (reportError)
+            ifaceError(VIR_ERR_INTERNAL_ERROR,
+                       _("interface %s does not exist"),
+                       ifname);
+        rc = ENODEV;
+    }
+
+err_exit:
+    close(fd);
+
+    return rc;
+}
Index: libvirt-acl/src/util/interface.h
===================================================================
--- /dev/null
+++ libvirt-acl/src/util/interface.h
@@ -0,0 +1,31 @@
+/*
+ * interface.h: interface helper APIs for libvirt
+ *
+ * Copyright (C) 2010 IBM Corporation, Inc.
+ *
+ * See COPYING.LIB for the License of this software
+ *
+ * Stefan Berger <stefanb at us.ibm.com>
+ */
+#ifndef __VIR_INTERFACE_H__
+# define __VIR_INTERFACE_H__
+
+#include "datatypes.h"
+
+int IfaceCtrl(const char *name, bool up);
+
+static inline int IfaceUp(const char *name) {
+    return IfaceCtrl(name, true);
+}
+
+static inline int IfaceDown(const char *name) {
+    return IfaceCtrl(name, false);
+}
+
+int IfaceCheck(bool reportError, const char *ifname,
+               const unsigned char *macaddr, int ifindex);
+
+int IfaceGetIndex(bool reportError, const char *ifname, int *ifindex);
+
+#endif /* __VIR_INTERFACE_H__ */
+
Index: libvirt-acl/src/Makefile.am
===================================================================
--- libvirt-acl.orig/src/Makefile.am
+++ libvirt-acl/src/Makefile.am
@@ -67,6 +67,7 @@ UTIL_SOURCES =							\
 		util/processinfo.c util/processinfo.h		\
 		util/hostusb.c util/hostusb.h			\
 		util/network.c util/network.h			\
+		util/interface.c util/interface.h		\
 		util/qparams.c util/qparams.h			\
 		util/stats_linux.c util/stats_linux.h		\
 		util/storage_file.c util/storage_file.h		\
Index: libvirt-acl/src/libvirt_private.syms
===================================================================
--- libvirt-acl.orig/src/libvirt_private.syms
+++ libvirt-acl/src/libvirt_private.syms
@@ -681,6 +681,10 @@ virFileWaitForDevices;
 virFileMatchesNameSuffix;
 virArgvToString;
 
+# interface.h
+IfaceCtrl;
+IfaceCheck;
+IfaceGetIndex;
 
 # usb.h
 usbGetDevice;
Index: libvirt-acl/src/nwfilter/nwfilter_learnipaddr.c
===================================================================
--- libvirt-acl.orig/src/nwfilter/nwfilter_learnipaddr.c
+++ libvirt-acl/src/nwfilter/nwfilter_learnipaddr.c
@@ -43,6 +43,7 @@
 #include "memory.h"
 #include "logging.h"
 #include "datatypes.h"
+#include "interface.h"
 #include "virterror_internal.h"
 #include "threads.h"
 #include "conf/nwfilter_params.h"
@@ -339,7 +340,7 @@ learnIPAddressThread(void *arg)
                 break;
             }
             /* listening on linkdev, check whether VM's dev is still there */
-            if (checkIf(req->ifname, req->macaddr)) {
+            if (IfaceCheck(false, req->ifname, req->macaddr, -1)) {
                 req->status = ENODEV;
                 break;
             }
Index: libvirt-acl/src/util/macvtap.c
===================================================================
--- libvirt-acl.orig/src/util/macvtap.c
+++ libvirt-acl/src/util/macvtap.c
@@ -44,6 +44,7 @@
 # include "util.h"
 # include "memory.h"
 # include "macvtap.h"
+# include "interface.h"
 # include "conf/domain_conf.h"
 # include "virterror_internal.h"
 
@@ -193,109 +194,6 @@ nlAppend(struct nlmsghdr *nlm, int totle
 
 
 static int
-getIfIndex(bool reportError,
-           const char *ifname,
-           int *idx)
-{
-    int rc = 0;
-    struct ifreq ifreq;
-    int fd = socket(PF_PACKET, SOCK_DGRAM, 0);
-
-    if (fd < 0)
-        return errno;
-
-    if (virStrncpy(ifreq.ifr_name, ifname, strlen(ifname),
-                   sizeof(ifreq.ifr_name)) == NULL) {
-        if (reportError)
-            macvtapError(VIR_ERR_INTERNAL_ERROR,
-                         _("invalid interface name %s"),
-                         ifname);
-        rc = EINVAL;
-        goto err_exit;
-    }
-    if (ioctl(fd, SIOCGIFINDEX, &ifreq) >= 0)
-        *idx = ifreq.ifr_ifindex;
-    else {
-        if (reportError)
-            macvtapError(VIR_ERR_INTERNAL_ERROR,
-                         _("interface %s does not exist"),
-                         ifname);
-        rc = ENODEV;
-    }
-
-err_exit:
-    close(fd);
-
-    return rc;
-}
-
-
-/*
- * chgIfFlags: Change flags on an interface
- * @ifname : name of the interface
- * @flagclear : the flags to clear
- * @flagset : the flags to set
- *
- * The new flags of the interface will be calculated as
- * flagmask = (~0 ^ flagclear)
- * newflags = (curflags & flagmask) | flagset;
- *
- * Returns 0 on success, errno on failure.
- */
-static int chgIfFlags(const char *ifname, short flagclear, short flagset) {
-    struct ifreq ifr;
-    int rc = 0;
-    int flags;
-    short flagmask = (~0 ^ flagclear);
-    int fd = socket(PF_PACKET, SOCK_DGRAM, 0);
-
-    if (fd < 0)
-        return errno;
-
-    if (virStrncpy(ifr.ifr_name,
-                   ifname, strlen(ifname), sizeof(ifr.ifr_name)) == NULL) {
-        rc = ENODEV;
-        goto err_exit;
-    }
-
-    if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
-        rc = errno;
-        goto err_exit;
-    }
-
-    flags = (ifr.ifr_flags & flagmask) | flagset;
-
-    if (ifr.ifr_flags != flags) {
-        ifr.ifr_flags = flags;
-
-        if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0)
-            rc = errno;
-    }
-
-err_exit:
-    close(fd);
-    return rc;
-}
-
-/*
- * ifUp
- * @name: name of the interface
- * @up: 1 for up, 0 for down
- *
- * Function to control if an interface is activated (up, 1) or not (down, 0)
- *
- * Returns 0 in case of success or an errno code in case of failure.
- */
-static int
-ifUp(const char *name, int up)
-{
-    return chgIfFlags(name,
-                      (up) ? 0      : IFF_UP,
-                      (up) ? IFF_UP : 0);
-}
-
-
-static int
 link_add(const char *type,
          const unsigned char *macaddress, int macaddrsize,
          const char *ifname,
@@ -314,7 +212,7 @@ link_add(const char *type,
     char *recvbuf = NULL;
     int recvbuflen;
 
-    if (getIfIndex(true, srcdev, &ifindex) != 0)
+    if (IfaceGetIndex(true, srcdev, &ifindex) != 0)
         return -1;
 
     *retry = 0;
@@ -708,7 +606,7 @@ openMacvtapTap(const char *tgifname,
     *res_ifname = NULL;
 
     if (tgifname) {
-        if(getIfIndex(false, tgifname, &ifindex) == 0) {
+        if(IfaceGetIndex(false, tgifname, &ifindex) == 0) {
             if (STRPREFIX(tgifname,
                           MACVTAP_NAME_PREFIX)) {
                 goto create_name;
@@ -727,7 +625,7 @@ create_name:
         retries = 5;
         for (c = 0; c < 8192; c++) {
             snprintf(ifname, sizeof(ifname), MACVTAP_NAME_PATTERN, c);
-            if (getIfIndex(false, ifname, &ifindex) == ENODEV) {
+            if (IfaceGetIndex(false, ifname, &ifindex) == ENODEV) {
                 rc = link_add(type, macaddress, 6, ifname, linkdev,
                               macvtapMode, &do_retry);
                 if (rc == 0)
@@ -741,7 +639,7 @@ create_name:
         cr_ifname = ifname;
     }
 
-    rc = ifUp(cr_ifname, 1);
+    rc = IfaceUp(cr_ifname);
     if (rc != 0) {
         virReportSystemError(errno,
                              _("cannot 'up' interface %s -- another "
Index: libvirt-acl/src/nwfilter/nwfilter_gentech_driver.h
===================================================================
--- libvirt-acl.orig/src/nwfilter/nwfilter_gentech_driver.h
+++ libvirt-acl/src/nwfilter/nwfilter_gentech_driver.h
@@ -63,6 +63,4 @@ void virNWFilterDomainFWUpdateCB(void *p
                                  const char *name ATTRIBUTE_UNUSED,
                                  void *data);
 
-int checkIf(const char *ifname, const unsigned char *macaddr);
-
 #endif




More information about the libvir-list mailing list