[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