Commit 12ac84c4a9c505e3e30529563b04cc8f6d5ebbf3

Authored by Stephen Hemminger
Committed by David S. Miller
1 parent f4ad2b162d

[BRIDGE]: use LLC to send STP

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>

Showing 1 changed file with 59 additions and 69 deletions Side-by-side Diff

net/bridge/br_stp_bpdu.c
... ... @@ -17,6 +17,7 @@
17 17 #include <linux/netfilter_bridge.h>
18 18 #include <linux/etherdevice.h>
19 19 #include <linux/llc.h>
  20 +#include <net/llc.h>
20 21 #include <net/llc_pdu.h>
21 22  
22 23 #include "br_private.h"
23 24  
24 25  
25 26  
26 27  
27 28  
28 29  
29 30  
... ... @@ -24,37 +25,32 @@
24 25  
25 26 #define STP_HZ 256
26 27  
27   -static void br_send_bpdu(struct net_bridge_port *p, unsigned char *data, int length)
  28 +#define LLC_RESERVE sizeof(struct llc_pdu_un)
  29 +
  30 +static void br_send_bpdu(struct net_bridge_port *p,
  31 + const unsigned char *data, int length)
28 32 {
29   - struct net_device *dev;
30 33 struct sk_buff *skb;
31   - int size;
32 34  
33 35 if (!p->br->stp_enabled)
34 36 return;
35 37  
36   - size = length + 2*ETH_ALEN + 2;
37   - if (size < 60)
38   - size = 60;
39   -
40   - dev = p->dev;
41   -
42   - if ((skb = dev_alloc_skb(size)) == NULL) {
43   - printk(KERN_INFO "br: memory squeeze!\n");
  38 + skb = dev_alloc_skb(length+LLC_RESERVE);
  39 + if (!skb)
44 40 return;
45   - }
46 41  
47   - skb->dev = dev;
  42 + skb->dev = p->dev;
48 43 skb->protocol = htons(ETH_P_802_2);
49   - skb->mac.raw = skb_put(skb, size);
50   - memcpy(skb->mac.raw, p->br->group_addr, ETH_ALEN);
51   - memcpy(skb->mac.raw+ETH_ALEN, dev->dev_addr, ETH_ALEN);
52   - skb->mac.raw[2*ETH_ALEN] = 0;
53   - skb->mac.raw[2*ETH_ALEN+1] = length;
54   - skb->nh.raw = skb->mac.raw + 2*ETH_ALEN + 2;
55   - memcpy(skb->nh.raw, data, length);
56   - memset(skb->nh.raw + length, 0xa5, size - length - 2*ETH_ALEN - 2);
57 44  
  45 + skb_reserve(skb, LLC_RESERVE);
  46 + memcpy(__skb_put(skb, length), data, length);
  47 +
  48 + llc_pdu_header_init(skb, LLC_PDU_TYPE_U, LLC_SAP_BSPAN,
  49 + LLC_SAP_BSPAN, LLC_PDU_CMD);
  50 + llc_pdu_init_as_ui_cmd(skb);
  51 +
  52 + llc_mac_hdr_init(skb, p->dev->dev_addr, p->br->group_addr);
  53 +
58 54 NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev,
59 55 dev_queue_xmit);
60 56 }
61 57  
62 58  
63 59  
64 60  
65 61  
66 62  
... ... @@ -76,60 +72,54 @@
76 72 /* called under bridge lock */
77 73 void br_send_config_bpdu(struct net_bridge_port *p, struct br_config_bpdu *bpdu)
78 74 {
79   - unsigned char buf[38];
  75 + unsigned char buf[35];
80 76  
81   - buf[0] = 0x42;
82   - buf[1] = 0x42;
83   - buf[2] = 0x03;
84   - buf[3] = 0;
85   - buf[4] = 0;
86   - buf[5] = 0;
87   - buf[6] = BPDU_TYPE_CONFIG;
88   - buf[7] = (bpdu->topology_change ? 0x01 : 0) |
  77 + buf[0] = 0;
  78 + buf[1] = 0;
  79 + buf[2] = 0;
  80 + buf[3] = BPDU_TYPE_CONFIG;
  81 + buf[4] = (bpdu->topology_change ? 0x01 : 0) |
89 82 (bpdu->topology_change_ack ? 0x80 : 0);
90   - buf[8] = bpdu->root.prio[0];
91   - buf[9] = bpdu->root.prio[1];
92   - buf[10] = bpdu->root.addr[0];
93   - buf[11] = bpdu->root.addr[1];
94   - buf[12] = bpdu->root.addr[2];
95   - buf[13] = bpdu->root.addr[3];
96   - buf[14] = bpdu->root.addr[4];
97   - buf[15] = bpdu->root.addr[5];
98   - buf[16] = (bpdu->root_path_cost >> 24) & 0xFF;
99   - buf[17] = (bpdu->root_path_cost >> 16) & 0xFF;
100   - buf[18] = (bpdu->root_path_cost >> 8) & 0xFF;
101   - buf[19] = bpdu->root_path_cost & 0xFF;
102   - buf[20] = bpdu->bridge_id.prio[0];
103   - buf[21] = bpdu->bridge_id.prio[1];
104   - buf[22] = bpdu->bridge_id.addr[0];
105   - buf[23] = bpdu->bridge_id.addr[1];
106   - buf[24] = bpdu->bridge_id.addr[2];
107   - buf[25] = bpdu->bridge_id.addr[3];
108   - buf[26] = bpdu->bridge_id.addr[4];
109   - buf[27] = bpdu->bridge_id.addr[5];
110   - buf[28] = (bpdu->port_id >> 8) & 0xFF;
111   - buf[29] = bpdu->port_id & 0xFF;
  83 + buf[5] = bpdu->root.prio[0];
  84 + buf[6] = bpdu->root.prio[1];
  85 + buf[7] = bpdu->root.addr[0];
  86 + buf[8] = bpdu->root.addr[1];
  87 + buf[9] = bpdu->root.addr[2];
  88 + buf[10] = bpdu->root.addr[3];
  89 + buf[11] = bpdu->root.addr[4];
  90 + buf[12] = bpdu->root.addr[5];
  91 + buf[13] = (bpdu->root_path_cost >> 24) & 0xFF;
  92 + buf[14] = (bpdu->root_path_cost >> 16) & 0xFF;
  93 + buf[15] = (bpdu->root_path_cost >> 8) & 0xFF;
  94 + buf[16] = bpdu->root_path_cost & 0xFF;
  95 + buf[17] = bpdu->bridge_id.prio[0];
  96 + buf[18] = bpdu->bridge_id.prio[1];
  97 + buf[19] = bpdu->bridge_id.addr[0];
  98 + buf[20] = bpdu->bridge_id.addr[1];
  99 + buf[21] = bpdu->bridge_id.addr[2];
  100 + buf[22] = bpdu->bridge_id.addr[3];
  101 + buf[23] = bpdu->bridge_id.addr[4];
  102 + buf[24] = bpdu->bridge_id.addr[5];
  103 + buf[25] = (bpdu->port_id >> 8) & 0xFF;
  104 + buf[26] = bpdu->port_id & 0xFF;
112 105  
113   - br_set_ticks(buf+30, bpdu->message_age);
114   - br_set_ticks(buf+32, bpdu->max_age);
115   - br_set_ticks(buf+34, bpdu->hello_time);
116   - br_set_ticks(buf+36, bpdu->forward_delay);
  106 + br_set_ticks(buf+27, bpdu->message_age);
  107 + br_set_ticks(buf+29, bpdu->max_age);
  108 + br_set_ticks(buf+31, bpdu->hello_time);
  109 + br_set_ticks(buf+33, bpdu->forward_delay);
117 110  
118   - br_send_bpdu(p, buf, 38);
  111 + br_send_bpdu(p, buf, 35);
119 112 }
120 113  
121 114 /* called under bridge lock */
122 115 void br_send_tcn_bpdu(struct net_bridge_port *p)
123 116 {
124   - unsigned char buf[7];
  117 + unsigned char buf[4];
125 118  
126   - buf[0] = 0x42;
127   - buf[1] = 0x42;
128   - buf[2] = 0x03;
129   - buf[3] = 0;
130   - buf[4] = 0;
131   - buf[5] = 0;
132   - buf[6] = BPDU_TYPE_TCN;
  119 + buf[0] = 0;
  120 + buf[1] = 0;
  121 + buf[2] = 0;
  122 + buf[3] = BPDU_TYPE_TCN;
133 123 br_send_bpdu(p, buf, 7);
134 124 }
135 125