bridge: Use STP demux

Use the STP demux layer for receiving STP PDUs instead of directly
registering with LLC.

Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Patrick McHardy 2008-07-05 21:25:56 -07:00 committed by David S. Miller
parent a19800d704
commit 7c85fbf065
4 changed files with 16 additions and 18 deletions

View file

@ -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

View file

@ -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 @@ err_out2:
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)
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;

View file

@ -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);

View file

@ -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)
* *
* 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,
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,
spin_unlock(&br->lock); spin_unlock(&br->lock);
err: err:
kfree_skb(skb); kfree_skb(skb);
return 0;
} }