+Mon Mar 2 12:34:25 EST 2009 Cole Robinson <crobinso@redhat.com>
+
+ * src/bridge.c src/bridge.h src/libvirt_private.syms src/network_conf.c
+ src/network_conf.h src/network_driver.c:
+ Generate network bridge names if none passed at define/create time.
+
Mon Mar 2 12:30:08 EST 2009 Cole Robinson <crobinso@redhat.com>
* src/domain_conf.c src/domain_conf.h src/qemu_driver.c:
#include "util.h"
#include "logging.h"
-#define MAX_BRIDGE_ID 256
+#define MAX_TAP_ID 256
#define JIFFIES_TO_MS(j) (((j)*1000)/HZ)
#define MS_TO_JIFFIES(ms) (((ms)*HZ)/1000)
#ifdef SIOCBRADDBR
int
brAddBridge(brControl *ctl,
- char **name)
+ const char *name)
{
if (!ctl || !ctl->fd || !name)
return EINVAL;
- if (*name) {
- if (ioctl(ctl->fd, SIOCBRADDBR, *name) == 0)
- return 0;
- } else {
- int id = 0;
- do {
- char try[50];
-
- snprintf(try, sizeof(try), "virbr%d", id);
-
- if (ioctl(ctl->fd, SIOCBRADDBR, try) == 0) {
- if (!(*name = strdup(try))) {
- ioctl(ctl->fd, SIOCBRDELBR, name);
- return ENOMEM;
- }
- return 0;
- }
-
- id++;
- } while (id < MAX_BRIDGE_ID);
- }
+ if (ioctl(ctl->fd, SIOCBRADDBR, name) == 0)
+ return 0;
return errno;
}
}
id++;
- } while (subst && id <= MAX_BRIDGE_ID);
+ } while (subst && id <= MAX_TAP_ID);
error:
close(fd);
void brShutdown (brControl *ctl);
int brAddBridge (brControl *ctl,
- char **name);
+ const char *name);
int brDeleteBridge (brControl *ctl,
const char *name);
int brHasBridge (brControl *ctl,
virNetworkDefParseNode;
virNetworkRemoveInactive;
virNetworkSaveConfig;
+virNetworkSetBridgeName;
virNetworkObjLock;
virNetworkObjUnlock;
#include "buf.h"
#include "c-ctype.h"
+#define MAX_BRIDGE_ID 256
#define VIR_FROM_THIS VIR_FROM_NETWORK
VIR_ENUM_DECL(virNetworkForward)
goto error;
}
+ /* Generate a bridge if none is found, but don't check for collisions
+ * if a bridge is hardcoded, so the network is at least defined
+ */
+ if (!def->bridge && !(def->bridge = virNetworkAllocateBridge(conn, nets)))
+ goto error;
+
if (!(net = virNetworkAssignDef(conn, nets, def)))
goto error;
return ret;
}
+int virNetworkBridgeInUse(const virNetworkObjListPtr nets,
+ const char *bridge,
+ const char *skipname)
+{
+ unsigned int i;
+ unsigned int ret = 0;
+
+ for (i = 0 ; i < nets->count ; i++) {
+ virNetworkObjLock(nets->objs[i]);
+ if (nets->objs[i]->def->bridge &&
+ STREQ(nets->objs[i]->def->bridge, bridge) &&
+ !(skipname && STREQ(nets->objs[i]->def->name, skipname)))
+ ret = 1;
+ virNetworkObjUnlock(nets->objs[i]);
+ }
+
+ return ret;
+}
+
+char *virNetworkAllocateBridge(virConnectPtr conn,
+ const virNetworkObjListPtr nets)
+{
+
+ int id = 0;
+ char *newname;
+
+ do {
+ char try[50];
+
+ snprintf(try, sizeof(try), "virbr%d", id);
+
+ if (!virNetworkBridgeInUse(nets, try, NULL)) {
+ if (!(newname = strdup(try))) {
+ virReportOOMError(conn);
+ return NULL;
+ }
+ return newname;
+ }
+
+ id++;
+ } while (id < MAX_BRIDGE_ID);
+
+ virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR,
+ _("Bridge generation exceeded max id %d"),
+ MAX_BRIDGE_ID);
+ return NULL;
+}
+
+int virNetworkSetBridgeName(virConnectPtr conn,
+ const virNetworkObjListPtr nets,
+ virNetworkDefPtr def) {
+
+ int ret = -1;
+
+ if (def->bridge) {
+ if (virNetworkBridgeInUse(nets, def->bridge, def->name)) {
+ networkReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+ _("bridge name '%s' already in use."),
+ def->bridge);
+ goto error;
+ }
+ } else {
+ /* Allocate a bridge name */
+ if (!(def->bridge = virNetworkAllocateBridge(conn, nets)))
+ goto error;
+ }
+
+ ret = 0;
+error:
+ return ret;
+}
void virNetworkObjLock(virNetworkObjPtr obj)
{
return net->active;
}
+#define networkReportError(conn, dom, net, code, fmt...) \
+ virReportErrorHelper(conn, VIR_FROM_QEMU, code, __FILE__, \
+ __FUNCTION__, __LINE__, fmt)
+
virNetworkObjPtr virNetworkFindByUUID(const virNetworkObjListPtr nets,
const unsigned char *uuid);
const char *dir,
const char *name);
+int virNetworkBridgeInUse(const virNetworkObjListPtr nets,
+ const char *bridge,
+ const char *skipname);
+
+char *virNetworkAllocateBridge(virConnectPtr conn,
+ const virNetworkObjListPtr nets);
+
+int virNetworkSetBridgeName(virConnectPtr conn,
+ const virNetworkObjListPtr nets,
+ virNetworkDefPtr def);
void virNetworkObjLock(virNetworkObjPtr obj);
void virNetworkObjUnlock(virNetworkObjPtr obj);
#define networkLog(level, msg...) fprintf(stderr, msg)
-#define networkReportError(conn, dom, net, code, fmt...) \
- virReportErrorHelper(conn, VIR_FROM_QEMU, code, __FILE__, \
- __FUNCTION__, __LINE__, fmt)
-
-
static int networkStartNetworkDaemon(virConnectPtr conn,
struct network_driver *driver,
virNetworkObjPtr network);
return -1;
}
- if ((err = brAddBridge(driver->brctl, &network->def->bridge))) {
+ if ((err = brAddBridge(driver->brctl, network->def->bridge))) {
virReportSystemError(conn, err,
_("cannot create bridge '%s'"),
network->def->bridge);
if (!(def = virNetworkDefParseString(conn, xml)))
goto cleanup;
+ if (virNetworkSetBridgeName(conn, &driver->networks, def))
+ goto cleanup;
+
if (!(network = virNetworkAssignDef(conn,
&driver->networks,
def)))
if (!(def = virNetworkDefParseString(conn, xml)))
goto cleanup;
+ if (virNetworkSetBridgeName(conn, &driver->networks, def))
+ goto cleanup;
+
if (!(network = virNetworkAssignDef(conn,
&driver->networks,
def)))