All, For ovirt, we need the ability to have a bridge configured that is "plugged in" to an external interface; that is, the physical interface is one of the interfaces on the bridge. This allows us to manage physical hardware outside this box, since the ovirt WUI appliance will be hooked to this same bridge and will send/receive traffic to these external machines. Currently we are doing this "by hand" with scripts, which is clearly sub-optimal. This relatively simple patch adds a new "forward" type called "bridge" (yes, it's a bad name; I'm open to suggestions). Basically, when you have a bridge with this forward type, we take the "dev" that is specified (say, eth1), plug it into the bridge, and add the appropriate iptables rule to bridge traffic. With this in place, we can get rid of our hacky scripts and let libvirt do the dirty work for us. I also imagine this could be useful to support "xen-style" bridges, without necessarily using the Xen networking scripts. Comments? Signed-off-by: Chris Lalancette <clalance@xxxxxxxxxx>
Index: src/iptables.c =================================================================== RCS file: /data/cvs/libvirt/src/iptables.c,v retrieving revision 1.30 diff -u -r1.30 iptables.c --- a/src/iptables.c 8 Aug 2008 15:43:38 -0000 1.30 +++ b/src/iptables.c 28 Aug 2008 11:59:53 -0000 @@ -706,6 +706,26 @@ } +static int iptablesAllowBridge(iptablesContext *ctx, int action) +{ + return iptablesAddRemoveRule(ctx->forward_filter, action, + "--match", "physdev", + "!", "--physdev-is-bridged", + "--jump", "REJECT", + "--reject-with", "icmp-host-prohibited", + NULL); +} + +int iptablesAddAllowBridge(iptablesContext *ctx) +{ + return iptablesAllowBridge(ctx, ADD); +} + +int iptablesRemoveAllowBridge(iptablesContext *ctx) +{ + return iptablesAllowBridge(ctx, REMOVE); +} + /* Allow all traffic coming from the bridge, with a valid network address * to proceed to WAN */ Index: src/iptables.h =================================================================== RCS file: /data/cvs/libvirt/src/iptables.h,v retrieving revision 1.5 diff -u -r1.5 iptables.h --- a/src/iptables.h 10 Apr 2008 16:53:29 -0000 1.5 +++ b/src/iptables.h 28 Aug 2008 11:59:53 -0000 @@ -46,6 +46,8 @@ const char *iface, int port); +int iptablesAddAllowBridge (iptablesContext *ctx); +int iptablesRemoveAllowBridge (iptablesContext *ctx); int iptablesAddForwardAllowOut (iptablesContext *ctx, const char *network, const char *iface, Index: src/network_conf.c =================================================================== RCS file: /data/cvs/libvirt/src/network_conf.c,v retrieving revision 1.7 diff -u -r1.7 network_conf.c --- a/src/network_conf.c 20 Aug 2008 12:50:29 -0000 1.7 +++ b/src/network_conf.c 28 Aug 2008 11:59:53 -0000 @@ -46,7 +46,7 @@ VIR_ENUM_IMPL(virNetworkForward, VIR_NETWORK_FORWARD_LAST, - "none", "nat", "route" ) + "none", "nat", "route", "bridge" ) static void virNetworkReportError(virConnectPtr conn, int code, const char *fmt, ...) Index: src/network_conf.h =================================================================== RCS file: /data/cvs/libvirt/src/network_conf.h,v retrieving revision 1.2 diff -u -r1.2 network_conf.h --- a/src/network_conf.h 20 Aug 2008 12:50:29 -0000 1.2 +++ b/src/network_conf.h 28 Aug 2008 11:59:53 -0000 @@ -31,6 +31,7 @@ VIR_NETWORK_FORWARD_NONE = 0, VIR_NETWORK_FORWARD_NAT, VIR_NETWORK_FORWARD_ROUTE, + VIR_NETWORK_FORWARD_BRIDGE, VIR_NETWORK_FORWARD_LAST, }; Index: src/qemu_driver.c =================================================================== RCS file: /data/cvs/libvirt/src/qemu_driver.c,v retrieving revision 1.112 diff -u -r1.112 qemu_driver.c --- a/src/qemu_driver.c 27 Aug 2008 11:42:52 -0000 1.112 +++ b/src/qemu_driver.c 28 Aug 2008 11:59:54 -0000 @@ -1332,6 +1332,7 @@ struct qemud_driver *driver, virNetworkObjPtr network) { int err; + brControl *brctl = NULL; if (!driver->iptables && !(driver->iptables = iptablesContextNew())) { qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, @@ -1404,7 +1405,36 @@ else if (network->def->forwardType == VIR_NETWORK_FORWARD_ROUTE && !qemudAddRoutingIptablesRules(conn, driver, network)) goto err8; + else if (network->def->forwardType == VIR_NETWORK_FORWARD_BRIDGE) { + if (brInit(&brctl) != 0) { + qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, + _("failed to initialize bridge %s: %s"), + network->def->bridge, strerror(err)); + goto err8; + } + if ((err = brAddInterface(brctl, network->def->bridge, + network->def->forwardDev)) != 0) { + qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, + _("failed to add interface %s to bridge %s: %s"), + network->def->forwardDev, network->def->bridge, + strerror(err)); + brShutdown(brctl); + goto err8; + } + if ((err = iptablesAddAllowBridge(driver->iptables)) != 0) { + brDeleteInterface(brctl, network->def->bridge, + network->def->forwardDev); + qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, + _("failed to add iptables rule to allow bridging from '%s' : %s\n"), + network->def->bridge, strerror(err)); + brShutdown(brctl); + goto err8; + } + + brShutdown(brctl); + } + iptablesSaveRules(driver->iptables); return 1; @@ -1433,6 +1463,8 @@ static void qemudRemoveIptablesRules(struct qemud_driver *driver, virNetworkObjPtr network) { + brControl *brctl = NULL; + if (network->def->forwardType != VIR_NETWORK_FORWARD_NONE) { iptablesRemoveForwardMasquerade(driver->iptables, network->def->network, @@ -1448,6 +1480,14 @@ network->def->network, network->def->bridge, network->def->forwardDev); + else if (network->def->forwardType == VIR_NETWORK_FORWARD_BRIDGE) { + iptablesRemoveAllowBridge(driver->iptables); + if (brInit(&brctl) == 0) { + brDeleteInterface(brctl, network->def->bridge, + network->def->forwardDev); + brShutdown(brctl); + } + } iptablesRemoveForwardAllowOut(driver->iptables, network->def->network,
-- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list