[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCH]: Allow libvirt to manage bridges "plugged into" physical devices



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 redhat com>
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,

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]