[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>
diff --git a/net/bridge/br_stp_bpdu.c b/net/bridge/br_stp_bpdu.c
index ed3a544..8934a54 100644
--- a/net/bridge/br_stp_bpdu.c
+++ b/net/bridge/br_stp_bpdu.c
@@ -17,6 +17,7 @@
 #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"
@@ -24,36 +25,31 @@
 
 #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);
@@ -76,60 +72,54 @@
 /* called under bridge lock */
 void br_send_config_bpdu(struct net_bridge_port *p, struct br_config_bpdu *bpdu)
 {
-	unsigned char buf[38];
+	unsigned char buf[35];
 
-	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) |
+	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;
+	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+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_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, 38);
+	br_send_bpdu(p, buf, 35);
 }
 
 /* called under bridge lock */
 void br_send_tcn_bpdu(struct net_bridge_port *p)
 {
-	unsigned char buf[7];
+	unsigned char buf[4];
 
-	buf[0] = 0x42;
-	buf[1] = 0x42;
-	buf[2] = 0x03;
-	buf[3] = 0;
-	buf[4] = 0;
-	buf[5] = 0;
-	buf[6] = BPDU_TYPE_TCN;
+	buf[0] = 0;
+	buf[1] = 0;
+	buf[2] = 0;
+	buf[3] = BPDU_TYPE_TCN;
 	br_send_bpdu(p, buf, 7);
 }