This source file includes following definitions.
- LIST_HEAD
- bstp_transmit
- bstp_transmit_bpdu
- bstp_transmit_tcn
- bstp_decode_bpdu
- bstp_send_bpdu
- bstp_pdu_flags
- bstp_input
- bstp_received_stp
- bstp_received_rstp
- bstp_received_tcn
- bstp_received_bpdu
- bstp_pdu_rcvtype
- bstp_pdu_bettersame
- bstp_info_cmp
- bstp_info_superior
- bstp_assign_roles
- bstp_update_state
- bstp_update_roles
- bstp_update_tc
- bstp_update_info
- bstp_set_other_tcprop
- bstp_set_all_reroot
- bstp_set_all_sync
- bstp_set_port_state
- bstp_set_port_role
- bstp_set_port_proto
- bstp_set_port_tc
- bstp_set_timer_tc
- bstp_set_timer_msgage
- bstp_rerooted
- bstp_calc_path_cost
- bstp_notify_rtage
- bstp_ifstate
- bstp_ifupdstatus
- bstp_enable_port
- bstp_disable_port
- bstp_tick
- bstp_timer_start
- bstp_timer_stop
- bstp_timer_latch
- bstp_timer_expired
- bstp_hello_timer_expiry
- bstp_message_age_expiry
- bstp_migrate_delay_expiry
- bstp_edge_delay_expiry
- bstp_addr_cmp
- bstp_same_bridgeid
- bstp_initialization
- bstp_create
- bstp_destroy
- bstp_stop
- bstp_add
- bstp_delete
- bstp_getstate
- bstp_ifsflags
- bstp_ioctl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 #if 0
36 __FBSDID("$FreeBSD: /repoman/r/ncvs/src/sys/net/bridgestp.c,v 1.25 2006/11/03 03:34:04 thompsa Exp $");
37 #endif
38
39 #include "bridge.h"
40
41 #if NBRIDGE > 0
42
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/mbuf.h>
46 #include <sys/socket.h>
47 #include <sys/ioctl.h>
48 #include <sys/device.h>
49 #include <sys/kernel.h>
50 #include <sys/timeout.h>
51
52 #include <net/if.h>
53 #include <net/if_types.h>
54 #include <net/if_dl.h>
55 #include <net/if_llc.h>
56 #include <net/if_media.h>
57 #include <net/route.h>
58 #include <net/netisr.h>
59
60 #ifdef INET
61 #include <netinet/in.h>
62 #include <netinet/in_systm.h>
63 #include <netinet/in_var.h>
64 #include <netinet/ip.h>
65 #include <netinet/if_ether.h>
66 #endif
67
68 #if NBPFILTER > 0
69 #include <net/bpf.h>
70 #endif
71
72 #include <net/if_bridge.h>
73
74
75 #define BSTP_IFSTATE_DISABLED 0
76 #define BSTP_IFSTATE_LISTENING 1
77 #define BSTP_IFSTATE_LEARNING 2
78 #define BSTP_IFSTATE_FORWARDING 3
79 #define BSTP_IFSTATE_BLOCKING 4
80 #define BSTP_IFSTATE_DISCARDING 5
81
82 #define BSTP_TCSTATE_ACTIVE 1
83 #define BSTP_TCSTATE_DETECTED 2
84 #define BSTP_TCSTATE_INACTIVE 3
85 #define BSTP_TCSTATE_LEARNING 4
86 #define BSTP_TCSTATE_PROPAG 5
87 #define BSTP_TCSTATE_ACK 6
88 #define BSTP_TCSTATE_TC 7
89 #define BSTP_TCSTATE_TCN 8
90
91 #define BSTP_ROLE_DISABLED 0
92 #define BSTP_ROLE_ROOT 1
93 #define BSTP_ROLE_DESIGNATED 2
94 #define BSTP_ROLE_ALTERNATE 3
95 #define BSTP_ROLE_BACKUP 4
96
97
98 #define BSTP_PORT_CANMIGRATE 0x0001
99 #define BSTP_PORT_NEWINFO 0x0002
100 #define BSTP_PORT_DISPUTED 0x0004
101 #define BSTP_PORT_ADMCOST 0x0008
102 #define BSTP_PORT_AUTOEDGE 0x0010
103
104
105 #define BSTP_PDU_SUPERIOR 1
106 #define BSTP_PDU_REPEATED 2
107 #define BSTP_PDU_INFERIOR 3
108 #define BSTP_PDU_INFERIORALT 4
109 #define BSTP_PDU_OTHER 5
110
111
112 #define BSTP_PDU_PRMASK 0x0c
113 #define BSTP_PDU_PRSHIFT 2
114 #define BSTP_PDU_F_UNKN 0x00
115 #define BSTP_PDU_F_ALT 0x01
116 #define BSTP_PDU_F_ROOT 0x02
117 #define BSTP_PDU_F_DESG 0x03
118
119 #define BSTP_PDU_STPMASK 0x81
120 #define BSTP_PDU_RSTPMASK 0x7f
121 #define BSTP_PDU_F_TC 0x01
122 #define BSTP_PDU_F_P 0x02
123 #define BSTP_PDU_F_L 0x10
124 #define BSTP_PDU_F_F 0x20
125 #define BSTP_PDU_F_A 0x40
126 #define BSTP_PDU_F_TCA 0x80
127
128
129
130
131 #define BSTP_DEFAULT_MAX_AGE (20 * 256)
132 #define BSTP_DEFAULT_HELLO_TIME (2 * 256)
133 #define BSTP_DEFAULT_FORWARD_DELAY (15 * 256)
134 #define BSTP_DEFAULT_HOLD_TIME (1 * 256)
135 #define BSTP_DEFAULT_MIGRATE_DELAY (3 * 256)
136 #define BSTP_DEFAULT_HOLD_COUNT 6
137 #define BSTP_DEFAULT_BRIDGE_PRIORITY 0x8000
138 #define BSTP_DEFAULT_PORT_PRIORITY 0x80
139 #define BSTP_DEFAULT_PATH_COST 55
140 #define BSTP_MIN_HELLO_TIME (1 * 256)
141 #define BSTP_MIN_MAX_AGE (6 * 256)
142 #define BSTP_MIN_FORWARD_DELAY (4 * 256)
143 #define BSTP_MIN_HOLD_COUNT 1
144 #define BSTP_MAX_HELLO_TIME (2 * 256)
145 #define BSTP_MAX_MAX_AGE (40 * 256)
146 #define BSTP_MAX_FORWARD_DELAY (30 * 256)
147 #define BSTP_MAX_HOLD_COUNT 10
148 #define BSTP_MAX_PRIORITY 61440
149 #define BSTP_MAX_PORT_PRIORITY 240
150 #define BSTP_MAX_PATH_COST 200000000
151
152
153 #define BSTP_MSGTYPE_CFG 0x00
154 #define BSTP_MSGTYPE_RSTP 0x02
155 #define BSTP_MSGTYPE_TCN 0x80
156
157 #define BSTP_INFO_RECIEVED 1
158 #define BSTP_INFO_MINE 2
159 #define BSTP_INFO_AGED 3
160 #define BSTP_INFO_DISABLED 4
161
162 #define BSTP_MESSAGE_AGE_INCR (1 * 256)
163 #define BSTP_TICK_VAL (1 * 256)
164 #define BSTP_LINK_TIMER (BSTP_TICK_VAL * 15)
165
166 #ifdef BRIDGESTP_DEBUG
167 #define DPRINTF(fmt, arg...) printf("bstp: " fmt, ##arg)
168 #else
169 #define DPRINTF(fmt, arg...)
170 #endif
171
172 #define PV2ADDR(pv, eaddr) do { \
173 eaddr[0] = pv >> 40; \
174 eaddr[1] = pv >> 32; \
175 eaddr[2] = pv >> 24; \
176 eaddr[3] = pv >> 16; \
177 eaddr[4] = pv >> 8; \
178 eaddr[5] = pv >> 0; \
179 } while (0)
180
181 #define INFO_BETTER 1
182 #define INFO_SAME 0
183 #define INFO_WORSE -1
184
185
186
187
188
189
190
191
192 struct bstp_cbpdu {
193 u_int8_t cbu_dsap;
194 u_int8_t cbu_ssap;
195 u_int8_t cbu_ctl;
196 u_int16_t cbu_protoid;
197 u_int8_t cbu_protover;
198 u_int8_t cbu_bpdutype;
199 u_int8_t cbu_flags;
200
201
202 u_int16_t cbu_rootpri;
203 u_int8_t cbu_rootaddr[6];
204
205 u_int32_t cbu_rootpathcost;
206
207
208 u_int16_t cbu_bridgepri;
209 u_int8_t cbu_bridgeaddr[6];
210
211 u_int16_t cbu_portid;
212 u_int16_t cbu_messageage;
213 u_int16_t cbu_maxage;
214 u_int16_t cbu_hellotime;
215 u_int16_t cbu_forwarddelay;
216 u_int8_t cbu_versionlen;
217 } __packed;
218
219 #define BSTP_BPDU_STP_LEN (3 + 35)
220 #define BSTP_BPDU_RSTP_LEN (3 + 36)
221
222
223 struct bstp_tbpdu {
224 u_int8_t tbu_dsap;
225 u_int8_t tbu_ssap;
226 u_int8_t tbu_ctl;
227 u_int16_t tbu_protoid;
228 u_int8_t tbu_protover;
229 u_int8_t tbu_bpdutype;
230 } __packed;
231
232 const u_int8_t bstp_etheraddr[] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 };
233
234 LIST_HEAD(, bstp_state) bstp_list;
235
236 void bstp_transmit(struct bstp_state *, struct bstp_port *);
237 void bstp_transmit_bpdu(struct bstp_state *, struct bstp_port *);
238 void bstp_transmit_tcn(struct bstp_state *, struct bstp_port *);
239 void bstp_decode_bpdu(struct bstp_port *, struct bstp_cbpdu *,
240 struct bstp_config_unit *);
241 void bstp_send_bpdu(struct bstp_state *, struct bstp_port *,
242 struct bstp_cbpdu *);
243 int bstp_pdu_flags(struct bstp_port *);
244 void bstp_received_stp(struct bstp_state *, struct bstp_port *,
245 struct mbuf **, struct bstp_tbpdu *);
246 void bstp_received_rstp(struct bstp_state *, struct bstp_port *,
247 struct mbuf **, struct bstp_tbpdu *);
248 void bstp_received_tcn(struct bstp_state *, struct bstp_port *,
249 struct bstp_tcn_unit *);
250 void bstp_received_bpdu(struct bstp_state *, struct bstp_port *,
251 struct bstp_config_unit *);
252 int bstp_pdu_rcvtype(struct bstp_port *, struct bstp_config_unit *);
253 int bstp_pdu_bettersame(struct bstp_port *, int);
254 int bstp_info_cmp(struct bstp_pri_vector *,
255 struct bstp_pri_vector *);
256 int bstp_info_superior(struct bstp_pri_vector *,
257 struct bstp_pri_vector *);
258 void bstp_assign_roles(struct bstp_state *);
259 void bstp_update_roles(struct bstp_state *, struct bstp_port *);
260 void bstp_update_state(struct bstp_state *, struct bstp_port *);
261 void bstp_update_tc(struct bstp_port *);
262 void bstp_update_info(struct bstp_port *);
263 void bstp_set_other_tcprop(struct bstp_port *);
264 void bstp_set_all_reroot(struct bstp_state *);
265 void bstp_set_all_sync(struct bstp_state *);
266 void bstp_set_port_state(struct bstp_port *, int);
267 void bstp_set_port_role(struct bstp_port *, int);
268 void bstp_set_port_proto(struct bstp_port *, int);
269 void bstp_set_port_tc(struct bstp_port *, int);
270 void bstp_set_timer_tc(struct bstp_port *);
271 void bstp_set_timer_msgage(struct bstp_port *);
272 int bstp_rerooted(struct bstp_state *, struct bstp_port *);
273 u_int32_t bstp_calc_path_cost(struct bstp_port *);
274 void bstp_notify_rtage(void *, int);
275 void bstp_ifupdstatus(struct bstp_state *, struct bstp_port *);
276 void bstp_enable_port(struct bstp_state *, struct bstp_port *);
277 void bstp_disable_port(struct bstp_state *, struct bstp_port *);
278 void bstp_tick(void *);
279 void bstp_timer_start(struct bstp_timer *, u_int16_t);
280 void bstp_timer_stop(struct bstp_timer *);
281 void bstp_timer_latch(struct bstp_timer *);
282 int bstp_timer_expired(struct bstp_timer *);
283 void bstp_hello_timer_expiry(struct bstp_state *,
284 struct bstp_port *);
285 void bstp_message_age_expiry(struct bstp_state *,
286 struct bstp_port *);
287 void bstp_migrate_delay_expiry(struct bstp_state *,
288 struct bstp_port *);
289 void bstp_edge_delay_expiry(struct bstp_state *,
290 struct bstp_port *);
291 int bstp_addr_cmp(const u_int8_t *, const u_int8_t *);
292 int bstp_same_bridgeid(u_int64_t, u_int64_t);
293
294 void
295 bstp_attach(int n)
296 {
297 LIST_INIT(&bstp_list);
298 }
299
300 void
301 bstp_transmit(struct bstp_state *bs, struct bstp_port *bp)
302 {
303 if ((bs->bs_ifflags & IFF_RUNNING) == 0 || bp == NULL)
304 return;
305
306
307
308
309
310 if (bp->bp_hello_timer.active == 0) {
311
312 bstp_hello_timer_expiry(bs, bp);
313 return;
314 }
315 if (bp->bp_txcount > bs->bs_txholdcount)
316
317 return;
318
319 if (bp->bp_protover == BSTP_PROTO_RSTP) {
320 bstp_transmit_bpdu(bs, bp);
321 bp->bp_tc_ack = 0;
322 } else {
323 switch (bp->bp_role) {
324 case BSTP_ROLE_DESIGNATED:
325 bstp_transmit_bpdu(bs, bp);
326 bp->bp_tc_ack = 0;
327 break;
328
329 case BSTP_ROLE_ROOT:
330 bstp_transmit_tcn(bs, bp);
331 break;
332 }
333 }
334 bstp_timer_start(&bp->bp_hello_timer, bp->bp_desg_htime);
335 bp->bp_flags &= ~BSTP_PORT_NEWINFO;
336 }
337
338 void
339 bstp_transmit_bpdu(struct bstp_state *bs, struct bstp_port *bp)
340 {
341 struct bstp_cbpdu bpdu;
342
343 bpdu.cbu_rootpri = htons(bp->bp_desg_pv.pv_root_id >> 48);
344 PV2ADDR(bp->bp_desg_pv.pv_root_id, bpdu.cbu_rootaddr);
345
346 bpdu.cbu_rootpathcost = htonl(bp->bp_desg_pv.pv_cost);
347
348 bpdu.cbu_bridgepri = htons(bp->bp_desg_pv.pv_dbridge_id >> 48);
349 PV2ADDR(bp->bp_desg_pv.pv_dbridge_id, bpdu.cbu_bridgeaddr);
350
351 bpdu.cbu_portid = htons(bp->bp_port_id);
352 bpdu.cbu_messageage = htons(bp->bp_desg_msg_age);
353 bpdu.cbu_maxage = htons(bp->bp_desg_max_age);
354 bpdu.cbu_hellotime = htons(bp->bp_desg_htime);
355 bpdu.cbu_forwarddelay = htons(bp->bp_desg_fdelay);
356
357 bpdu.cbu_flags = bstp_pdu_flags(bp);
358
359 switch (bp->bp_protover) {
360 case BSTP_PROTO_STP:
361 bpdu.cbu_bpdutype = BSTP_MSGTYPE_CFG;
362 break;
363 case BSTP_PROTO_RSTP:
364 bpdu.cbu_bpdutype = BSTP_MSGTYPE_RSTP;
365 break;
366 }
367
368 bstp_send_bpdu(bs, bp, &bpdu);
369 }
370
371 void
372 bstp_transmit_tcn(struct bstp_state *bs, struct bstp_port *bp)
373 {
374 struct bstp_tbpdu bpdu;
375 struct ifnet *ifp = bp->bp_ifp;
376 struct ether_header *eh;
377 struct mbuf *m;
378 int s,error;
379
380 if (ifp == NULL || (ifp->if_flags & IFF_RUNNING) == 0)
381 return;
382
383 MGETHDR(m, M_DONTWAIT, MT_DATA);
384 if (m == NULL)
385 return;
386 m->m_pkthdr.rcvif = ifp;
387 m->m_pkthdr.len = sizeof(*eh) + sizeof(bpdu);
388 m->m_len = m->m_pkthdr.len;
389
390 eh = mtod(m, struct ether_header *);
391 bcopy(LLADDR(ifp->if_sadl), eh->ether_shost, ETHER_ADDR_LEN);
392 bcopy(bstp_etheraddr, eh->ether_dhost, ETHER_ADDR_LEN);
393 eh->ether_type = htons(sizeof(bpdu));
394
395 bpdu.tbu_ssap = bpdu.tbu_dsap = LLC_8021D_LSAP;
396 bpdu.tbu_ctl = LLC_UI;
397 bpdu.tbu_protoid = 0;
398 bpdu.tbu_protover = 0;
399 bpdu.tbu_bpdutype = BSTP_MSGTYPE_TCN;
400 bcopy(&bpdu, mtod(m, caddr_t) + sizeof(*eh), sizeof(bpdu));
401
402 s = splnet();
403 bp->bp_txcount++;
404 IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error);
405 if (error == 0 && (ifp->if_flags & IFF_OACTIVE) == 0)
406 (*ifp->if_start)(ifp);
407 splx(s);
408 }
409
410 void
411 bstp_decode_bpdu(struct bstp_port *bp, struct bstp_cbpdu *cpdu,
412 struct bstp_config_unit *cu)
413 {
414 int flags;
415
416 cu->cu_pv.pv_root_id =
417 (((u_int64_t)ntohs(cpdu->cbu_rootpri)) << 48) |
418 (((u_int64_t)cpdu->cbu_rootaddr[0]) << 40) |
419 (((u_int64_t)cpdu->cbu_rootaddr[1]) << 32) |
420 (((u_int64_t)cpdu->cbu_rootaddr[2]) << 24) |
421 (((u_int64_t)cpdu->cbu_rootaddr[3]) << 16) |
422 (((u_int64_t)cpdu->cbu_rootaddr[4]) << 8) |
423 (((u_int64_t)cpdu->cbu_rootaddr[5]) << 0);
424
425 cu->cu_pv.pv_dbridge_id =
426 (((u_int64_t)ntohs(cpdu->cbu_bridgepri)) << 48) |
427 (((u_int64_t)cpdu->cbu_bridgeaddr[0]) << 40) |
428 (((u_int64_t)cpdu->cbu_bridgeaddr[1]) << 32) |
429 (((u_int64_t)cpdu->cbu_bridgeaddr[2]) << 24) |
430 (((u_int64_t)cpdu->cbu_bridgeaddr[3]) << 16) |
431 (((u_int64_t)cpdu->cbu_bridgeaddr[4]) << 8) |
432 (((u_int64_t)cpdu->cbu_bridgeaddr[5]) << 0);
433
434 cu->cu_pv.pv_cost = ntohl(cpdu->cbu_rootpathcost);
435 cu->cu_message_age = ntohs(cpdu->cbu_messageage);
436 cu->cu_max_age = ntohs(cpdu->cbu_maxage);
437 cu->cu_hello_time = ntohs(cpdu->cbu_hellotime);
438 cu->cu_forward_delay = ntohs(cpdu->cbu_forwarddelay);
439 cu->cu_pv.pv_dport_id = ntohs(cpdu->cbu_portid);
440 cu->cu_pv.pv_port_id = bp->bp_port_id;
441 cu->cu_message_type = cpdu->cbu_bpdutype;
442
443
444 flags = cpdu->cbu_flags;
445 switch (cpdu->cbu_protover) {
446 case BSTP_PROTO_STP:
447 flags &= BSTP_PDU_STPMASK;
448
449 cu->cu_role = BSTP_ROLE_DESIGNATED;
450 break;
451 case BSTP_PROTO_RSTP:
452 flags &= BSTP_PDU_RSTPMASK;
453 break;
454 }
455
456 cu->cu_topology_change_ack =
457 (flags & BSTP_PDU_F_TCA) ? 1 : 0;
458 cu->cu_proposal =
459 (flags & BSTP_PDU_F_P) ? 1 : 0;
460 cu->cu_agree =
461 (flags & BSTP_PDU_F_A) ? 1 : 0;
462 cu->cu_learning =
463 (flags & BSTP_PDU_F_L) ? 1 : 0;
464 cu->cu_forwarding =
465 (flags & BSTP_PDU_F_F) ? 1 : 0;
466 cu->cu_topology_change =
467 (flags & BSTP_PDU_F_TC) ? 1 : 0;
468
469 switch ((flags & BSTP_PDU_PRMASK) >> BSTP_PDU_PRSHIFT) {
470 case BSTP_PDU_F_ROOT:
471 cu->cu_role = BSTP_ROLE_ROOT;
472 break;
473 case BSTP_PDU_F_ALT:
474 cu->cu_role = BSTP_ROLE_ALTERNATE;
475 break;
476 case BSTP_PDU_F_DESG:
477 cu->cu_role = BSTP_ROLE_DESIGNATED;
478 break;
479 }
480 }
481
482 void
483 bstp_send_bpdu(struct bstp_state *bs, struct bstp_port *bp,
484 struct bstp_cbpdu *bpdu)
485 {
486 struct ifnet *ifp = bp->bp_ifp;
487 struct mbuf *m;
488 struct ether_header *eh;
489 int s, error;
490
491 s = splnet();
492 if (ifp == NULL || (ifp->if_flags & IFF_RUNNING) == 0)
493 goto done;
494
495 #ifdef ALTQ
496 if (!ALTQ_IS_ENABLED(&ifp->if_snd))
497 #endif
498 if (IF_QFULL(&ifp->if_snd))
499 goto done;
500
501 MGETHDR(m, M_DONTWAIT, MT_DATA);
502 if (m == NULL)
503 goto done;
504
505 eh = mtod(m, struct ether_header *);
506
507 bpdu->cbu_ssap = bpdu->cbu_dsap = LLC_8021D_LSAP;
508 bpdu->cbu_ctl = LLC_UI;
509 bpdu->cbu_protoid = htons(BSTP_PROTO_ID);
510
511 memcpy(eh->ether_shost, LLADDR(ifp->if_sadl), ETHER_ADDR_LEN);
512 memcpy(eh->ether_dhost, bstp_etheraddr, ETHER_ADDR_LEN);
513
514 switch (bpdu->cbu_bpdutype) {
515 case BSTP_MSGTYPE_CFG:
516 bpdu->cbu_protover = BSTP_PROTO_STP;
517 m->m_pkthdr.len = sizeof(*eh) + BSTP_BPDU_STP_LEN;
518 eh->ether_type = htons(BSTP_BPDU_STP_LEN);
519 memcpy(mtod(m, caddr_t) + sizeof(*eh), bpdu,
520 BSTP_BPDU_STP_LEN);
521 break;
522 case BSTP_MSGTYPE_RSTP:
523 bpdu->cbu_protover = BSTP_PROTO_RSTP;
524 bpdu->cbu_versionlen = htons(0);
525 m->m_pkthdr.len = sizeof(*eh) + BSTP_BPDU_RSTP_LEN;
526 eh->ether_type = htons(BSTP_BPDU_RSTP_LEN);
527 memcpy(mtod(m, caddr_t) + sizeof(*eh), bpdu,
528 BSTP_BPDU_RSTP_LEN);
529 break;
530 default:
531 panic("not implemented");
532 }
533 m->m_pkthdr.rcvif = ifp;
534 m->m_len = m->m_pkthdr.len;
535
536 bp->bp_txcount++;
537 IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error);
538 if (error == 0 && (ifp->if_flags & IFF_OACTIVE) == 0)
539 (*ifp->if_start)(ifp);
540 done:
541 splx(s);
542 }
543
544 int
545 bstp_pdu_flags(struct bstp_port *bp)
546 {
547 int flags = 0;
548
549 if (bp->bp_proposing && bp->bp_state != BSTP_IFSTATE_FORWARDING)
550 flags |= BSTP_PDU_F_P;
551
552 if (bp->bp_agree)
553 flags |= BSTP_PDU_F_A;
554
555 if (bp->bp_tc_timer.active)
556 flags |= BSTP_PDU_F_TC;
557
558 if (bp->bp_tc_ack)
559 flags |= BSTP_PDU_F_TCA;
560
561 switch (bp->bp_state) {
562 case BSTP_IFSTATE_LEARNING:
563 flags |= BSTP_PDU_F_L;
564 break;
565 case BSTP_IFSTATE_FORWARDING:
566 flags |= (BSTP_PDU_F_L | BSTP_PDU_F_F);
567 break;
568 }
569
570 switch (bp->bp_role) {
571 case BSTP_ROLE_ROOT:
572 flags |= (BSTP_PDU_F_ROOT << BSTP_PDU_PRSHIFT);
573 break;
574 case BSTP_ROLE_ALTERNATE:
575 case BSTP_ROLE_BACKUP:
576 flags |= (BSTP_PDU_F_ALT << BSTP_PDU_PRSHIFT);
577 break;
578 case BSTP_ROLE_DESIGNATED:
579 flags |= (BSTP_PDU_F_DESG << BSTP_PDU_PRSHIFT);
580 break;
581 }
582
583
584 switch (bp->bp_protover) {
585 case BSTP_PROTO_STP:
586 flags &= BSTP_PDU_STPMASK;
587 break;
588 case BSTP_PROTO_RSTP:
589 flags &= BSTP_PDU_RSTPMASK;
590 break;
591 }
592 return (flags);
593 }
594
595 struct mbuf *
596 bstp_input(struct bstp_state *bs, struct bstp_port *bp,
597 struct ether_header *eh, struct mbuf *m)
598 {
599 struct bstp_tbpdu tpdu;
600 u_int16_t len;
601
602 if (bs == NULL || bp == NULL || bp->bp_active == 0)
603 goto out;
604
605 len = ntohs(eh->ether_type);
606 if (len < sizeof(tpdu))
607 goto out;
608 if (m->m_pkthdr.len > len)
609 m_adj(m, len - m->m_pkthdr.len);
610 if ((m = m_pullup(m, sizeof(tpdu))) == NULL)
611 goto out;
612 bcopy(mtod(m, struct tpdu *), &tpdu, sizeof(tpdu));
613
614 if (tpdu.tbu_dsap != LLC_8021D_LSAP ||
615 tpdu.tbu_ssap != LLC_8021D_LSAP ||
616 tpdu.tbu_ctl != LLC_UI)
617 goto out;
618 if (tpdu.tbu_protoid != BSTP_PROTO_ID)
619 goto out;
620
621
622
623
624
625 if (tpdu.tbu_protover > BSTP_PROTO_MAX)
626 tpdu.tbu_protover = BSTP_PROTO_MAX;
627
628 if (tpdu.tbu_protover != bp->bp_protover) {
629
630
631
632
633 if (bp->bp_flags & BSTP_PORT_CANMIGRATE)
634 bstp_set_port_proto(bp, tpdu.tbu_protover);
635 else
636 goto out;
637 }
638
639
640 bp->bp_operedge = 0;
641 bstp_timer_start(&bp->bp_edge_delay_timer,
642 BSTP_DEFAULT_MIGRATE_DELAY);
643
644 switch (tpdu.tbu_protover) {
645 case BSTP_PROTO_STP:
646 bstp_received_stp(bs, bp, &m, &tpdu);
647 break;
648 case BSTP_PROTO_RSTP:
649 bstp_received_rstp(bs, bp, &m, &tpdu);
650 break;
651 }
652 out:
653 if (m)
654 m_freem(m);
655 return (NULL);
656 }
657
658 void
659 bstp_received_stp(struct bstp_state *bs, struct bstp_port *bp,
660 struct mbuf **mp, struct bstp_tbpdu *tpdu)
661 {
662 struct bstp_cbpdu cpdu;
663 struct bstp_config_unit *cu = &bp->bp_msg_cu;
664 struct bstp_tcn_unit tu;
665
666 switch (tpdu->tbu_bpdutype) {
667 case BSTP_MSGTYPE_TCN:
668 tu.tu_message_type = tpdu->tbu_bpdutype;
669 bstp_received_tcn(bs, bp, &tu);
670 break;
671 case BSTP_MSGTYPE_CFG:
672 if ((*mp)->m_len < BSTP_BPDU_STP_LEN &&
673 (*mp = m_pullup(*mp, BSTP_BPDU_STP_LEN)) == NULL)
674 return;
675 memcpy(&cpdu, mtod(*mp, caddr_t), BSTP_BPDU_STP_LEN);
676
677 bstp_decode_bpdu(bp, &cpdu, cu);
678 bstp_received_bpdu(bs, bp, cu);
679 break;
680 }
681 }
682
683 void
684 bstp_received_rstp(struct bstp_state *bs, struct bstp_port *bp,
685 struct mbuf **mp, struct bstp_tbpdu *tpdu)
686 {
687 struct bstp_cbpdu cpdu;
688 struct bstp_config_unit *cu = &bp->bp_msg_cu;
689
690 if (tpdu->tbu_bpdutype != BSTP_MSGTYPE_RSTP)
691 return;
692
693 if ((*mp)->m_len < BSTP_BPDU_RSTP_LEN &&
694 (*mp = m_pullup(*mp, BSTP_BPDU_RSTP_LEN)) == NULL)
695 return;
696 memcpy(&cpdu, mtod(*mp, caddr_t), BSTP_BPDU_RSTP_LEN);
697
698 bstp_decode_bpdu(bp, &cpdu, cu);
699 bstp_received_bpdu(bs, bp, cu);
700 }
701
702 void
703 bstp_received_tcn(struct bstp_state *bs, struct bstp_port *bp,
704 struct bstp_tcn_unit *tcn)
705 {
706 bp->bp_rcvdtcn = 1;
707 bstp_update_tc(bp);
708 }
709
710 void
711 bstp_received_bpdu(struct bstp_state *bs, struct bstp_port *bp,
712 struct bstp_config_unit *cu)
713 {
714 int type;
715
716
717 switch (bp->bp_infois) {
718 case BSTP_INFO_DISABLED:
719 case BSTP_INFO_AGED:
720 return;
721 }
722
723 type = bstp_pdu_rcvtype(bp, cu);
724
725 switch (type) {
726 case BSTP_PDU_SUPERIOR:
727 bs->bs_allsynced = 0;
728 bp->bp_agreed = 0;
729 bp->bp_proposing = 0;
730
731 if (cu->cu_proposal && cu->cu_forwarding == 0)
732 bp->bp_proposed = 1;
733 if (cu->cu_topology_change)
734 bp->bp_rcvdtc = 1;
735 if (cu->cu_topology_change_ack)
736 bp->bp_rcvdtca = 1;
737
738 if (bp->bp_agree &&
739 !bstp_pdu_bettersame(bp, BSTP_INFO_RECIEVED))
740 bp->bp_agree = 0;
741
742
743 bp->bp_port_pv = cu->cu_pv;
744 bp->bp_port_msg_age = cu->cu_message_age;
745 bp->bp_port_max_age = cu->cu_max_age;
746 bp->bp_port_fdelay = cu->cu_forward_delay;
747 bp->bp_port_htime =
748 (cu->cu_hello_time > BSTP_MIN_HELLO_TIME ?
749 cu->cu_hello_time : BSTP_MIN_HELLO_TIME);
750
751
752 bstp_set_timer_msgage(bp);
753
754 bp->bp_infois = BSTP_INFO_RECIEVED;
755 bstp_assign_roles(bs);
756 break;
757
758 case BSTP_PDU_REPEATED:
759 if (cu->cu_proposal && cu->cu_forwarding == 0)
760 bp->bp_proposed = 1;
761 if (cu->cu_topology_change)
762 bp->bp_rcvdtc = 1;
763 if (cu->cu_topology_change_ack)
764 bp->bp_rcvdtca = 1;
765
766
767 bstp_set_timer_msgage(bp);
768 break;
769
770 case BSTP_PDU_INFERIOR:
771 if (cu->cu_learning) {
772 bp->bp_agreed = 1;
773 bp->bp_proposing = 0;
774 }
775 break;
776
777 case BSTP_PDU_INFERIORALT:
778
779
780
781
782 if (cu->cu_agree && bp->bp_ptp_link) {
783 bp->bp_agreed = 1;
784 bp->bp_proposing = 0;
785 } else
786 bp->bp_agreed = 0;
787
788 if (cu->cu_topology_change)
789 bp->bp_rcvdtc = 1;
790 if (cu->cu_topology_change_ack)
791 bp->bp_rcvdtca = 1;
792 break;
793
794 case BSTP_PDU_OTHER:
795 return;
796 }
797
798
799 bstp_update_state(bs, bp);
800 }
801
802 int
803 bstp_pdu_rcvtype(struct bstp_port *bp, struct bstp_config_unit *cu)
804 {
805 int type;
806
807
808 type = BSTP_PDU_OTHER;
809
810 switch (cu->cu_role) {
811 case BSTP_ROLE_DESIGNATED:
812 if (bstp_info_superior(&bp->bp_port_pv, &cu->cu_pv))
813
814 type = BSTP_PDU_SUPERIOR;
815 else if (bstp_info_cmp(&bp->bp_port_pv, &cu->cu_pv) ==
816 INFO_SAME) {
817 if (bp->bp_port_msg_age != cu->cu_message_age ||
818 bp->bp_port_max_age != cu->cu_max_age ||
819 bp->bp_port_fdelay != cu->cu_forward_delay ||
820 bp->bp_port_htime != cu->cu_hello_time)
821
822 type = BSTP_PDU_SUPERIOR;
823 else
824
825 type = BSTP_PDU_REPEATED;
826 } else
827
828 type = BSTP_PDU_INFERIOR;
829
830 break;
831
832 case BSTP_ROLE_ROOT:
833 case BSTP_ROLE_ALTERNATE:
834 case BSTP_ROLE_BACKUP:
835 if (bstp_info_cmp(&bp->bp_port_pv, &cu->cu_pv) <= INFO_SAME)
836
837
838
839
840 type = BSTP_PDU_INFERIORALT;
841 break;
842 }
843
844 return (type);
845 }
846
847 int
848 bstp_pdu_bettersame(struct bstp_port *bp, int newinfo)
849 {
850 if (newinfo == BSTP_INFO_RECIEVED &&
851 bp->bp_infois == BSTP_INFO_RECIEVED &&
852 bstp_info_cmp(&bp->bp_port_pv, &bp->bp_msg_cu.cu_pv) >= INFO_SAME)
853 return (1);
854
855 if (newinfo == BSTP_INFO_MINE &&
856 bp->bp_infois == BSTP_INFO_MINE &&
857 bstp_info_cmp(&bp->bp_port_pv, &bp->bp_desg_pv) >= INFO_SAME)
858 return (1);
859
860 return (0);
861 }
862
863 int
864 bstp_info_cmp(struct bstp_pri_vector *pv,
865 struct bstp_pri_vector *cpv)
866 {
867 if (cpv->pv_root_id < pv->pv_root_id)
868 return (INFO_BETTER);
869 if (cpv->pv_root_id > pv->pv_root_id)
870 return (INFO_WORSE);
871
872 if (cpv->pv_cost < pv->pv_cost)
873 return (INFO_BETTER);
874 if (cpv->pv_cost > pv->pv_cost)
875 return (INFO_WORSE);
876
877 if (cpv->pv_dbridge_id < pv->pv_dbridge_id)
878 return (INFO_BETTER);
879 if (cpv->pv_dbridge_id > pv->pv_dbridge_id)
880 return (INFO_WORSE);
881
882 if (cpv->pv_dport_id < pv->pv_dport_id)
883 return (INFO_BETTER);
884 if (cpv->pv_dport_id > pv->pv_dport_id)
885 return (INFO_WORSE);
886
887 return (INFO_SAME);
888 }
889
890
891
892
893
894
895
896 int
897 bstp_info_superior(struct bstp_pri_vector *pv,
898 struct bstp_pri_vector *cpv)
899 {
900 if (bstp_info_cmp(pv, cpv) == INFO_BETTER ||
901 (bstp_same_bridgeid(pv->pv_dbridge_id, cpv->pv_dbridge_id) &&
902 (cpv->pv_dport_id & 0xfff) == (pv->pv_dport_id & 0xfff)))
903 return (1);
904 return (0);
905 }
906
907 void
908 bstp_assign_roles(struct bstp_state *bs)
909 {
910 struct bstp_port *bp, *rbp = NULL;
911 struct bstp_pri_vector pv;
912
913
914 bs->bs_root_pv = bs->bs_bridge_pv;
915 bs->bs_root_msg_age = 0;
916 bs->bs_root_max_age = bs->bs_bridge_max_age;
917 bs->bs_root_fdelay = bs->bs_bridge_fdelay;
918 bs->bs_root_htime = bs->bs_bridge_htime;
919 bs->bs_root_port = NULL;
920
921
922 LIST_FOREACH(bp, &bs->bs_bplist, bp_next) {
923 if (bp->bp_infois != BSTP_INFO_RECIEVED)
924 continue;
925
926 pv = bp->bp_port_pv;
927 pv.pv_cost += bp->bp_path_cost;
928
929
930
931
932
933
934 if (bstp_same_bridgeid(pv.pv_dbridge_id,
935 bs->bs_bridge_pv.pv_dbridge_id) == 0 &&
936 bstp_info_cmp(&bs->bs_root_pv, &pv) == INFO_BETTER) {
937
938 bs->bs_root_pv = pv;
939 bs->bs_root_msg_age = bp->bp_port_msg_age +
940 BSTP_MESSAGE_AGE_INCR;
941 bs->bs_root_max_age = bp->bp_port_max_age;
942 bs->bs_root_fdelay = bp->bp_port_fdelay;
943 bs->bs_root_htime = bp->bp_port_htime;
944 rbp = bp;
945 }
946 }
947
948 LIST_FOREACH(bp, &bs->bs_bplist, bp_next) {
949
950 bp->bp_desg_pv.pv_root_id = bs->bs_root_pv.pv_root_id;
951 bp->bp_desg_pv.pv_cost = bs->bs_root_pv.pv_cost;
952 bp->bp_desg_pv.pv_dbridge_id = bs->bs_bridge_pv.pv_dbridge_id;
953 bp->bp_desg_pv.pv_dport_id = bp->bp_port_id;
954 bp->bp_desg_pv.pv_port_id = bp->bp_port_id;
955
956
957 bp->bp_desg_msg_age = bs->bs_root_msg_age;
958 bp->bp_desg_max_age = bs->bs_root_max_age;
959 bp->bp_desg_fdelay = bs->bs_root_fdelay;
960 bp->bp_desg_htime = bs->bs_bridge_htime;
961
962
963 switch (bp->bp_infois) {
964 case BSTP_INFO_DISABLED:
965 bstp_set_port_role(bp, BSTP_ROLE_DISABLED);
966 break;
967
968 case BSTP_INFO_AGED:
969 bstp_set_port_role(bp, BSTP_ROLE_DESIGNATED);
970 bstp_update_info(bp);
971 break;
972
973 case BSTP_INFO_MINE:
974 bstp_set_port_role(bp, BSTP_ROLE_DESIGNATED);
975
976 if (bstp_info_cmp(&bp->bp_port_pv,
977 &bp->bp_desg_pv) != INFO_SAME ||
978 (rbp != NULL &&
979 (bp->bp_port_msg_age != rbp->bp_port_msg_age ||
980 bp->bp_port_max_age != rbp->bp_port_max_age ||
981 bp->bp_port_fdelay != rbp->bp_port_fdelay ||
982 bp->bp_port_htime != rbp->bp_port_htime)))
983 bstp_update_info(bp);
984 break;
985
986 case BSTP_INFO_RECIEVED:
987 if (bp == rbp) {
988
989
990
991
992 bstp_set_port_role(bp, BSTP_ROLE_ROOT);
993 bs->bs_root_port = bp;
994 } else if (bstp_info_cmp(&bp->bp_port_pv,
995 &bp->bp_desg_pv) == INFO_BETTER) {
996
997
998
999
1000 bstp_set_port_role(bp, BSTP_ROLE_DESIGNATED);
1001 bstp_update_info(bp);
1002 } else {
1003 if (bstp_same_bridgeid(
1004 bp->bp_port_pv.pv_dbridge_id,
1005 bs->bs_bridge_pv.pv_dbridge_id)) {
1006
1007
1008
1009
1010 bstp_set_port_role(bp,
1011 BSTP_ROLE_BACKUP);
1012 } else {
1013
1014
1015
1016
1017 bstp_set_port_role(bp,
1018 BSTP_ROLE_ALTERNATE);
1019 }
1020 }
1021 break;
1022 }
1023 }
1024 }
1025
1026 void
1027 bstp_update_state(struct bstp_state *bs, struct bstp_port *bp)
1028 {
1029 struct bstp_port *bp2;
1030 int synced;
1031
1032
1033 if (!bs->bs_allsynced) {
1034 synced = 1;
1035 LIST_FOREACH(bp2, &bs->bs_bplist, bp_next) {
1036 if (!(bp->bp_synced ||
1037 bp->bp_role == BSTP_ROLE_ROOT)) {
1038 synced = 0;
1039 break;
1040 }
1041 }
1042 bs->bs_allsynced = synced;
1043 }
1044
1045 bstp_update_roles(bs, bp);
1046 bstp_update_tc(bp);
1047 }
1048
1049 void
1050 bstp_update_roles(struct bstp_state *bs, struct bstp_port *bp)
1051 {
1052 switch (bp->bp_role) {
1053 case BSTP_ROLE_DISABLED:
1054
1055 if (bp->bp_sync || !bp->bp_synced || bp->bp_reroot) {
1056 bp->bp_sync = 0;
1057 bp->bp_synced = 1;
1058 bp->bp_reroot = 0;
1059 }
1060 break;
1061
1062 case BSTP_ROLE_ALTERNATE:
1063 case BSTP_ROLE_BACKUP:
1064 if ((bs->bs_allsynced && !bp->bp_agree) ||
1065 (bp->bp_proposed && bp->bp_agree)) {
1066 bp->bp_proposed = 0;
1067 bp->bp_agree = 1;
1068 bp->bp_flags |= BSTP_PORT_NEWINFO;
1069 DPRINTF("%s -> ALTERNATE_AGREED\n",
1070 bp->bp_ifp->if_xname);
1071 }
1072
1073 if (bp->bp_proposed && !bp->bp_agree) {
1074 bstp_set_all_sync(bs);
1075 bp->bp_proposed = 0;
1076 DPRINTF("%s -> ALTERNATE_PROPOSED\n",
1077 bp->bp_ifp->if_xname);
1078 }
1079
1080
1081 if (bp->bp_sync || !bp->bp_synced || bp->bp_reroot) {
1082 bp->bp_sync = 0;
1083 bp->bp_synced = 1;
1084 bp->bp_reroot = 0;
1085 DPRINTF("%s -> ALTERNATE_PORT\n", bp->bp_ifp->if_xname);
1086 }
1087 break;
1088
1089 case BSTP_ROLE_ROOT:
1090 if (bp->bp_state != BSTP_IFSTATE_FORWARDING && !bp->bp_reroot) {
1091 bstp_set_all_reroot(bs);
1092 DPRINTF("%s -> ROOT_REROOT\n", bp->bp_ifp->if_xname);
1093 }
1094
1095 if ((bs->bs_allsynced && !bp->bp_agree) ||
1096 (bp->bp_proposed && bp->bp_agree)) {
1097 bp->bp_proposed = 0;
1098 bp->bp_sync = 0;
1099 bp->bp_agree = 1;
1100 bp->bp_flags |= BSTP_PORT_NEWINFO;
1101 DPRINTF("%s -> ROOT_AGREED\n", bp->bp_ifp->if_xname);
1102 }
1103
1104 if (bp->bp_proposed && !bp->bp_agree) {
1105 bstp_set_all_sync(bs);
1106 bp->bp_proposed = 0;
1107 DPRINTF("%s -> ROOT_PROPOSED\n", bp->bp_ifp->if_xname);
1108 }
1109
1110 if (bp->bp_state != BSTP_IFSTATE_FORWARDING &&
1111 (bp->bp_forward_delay_timer.active == 0 ||
1112 (bstp_rerooted(bs, bp) &&
1113 bp->bp_recent_backup_timer.active == 0 &&
1114 bp->bp_protover == BSTP_PROTO_RSTP))) {
1115 switch (bp->bp_state) {
1116 case BSTP_IFSTATE_DISCARDING:
1117 bstp_set_port_state(bp, BSTP_IFSTATE_LEARNING);
1118 break;
1119 case BSTP_IFSTATE_LEARNING:
1120 bstp_set_port_state(bp,
1121 BSTP_IFSTATE_FORWARDING);
1122 break;
1123 }
1124 }
1125
1126 if (bp->bp_state == BSTP_IFSTATE_FORWARDING && bp->bp_reroot) {
1127 bp->bp_reroot = 0;
1128 DPRINTF("%s -> ROOT_REROOTED\n", bp->bp_ifp->if_xname);
1129 }
1130 break;
1131
1132 case BSTP_ROLE_DESIGNATED:
1133 if (bp->bp_recent_root_timer.active == 0 && bp->bp_reroot) {
1134 bp->bp_reroot = 0;
1135 DPRINTF("%s -> DESIGNATED_RETIRED\n",
1136 bp->bp_ifp->if_xname);
1137 }
1138
1139 if ((bp->bp_state == BSTP_IFSTATE_DISCARDING &&
1140 !bp->bp_synced) || (bp->bp_agreed && !bp->bp_synced) ||
1141 (bp->bp_operedge && !bp->bp_synced) ||
1142 (bp->bp_sync && bp->bp_synced)) {
1143 bstp_timer_stop(&bp->bp_recent_root_timer);
1144 bp->bp_synced = 1;
1145 bp->bp_sync = 0;
1146 DPRINTF("%s -> DESIGNATED_SYNCED\n",
1147 bp->bp_ifp->if_xname);
1148 }
1149
1150 if (bp->bp_state != BSTP_IFSTATE_FORWARDING &&
1151 !bp->bp_agreed && !bp->bp_proposing &&
1152 !bp->bp_operedge) {
1153 bp->bp_proposing = 1;
1154 bp->bp_flags |= BSTP_PORT_NEWINFO;
1155 bstp_timer_start(&bp->bp_edge_delay_timer,
1156 (bp->bp_ptp_link ? BSTP_DEFAULT_MIGRATE_DELAY :
1157 bp->bp_desg_max_age));
1158 DPRINTF("%s -> DESIGNATED_PROPOSE\n",
1159 bp->bp_ifp->if_xname);
1160 }
1161
1162 if (bp->bp_state != BSTP_IFSTATE_FORWARDING &&
1163 (bp->bp_forward_delay_timer.active == 0 || bp->bp_agreed ||
1164 bp->bp_operedge) &&
1165 (bp->bp_recent_root_timer.active == 0 || !bp->bp_reroot) &&
1166 !bp->bp_sync) {
1167 if (bp->bp_agreed)
1168 DPRINTF("%s -> AGREED\n", bp->bp_ifp->if_xname);
1169
1170
1171
1172
1173 if (bp->bp_agreed || bp->bp_operedge ||
1174 bp->bp_state == BSTP_IFSTATE_LEARNING) {
1175 bstp_set_port_state(bp,
1176 BSTP_IFSTATE_FORWARDING);
1177 bp->bp_agreed = bp->bp_protover;
1178 } else if (bp->bp_state == BSTP_IFSTATE_DISCARDING)
1179 bstp_set_port_state(bp, BSTP_IFSTATE_LEARNING);
1180 }
1181
1182 if (((bp->bp_sync && !bp->bp_synced) ||
1183 (bp->bp_reroot && bp->bp_recent_root_timer.active) ||
1184 (bp->bp_flags & BSTP_PORT_DISPUTED)) && !bp->bp_operedge &&
1185 bp->bp_state != BSTP_IFSTATE_DISCARDING) {
1186 bstp_set_port_state(bp, BSTP_IFSTATE_DISCARDING);
1187 bp->bp_flags &= ~BSTP_PORT_DISPUTED;
1188 bstp_timer_start(&bp->bp_forward_delay_timer,
1189 bp->bp_protover == BSTP_PROTO_RSTP ?
1190 bp->bp_desg_htime : bp->bp_desg_fdelay);
1191 DPRINTF("%s -> DESIGNATED_DISCARD\n",
1192 bp->bp_ifp->if_xname);
1193 }
1194 break;
1195 }
1196
1197 if (bp->bp_flags & BSTP_PORT_NEWINFO)
1198 bstp_transmit(bs, bp);
1199 }
1200
1201 void
1202 bstp_update_tc(struct bstp_port *bp)
1203 {
1204 switch (bp->bp_tcstate) {
1205 case BSTP_TCSTATE_ACTIVE:
1206 if ((bp->bp_role != BSTP_ROLE_DESIGNATED &&
1207 bp->bp_role != BSTP_ROLE_ROOT) || bp->bp_operedge)
1208 bstp_set_port_tc(bp, BSTP_TCSTATE_LEARNING);
1209
1210 if (bp->bp_rcvdtcn)
1211 bstp_set_port_tc(bp, BSTP_TCSTATE_TCN);
1212 if (bp->bp_rcvdtc)
1213 bstp_set_port_tc(bp, BSTP_TCSTATE_TC);
1214
1215 if (bp->bp_tc_prop && !bp->bp_operedge)
1216 bstp_set_port_tc(bp, BSTP_TCSTATE_PROPAG);
1217
1218 if (bp->bp_rcvdtca)
1219 bstp_set_port_tc(bp, BSTP_TCSTATE_ACK);
1220 break;
1221
1222 case BSTP_TCSTATE_INACTIVE:
1223 if ((bp->bp_state == BSTP_IFSTATE_LEARNING ||
1224 bp->bp_state == BSTP_IFSTATE_FORWARDING) &&
1225 bp->bp_fdbflush == 0)
1226 bstp_set_port_tc(bp, BSTP_TCSTATE_LEARNING);
1227 break;
1228
1229 case BSTP_TCSTATE_LEARNING:
1230 if (bp->bp_rcvdtc || bp->bp_rcvdtcn || bp->bp_rcvdtca ||
1231 bp->bp_tc_prop)
1232 bstp_set_port_tc(bp, BSTP_TCSTATE_LEARNING);
1233 else if (bp->bp_role != BSTP_ROLE_DESIGNATED &&
1234 bp->bp_role != BSTP_ROLE_ROOT &&
1235 bp->bp_state == BSTP_IFSTATE_DISCARDING)
1236 bstp_set_port_tc(bp, BSTP_TCSTATE_INACTIVE);
1237
1238 if ((bp->bp_role == BSTP_ROLE_DESIGNATED ||
1239 bp->bp_role == BSTP_ROLE_ROOT) &&
1240 bp->bp_state == BSTP_IFSTATE_FORWARDING &&
1241 !bp->bp_operedge)
1242 bstp_set_port_tc(bp, BSTP_TCSTATE_DETECTED);
1243 break;
1244
1245
1246 case BSTP_TCSTATE_DETECTED:
1247 case BSTP_TCSTATE_TCN:
1248 case BSTP_TCSTATE_TC:
1249 case BSTP_TCSTATE_PROPAG:
1250 case BSTP_TCSTATE_ACK:
1251 DPRINTF("Invalid TC state for %s\n",
1252 bp->bp_ifp->if_xname);
1253 break;
1254 }
1255
1256 }
1257
1258 void
1259 bstp_update_info(struct bstp_port *bp)
1260 {
1261 struct bstp_state *bs = bp->bp_bs;
1262
1263 bp->bp_proposing = 0;
1264 bp->bp_proposed = 0;
1265
1266 if (bp->bp_agreed && !bstp_pdu_bettersame(bp, BSTP_INFO_MINE))
1267 bp->bp_agreed = 0;
1268
1269 if (bp->bp_synced && !bp->bp_agreed) {
1270 bp->bp_synced = 0;
1271 bs->bs_allsynced = 0;
1272 }
1273
1274
1275 bp->bp_port_pv = bp->bp_desg_pv;
1276 bp->bp_port_msg_age = bp->bp_desg_msg_age;
1277 bp->bp_port_max_age = bp->bp_desg_max_age;
1278 bp->bp_port_fdelay = bp->bp_desg_fdelay;
1279 bp->bp_port_htime = bp->bp_desg_htime;
1280 bp->bp_infois = BSTP_INFO_MINE;
1281
1282
1283 bp->bp_flags |= BSTP_PORT_NEWINFO;
1284 }
1285
1286
1287 void
1288 bstp_set_other_tcprop(struct bstp_port *bp)
1289 {
1290 struct bstp_state *bs = bp->bp_bs;
1291 struct bstp_port *bp2;
1292
1293 LIST_FOREACH(bp2, &bs->bs_bplist, bp_next) {
1294 if (bp2 == bp)
1295 continue;
1296 bp2->bp_tc_prop = 1;
1297 }
1298 }
1299
1300 void
1301 bstp_set_all_reroot(struct bstp_state *bs)
1302 {
1303 struct bstp_port *bp;
1304
1305 LIST_FOREACH(bp, &bs->bs_bplist, bp_next)
1306 bp->bp_reroot = 1;
1307 }
1308
1309 void
1310 bstp_set_all_sync(struct bstp_state *bs)
1311 {
1312 struct bstp_port *bp;
1313
1314 LIST_FOREACH(bp, &bs->bs_bplist, bp_next) {
1315 bp->bp_sync = 1;
1316 bp->bp_synced = 0;
1317 }
1318
1319 bs->bs_allsynced = 0;
1320 }
1321
1322 void
1323 bstp_set_port_state(struct bstp_port *bp, int state)
1324 {
1325 if (bp->bp_state == state)
1326 return;
1327
1328 bp->bp_state = state;
1329
1330 switch (bp->bp_state) {
1331 case BSTP_IFSTATE_DISCARDING:
1332 DPRINTF("state changed to DISCARDING on %s\n",
1333 bp->bp_ifp->if_xname);
1334 break;
1335
1336 case BSTP_IFSTATE_LEARNING:
1337 DPRINTF("state changed to LEARNING on %s\n",
1338 bp->bp_ifp->if_xname);
1339
1340 bstp_timer_start(&bp->bp_forward_delay_timer,
1341 bp->bp_protover == BSTP_PROTO_RSTP ?
1342 bp->bp_desg_htime : bp->bp_desg_fdelay);
1343 break;
1344
1345 case BSTP_IFSTATE_FORWARDING:
1346 DPRINTF("state changed to FORWARDING on %s\n",
1347 bp->bp_ifp->if_xname);
1348
1349 bstp_timer_stop(&bp->bp_forward_delay_timer);
1350
1351 bp->bp_forward_transitions++;
1352 break;
1353 }
1354 }
1355
1356 void
1357 bstp_set_port_role(struct bstp_port *bp, int role)
1358 {
1359 struct bstp_state *bs = bp->bp_bs;
1360
1361 if (bp->bp_role == role)
1362 return;
1363
1364
1365 switch (bp->bp_role) {
1366 case BSTP_ROLE_DISABLED:
1367 bstp_timer_start(&bp->bp_forward_delay_timer,
1368 bp->bp_desg_max_age);
1369 break;
1370
1371 case BSTP_ROLE_BACKUP:
1372 bstp_timer_start(&bp->bp_recent_backup_timer,
1373 bp->bp_desg_htime * 2);
1374
1375 case BSTP_ROLE_ALTERNATE:
1376 bstp_timer_start(&bp->bp_forward_delay_timer,
1377 bp->bp_desg_fdelay);
1378 bp->bp_sync = 0;
1379 bp->bp_synced = 1;
1380 bp->bp_reroot = 0;
1381 break;
1382
1383 case BSTP_ROLE_ROOT:
1384 bstp_timer_start(&bp->bp_recent_root_timer,
1385 BSTP_DEFAULT_FORWARD_DELAY);
1386 break;
1387 }
1388
1389 bp->bp_role = role;
1390
1391 bp->bp_proposing = 0;
1392 bs->bs_allsynced = 0;
1393
1394
1395 switch (bp->bp_role) {
1396 case BSTP_ROLE_DISABLED:
1397 case BSTP_ROLE_ALTERNATE:
1398 case BSTP_ROLE_BACKUP:
1399 DPRINTF("%s role -> ALT/BACK/DISABLED\n",
1400 bp->bp_ifp->if_xname);
1401 bstp_set_port_state(bp, BSTP_IFSTATE_DISCARDING);
1402 bstp_timer_stop(&bp->bp_recent_root_timer);
1403 bstp_timer_latch(&bp->bp_forward_delay_timer);
1404 bp->bp_sync = 0;
1405 bp->bp_synced = 1;
1406 bp->bp_reroot = 0;
1407 break;
1408
1409 case BSTP_ROLE_ROOT:
1410 DPRINTF("%s role -> ROOT\n",
1411 bp->bp_ifp->if_xname);
1412 bstp_set_port_state(bp, BSTP_IFSTATE_DISCARDING);
1413 bstp_timer_latch(&bp->bp_recent_root_timer);
1414 bp->bp_proposing = 0;
1415 break;
1416
1417 case BSTP_ROLE_DESIGNATED:
1418 DPRINTF("%s role -> DESIGNATED\n",
1419 bp->bp_ifp->if_xname);
1420 bstp_timer_start(&bp->bp_hello_timer,
1421 bp->bp_desg_htime);
1422 bp->bp_agree = 0;
1423 break;
1424 }
1425
1426
1427 bstp_update_tc(bp);
1428 }
1429
1430 void
1431 bstp_set_port_proto(struct bstp_port *bp, int proto)
1432 {
1433 struct bstp_state *bs = bp->bp_bs;
1434
1435
1436 switch (proto) {
1437 case BSTP_PROTO_STP:
1438
1439 bstp_timer_stop(&bp->bp_migrate_delay_timer);
1440
1441 bp->bp_operedge = 0;
1442 break;
1443
1444 case BSTP_PROTO_RSTP:
1445 bstp_timer_start(&bp->bp_migrate_delay_timer,
1446 bs->bs_migration_delay);
1447 break;
1448
1449 default:
1450 DPRINTF("Unsupported STP version %d\n", proto);
1451 return;
1452 }
1453
1454 bp->bp_protover = proto;
1455 bp->bp_flags &= ~BSTP_PORT_CANMIGRATE;
1456 }
1457
1458 void
1459 bstp_set_port_tc(struct bstp_port *bp, int state)
1460 {
1461 struct bstp_state *bs = bp->bp_bs;
1462
1463 bp->bp_tcstate = state;
1464
1465
1466 switch (bp->bp_tcstate) {
1467 case BSTP_TCSTATE_ACTIVE:
1468 DPRINTF("%s -> TC_ACTIVE\n", bp->bp_ifp->if_xname);
1469
1470 break;
1471
1472 case BSTP_TCSTATE_INACTIVE:
1473 bstp_timer_stop(&bp->bp_tc_timer);
1474
1475 bp->bp_fdbflush = 1;
1476 bstp_notify_rtage(bp->bp_ifp, 0);
1477 bp->bp_tc_ack = 0;
1478 DPRINTF("%s -> TC_INACTIVE\n", bp->bp_ifp->if_xname);
1479 break;
1480
1481 case BSTP_TCSTATE_LEARNING:
1482 bp->bp_rcvdtc = 0;
1483 bp->bp_rcvdtcn = 0;
1484 bp->bp_rcvdtca = 0;
1485 bp->bp_tc_prop = 0;
1486 DPRINTF("%s -> TC_LEARNING\n", bp->bp_ifp->if_xname);
1487 break;
1488
1489 case BSTP_TCSTATE_DETECTED:
1490 bstp_set_timer_tc(bp);
1491 bstp_set_other_tcprop(bp);
1492
1493 bp->bp_flags |= BSTP_PORT_NEWINFO;
1494 bstp_transmit(bs, bp);
1495 getmicrotime(&bs->bs_last_tc_time);
1496 DPRINTF("%s -> TC_DETECTED\n", bp->bp_ifp->if_xname);
1497 bp->bp_tcstate = BSTP_TCSTATE_ACTIVE;
1498 break;
1499
1500 case BSTP_TCSTATE_TCN:
1501 bstp_set_timer_tc(bp);
1502 DPRINTF("%s -> TC_TCN\n", bp->bp_ifp->if_xname);
1503
1504 case BSTP_TCSTATE_TC:
1505 bp->bp_rcvdtc = 0;
1506 bp->bp_rcvdtcn = 0;
1507 if (bp->bp_role == BSTP_ROLE_DESIGNATED)
1508 bp->bp_tc_ack = 1;
1509
1510 bstp_set_other_tcprop(bp);
1511 DPRINTF("%s -> TC_TC\n", bp->bp_ifp->if_xname);
1512 bp->bp_tcstate = BSTP_TCSTATE_ACTIVE;
1513 break;
1514
1515 case BSTP_TCSTATE_PROPAG:
1516
1517 bp->bp_fdbflush = 1;
1518 bstp_notify_rtage(bp->bp_ifp, 0);
1519 bp->bp_tc_prop = 0;
1520 bstp_set_timer_tc(bp);
1521 DPRINTF("%s -> TC_PROPAG\n", bp->bp_ifp->if_xname);
1522 bp->bp_tcstate = BSTP_TCSTATE_ACTIVE;
1523 break;
1524
1525 case BSTP_TCSTATE_ACK:
1526 bstp_timer_stop(&bp->bp_tc_timer);
1527 bp->bp_rcvdtca = 0;
1528 DPRINTF("%s -> TC_ACK\n", bp->bp_ifp->if_xname);
1529 bp->bp_tcstate = BSTP_TCSTATE_ACTIVE;
1530 break;
1531 }
1532 }
1533
1534 void
1535 bstp_set_timer_tc(struct bstp_port *bp)
1536 {
1537 struct bstp_state *bs = bp->bp_bs;
1538
1539 if (bp->bp_tc_timer.active)
1540 return;
1541
1542 switch (bp->bp_protover) {
1543 case BSTP_PROTO_RSTP:
1544 bstp_timer_start(&bp->bp_tc_timer,
1545 bp->bp_desg_htime + BSTP_TICK_VAL);
1546 bp->bp_flags |= BSTP_PORT_NEWINFO;
1547 break;
1548 case BSTP_PROTO_STP:
1549 bstp_timer_start(&bp->bp_tc_timer,
1550 bs->bs_root_max_age + bs->bs_root_fdelay);
1551 break;
1552 }
1553 }
1554
1555 void
1556 bstp_set_timer_msgage(struct bstp_port *bp)
1557 {
1558 if (bp->bp_port_msg_age + BSTP_MESSAGE_AGE_INCR <=
1559 bp->bp_port_max_age) {
1560 bstp_timer_start(&bp->bp_message_age_timer,
1561 bp->bp_port_htime * 3);
1562 } else
1563
1564 bstp_timer_start(&bp->bp_message_age_timer, 0);
1565 }
1566
1567 int
1568 bstp_rerooted(struct bstp_state *bs, struct bstp_port *bp)
1569 {
1570 struct bstp_port *bp2;
1571 int rr_set = 0;
1572
1573 LIST_FOREACH(bp2, &bs->bs_bplist, bp_next) {
1574 if (bp2 == bp)
1575 continue;
1576 if (bp2->bp_recent_root_timer.active) {
1577 rr_set = 1;
1578 break;
1579 }
1580 }
1581 return (!rr_set);
1582 }
1583
1584
1585
1586
1587 u_int32_t
1588 bstp_calc_path_cost(struct bstp_port *bp)
1589 {
1590 struct ifnet *ifp = bp->bp_ifp;
1591 u_int32_t path_cost;
1592
1593
1594 if (bp->bp_flags & BSTP_PORT_ADMCOST)
1595 return bp->bp_path_cost;
1596
1597 if (ifp->if_baudrate < 1000)
1598 return (BSTP_DEFAULT_PATH_COST);
1599
1600
1601 path_cost = 20000000000ULL / (ifp->if_baudrate / 1000);
1602
1603 if (path_cost > BSTP_MAX_PATH_COST)
1604 path_cost = BSTP_MAX_PATH_COST;
1605
1606
1607 if (bp->bp_protover == BSTP_PROTO_STP && path_cost > 65535)
1608 path_cost = 65535;
1609
1610 return (path_cost);
1611 }
1612
1613 void
1614 bstp_notify_rtage(void *arg, int pending)
1615 {
1616 struct bstp_port *bp = (struct bstp_port *)arg;
1617 int age = 0;
1618
1619 splassert(IPL_NET);
1620
1621 switch (bp->bp_protover) {
1622 case BSTP_PROTO_STP:
1623
1624 age = bp->bp_desg_fdelay / BSTP_TICK_VAL;
1625 break;
1626 case BSTP_PROTO_RSTP:
1627 age = 0;
1628 break;
1629 }
1630
1631 if (bp->bp_active == 1)
1632 bridge_rtagenode(bp->bp_ifp, age);
1633
1634
1635 bp->bp_fdbflush = 0;
1636 }
1637
1638 void
1639 bstp_ifstate(void *arg)
1640 {
1641 struct ifnet *ifp = (struct ifnet *)arg;
1642 struct bridge_softc *sc;
1643 struct bridge_iflist *p;
1644 struct bstp_port *bp;
1645 struct bstp_state *bs;
1646 int s;
1647
1648 if (ifp->if_type == IFT_BRIDGE)
1649 return;
1650 sc = (struct bridge_softc *)ifp->if_bridge;
1651
1652 s = splnet();
1653 LIST_FOREACH(p, &sc->sc_iflist, next) {
1654 if ((p->bif_flags & IFBIF_STP) == 0)
1655 continue;
1656 if (p->ifp == ifp)
1657 break;
1658 }
1659 if (p == LIST_END(&sc->sc_iflist))
1660 goto done;
1661 if ((bp = p->bif_stp) == NULL)
1662 goto done;
1663 if ((bs = bp->bp_bs) == NULL)
1664 goto done;
1665
1666
1667 bstp_ifupdstatus(bs, bp);
1668 bstp_update_state(bs, bp);
1669 done:
1670 splx(s);
1671 }
1672
1673 void
1674 bstp_ifupdstatus(struct bstp_state *bs, struct bstp_port *bp)
1675 {
1676 struct ifnet *ifp = bp->bp_ifp;
1677
1678 if (ifp == NULL)
1679 return;
1680
1681 bp->bp_path_cost = bstp_calc_path_cost(bp);
1682
1683 if ((ifp->if_flags & IFF_UP) &&
1684 ifp->if_link_state != LINK_STATE_DOWN) {
1685 if (bp->bp_flags & BSTP_PORT_AUTOPTP) {
1686
1687 bp->bp_ptp_link = ifp->if_link_state ==
1688 LINK_STATE_FULL_DUPLEX ? 1 : 0;
1689 }
1690
1691 if (bp->bp_infois == BSTP_INFO_DISABLED)
1692 bstp_enable_port(bs, bp);
1693 } else {
1694 if (bp->bp_infois != BSTP_INFO_DISABLED)
1695 bstp_disable_port(bs, bp);
1696 }
1697 }
1698
1699 void
1700 bstp_enable_port(struct bstp_state *bs, struct bstp_port *bp)
1701 {
1702 bp->bp_infois = BSTP_INFO_AGED;
1703 bstp_assign_roles(bs);
1704 }
1705
1706 void
1707 bstp_disable_port(struct bstp_state *bs, struct bstp_port *bp)
1708 {
1709 bp->bp_infois = BSTP_INFO_DISABLED;
1710 bstp_set_port_state(bp, BSTP_IFSTATE_DISCARDING);
1711 bstp_assign_roles(bs);
1712 }
1713
1714 void
1715 bstp_tick(void *arg)
1716 {
1717 struct bstp_state *bs = (struct bstp_state *)arg;
1718 struct bstp_port *bp;
1719 int s;
1720
1721 s = splnet();
1722 if ((bs->bs_ifflags & IFF_RUNNING) == 0) {
1723 splx(s);
1724 return;
1725 }
1726
1727
1728 if (bstp_timer_expired(&bs->bs_link_timer)) {
1729 LIST_FOREACH(bp, &bs->bs_bplist, bp_next)
1730 bstp_ifupdstatus(bs, bp);
1731 bstp_timer_start(&bs->bs_link_timer, BSTP_LINK_TIMER);
1732 }
1733
1734 LIST_FOREACH(bp, &bs->bs_bplist, bp_next) {
1735
1736 bstp_timer_expired(&bp->bp_tc_timer);
1737 bstp_timer_expired(&bp->bp_recent_root_timer);
1738 bstp_timer_expired(&bp->bp_forward_delay_timer);
1739 bstp_timer_expired(&bp->bp_recent_backup_timer);
1740
1741 if (bstp_timer_expired(&bp->bp_hello_timer))
1742 bstp_hello_timer_expiry(bs, bp);
1743
1744 if (bstp_timer_expired(&bp->bp_message_age_timer))
1745 bstp_message_age_expiry(bs, bp);
1746
1747 if (bstp_timer_expired(&bp->bp_migrate_delay_timer))
1748 bstp_migrate_delay_expiry(bs, bp);
1749
1750 if (bstp_timer_expired(&bp->bp_edge_delay_timer))
1751 bstp_edge_delay_expiry(bs, bp);
1752
1753
1754 bstp_update_state(bs, bp);
1755
1756 if (bp->bp_txcount > 0)
1757 bp->bp_txcount--;
1758 }
1759
1760 if (bs->bs_ifp->if_flags & IFF_RUNNING)
1761 timeout_add(&bs->bs_bstptimeout, hz);
1762
1763 splx(s);
1764 }
1765
1766 void
1767 bstp_timer_start(struct bstp_timer *t, u_int16_t v)
1768 {
1769 t->value = v;
1770 t->active = 1;
1771 t->latched = 0;
1772 }
1773
1774 void
1775 bstp_timer_stop(struct bstp_timer *t)
1776 {
1777 t->value = 0;
1778 t->active = 0;
1779 t->latched = 0;
1780 }
1781
1782 void
1783 bstp_timer_latch(struct bstp_timer *t)
1784 {
1785 t->latched = 1;
1786 t->active = 1;
1787 }
1788
1789 int
1790 bstp_timer_expired(struct bstp_timer *t)
1791 {
1792 if (t->active == 0 || t->latched)
1793 return (0);
1794 t->value -= BSTP_TICK_VAL;
1795 if (t->value <= 0) {
1796 bstp_timer_stop(t);
1797 return (1);
1798 }
1799 return (0);
1800 }
1801
1802 void
1803 bstp_hello_timer_expiry(struct bstp_state *bs, struct bstp_port *bp)
1804 {
1805 if ((bp->bp_flags & BSTP_PORT_NEWINFO) ||
1806 bp->bp_role == BSTP_ROLE_DESIGNATED ||
1807 (bp->bp_role == BSTP_ROLE_ROOT &&
1808 bp->bp_tc_timer.active == 1)) {
1809 bstp_timer_start(&bp->bp_hello_timer, bp->bp_desg_htime);
1810 bp->bp_flags |= BSTP_PORT_NEWINFO;
1811 bstp_transmit(bs, bp);
1812 }
1813 }
1814
1815 void
1816 bstp_message_age_expiry(struct bstp_state *bs, struct bstp_port *bp)
1817 {
1818 if (bp->bp_infois == BSTP_INFO_RECIEVED) {
1819 bp->bp_infois = BSTP_INFO_AGED;
1820 bstp_assign_roles(bs);
1821 DPRINTF("aged info on %s\n", bp->bp_ifp->if_xname);
1822 }
1823 }
1824
1825 void
1826 bstp_migrate_delay_expiry(struct bstp_state *bs, struct bstp_port *bp)
1827 {
1828 bp->bp_flags |= BSTP_PORT_CANMIGRATE;
1829 }
1830
1831 void
1832 bstp_edge_delay_expiry(struct bstp_state *bs, struct bstp_port *bp)
1833 {
1834 if ((bp->bp_flags & BSTP_PORT_AUTOEDGE) &&
1835 bp->bp_protover == BSTP_PROTO_RSTP && bp->bp_proposing &&
1836 bp->bp_role == BSTP_ROLE_DESIGNATED)
1837 bp->bp_operedge = 1;
1838 }
1839
1840 int
1841 bstp_addr_cmp(const u_int8_t *a, const u_int8_t *b)
1842 {
1843 int i, d;
1844
1845 for (i = 0, d = 0; i < ETHER_ADDR_LEN && d == 0; i++) {
1846 d = ((int)a[i]) - ((int)b[i]);
1847 }
1848
1849 return (d);
1850 }
1851
1852
1853
1854
1855 int
1856 bstp_same_bridgeid(u_int64_t id1, u_int64_t id2)
1857 {
1858 u_char addr1[ETHER_ADDR_LEN];
1859 u_char addr2[ETHER_ADDR_LEN];
1860
1861 PV2ADDR(id1, addr1);
1862 PV2ADDR(id2, addr2);
1863
1864 if (bstp_addr_cmp(addr1, addr2) == 0)
1865 return (1);
1866
1867 return (0);
1868 }
1869
1870 void
1871 bstp_initialization(struct bstp_state *bs)
1872 {
1873 struct bstp_port *bp;
1874 struct ifnet *ifp, *mif;
1875 u_char *e_addr;
1876
1877 if (LIST_EMPTY(&bs->bs_bplist)) {
1878 bstp_stop(bs);
1879 return;
1880 }
1881
1882 mif = NULL;
1883
1884
1885
1886
1887
1888
1889
1890
1891 TAILQ_FOREACH(ifp, &ifnet, if_list) {
1892 if (ifp->if_type != IFT_ETHER)
1893 continue;
1894 if (mif == NULL) {
1895 mif = ifp;
1896 continue;
1897 }
1898 if (bstp_addr_cmp(LLADDR(ifp->if_sadl),
1899 LLADDR(mif->if_sadl)) < 0) {
1900 mif = ifp;
1901 continue;
1902 }
1903 }
1904
1905 e_addr = LLADDR(mif->if_sadl);
1906 bs->bs_bridge_pv.pv_dbridge_id =
1907 (((u_int64_t)bs->bs_bridge_priority) << 48) |
1908 (((u_int64_t)e_addr[0]) << 40) |
1909 (((u_int64_t)e_addr[1]) << 32) |
1910 (((u_int64_t)e_addr[2]) << 24) |
1911 (((u_int64_t)e_addr[3]) << 16) |
1912 (((u_int64_t)e_addr[4]) << 8) |
1913 (((u_int64_t)e_addr[5]));
1914
1915 bs->bs_bridge_pv.pv_root_id = bs->bs_bridge_pv.pv_dbridge_id;
1916 bs->bs_bridge_pv.pv_cost = 0;
1917 bs->bs_bridge_pv.pv_dport_id = 0;
1918 bs->bs_bridge_pv.pv_port_id = 0;
1919
1920 if (!timeout_initialized(&bs->bs_bstptimeout))
1921 timeout_set(&bs->bs_bstptimeout, bstp_tick, bs);
1922 if (bs->bs_ifflags & IFF_RUNNING &&
1923 !timeout_pending(&bs->bs_bstptimeout))
1924 timeout_add(&bs->bs_bstptimeout, hz);
1925
1926 LIST_FOREACH(bp, &bs->bs_bplist, bp_next) {
1927 bp->bp_port_id = (bp->bp_priority << 8) |
1928 (bp->bp_ifp->if_index & 0xfff);
1929 bstp_ifupdstatus(bs, bp);
1930 }
1931
1932 bstp_assign_roles(bs);
1933 bstp_timer_start(&bs->bs_link_timer, BSTP_LINK_TIMER);
1934 }
1935
1936 struct bstp_state *
1937 bstp_create(struct ifnet *ifp)
1938 {
1939 struct bstp_state *bs;
1940 int s;
1941
1942 s = splnet();
1943 bs = (struct bstp_state *)malloc(sizeof(*bs), M_DEVBUF, M_WAITOK);
1944 bzero(bs, sizeof(*bs));
1945 LIST_INIT(&bs->bs_bplist);
1946
1947 bs->bs_ifp = ifp;
1948 bs->bs_bridge_max_age = BSTP_DEFAULT_MAX_AGE;
1949 bs->bs_bridge_htime = BSTP_DEFAULT_HELLO_TIME;
1950 bs->bs_bridge_fdelay = BSTP_DEFAULT_FORWARD_DELAY;
1951 bs->bs_bridge_priority = BSTP_DEFAULT_BRIDGE_PRIORITY;
1952 bs->bs_hold_time = BSTP_DEFAULT_HOLD_TIME;
1953 bs->bs_migration_delay = BSTP_DEFAULT_MIGRATE_DELAY;
1954 bs->bs_txholdcount = BSTP_DEFAULT_HOLD_COUNT;
1955 bs->bs_protover = BSTP_PROTO_RSTP;
1956
1957 getmicrotime(&bs->bs_last_tc_time);
1958
1959 LIST_INSERT_HEAD(&bstp_list, bs, bs_list);
1960 splx(s);
1961
1962 return (bs);
1963 }
1964
1965 void
1966 bstp_destroy(struct bstp_state *bs)
1967 {
1968 int s;
1969
1970 if (bs == NULL)
1971 return;
1972
1973 if (!LIST_EMPTY(&bs->bs_bplist))
1974 panic("bstp still active");
1975
1976 s = splnet();
1977 LIST_REMOVE(bs, bs_list);
1978 free(bs, M_DEVBUF);
1979 splx(s);
1980 }
1981
1982 void
1983 bstp_stop(struct bstp_state *bs)
1984 {
1985 struct bstp_port *bp;
1986
1987 LIST_FOREACH(bp, &bs->bs_bplist, bp_next)
1988 bstp_set_port_state(bp, BSTP_IFSTATE_DISCARDING);
1989
1990 if (timeout_initialized(&bs->bs_bstptimeout) &&
1991 timeout_pending(&bs->bs_bstptimeout))
1992 timeout_del(&bs->bs_bstptimeout);
1993 }
1994
1995 struct bstp_port *
1996 bstp_add(struct bstp_state *bs, struct ifnet *ifp)
1997 {
1998 struct bstp_port *bp;
1999
2000 switch (ifp->if_type) {
2001 case IFT_ETHER:
2002 break;
2003 default:
2004
2005 return (NULL);
2006 }
2007
2008 bp = (struct bstp_port *)malloc(sizeof(*bp), M_DEVBUF, M_NOWAIT);
2009 if (bp == NULL)
2010 return (NULL);
2011 bzero(bp, sizeof(*bp));
2012
2013 bp->bp_ifp = ifp;
2014 bp->bp_bs = bs;
2015 bp->bp_priority = BSTP_DEFAULT_PORT_PRIORITY;
2016 bp->bp_txcount = 0;
2017
2018
2019 bp->bp_infois = BSTP_INFO_DISABLED;
2020 bp->bp_flags = BSTP_PORT_AUTOEDGE | BSTP_PORT_AUTOPTP;
2021 bstp_set_port_state(bp, BSTP_IFSTATE_DISCARDING);
2022 bstp_set_port_proto(bp, bs->bs_protover);
2023 bstp_set_port_role(bp, BSTP_ROLE_DISABLED);
2024 bstp_set_port_tc(bp, BSTP_TCSTATE_INACTIVE);
2025 bp->bp_path_cost = bstp_calc_path_cost(bp);
2026
2027 LIST_INSERT_HEAD(&bs->bs_bplist, bp, bp_next);
2028
2029 bp->bp_active = 1;
2030 bp->bp_flags |= BSTP_PORT_NEWINFO;
2031 bstp_initialization(bs);
2032 bstp_update_roles(bs, bp);
2033
2034
2035 if (ifp->if_linkstatehooks != NULL)
2036 bp->bp_lhcookie = hook_establish(ifp->if_linkstatehooks, 1,
2037 bstp_ifstate, ifp);
2038
2039 return (bp);
2040 }
2041
2042 void
2043 bstp_delete(struct bstp_port *bp)
2044 {
2045 struct bstp_state *bs = bp->bp_bs;
2046 struct ifnet *ifp = bp->bp_ifp;
2047
2048 if (!bp->bp_active)
2049 panic("not a bstp member");
2050
2051 if (ifp != NULL && ifp->if_linkstatehooks != NULL)
2052 hook_disestablish(ifp->if_linkstatehooks, bp->bp_lhcookie);
2053
2054 LIST_REMOVE(bp, bp_next);
2055 bp->bp_bs = NULL;
2056 bp->bp_active = 0;
2057 free(bp, M_DEVBUF);
2058 bstp_initialization(bs);
2059 }
2060
2061 u_int8_t
2062 bstp_getstate(struct bstp_state *bs, struct bstp_port *bp)
2063 {
2064 u_int8_t state = bp->bp_state;
2065
2066 if (bs->bs_protover != BSTP_PROTO_STP)
2067 return (state);
2068
2069
2070
2071
2072
2073 if (bp->bp_role == BSTP_ROLE_DISABLED)
2074 state = BSTP_IFSTATE_DISABLED;
2075 else if (bp->bp_role == BSTP_ROLE_ALTERNATE ||
2076 bp->bp_role == BSTP_ROLE_BACKUP)
2077 state = BSTP_IFSTATE_BLOCKING;
2078 else if (state == BSTP_IFSTATE_DISCARDING)
2079 state = BSTP_IFSTATE_LISTENING;
2080
2081 return (state);
2082 }
2083
2084 void
2085 bstp_ifsflags(struct bstp_port *bp, u_int flags)
2086 {
2087 struct bstp_state *bs;
2088
2089 if ((flags & IFBIF_STP) == 0)
2090 return;
2091 bs = bp->bp_bs;
2092
2093
2094
2095
2096 if (flags & IFBIF_BSTP_AUTOEDGE) {
2097 if ((bp->bp_flags & BSTP_PORT_AUTOEDGE) == 0) {
2098 bp->bp_flags |= BSTP_PORT_AUTOEDGE;
2099
2100
2101 if (bp->bp_edge_delay_timer.active == 0)
2102 bstp_edge_delay_expiry(bs, bp);
2103 }
2104 } else
2105 bp->bp_flags &= ~BSTP_PORT_AUTOEDGE;
2106
2107 if (flags & IFBIF_BSTP_EDGE)
2108 bp->bp_operedge = 1;
2109 else
2110 bp->bp_operedge = 0;
2111
2112
2113
2114
2115 if (flags & IFBIF_BSTP_AUTOPTP) {
2116 if ((bp->bp_flags & BSTP_PORT_AUTOPTP) == 0) {
2117 bp->bp_flags |= BSTP_PORT_AUTOPTP;
2118
2119 bstp_ifupdstatus(bs, bp);
2120 }
2121 } else
2122 bp->bp_flags &= ~BSTP_PORT_AUTOPTP;
2123
2124 if (flags & IFBIF_BSTP_PTP)
2125 bp->bp_ptp_link = 1;
2126 else
2127 bp->bp_ptp_link = 0;
2128 }
2129
2130 int
2131 bstp_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
2132 {
2133 struct bridge_softc *sc = (struct bridge_softc *)ifp;
2134 struct bstp_state *bs = sc->sc_stp;
2135 struct ifbrparam *ifbp = (struct ifbrparam *)data;
2136 struct ifbreq *ifbr = (struct ifbreq *)data;
2137 struct bridge_iflist *p;
2138 struct ifnet *ifs;
2139 struct bstp_port *bp;
2140 int r = 0, err = 0, val;
2141
2142 switch (cmd) {
2143 case SIOCBRDGSIFPRIO:
2144 case SIOCBRDGSIFCOST:
2145 ifs = ifunit(ifbr->ifbr_ifsname);
2146 if (ifs == NULL) {
2147 err = ENOENT;
2148 break;
2149 }
2150 if ((caddr_t)sc != ifs->if_bridge) {
2151 err = ESRCH;
2152 break;
2153 }
2154 LIST_FOREACH(p, &sc->sc_iflist, next) {
2155 if (p->ifp == ifs)
2156 break;
2157 }
2158 if (p == LIST_END(&sc->sc_iflist)) {
2159 err = ESRCH;
2160 break;
2161 }
2162 if ((p->bif_flags & IFBIF_STP) == 0) {
2163 err = EINVAL;
2164 break;
2165 }
2166 bp = p->bif_stp;
2167 break;
2168 default:
2169 break;
2170 }
2171 if (err)
2172 return (err);
2173
2174 switch (cmd) {
2175 case SIOCBRDGGPRI:
2176 ifbp->ifbrp_prio = bs->bs_bridge_priority;
2177 break;
2178 case SIOCBRDGSPRI:
2179 val = ifbp->ifbrp_prio;
2180 if (val < 0 || val > BSTP_MAX_PRIORITY) {
2181 err = EINVAL;
2182 break;
2183 }
2184
2185
2186 val -= val % 4096;
2187 bs->bs_bridge_priority = val;
2188 r = 1;
2189 break;
2190 case SIOCBRDGGMA:
2191 ifbp->ifbrp_maxage = bs->bs_bridge_max_age >> 8;
2192 break;
2193 case SIOCBRDGSMA:
2194 val = ifbp->ifbrp_maxage;
2195
2196
2197 val *= BSTP_TICK_VAL;
2198
2199 if (val < BSTP_MIN_MAX_AGE || val > BSTP_MAX_MAX_AGE) {
2200 err = EINVAL;
2201 break;
2202 }
2203 bs->bs_bridge_max_age = val;
2204 r = 1;
2205 break;
2206 case SIOCBRDGGHT:
2207 ifbp->ifbrp_hellotime = bs->bs_bridge_htime >> 8;
2208 break;
2209 case SIOCBRDGSHT:
2210 val = ifbp->ifbrp_hellotime;
2211
2212
2213 val *= BSTP_TICK_VAL;
2214
2215
2216 if (bs->bs_protover != BSTP_PROTO_STP) {
2217 err = EPERM;
2218 break;
2219 }
2220 if (val < BSTP_MIN_HELLO_TIME || val > BSTP_MAX_HELLO_TIME) {
2221 err = EINVAL;
2222 break;
2223 }
2224 bs->bs_bridge_htime = val;
2225 r = 1;
2226 break;
2227 case SIOCBRDGGFD:
2228 ifbp->ifbrp_fwddelay = bs->bs_bridge_fdelay >> 8;
2229 break;
2230 case SIOCBRDGSFD:
2231 val = ifbp->ifbrp_fwddelay;
2232
2233
2234 val *= BSTP_TICK_VAL;
2235
2236 if (val < BSTP_MIN_FORWARD_DELAY ||
2237 val > BSTP_MAX_FORWARD_DELAY) {
2238 err = EINVAL;
2239 break;
2240 }
2241 bs->bs_bridge_fdelay = val;
2242 r = 1;
2243 break;
2244 case SIOCBRDGSTXHC:
2245 val = ifbp->ifbrp_txhc;
2246
2247 if (val < BSTP_MIN_HOLD_COUNT || val > BSTP_MAX_HOLD_COUNT) {
2248 err = EINVAL;
2249 break;
2250 }
2251 bs->bs_txholdcount = val;
2252 LIST_FOREACH(bp, &bs->bs_bplist, bp_next)
2253 bp->bp_txcount = 0;
2254 break;
2255 case SIOCBRDGSIFPRIO:
2256 val = ifbr->ifbr_priority;
2257 if (val < 0 || val > BSTP_MAX_PORT_PRIORITY)
2258 return (EINVAL);
2259
2260
2261 val -= val % 16;
2262 bp->bp_priority = val;
2263 r = 1;
2264 break;
2265 case SIOCBRDGSIFCOST:
2266 val = ifbr->ifbr_path_cost;
2267 if (val > BSTP_MAX_PATH_COST) {
2268 err = EINVAL;
2269 break;
2270 }
2271 if (val == 0) {
2272 bp->bp_flags &= ~BSTP_PORT_ADMCOST;
2273 bp->bp_path_cost = bstp_calc_path_cost(bp);
2274 } else {
2275 bp->bp_path_cost = val;
2276 bp->bp_flags |= BSTP_PORT_ADMCOST;
2277 }
2278 r = 1;
2279 break;
2280 case SIOCBRDGSPROTO:
2281 val = ifbp->ifbrp_proto;
2282
2283
2284 switch (val) {
2285 case BSTP_PROTO_STP:
2286 case BSTP_PROTO_RSTP:
2287 bs->bs_protover = val;
2288 bs->bs_bridge_htime = BSTP_DEFAULT_HELLO_TIME;
2289 LIST_FOREACH(bp, &bs->bs_bplist, bp_next) {
2290
2291 bp->bp_infois = BSTP_INFO_DISABLED;
2292 bp->bp_txcount = 0;
2293 bstp_set_port_proto(bp, bs->bs_protover);
2294 bstp_set_port_role(bp, BSTP_ROLE_DISABLED);
2295 bstp_set_port_tc(bp, BSTP_TCSTATE_INACTIVE);
2296 bstp_timer_stop(&bp->bp_recent_backup_timer);
2297 }
2298 r = 1;
2299 break;
2300 default:
2301 err = EINVAL;
2302 }
2303 break;
2304 default:
2305 break;
2306 }
2307
2308 if (r)
2309 bstp_initialization(bs);
2310
2311 return (err);
2312 }
2313 #endif