[PATCH 3/7 rhel6-branch] bonding support: boot option

Radek Vykydal rvykydal at redhat.com
Mon Aug 27 08:46:35 UTC 2012


bond=bond0:eth0,eth1:mode=active-backup,primary=eth1
(as in dracut)
---
 isys/iface.c        |    2 +
 isys/iface.h        |    4 ++
 loader/loader.c     |   45 +++++++++++++++---
 loader/loader.h     |    2 +
 loader/loadermisc.c |   13 +++++
 loader/loadermisc.h |    1 +
 loader/net.c        |  128 +++++++++++++++++++++++++++++++++++++++++++++++++--
 loader/net.h        |    3 +
 8 files changed, 186 insertions(+), 12 deletions(-)

diff --git a/isys/iface.c b/isys/iface.c
index 64a7663..0e80144 100644
--- a/isys/iface.c
+++ b/isys/iface.c
@@ -386,6 +386,8 @@ void iface_init_iface_t(iface_t *iface) {
     iface->ipv4method = IPV4_UNUSED_METHOD;
     iface->ipv6method = IPV6_UNUSED_METHOD;
     iface->defroute = 1;
+    iface->bonding_slaves = NULL;
+    iface->bonding_opts = NULL;
 
     return;
 }
diff --git a/isys/iface.h b/isys/iface.h
index 933ac84..f08b751 100644
--- a/isys/iface.h
+++ b/isys/iface.h
@@ -56,6 +56,10 @@ typedef struct _iface_t {
     /* MAC address as xx:xx:xx:xx:xx:xx */
     char *macaddr;
 
+    /* bonding support */
+    char *bonding_slaves;
+    char *bonding_opts;
+
     /* IPv4 (store addresses in in_addr format, use inet_pton() to display) */
     struct in_addr ipaddr;
     struct in_addr netmask;
diff --git a/loader/loader.c b/loader/loader.c
index 926cecc..2d3c7f5 100644
--- a/loader/loader.c
+++ b/loader/loader.c
@@ -706,6 +706,8 @@ static void readNetInfo(struct loaderData_s ** ld) {
     loaderData->ipv6prefix = NULL;
     loaderData->gateway6 = NULL;
 #endif
+    loaderData->bonding_slaves = NULL;
+    loaderData->bonding_opts = NULL;
 
     /*
      * The ifcfg file is written out by /sbin/init on s390x (which is
@@ -884,6 +886,36 @@ static void parseCmdLineIpv6(struct loaderData_s * loaderData, char *argv)
 }
 #endif
 
+/*
+ * parse bond=<bondname>:<bondslaves>[:<options>]
+ *
+ * dracut option syntax
+ *
+ * bondslaves separated with ',': eth0,eth1
+ * options separated with ',' or with ';' if ',' is used in option
+ */
+static int parseCmdLineBond(struct loaderData_s * loaderData, char *argv)
+{
+    if (split_bond_option(argv+5,
+                          &(loaderData->netDev),
+                          &(loaderData->bonding_slaves),
+                          &(loaderData->bonding_opts))) {
+        if (loaderData->bonding_opts) {
+            if (strchr(loaderData->bonding_opts, ';')) {
+                replaceChars(loaderData->bonding_opts, ';', ' ');
+            } else {
+                replaceChars(loaderData->bonding_opts, ',', ' ');
+            }
+        }
+        loaderData->netDev_set = 1;
+        return 1;
+    } else {
+        logMessage(WARNING, "parseCmdLineBond could not parse %s", argv);
+        return 0;
+    }
+
+}
+
 static long argToLong(char *arg, int offset) {
     long retval;
 
@@ -913,7 +945,6 @@ static void parseCmdLineFlags(struct loaderData_s * loaderData,
     GError *optErr = NULL;
     int numExtraArgs = 0;
     int i;
-    char *front;
 
     /* we want to default to graphical and allow override with 'text' */
     flags |= LOADER_FLAGS_GRAPHICAL;
@@ -1044,13 +1075,8 @@ static void parseCmdLineFlags(struct loaderData_s * loaderData,
             loaderData->bootIf = strdup(argv[i] + 10);
 
             /* scan the BOOTIF value and replace '-' with ':' */
-            front = loaderData->bootIf;
-            if (front) {
-                while (*front != '\0') {
-                    if (*front == '-')
-                        *front = ':';
-                    front++;
-                }
+            if (loaderData->bootIf) {
+                replaceChars(loaderData->bootIf, '-', ':');
             }
 
             loaderData->bootIf_set = 1;
@@ -1101,6 +1127,9 @@ static void parseCmdLineFlags(struct loaderData_s * loaderData,
             loaderData->essid = strdup(argv[i] + 6);
         else if (!strncasecmp(argv[i], "mtu=", 4))
             loaderData->mtu = argToLong(argv[i], 4);
+        else if (!strncasecmp(argv[i], "bond=", 5))
+            /* overrides ksdevice setting */
+            parseCmdLineBond(loaderData, argv[i]);
         else if (!strncasecmp(argv[i], "wepkey=", 7))
             loaderData->wepkey = strdup(argv[i] + 7);
         else if (!strncasecmp(argv[i], "linksleep=", 10))
diff --git a/loader/loader.h b/loader/loader.h
index 44eca6e..f958533 100644
--- a/loader/loader.h
+++ b/loader/loader.h
@@ -145,6 +145,8 @@ struct loaderData_s {
     int mtu;
     int noDns;
     int dhcpTimeout;
+    char * bonding_slaves;
+    char * bonding_opts;
     int ipinfo_set;
     char * ksFile;
     int method;
diff --git a/loader/loadermisc.c b/loader/loadermisc.c
index 55b4520..5da8580 100644
--- a/loader/loadermisc.c
+++ b/loader/loadermisc.c
@@ -142,3 +142,16 @@ guint64 totalMemory(void) {
     g_strfreev(lines);
     return total;
 }
+
+int replaceChars(char *str, char old, char new) {
+    char *pos = str;
+    int count = 0;
+    while (*pos != '\0') {
+        if (*pos == old) {
+            *pos = new;
+            count++;
+        }
+        pos++;
+    }
+    return count;
+}
diff --git a/loader/loadermisc.h b/loader/loadermisc.h
index 5f8b068..c07867a 100644
--- a/loader/loadermisc.h
+++ b/loader/loadermisc.h
@@ -32,5 +32,6 @@ int copyFileFd(int infd, char * dest, progressCB pbcb,
                struct progressCBdata *data, long long total);
 int simpleStringCmp(const void * a, const void * b);
 guint64 totalMemory(void);
+int replaceChars(char *str, char old, char new);
 
 #endif
diff --git a/loader/net.c b/loader/net.c
index 17c91ac..23aa86a 100644
--- a/loader/net.c
+++ b/loader/net.c
@@ -259,6 +259,21 @@ int split_ipv6addr_prefix_length(char *str, char **address, char **prefix) {
     return rc;
 }
 
+int split_bond_option(char *str, char **bondname, char **bondslaves, char **options) {
+    gchar **elements = g_strsplit(str, ":", 3);
+    int rc = 0;
+
+    if (elements[0] && elements[1]) {
+        *bondname = strdup(elements[0]);
+        *bondslaves = strdup(elements[1]);
+        if (elements[2]) {
+            *options = strdup(elements[2]);
+        }
+        rc = 1;
+    }
+    g_strfreev(elements);
+    return rc;
+}
 
 /* given loader data from kickstart, populate network configuration struct */
 void setupIfaceStruct(iface_t * iface, struct loaderData_s * loaderData) {
@@ -404,6 +419,13 @@ void setupIfaceStruct(iface_t * iface, struct loaderData_s * loaderData) {
         iface->mtu = loaderData->mtu;
     }
 
+    if (loaderData->bonding_slaves) {
+        iface->bonding_slaves = strdup(loaderData->bonding_slaves);
+        if (loaderData->bonding_opts) {
+            iface->bonding_opts = strdup(loaderData->bonding_opts);
+        }
+    }
+
     if (loaderData->peerid) {
         iface->peerid = strdup(loaderData->peerid);
     }
@@ -1156,6 +1178,21 @@ int manualNetConfig(char * device, iface_t * iface,
     return LOADER_OK;
 }
 
+int networkDeviceExists(char *name) {
+    int i = 0;
+    struct device **devs = NULL;
+
+    devs = getDevices(DEVICE_NETWORK);
+
+    for (i = 0; devs && devs[i]; i++) {
+        if (!strcmp(name, devs[i]->device)) {
+            return 1;
+        }
+    }
+
+    return 0;
+}
+
 /*
  * By default, we disable all network interfaces and then only
  * bring up the ones the user wants.
@@ -1348,15 +1385,24 @@ int writeEnabledNetInfo(iface_t *iface) {
 
     fprintf(fp, "DEVICE=%s\n", iface->device);
 #if !defined(__s390__) && !defined(__s390x__)
-    fprintf(fp, "HWADDR=%s\n", iface_mac2str(iface->device));
+    if (!iface->bonding_slaves) {
+        fprintf(fp, "HWADDR=%s\n", iface_mac2str(iface->device));
+    }
 #endif
     uuid = nm_utils_uuid_generate();
     fprintf(fp, "UUID=%s\n", uuid);
     g_free(uuid);
     fprintf(fp, "ONBOOT=yes\n");
-    char *str_type = netArpTypeStr(iface->device);
-    if (str_type) fprintf(fp, "TYPE=%s\n", str_type);
-    free(str_type);
+    if (iface->bonding_slaves) {
+	fprintf(fp, "TYPE=Bond\n");
+	if (iface->bonding_opts) {
+	    fprintf(fp, "BONDING_OPTS=\"%s\"\n", iface->bonding_opts);
+	}
+    } else {
+        char *str_type = netArpTypeStr(iface->device);
+        if (str_type) fprintf(fp, "TYPE=%s\n", str_type);
+        free(str_type);
+    }
 
     if (!FL_NOIPV4(flags)) {
         if (iface->ipv4method == IPV4_IBFT_METHOD) {
@@ -1513,6 +1559,24 @@ int writeEnabledNetInfo(iface_t *iface) {
         return 8;
     }
 
+    if (iface->bonding_slaves) {
+        gchar **slaves = NULL;
+        int i;
+
+        if ((slaves = g_strsplit(iface->bonding_slaves, ",", 0)) != NULL) {
+            for (i=0; i < g_strv_length(slaves); i++) {
+                if (slaves[i] != NULL && g_strcmp0(slaves[i], "")) {
+                    if (networkDeviceExists(slaves[i])) {
+                        writeBondSlaveIfcfgFile(slaves[i], iface->device);
+                    } else {
+                        logMessage(WARNING, "bond slave device %s does not exist", slaves[i]);
+                    }
+                }
+            }
+            g_strfreev(slaves);
+        }
+    }
+
     if (rename(ofile, nfile) == -1) {
         free(ofile);
         free(nfile);
@@ -1598,6 +1662,57 @@ int enable_NM_BOND_VLAN() {
 
 }
 
+int writeBondSlaveIfcfgFile(char *slave, char *master) {
+    char *ofile = NULL;
+    char *nfile = NULL;
+    FILE *fp = NULL;
+    char *uuid = NULL;
+
+    checked_asprintf(&ofile, "%s/.ifcfg-%s",
+                     NETWORK_SCRIPTS_PATH,
+                     slave);
+    checked_asprintf(&nfile, "%s/ifcfg-%s",
+                     NETWORK_SCRIPTS_PATH,
+                     slave);
+
+    if ((fp = fopen(ofile, "w")) == NULL) {
+        free(ofile);
+        return 2;
+    }
+
+    fprintf(fp, "DEVICE=%s\n", slave);
+    fprintf(fp, "HWADDR=%s\n", iface_mac2str(slave));
+    uuid = nm_utils_uuid_generate();
+    fprintf(fp, "SLAVE=yes\n");
+    fprintf(fp, "MASTER=%s\n", master);
+    fprintf(fp, "UUID=%s\n", uuid);
+    g_free(uuid);
+    fprintf(fp, "ONBOOT=yes\n");
+    fprintf(fp, "NM_CONTROLLED=yes\n");
+
+    if (fclose(fp) == EOF) {
+        return 3;
+    }
+
+    if (rename(ofile, nfile) == -1) {
+        free(ofile);
+        free(nfile);
+        return 4;
+    }
+
+    if (ofile) {
+        free(ofile);
+        ofile = NULL;
+    }
+
+    if (nfile) {
+        free(nfile);
+        nfile = NULL;
+    }
+
+    return 0;
+}
+
 void setKickstartNetwork(struct loaderData_s * loaderData, int argc, 
                          char ** argv) {
     iface_t iface;
@@ -1826,6 +1941,11 @@ int chooseNetworkInterface(struct loaderData_s * loaderData) {
                                    {NULL, NULL, 0 }};
     extern int num_link_checks;
 
+    if (loaderData->bonding_slaves) {
+        logMessage(INFO, "bonded device %s chosen", loaderData->netDev);
+        return LOADER_NOOP;
+    }
+
     devs = getDevices(DEVICE_NETWORK);
     if (!devs) {
         logMessage(ERROR, "no network devices in choose network device!");
diff --git a/loader/net.h b/loader/net.h
index 99ae23e..c95ef77 100644
--- a/loader/net.h
+++ b/loader/net.h
@@ -87,5 +87,8 @@ int wait_for_iface_disconnection(char *ifname);
 int isURLRemote(char *url);
 int split_ipv6addr_prefix_length(char *str, char **address, char **prefix);
 int enable_NM_BOND_VLAN(void);
+int split_bond_option(char *str, char **bondname, char **bondslaves, char **options);
+int networkDeviceExists(char *name);
+int writeBondSlaveIfcfgFile(char *slave, char *master);
 
 #endif
-- 
1.7.4



More information about the anaconda-patches mailing list