2 * Spanning tree protocol; BPDU handling
3 * Linux ethernet bridge
6 * Lennert Buytenhek <buytenh@gnu.org>
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version
11 * 2 of the License, or (at your option) any later version.
14 #include <linux/kernel.h>
15 #include <linux/netfilter_bridge.h>
16 #include <linux/etherdevice.h>
17 #include <linux/llc.h>
18 #include <linux/slab.h>
19 #include <linux/pkt_sched.h>
20 #include <net/net_namespace.h>
22 #include <net/llc_pdu.h>
24 #include <asm/unaligned.h>
26 #include "br_private.h"
27 #include "br_private_stp.h"
31 #define LLC_RESERVE sizeof(struct llc_pdu_un)
33 static int br_send_bpdu_finish(struct net
*net
, struct sock
*sk
,
36 return dev_queue_xmit(skb
);
39 static void br_send_bpdu(struct net_bridge_port
*p
,
40 const unsigned char *data
, int length
)
44 skb
= dev_alloc_skb(length
+LLC_RESERVE
);
49 skb
->protocol
= htons(ETH_P_802_2
);
50 skb
->priority
= TC_PRIO_CONTROL
;
52 skb_reserve(skb
, LLC_RESERVE
);
53 __skb_put_data(skb
, data
, length
);
55 llc_pdu_header_init(skb
, LLC_PDU_TYPE_U
, LLC_SAP_BSPAN
,
56 LLC_SAP_BSPAN
, LLC_PDU_CMD
);
57 llc_pdu_init_as_ui_cmd(skb
);
59 llc_mac_hdr_init(skb
, p
->dev
->dev_addr
, p
->br
->group_addr
);
61 skb_reset_mac_header(skb
);
63 NF_HOOK(NFPROTO_BRIDGE
, NF_BR_LOCAL_OUT
,
64 dev_net(p
->dev
), NULL
, skb
, NULL
, skb
->dev
,
68 static inline void br_set_ticks(unsigned char *dest
, int j
)
70 unsigned long ticks
= (STP_HZ
* j
)/ HZ
;
72 put_unaligned_be16(ticks
, dest
);
75 static inline int br_get_ticks(const unsigned char *src
)
77 unsigned long ticks
= get_unaligned_be16(src
);
79 return DIV_ROUND_UP(ticks
* HZ
, STP_HZ
);
82 /* called under bridge lock */
83 void br_send_config_bpdu(struct net_bridge_port
*p
, struct br_config_bpdu
*bpdu
)
85 unsigned char buf
[35];
87 if (p
->br
->stp_enabled
!= BR_KERNEL_STP
)
93 buf
[3] = BPDU_TYPE_CONFIG
;
94 buf
[4] = (bpdu
->topology_change
? 0x01 : 0) |
95 (bpdu
->topology_change_ack
? 0x80 : 0);
96 buf
[5] = bpdu
->root
.prio
[0];
97 buf
[6] = bpdu
->root
.prio
[1];
98 buf
[7] = bpdu
->root
.addr
[0];
99 buf
[8] = bpdu
->root
.addr
[1];
100 buf
[9] = bpdu
->root
.addr
[2];
101 buf
[10] = bpdu
->root
.addr
[3];
102 buf
[11] = bpdu
->root
.addr
[4];
103 buf
[12] = bpdu
->root
.addr
[5];
104 buf
[13] = (bpdu
->root_path_cost
>> 24) & 0xFF;
105 buf
[14] = (bpdu
->root_path_cost
>> 16) & 0xFF;
106 buf
[15] = (bpdu
->root_path_cost
>> 8) & 0xFF;
107 buf
[16] = bpdu
->root_path_cost
& 0xFF;
108 buf
[17] = bpdu
->bridge_id
.prio
[0];
109 buf
[18] = bpdu
->bridge_id
.prio
[1];
110 buf
[19] = bpdu
->bridge_id
.addr
[0];
111 buf
[20] = bpdu
->bridge_id
.addr
[1];
112 buf
[21] = bpdu
->bridge_id
.addr
[2];
113 buf
[22] = bpdu
->bridge_id
.addr
[3];
114 buf
[23] = bpdu
->bridge_id
.addr
[4];
115 buf
[24] = bpdu
->bridge_id
.addr
[5];
116 buf
[25] = (bpdu
->port_id
>> 8) & 0xFF;
117 buf
[26] = bpdu
->port_id
& 0xFF;
119 br_set_ticks(buf
+27, bpdu
->message_age
);
120 br_set_ticks(buf
+29, bpdu
->max_age
);
121 br_set_ticks(buf
+31, bpdu
->hello_time
);
122 br_set_ticks(buf
+33, bpdu
->forward_delay
);
124 br_send_bpdu(p
, buf
, 35);
127 /* called under bridge lock */
128 void br_send_tcn_bpdu(struct net_bridge_port
*p
)
130 unsigned char buf
[4];
132 if (p
->br
->stp_enabled
!= BR_KERNEL_STP
)
138 buf
[3] = BPDU_TYPE_TCN
;
139 br_send_bpdu(p
, buf
, 4);
145 * NO locks, but rcu_read_lock
147 void br_stp_rcv(const struct stp_proto
*proto
, struct sk_buff
*skb
,
148 struct net_device
*dev
)
150 const unsigned char *dest
= eth_hdr(skb
)->h_dest
;
151 struct net_bridge_port
*p
;
152 struct net_bridge
*br
;
153 const unsigned char *buf
;
155 if (!pskb_may_pull(skb
, 4))
158 /* compare of protocol id and version */
160 if (buf
[0] != 0 || buf
[1] != 0 || buf
[2] != 0)
163 p
= br_port_get_check_rcu(dev
);
168 spin_lock(&br
->lock
);
170 if (br
->stp_enabled
!= BR_KERNEL_STP
)
173 if (!(br
->dev
->flags
& IFF_UP
))
176 if (p
->state
== BR_STATE_DISABLED
)
179 if (!ether_addr_equal(dest
, br
->group_addr
))
182 if (p
->flags
& BR_BPDU_GUARD
) {
183 br_notice(br
, "BPDU received on blocked port %u(%s)\n",
184 (unsigned int) p
->port_no
, p
->dev
->name
);
185 br_stp_disable_port(p
);
189 buf
= skb_pull(skb
, 3);
191 if (buf
[0] == BPDU_TYPE_CONFIG
) {
192 struct br_config_bpdu bpdu
;
194 if (!pskb_may_pull(skb
, 32))
198 bpdu
.topology_change
= (buf
[1] & 0x01) ? 1 : 0;
199 bpdu
.topology_change_ack
= (buf
[1] & 0x80) ? 1 : 0;
201 bpdu
.root
.prio
[0] = buf
[2];
202 bpdu
.root
.prio
[1] = buf
[3];
203 bpdu
.root
.addr
[0] = buf
[4];
204 bpdu
.root
.addr
[1] = buf
[5];
205 bpdu
.root
.addr
[2] = buf
[6];
206 bpdu
.root
.addr
[3] = buf
[7];
207 bpdu
.root
.addr
[4] = buf
[8];
208 bpdu
.root
.addr
[5] = buf
[9];
209 bpdu
.root_path_cost
=
214 bpdu
.bridge_id
.prio
[0] = buf
[14];
215 bpdu
.bridge_id
.prio
[1] = buf
[15];
216 bpdu
.bridge_id
.addr
[0] = buf
[16];
217 bpdu
.bridge_id
.addr
[1] = buf
[17];
218 bpdu
.bridge_id
.addr
[2] = buf
[18];
219 bpdu
.bridge_id
.addr
[3] = buf
[19];
220 bpdu
.bridge_id
.addr
[4] = buf
[20];
221 bpdu
.bridge_id
.addr
[5] = buf
[21];
222 bpdu
.port_id
= (buf
[22] << 8) | buf
[23];
224 bpdu
.message_age
= br_get_ticks(buf
+24);
225 bpdu
.max_age
= br_get_ticks(buf
+26);
226 bpdu
.hello_time
= br_get_ticks(buf
+28);
227 bpdu
.forward_delay
= br_get_ticks(buf
+30);
229 if (bpdu
.message_age
> bpdu
.max_age
) {
232 "port %u config from %pM"
233 " (message_age %ul > max_age %ul)\n",
235 eth_hdr(skb
)->h_source
,
236 bpdu
.message_age
, bpdu
.max_age
);
240 br_received_config_bpdu(p
, &bpdu
);
241 } else if (buf
[0] == BPDU_TYPE_TCN
) {
242 br_received_tcn_bpdu(p
);
245 spin_unlock(&br
->lock
);