#include <linux/etherdevice.h>
#include <linux/kernel.h>
#include <linux/kthread.h>
+#include <linux/llc.h>
#include <linux/mutex.h>
#include <linux/percpu.h>
#include <linux/rcupdate.h>
#include <linux/rculist.h>
#include <linux/workqueue.h>
#include <linux/dmi.h>
+#include <net/llc.h>
#include "openvswitch/datapath-protocol.h"
#include "datapath.h"
};
static int major;
+static struct llc_sap *dp_stp_sap;
+
+static int dp_stp_rcv(struct sk_buff *skb, struct net_device *dev,
+ struct packet_type *pt, struct net_device *orig_dev)
+{
+ /* We don't really care about STP packets, we just listen for them for
+ * mutual exclusion with the bridge module, so this just discards
+ * them. */
+ kfree_skb(skb);
+ return 0;
+}
static int __init dp_init(void)
{
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
+ * module, preventing both of them from being loaded at the same
+ * time. */
+ dp_stp_sap = llc_sap_open(LLC_SAP_BSPAN, dp_stp_rcv);
+ if (!dp_stp_sap) {
+ printk(KERN_ERR "openvswitch: can't register sap for STP (probably the bridge module is loaded)\n");
+ return -EADDRINUSE;
+ }
+
err = flow_init();
if (err)
goto error;
/* Hook into callback used by the bridge to intercept packets.
* Parasites we are. */
- rtnl_lock();
- if (br_handle_frame_hook) {
- struct net_device *dev;
- for_each_netdev (&init_net, dev) {
- if (!dev->br_port)
- continue;
-
- rtnl_unlock();
- printk("openvswitch: must delete bridges "
- "before loading\n");
- err = -EBUSY;
- goto error_unreg_notifier;
- }
- printk("openvswitch: hijacking bridge hook\n");
- }
br_handle_frame_hook = dp_frame_hook;
- rtnl_unlock();
return 0;
unregister_netdevice_notifier(&dp_device_notifier);
flow_exit();
br_handle_frame_hook = NULL;
+ llc_sap_put(dp_stp_sap);
}
module_init(dp_init);