Commit 7c85fbf0 authored by Patrick McHardy's avatar Patrick McHardy Committed by David S. Miller

bridge: Use STP demux

Use the STP demux layer for receiving STP PDUs instead of directly
registering with LLC.
Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a19800d7
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
config BRIDGE config BRIDGE
tristate "802.1d Ethernet Bridging" tristate "802.1d Ethernet Bridging"
select LLC select LLC
select STP
---help--- ---help---
If you say Y here, then your Linux box will be able to act as an If you say Y here, then your Linux box will be able to act as an
Ethernet bridge, which means that the different Ethernet segments it Ethernet bridge, which means that the different Ethernet segments it
......
...@@ -18,21 +18,24 @@ ...@@ -18,21 +18,24 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/llc.h> #include <linux/llc.h>
#include <net/llc.h> #include <net/llc.h>
#include <net/stp.h>
#include "br_private.h" #include "br_private.h"
int (*br_should_route_hook)(struct sk_buff *skb); int (*br_should_route_hook)(struct sk_buff *skb);
static struct llc_sap *br_stp_sap; static const struct stp_proto br_stp_proto = {
.rcv = br_stp_rcv,
};
static int __init br_init(void) static int __init br_init(void)
{ {
int err; int err;
br_stp_sap = llc_sap_open(LLC_SAP_BSPAN, br_stp_rcv); err = stp_proto_register(&br_stp_proto);
if (!br_stp_sap) { if (err < 0) {
printk(KERN_ERR "bridge: can't register sap for STP\n"); printk(KERN_ERR "bridge: can't register sap for STP\n");
return -EADDRINUSE; return err;
} }
err = br_fdb_init(); err = br_fdb_init();
...@@ -65,13 +68,13 @@ static int __init br_init(void) ...@@ -65,13 +68,13 @@ static int __init br_init(void)
err_out1: err_out1:
br_fdb_fini(); br_fdb_fini();
err_out: err_out:
llc_sap_put(br_stp_sap); stp_proto_unregister(&br_stp_proto);
return err; return err;
} }
static void __exit br_deinit(void) static void __exit br_deinit(void)
{ {
rcu_assign_pointer(br_stp_sap->rcv_func, NULL); stp_proto_unregister(&br_stp_proto);
br_netlink_fini(); br_netlink_fini();
unregister_netdevice_notifier(&br_device_notifier); unregister_netdevice_notifier(&br_device_notifier);
...@@ -82,7 +85,6 @@ static void __exit br_deinit(void) ...@@ -82,7 +85,6 @@ static void __exit br_deinit(void)
synchronize_net(); synchronize_net();
br_netfilter_fini(); br_netfilter_fini();
llc_sap_put(br_stp_sap);
br_fdb_get_hook = NULL; br_fdb_get_hook = NULL;
br_fdb_put_hook = NULL; br_fdb_put_hook = NULL;
......
...@@ -226,8 +226,9 @@ extern void br_stp_set_path_cost(struct net_bridge_port *p, ...@@ -226,8 +226,9 @@ extern void br_stp_set_path_cost(struct net_bridge_port *p,
extern ssize_t br_show_bridge_id(char *buf, const struct bridge_id *id); extern ssize_t br_show_bridge_id(char *buf, const struct bridge_id *id);
/* br_stp_bpdu.c */ /* br_stp_bpdu.c */
extern int br_stp_rcv(struct sk_buff *skb, struct net_device *dev, struct stp_proto;
struct packet_type *pt, struct net_device *orig_dev); extern void br_stp_rcv(const struct stp_proto *proto, struct sk_buff *skb,
struct net_device *dev);
/* br_stp_timer.c */ /* br_stp_timer.c */
extern void br_stp_timer_init(struct net_bridge *br); extern void br_stp_timer_init(struct net_bridge *br);
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <net/net_namespace.h> #include <net/net_namespace.h>
#include <net/llc.h> #include <net/llc.h>
#include <net/llc_pdu.h> #include <net/llc_pdu.h>
#include <net/stp.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
#include "br_private.h" #include "br_private.h"
...@@ -131,10 +132,9 @@ void br_send_tcn_bpdu(struct net_bridge_port *p) ...@@ -131,10 +132,9 @@ void br_send_tcn_bpdu(struct net_bridge_port *p)
* *
* NO locks, but rcu_read_lock (preempt_disabled) * NO locks, but rcu_read_lock (preempt_disabled)
*/ */
int br_stp_rcv(struct sk_buff *skb, struct net_device *dev, void br_stp_rcv(const struct stp_proto *proto, struct sk_buff *skb,
struct packet_type *pt, struct net_device *orig_dev) struct net_device *dev)
{ {
const struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
const unsigned char *dest = eth_hdr(skb)->h_dest; const unsigned char *dest = eth_hdr(skb)->h_dest;
struct net_bridge_port *p = rcu_dereference(dev->br_port); struct net_bridge_port *p = rcu_dereference(dev->br_port);
struct net_bridge *br; struct net_bridge *br;
...@@ -146,11 +146,6 @@ int br_stp_rcv(struct sk_buff *skb, struct net_device *dev, ...@@ -146,11 +146,6 @@ int br_stp_rcv(struct sk_buff *skb, struct net_device *dev,
if (!p) if (!p)
goto err; goto err;
if (pdu->ssap != LLC_SAP_BSPAN
|| pdu->dsap != LLC_SAP_BSPAN
|| pdu->ctrl_1 != LLC_PDU_TYPE_U)
goto err;
if (!pskb_may_pull(skb, 4)) if (!pskb_may_pull(skb, 4))
goto err; goto err;
...@@ -224,5 +219,4 @@ int br_stp_rcv(struct sk_buff *skb, struct net_device *dev, ...@@ -224,5 +219,4 @@ int br_stp_rcv(struct sk_buff *skb, struct net_device *dev,
spin_unlock(&br->lock); spin_unlock(&br->lock);
err: err:
kfree_skb(skb); kfree_skb(skb);
return 0;
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment