[ovs-dev] [PATCH] datapath: Fix mutual exclusion with bridge on Linux 2.6.27+.

Ben Pfaff blp at nicira.com
Fri Sep 11 22:49:54 UTC 2009


Linux 2.6.27 introduces a new mechanism for sharing STP packets among
kernel modules, which means that the code in datapath.c to avoid loading
when the Linux bridging module is also loaded has false positives.  So
fall back on these newer kernels to a less reliable way of avoiding the
bridge module, but one that does not have false positives.

CC: Jean Tourrihles <jt at hpl.hp.com>
---
 datapath/datapath.c |   47 +++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 41 insertions(+), 6 deletions(-)

diff --git a/datapath/datapath.c b/datapath/datapath.c
index 427391a..e460b16 100644
--- a/datapath/datapath.c
+++ b/datapath/datapath.c
@@ -1571,6 +1571,8 @@ struct file_operations openvswitch_fops = {
 };
 
 static int major;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
 static struct llc_sap *dp_stp_sap;
 
 static int dp_stp_rcv(struct sk_buff *skb, struct net_device *dev,
@@ -1583,12 +1585,8 @@ static int dp_stp_rcv(struct sk_buff *skb, struct net_device *dev,
 	return 0;
 }
 
-static int __init dp_init(void)
+static int dp_avoid_bridge_init(void)
 {
-	int err;
-
-	printk("Open vSwitch %s, built "__DATE__" "__TIME__"\n", VERSION BUILDNR);
-
 	/* Register to receive STP packets because the bridge module also
 	 * attempts to do so.  Since there can only be a single listener for a
 	 * given protocol, this provides mutual exclusion against the bridge
@@ -1599,6 +1597,43 @@ static int __init dp_init(void)
 		printk(KERN_ERR "openvswitch: can't register sap for STP (probably the bridge module is loaded)\n");
 		return -EADDRINUSE;
 	}
+	return 0;
+}
+
+static void dp_avoid_bridge_exit(void)
+{
+	llc_sap_put(dp_stp_sap);
+}
+#else  /* Linux 2.6.27 or later. */
+static int dp_avoid_bridge_init(void)
+{
+	/* Linux 2.6.27 introduces a way for multiple clients to register for
+	 * STP packets, which interferes with what we try to do above.
+	 * Instead, just check whether there's a bridge hook defined.  This is
+	 * not as safe--the bridge module is willing to load over the top of
+	 * us--but it provides a little bit of protection. */
+	if (br_handle_frame_hook) {
+		printk(KERN_ERR "openvswitch: bridge module is loaded, cannot load over it\n");
+		return -EADDRINUSE;
+	}
+	return 0;
+}
+
+static void dp_avoid_bridge_exit(void)
+{
+	/* Nothing to do. */
+}
+#endif	/* Linux 2.6.27 or later */
+
+static int __init dp_init(void)
+{
+	int err;
+
+	printk("Open vSwitch %s, built "__DATE__" "__TIME__"\n", VERSION BUILDNR);
+
+	err = dp_avoid_bridge_init();
+	if (err)
+		return err;
 
 	err = flow_init();
 	if (err)
@@ -1633,7 +1668,7 @@ static void dp_cleanup(void)
 	unregister_netdevice_notifier(&dp_device_notifier);
 	flow_exit();
 	br_handle_frame_hook = NULL;
-	llc_sap_put(dp_stp_sap);
+	dp_avoid_bridge_exit();
 }
 
 module_init(dp_init);
-- 
1.6.3.3





More information about the dev mailing list