Skip to content

Commit

Permalink
[BRIDGE]: use LLC to send STP
Browse files Browse the repository at this point in the history
The bridge code can use existing LLC output code when building
spanning tree protocol packets.

Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Stephen Hemminger authored and David S. Miller committed Mar 21, 2006
1 parent f4ad2b1 commit 12ac84c
Showing 1 changed file with 59 additions and 69 deletions.
128 changes: 59 additions & 69 deletions net/bridge/br_stp_bpdu.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,43 +17,39 @@
#include <linux/netfilter_bridge.h>
#include <linux/etherdevice.h>
#include <linux/llc.h>
#include <net/llc.h>
#include <net/llc_pdu.h>

#include "br_private.h"
#include "br_private_stp.h"

#define STP_HZ 256

static void br_send_bpdu(struct net_bridge_port *p, unsigned char *data, int length)
#define LLC_RESERVE sizeof(struct llc_pdu_un)

static void br_send_bpdu(struct net_bridge_port *p,
const unsigned char *data, int length)
{
struct net_device *dev;
struct sk_buff *skb;
int size;

if (!p->br->stp_enabled)
return;

size = length + 2*ETH_ALEN + 2;
if (size < 60)
size = 60;

dev = p->dev;

if ((skb = dev_alloc_skb(size)) == NULL) {
printk(KERN_INFO "br: memory squeeze!\n");
skb = dev_alloc_skb(length+LLC_RESERVE);
if (!skb)
return;
}

skb->dev = dev;
skb->dev = p->dev;
skb->protocol = htons(ETH_P_802_2);
skb->mac.raw = skb_put(skb, size);
memcpy(skb->mac.raw, p->br->group_addr, ETH_ALEN);
memcpy(skb->mac.raw+ETH_ALEN, dev->dev_addr, ETH_ALEN);
skb->mac.raw[2*ETH_ALEN] = 0;
skb->mac.raw[2*ETH_ALEN+1] = length;
skb->nh.raw = skb->mac.raw + 2*ETH_ALEN + 2;
memcpy(skb->nh.raw, data, length);
memset(skb->nh.raw + length, 0xa5, size - length - 2*ETH_ALEN - 2);

skb_reserve(skb, LLC_RESERVE);
memcpy(__skb_put(skb, length), data, length);

llc_pdu_header_init(skb, LLC_PDU_TYPE_U, LLC_SAP_BSPAN,
LLC_SAP_BSPAN, LLC_PDU_CMD);
llc_pdu_init_as_ui_cmd(skb);

llc_mac_hdr_init(skb, p->dev->dev_addr, p->br->group_addr);

NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev,
dev_queue_xmit);
Expand All @@ -76,60 +72,54 @@ static inline int br_get_ticks(const unsigned char *src)
/* called under bridge lock */
void br_send_config_bpdu(struct net_bridge_port *p, struct br_config_bpdu *bpdu)
{
unsigned char buf[38];

buf[0] = 0x42;
buf[1] = 0x42;
buf[2] = 0x03;
buf[3] = 0;
buf[4] = 0;
buf[5] = 0;
buf[6] = BPDU_TYPE_CONFIG;
buf[7] = (bpdu->topology_change ? 0x01 : 0) |
unsigned char buf[35];

buf[0] = 0;
buf[1] = 0;
buf[2] = 0;
buf[3] = BPDU_TYPE_CONFIG;
buf[4] = (bpdu->topology_change ? 0x01 : 0) |
(bpdu->topology_change_ack ? 0x80 : 0);
buf[8] = bpdu->root.prio[0];
buf[9] = bpdu->root.prio[1];
buf[10] = bpdu->root.addr[0];
buf[11] = bpdu->root.addr[1];
buf[12] = bpdu->root.addr[2];
buf[13] = bpdu->root.addr[3];
buf[14] = bpdu->root.addr[4];
buf[15] = bpdu->root.addr[5];
buf[16] = (bpdu->root_path_cost >> 24) & 0xFF;
buf[17] = (bpdu->root_path_cost >> 16) & 0xFF;
buf[18] = (bpdu->root_path_cost >> 8) & 0xFF;
buf[19] = bpdu->root_path_cost & 0xFF;
buf[20] = bpdu->bridge_id.prio[0];
buf[21] = bpdu->bridge_id.prio[1];
buf[22] = bpdu->bridge_id.addr[0];
buf[23] = bpdu->bridge_id.addr[1];
buf[24] = bpdu->bridge_id.addr[2];
buf[25] = bpdu->bridge_id.addr[3];
buf[26] = bpdu->bridge_id.addr[4];
buf[27] = bpdu->bridge_id.addr[5];
buf[28] = (bpdu->port_id >> 8) & 0xFF;
buf[29] = bpdu->port_id & 0xFF;

br_set_ticks(buf+30, bpdu->message_age);
br_set_ticks(buf+32, bpdu->max_age);
br_set_ticks(buf+34, bpdu->hello_time);
br_set_ticks(buf+36, bpdu->forward_delay);

br_send_bpdu(p, buf, 38);
buf[5] = bpdu->root.prio[0];
buf[6] = bpdu->root.prio[1];
buf[7] = bpdu->root.addr[0];
buf[8] = bpdu->root.addr[1];
buf[9] = bpdu->root.addr[2];
buf[10] = bpdu->root.addr[3];
buf[11] = bpdu->root.addr[4];
buf[12] = bpdu->root.addr[5];
buf[13] = (bpdu->root_path_cost >> 24) & 0xFF;
buf[14] = (bpdu->root_path_cost >> 16) & 0xFF;
buf[15] = (bpdu->root_path_cost >> 8) & 0xFF;
buf[16] = bpdu->root_path_cost & 0xFF;
buf[17] = bpdu->bridge_id.prio[0];
buf[18] = bpdu->bridge_id.prio[1];
buf[19] = bpdu->bridge_id.addr[0];
buf[20] = bpdu->bridge_id.addr[1];
buf[21] = bpdu->bridge_id.addr[2];
buf[22] = bpdu->bridge_id.addr[3];
buf[23] = bpdu->bridge_id.addr[4];
buf[24] = bpdu->bridge_id.addr[5];
buf[25] = (bpdu->port_id >> 8) & 0xFF;
buf[26] = bpdu->port_id & 0xFF;

br_set_ticks(buf+27, bpdu->message_age);
br_set_ticks(buf+29, bpdu->max_age);
br_set_ticks(buf+31, bpdu->hello_time);
br_set_ticks(buf+33, bpdu->forward_delay);

br_send_bpdu(p, buf, 35);
}

/* called under bridge lock */
void br_send_tcn_bpdu(struct net_bridge_port *p)
{
unsigned char buf[7];

buf[0] = 0x42;
buf[1] = 0x42;
buf[2] = 0x03;
buf[3] = 0;
buf[4] = 0;
buf[5] = 0;
buf[6] = BPDU_TYPE_TCN;
unsigned char buf[4];

buf[0] = 0;
buf[1] = 0;
buf[2] = 0;
buf[3] = BPDU_TYPE_TCN;
br_send_bpdu(p, buf, 7);
}

Expand Down

0 comments on commit 12ac84c

Please sign in to comment.