1 /* $NetBSD: bridgestp.c,v 1.5 2003/11/28 08:56:48 keihan Exp $ */ 2 3 /* 4 * Copyright (c) 2000 Jason L. Wright (jason@thought.net) 5 * Copyright (c) 2006 Andrew Thompson (thompsa@FreeBSD.org) 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 21 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 25 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 26 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 * POSSIBILITY OF SUCH DAMAGE. 28 * 29 * OpenBSD: bridgestp.c,v 1.5 2001/03/22 03:48:29 jason Exp 30 */ 31 32 /* 33 * Implementation of the spanning tree protocol as defined in 34 * ISO/IEC 802.1D-2004, June 9, 2004. 35 */ 36 37 #include <sys/cdefs.h> 38 __FBSDID("$FreeBSD$"); 39 40 #include "opt_route.h" 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/mbuf.h> 45 #include <sys/socket.h> 46 #include <sys/sockio.h> 47 #include <sys/kernel.h> 48 #include <sys/callout.h> 49 #include <sys/module.h> 50 #include <sys/proc.h> 51 #include <sys/lock.h> 52 #include <sys/mutex.h> 53 #include <sys/taskqueue.h> 54 #include <sys/vimage.h> 55 56 #include <net/if.h> 57 #include <net/if_dl.h> 58 #include <net/if_types.h> 59 #include <net/if_llc.h> 60 #include <net/if_media.h> 61 #include <net/route.h> 62 #include <net/vnet.h> 63 64 #include <netinet/in.h> 65 #include <netinet/in_systm.h> 66 #include <netinet/in_var.h> 67 #include <netinet/if_ether.h> 68 #include <net/bridgestp.h> 69 70 #ifdef BRIDGESTP_DEBUG 71 #define DPRINTF(fmt, arg...) printf("bstp: " fmt, ##arg) 72 #else 73 #define DPRINTF(fmt, arg...) 74 #endif 75 76 #define PV2ADDR(pv, eaddr) do { \ 77 eaddr[0] = pv >> 40; \ 78 eaddr[1] = pv >> 32; \ 79 eaddr[2] = pv >> 24; \ 80 eaddr[3] = pv >> 16; \ 81 eaddr[4] = pv >> 8; \ 82 eaddr[5] = pv >> 0; \ 83 } while (0) 84 85 #define INFO_BETTER 1 86 #define INFO_SAME 0 87 #define INFO_WORSE -1 88 89 const uint8_t bstp_etheraddr[] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 }; 90 91 LIST_HEAD(, bstp_state) bstp_list; 92 static struct mtx bstp_list_mtx; 93 94 static void bstp_transmit(struct bstp_state *, struct bstp_port *); 95 static void bstp_transmit_bpdu(struct bstp_state *, struct bstp_port *); 96 static void bstp_transmit_tcn(struct bstp_state *, struct bstp_port *); 97 static void bstp_decode_bpdu(struct bstp_port *, struct bstp_cbpdu *, 98 struct bstp_config_unit *); 99 static void bstp_send_bpdu(struct bstp_state *, struct bstp_port *, 100 struct bstp_cbpdu *); 101 static int bstp_pdu_flags(struct bstp_port *); 102 static void bstp_received_stp(struct bstp_state *, struct bstp_port *, 103 struct mbuf **, struct bstp_tbpdu *); 104 static void bstp_received_rstp(struct bstp_state *, struct bstp_port *, 105 struct mbuf **, struct bstp_tbpdu *); 106 static void bstp_received_tcn(struct bstp_state *, struct bstp_port *, 107 struct bstp_tcn_unit *); 108 static void bstp_received_bpdu(struct bstp_state *, struct bstp_port *, 109 struct bstp_config_unit *); 110 static int bstp_pdu_rcvtype(struct bstp_port *, struct bstp_config_unit *); 111 static int bstp_pdu_bettersame(struct bstp_port *, int); 112 static int bstp_info_cmp(struct bstp_pri_vector *, 113 struct bstp_pri_vector *); 114 static int bstp_info_superior(struct bstp_pri_vector *, 115 struct bstp_pri_vector *); 116 static void bstp_assign_roles(struct bstp_state *); 117 static void bstp_update_roles(struct bstp_state *, struct bstp_port *); 118 static void bstp_update_state(struct bstp_state *, struct bstp_port *); 119 static void bstp_update_tc(struct bstp_port *); 120 static void bstp_update_info(struct bstp_port *); 121 static void bstp_set_other_tcprop(struct bstp_port *); 122 static void bstp_set_all_reroot(struct bstp_state *); 123 static void bstp_set_all_sync(struct bstp_state *); 124 static void bstp_set_port_state(struct bstp_port *, int); 125 static void bstp_set_port_role(struct bstp_port *, int); 126 static void bstp_set_port_proto(struct bstp_port *, int); 127 static void bstp_set_port_tc(struct bstp_port *, int); 128 static void bstp_set_timer_tc(struct bstp_port *); 129 static void bstp_set_timer_msgage(struct bstp_port *); 130 static int bstp_rerooted(struct bstp_state *, struct bstp_port *); 131 static uint32_t bstp_calc_path_cost(struct bstp_port *); 132 static void bstp_notify_state(void *, int); 133 static void bstp_notify_rtage(void *, int); 134 static void bstp_ifupdstatus(struct bstp_state *, struct bstp_port *); 135 static void bstp_enable_port(struct bstp_state *, struct bstp_port *); 136 static void bstp_disable_port(struct bstp_state *, struct bstp_port *); 137 static void bstp_tick(void *); 138 static void bstp_timer_start(struct bstp_timer *, uint16_t); 139 static void bstp_timer_stop(struct bstp_timer *); 140 static void bstp_timer_latch(struct bstp_timer *); 141 static int bstp_timer_expired(struct bstp_timer *); 142 static void bstp_hello_timer_expiry(struct bstp_state *, 143 struct bstp_port *); 144 static void bstp_message_age_expiry(struct bstp_state *, 145 struct bstp_port *); 146 static void bstp_migrate_delay_expiry(struct bstp_state *, 147 struct bstp_port *); 148 static void bstp_edge_delay_expiry(struct bstp_state *, 149 struct bstp_port *); 150 static int bstp_addr_cmp(const uint8_t *, const uint8_t *); 151 static int bstp_same_bridgeid(uint64_t, uint64_t); 152 static void bstp_reinit(struct bstp_state *); 153 154 static void 155 bstp_transmit(struct bstp_state *bs, struct bstp_port *bp) 156 { 157 if (bs->bs_running == 0) 158 return; 159 160 /* 161 * a PDU can only be sent if we have tx quota left and the 162 * hello timer is running. 163 */ 164 if (bp->bp_hello_timer.active == 0) { 165 /* Test if it needs to be reset */ 166 bstp_hello_timer_expiry(bs, bp); 167 return; 168 } 169 if (bp->bp_txcount > bs->bs_txholdcount) 170 /* Ran out of karma */ 171 return; 172 173 if (bp->bp_protover == BSTP_PROTO_RSTP) { 174 bstp_transmit_bpdu(bs, bp); 175 bp->bp_tc_ack = 0; 176 } else { /* STP */ 177 switch (bp->bp_role) { 178 case BSTP_ROLE_DESIGNATED: 179 bstp_transmit_bpdu(bs, bp); 180 bp->bp_tc_ack = 0; 181 break; 182 183 case BSTP_ROLE_ROOT: 184 bstp_transmit_tcn(bs, bp); 185 break; 186 } 187 } 188 bstp_timer_start(&bp->bp_hello_timer, bp->bp_desg_htime); 189 bp->bp_flags &= ~BSTP_PORT_NEWINFO; 190 } 191 192 static void 193 bstp_transmit_bpdu(struct bstp_state *bs, struct bstp_port *bp) 194 { 195 struct bstp_cbpdu bpdu; 196 197 BSTP_LOCK_ASSERT(bs); 198 199 bpdu.cbu_rootpri = htons(bp->bp_desg_pv.pv_root_id >> 48); 200 PV2ADDR(bp->bp_desg_pv.pv_root_id, bpdu.cbu_rootaddr); 201 202 bpdu.cbu_rootpathcost = htonl(bp->bp_desg_pv.pv_cost); 203 204 bpdu.cbu_bridgepri = htons(bp->bp_desg_pv.pv_dbridge_id >> 48); 205 PV2ADDR(bp->bp_desg_pv.pv_dbridge_id, bpdu.cbu_bridgeaddr); 206 207 bpdu.cbu_portid = htons(bp->bp_port_id); 208 bpdu.cbu_messageage = htons(bp->bp_desg_msg_age); 209 bpdu.cbu_maxage = htons(bp->bp_desg_max_age); 210 bpdu.cbu_hellotime = htons(bp->bp_desg_htime); 211 bpdu.cbu_forwarddelay = htons(bp->bp_desg_fdelay); 212 213 bpdu.cbu_flags = bstp_pdu_flags(bp); 214 215 switch (bp->bp_protover) { 216 case BSTP_PROTO_STP: 217 bpdu.cbu_bpdutype = BSTP_MSGTYPE_CFG; 218 break; 219 220 case BSTP_PROTO_RSTP: 221 bpdu.cbu_bpdutype = BSTP_MSGTYPE_RSTP; 222 break; 223 } 224 225 bstp_send_bpdu(bs, bp, &bpdu); 226 } 227 228 static void 229 bstp_transmit_tcn(struct bstp_state *bs, struct bstp_port *bp) 230 { 231 struct bstp_tbpdu bpdu; 232 struct ifnet *ifp = bp->bp_ifp; 233 struct ether_header *eh; 234 struct mbuf *m; 235 236 KASSERT(bp == bs->bs_root_port, ("%s: bad root port\n", __func__)); 237 238 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) 239 return; 240 241 MGETHDR(m, M_DONTWAIT, MT_DATA); 242 if (m == NULL) 243 return; 244 245 m->m_pkthdr.rcvif = ifp; 246 m->m_pkthdr.len = sizeof(*eh) + sizeof(bpdu); 247 m->m_len = m->m_pkthdr.len; 248 249 eh = mtod(m, struct ether_header *); 250 251 memcpy(eh->ether_shost, IF_LLADDR(ifp), ETHER_ADDR_LEN); 252 memcpy(eh->ether_dhost, bstp_etheraddr, ETHER_ADDR_LEN); 253 eh->ether_type = htons(sizeof(bpdu)); 254 255 bpdu.tbu_ssap = bpdu.tbu_dsap = LLC_8021D_LSAP; 256 bpdu.tbu_ctl = LLC_UI; 257 bpdu.tbu_protoid = 0; 258 bpdu.tbu_protover = 0; 259 bpdu.tbu_bpdutype = BSTP_MSGTYPE_TCN; 260 261 memcpy(mtod(m, caddr_t) + sizeof(*eh), &bpdu, sizeof(bpdu)); 262 263 bp->bp_txcount++; 264 ifp->if_transmit(ifp, m); 265 } 266 267 static void 268 bstp_decode_bpdu(struct bstp_port *bp, struct bstp_cbpdu *cpdu, 269 struct bstp_config_unit *cu) 270 { 271 int flags; 272 273 cu->cu_pv.pv_root_id = 274 (((uint64_t)ntohs(cpdu->cbu_rootpri)) << 48) | 275 (((uint64_t)cpdu->cbu_rootaddr[0]) << 40) | 276 (((uint64_t)cpdu->cbu_rootaddr[1]) << 32) | 277 (((uint64_t)cpdu->cbu_rootaddr[2]) << 24) | 278 (((uint64_t)cpdu->cbu_rootaddr[3]) << 16) | 279 (((uint64_t)cpdu->cbu_rootaddr[4]) << 8) | 280 (((uint64_t)cpdu->cbu_rootaddr[5]) << 0); 281 282 cu->cu_pv.pv_dbridge_id = 283 (((uint64_t)ntohs(cpdu->cbu_bridgepri)) << 48) | 284 (((uint64_t)cpdu->cbu_bridgeaddr[0]) << 40) | 285 (((uint64_t)cpdu->cbu_bridgeaddr[1]) << 32) | 286 (((uint64_t)cpdu->cbu_bridgeaddr[2]) << 24) | 287 (((uint64_t)cpdu->cbu_bridgeaddr[3]) << 16) | 288 (((uint64_t)cpdu->cbu_bridgeaddr[4]) << 8) | 289 (((uint64_t)cpdu->cbu_bridgeaddr[5]) << 0); 290 291 cu->cu_pv.pv_cost = ntohl(cpdu->cbu_rootpathcost); 292 cu->cu_message_age = ntohs(cpdu->cbu_messageage); 293 cu->cu_max_age = ntohs(cpdu->cbu_maxage); 294 cu->cu_hello_time = ntohs(cpdu->cbu_hellotime); 295 cu->cu_forward_delay = ntohs(cpdu->cbu_forwarddelay); 296 cu->cu_pv.pv_dport_id = ntohs(cpdu->cbu_portid); 297 cu->cu_pv.pv_port_id = bp->bp_port_id; 298 cu->cu_message_type = cpdu->cbu_bpdutype; 299 300 /* Strip off unused flags in STP mode */ 301 flags = cpdu->cbu_flags; 302 switch (cpdu->cbu_protover) { 303 case BSTP_PROTO_STP: 304 flags &= BSTP_PDU_STPMASK; 305 /* A STP BPDU explicitly conveys a Designated Port */ 306 cu->cu_role = BSTP_ROLE_DESIGNATED; 307 break; 308 309 case BSTP_PROTO_RSTP: 310 flags &= BSTP_PDU_RSTPMASK; 311 break; 312 } 313 314 cu->cu_topology_change_ack = 315 (flags & BSTP_PDU_F_TCA) ? 1 : 0; 316 cu->cu_proposal = 317 (flags & BSTP_PDU_F_P) ? 1 : 0; 318 cu->cu_agree = 319 (flags & BSTP_PDU_F_A) ? 1 : 0; 320 cu->cu_learning = 321 (flags & BSTP_PDU_F_L) ? 1 : 0; 322 cu->cu_forwarding = 323 (flags & BSTP_PDU_F_F) ? 1 : 0; 324 cu->cu_topology_change = 325 (flags & BSTP_PDU_F_TC) ? 1 : 0; 326 327 switch ((flags & BSTP_PDU_PRMASK) >> BSTP_PDU_PRSHIFT) { 328 case BSTP_PDU_F_ROOT: 329 cu->cu_role = BSTP_ROLE_ROOT; 330 break; 331 case BSTP_PDU_F_ALT: 332 cu->cu_role = BSTP_ROLE_ALTERNATE; 333 break; 334 case BSTP_PDU_F_DESG: 335 cu->cu_role = BSTP_ROLE_DESIGNATED; 336 break; 337 } 338 } 339 340 static void 341 bstp_send_bpdu(struct bstp_state *bs, struct bstp_port *bp, 342 struct bstp_cbpdu *bpdu) 343 { 344 struct ifnet *ifp; 345 struct mbuf *m; 346 struct ether_header *eh; 347 348 BSTP_LOCK_ASSERT(bs); 349 350 ifp = bp->bp_ifp; 351 352 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) 353 return; 354 355 MGETHDR(m, M_DONTWAIT, MT_DATA); 356 if (m == NULL) 357 return; 358 359 eh = mtod(m, struct ether_header *); 360 361 bpdu->cbu_ssap = bpdu->cbu_dsap = LLC_8021D_LSAP; 362 bpdu->cbu_ctl = LLC_UI; 363 bpdu->cbu_protoid = htons(BSTP_PROTO_ID); 364 365 memcpy(eh->ether_shost, IF_LLADDR(ifp), ETHER_ADDR_LEN); 366 memcpy(eh->ether_dhost, bstp_etheraddr, ETHER_ADDR_LEN); 367 368 switch (bpdu->cbu_bpdutype) { 369 case BSTP_MSGTYPE_CFG: 370 bpdu->cbu_protover = BSTP_PROTO_STP; 371 m->m_pkthdr.len = sizeof(*eh) + BSTP_BPDU_STP_LEN; 372 eh->ether_type = htons(BSTP_BPDU_STP_LEN); 373 memcpy(mtod(m, caddr_t) + sizeof(*eh), bpdu, 374 BSTP_BPDU_STP_LEN); 375 break; 376 377 case BSTP_MSGTYPE_RSTP: 378 bpdu->cbu_protover = BSTP_PROTO_RSTP; 379 bpdu->cbu_versionlen = htons(0); 380 m->m_pkthdr.len = sizeof(*eh) + BSTP_BPDU_RSTP_LEN; 381 eh->ether_type = htons(BSTP_BPDU_RSTP_LEN); 382 memcpy(mtod(m, caddr_t) + sizeof(*eh), bpdu, 383 BSTP_BPDU_RSTP_LEN); 384 break; 385 386 default: 387 panic("not implemented"); 388 } 389 m->m_pkthdr.rcvif = ifp; 390 m->m_len = m->m_pkthdr.len; 391 392 bp->bp_txcount++; 393 ifp->if_transmit(ifp, m); 394 } 395 396 static int 397 bstp_pdu_flags(struct bstp_port *bp) 398 { 399 int flags = 0; 400 401 if (bp->bp_proposing && bp->bp_state != BSTP_IFSTATE_FORWARDING) 402 flags |= BSTP_PDU_F_P; 403 404 if (bp->bp_agree) 405 flags |= BSTP_PDU_F_A; 406 407 if (bp->bp_tc_timer.active) 408 flags |= BSTP_PDU_F_TC; 409 410 if (bp->bp_tc_ack) 411 flags |= BSTP_PDU_F_TCA; 412 413 switch (bp->bp_state) { 414 case BSTP_IFSTATE_LEARNING: 415 flags |= BSTP_PDU_F_L; 416 break; 417 418 case BSTP_IFSTATE_FORWARDING: 419 flags |= (BSTP_PDU_F_L | BSTP_PDU_F_F); 420 break; 421 } 422 423 switch (bp->bp_role) { 424 case BSTP_ROLE_ROOT: 425 flags |= 426 (BSTP_PDU_F_ROOT << BSTP_PDU_PRSHIFT); 427 break; 428 429 case BSTP_ROLE_ALTERNATE: 430 case BSTP_ROLE_BACKUP: /* fall through */ 431 flags |= 432 (BSTP_PDU_F_ALT << BSTP_PDU_PRSHIFT); 433 break; 434 435 case BSTP_ROLE_DESIGNATED: 436 flags |= 437 (BSTP_PDU_F_DESG << BSTP_PDU_PRSHIFT); 438 break; 439 } 440 441 /* Strip off unused flags in either mode */ 442 switch (bp->bp_protover) { 443 case BSTP_PROTO_STP: 444 flags &= BSTP_PDU_STPMASK; 445 break; 446 case BSTP_PROTO_RSTP: 447 flags &= BSTP_PDU_RSTPMASK; 448 break; 449 } 450 return (flags); 451 } 452 453 struct mbuf * 454 bstp_input(struct bstp_port *bp, struct ifnet *ifp, struct mbuf *m) 455 { 456 struct bstp_state *bs = bp->bp_bs; 457 struct ether_header *eh; 458 struct bstp_tbpdu tpdu; 459 uint16_t len; 460 461 if (bp->bp_active == 0) { 462 m_freem(m); 463 return (NULL); 464 } 465 466 BSTP_LOCK(bs); 467 468 eh = mtod(m, struct ether_header *); 469 470 len = ntohs(eh->ether_type); 471 if (len < sizeof(tpdu)) 472 goto out; 473 474 m_adj(m, ETHER_HDR_LEN); 475 476 if (m->m_pkthdr.len > len) 477 m_adj(m, len - m->m_pkthdr.len); 478 if (m->m_len < sizeof(tpdu) && 479 (m = m_pullup(m, sizeof(tpdu))) == NULL) 480 goto out; 481 482 memcpy(&tpdu, mtod(m, caddr_t), sizeof(tpdu)); 483 484 /* basic packet checks */ 485 if (tpdu.tbu_dsap != LLC_8021D_LSAP || 486 tpdu.tbu_ssap != LLC_8021D_LSAP || 487 tpdu.tbu_ctl != LLC_UI) 488 goto out; 489 if (tpdu.tbu_protoid != BSTP_PROTO_ID) 490 goto out; 491 492 /* 493 * We can treat later versions of the PDU as the same as the maximum 494 * version we implement. All additional parameters/flags are ignored. 495 */ 496 if (tpdu.tbu_protover > BSTP_PROTO_MAX) 497 tpdu.tbu_protover = BSTP_PROTO_MAX; 498 499 if (tpdu.tbu_protover != bp->bp_protover) { 500 /* 501 * Wait for the migration delay timer to expire before changing 502 * protocol version to avoid flip-flops. 503 */ 504 if (bp->bp_flags & BSTP_PORT_CANMIGRATE) 505 bstp_set_port_proto(bp, tpdu.tbu_protover); 506 else 507 goto out; 508 } 509 510 /* Clear operedge upon receiving a PDU on the port */ 511 bp->bp_operedge = 0; 512 bstp_timer_start(&bp->bp_edge_delay_timer, 513 BSTP_DEFAULT_MIGRATE_DELAY); 514 515 switch (tpdu.tbu_protover) { 516 case BSTP_PROTO_STP: 517 bstp_received_stp(bs, bp, &m, &tpdu); 518 break; 519 520 case BSTP_PROTO_RSTP: 521 bstp_received_rstp(bs, bp, &m, &tpdu); 522 break; 523 } 524 out: 525 BSTP_UNLOCK(bs); 526 if (m) 527 m_freem(m); 528 return (NULL); 529 } 530 531 static void 532 bstp_received_stp(struct bstp_state *bs, struct bstp_port *bp, 533 struct mbuf **mp, struct bstp_tbpdu *tpdu) 534 { 535 struct bstp_cbpdu cpdu; 536 struct bstp_config_unit *cu = &bp->bp_msg_cu; 537 struct bstp_tcn_unit tu; 538 539 switch (tpdu->tbu_bpdutype) { 540 case BSTP_MSGTYPE_TCN: 541 tu.tu_message_type = tpdu->tbu_bpdutype; 542 bstp_received_tcn(bs, bp, &tu); 543 break; 544 case BSTP_MSGTYPE_CFG: 545 if ((*mp)->m_len < BSTP_BPDU_STP_LEN && 546 (*mp = m_pullup(*mp, BSTP_BPDU_STP_LEN)) == NULL) 547 return; 548 memcpy(&cpdu, mtod(*mp, caddr_t), BSTP_BPDU_STP_LEN); 549 550 bstp_decode_bpdu(bp, &cpdu, cu); 551 bstp_received_bpdu(bs, bp, cu); 552 break; 553 } 554 } 555 556 static void 557 bstp_received_rstp(struct bstp_state *bs, struct bstp_port *bp, 558 struct mbuf **mp, struct bstp_tbpdu *tpdu) 559 { 560 struct bstp_cbpdu cpdu; 561 struct bstp_config_unit *cu = &bp->bp_msg_cu; 562 563 if (tpdu->tbu_bpdutype != BSTP_MSGTYPE_RSTP) 564 return; 565 566 if ((*mp)->m_len < BSTP_BPDU_RSTP_LEN && 567 (*mp = m_pullup(*mp, BSTP_BPDU_RSTP_LEN)) == NULL) 568 return; 569 memcpy(&cpdu, mtod(*mp, caddr_t), BSTP_BPDU_RSTP_LEN); 570 571 bstp_decode_bpdu(bp, &cpdu, cu); 572 bstp_received_bpdu(bs, bp, cu); 573 } 574 575 static void 576 bstp_received_tcn(struct bstp_state *bs, struct bstp_port *bp, 577 struct bstp_tcn_unit *tcn) 578 { 579 bp->bp_rcvdtcn = 1; 580 bstp_update_tc(bp); 581 } 582 583 static void 584 bstp_received_bpdu(struct bstp_state *bs, struct bstp_port *bp, 585 struct bstp_config_unit *cu) 586 { 587 int type; 588 589 BSTP_LOCK_ASSERT(bs); 590 591 /* We need to have transitioned to INFO_MINE before proceeding */ 592 switch (bp->bp_infois) { 593 case BSTP_INFO_DISABLED: 594 case BSTP_INFO_AGED: 595 return; 596 } 597 598 type = bstp_pdu_rcvtype(bp, cu); 599 600 switch (type) { 601 case BSTP_PDU_SUPERIOR: 602 bs->bs_allsynced = 0; 603 bp->bp_agreed = 0; 604 bp->bp_proposing = 0; 605 606 if (cu->cu_proposal && cu->cu_forwarding == 0) 607 bp->bp_proposed = 1; 608 if (cu->cu_topology_change) 609 bp->bp_rcvdtc = 1; 610 if (cu->cu_topology_change_ack) 611 bp->bp_rcvdtca = 1; 612 613 if (bp->bp_agree && 614 !bstp_pdu_bettersame(bp, BSTP_INFO_RECEIVED)) 615 bp->bp_agree = 0; 616 617 /* copy the received priority and timers to the port */ 618 bp->bp_port_pv = cu->cu_pv; 619 bp->bp_port_msg_age = cu->cu_message_age; 620 bp->bp_port_max_age = cu->cu_max_age; 621 bp->bp_port_fdelay = cu->cu_forward_delay; 622 bp->bp_port_htime = 623 (cu->cu_hello_time > BSTP_MIN_HELLO_TIME ? 624 cu->cu_hello_time : BSTP_MIN_HELLO_TIME); 625 626 /* set expiry for the new info */ 627 bstp_set_timer_msgage(bp); 628 629 bp->bp_infois = BSTP_INFO_RECEIVED; 630 bstp_assign_roles(bs); 631 break; 632 633 case BSTP_PDU_REPEATED: 634 if (cu->cu_proposal && cu->cu_forwarding == 0) 635 bp->bp_proposed = 1; 636 if (cu->cu_topology_change) 637 bp->bp_rcvdtc = 1; 638 if (cu->cu_topology_change_ack) 639 bp->bp_rcvdtca = 1; 640 641 /* rearm the age timer */ 642 bstp_set_timer_msgage(bp); 643 break; 644 645 case BSTP_PDU_INFERIOR: 646 if (cu->cu_learning) { 647 bp->bp_agreed = 1; 648 bp->bp_proposing = 0; 649 } 650 break; 651 652 case BSTP_PDU_INFERIORALT: 653 /* 654 * only point to point links are allowed fast 655 * transitions to forwarding. 656 */ 657 if (cu->cu_agree && bp->bp_ptp_link) { 658 bp->bp_agreed = 1; 659 bp->bp_proposing = 0; 660 } else 661 bp->bp_agreed = 0; 662 663 if (cu->cu_topology_change) 664 bp->bp_rcvdtc = 1; 665 if (cu->cu_topology_change_ack) 666 bp->bp_rcvdtca = 1; 667 break; 668 669 case BSTP_PDU_OTHER: 670 return; /* do nothing */ 671 } 672 /* update the state machines with the new data */ 673 bstp_update_state(bs, bp); 674 } 675 676 static int 677 bstp_pdu_rcvtype(struct bstp_port *bp, struct bstp_config_unit *cu) 678 { 679 int type; 680 681 /* default return type */ 682 type = BSTP_PDU_OTHER; 683 684 switch (cu->cu_role) { 685 case BSTP_ROLE_DESIGNATED: 686 if (bstp_info_superior(&bp->bp_port_pv, &cu->cu_pv)) 687 /* bpdu priority is superior */ 688 type = BSTP_PDU_SUPERIOR; 689 else if (bstp_info_cmp(&bp->bp_port_pv, &cu->cu_pv) == 690 INFO_SAME) { 691 if (bp->bp_port_msg_age != cu->cu_message_age || 692 bp->bp_port_max_age != cu->cu_max_age || 693 bp->bp_port_fdelay != cu->cu_forward_delay || 694 bp->bp_port_htime != cu->cu_hello_time) 695 /* bpdu priority is equal and timers differ */ 696 type = BSTP_PDU_SUPERIOR; 697 else 698 /* bpdu is equal */ 699 type = BSTP_PDU_REPEATED; 700 } else 701 /* bpdu priority is worse */ 702 type = BSTP_PDU_INFERIOR; 703 704 break; 705 706 case BSTP_ROLE_ROOT: 707 case BSTP_ROLE_ALTERNATE: 708 case BSTP_ROLE_BACKUP: 709 if (bstp_info_cmp(&bp->bp_port_pv, &cu->cu_pv) <= INFO_SAME) 710 /* 711 * not a designated port and priority is the same or 712 * worse 713 */ 714 type = BSTP_PDU_INFERIORALT; 715 break; 716 } 717 718 return (type); 719 } 720 721 static int 722 bstp_pdu_bettersame(struct bstp_port *bp, int newinfo) 723 { 724 if (newinfo == BSTP_INFO_RECEIVED && 725 bp->bp_infois == BSTP_INFO_RECEIVED && 726 bstp_info_cmp(&bp->bp_port_pv, &bp->bp_msg_cu.cu_pv) >= INFO_SAME) 727 return (1); 728 729 if (newinfo == BSTP_INFO_MINE && 730 bp->bp_infois == BSTP_INFO_MINE && 731 bstp_info_cmp(&bp->bp_port_pv, &bp->bp_desg_pv) >= INFO_SAME) 732 return (1); 733 734 return (0); 735 } 736 737 static int 738 bstp_info_cmp(struct bstp_pri_vector *pv, 739 struct bstp_pri_vector *cpv) 740 { 741 if (cpv->pv_root_id < pv->pv_root_id) 742 return (INFO_BETTER); 743 if (cpv->pv_root_id > pv->pv_root_id) 744 return (INFO_WORSE); 745 746 if (cpv->pv_cost < pv->pv_cost) 747 return (INFO_BETTER); 748 if (cpv->pv_cost > pv->pv_cost) 749 return (INFO_WORSE); 750 751 if (cpv->pv_dbridge_id < pv->pv_dbridge_id) 752 return (INFO_BETTER); 753 if (cpv->pv_dbridge_id > pv->pv_dbridge_id) 754 return (INFO_WORSE); 755 756 if (cpv->pv_dport_id < pv->pv_dport_id) 757 return (INFO_BETTER); 758 if (cpv->pv_dport_id > pv->pv_dport_id) 759 return (INFO_WORSE); 760 761 return (INFO_SAME); 762 } 763 764 /* 765 * This message priority vector is superior to the port priority vector and 766 * will replace it if, and only if, the message priority vector is better than 767 * the port priority vector, or the message has been transmitted from the same 768 * designated bridge and designated port as the port priority vector. 769 */ 770 static int 771 bstp_info_superior(struct bstp_pri_vector *pv, 772 struct bstp_pri_vector *cpv) 773 { 774 if (bstp_info_cmp(pv, cpv) == INFO_BETTER || 775 (bstp_same_bridgeid(pv->pv_dbridge_id, cpv->pv_dbridge_id) && 776 (cpv->pv_dport_id & 0xfff) == (pv->pv_dport_id & 0xfff))) 777 return (1); 778 return (0); 779 } 780 781 static void 782 bstp_assign_roles(struct bstp_state *bs) 783 { 784 struct bstp_port *bp, *rbp = NULL; 785 struct bstp_pri_vector pv; 786 787 /* default to our priority vector */ 788 bs->bs_root_pv = bs->bs_bridge_pv; 789 bs->bs_root_msg_age = 0; 790 bs->bs_root_max_age = bs->bs_bridge_max_age; 791 bs->bs_root_fdelay = bs->bs_bridge_fdelay; 792 bs->bs_root_htime = bs->bs_bridge_htime; 793 bs->bs_root_port = NULL; 794 795 /* check if any recieved info supersedes us */ 796 LIST_FOREACH(bp, &bs->bs_bplist, bp_next) { 797 if (bp->bp_infois != BSTP_INFO_RECEIVED) 798 continue; 799 800 pv = bp->bp_port_pv; 801 pv.pv_cost += bp->bp_path_cost; 802 803 /* 804 * The root priority vector is the best of the set comprising 805 * the bridge priority vector plus all root path priority 806 * vectors whose bridge address is not equal to us. 807 */ 808 if (bstp_same_bridgeid(pv.pv_dbridge_id, 809 bs->bs_bridge_pv.pv_dbridge_id) == 0 && 810 bstp_info_cmp(&bs->bs_root_pv, &pv) == INFO_BETTER) { 811 /* the port vector replaces the root */ 812 bs->bs_root_pv = pv; 813 bs->bs_root_msg_age = bp->bp_port_msg_age + 814 BSTP_MESSAGE_AGE_INCR; 815 bs->bs_root_max_age = bp->bp_port_max_age; 816 bs->bs_root_fdelay = bp->bp_port_fdelay; 817 bs->bs_root_htime = bp->bp_port_htime; 818 rbp = bp; 819 } 820 } 821 822 LIST_FOREACH(bp, &bs->bs_bplist, bp_next) { 823 /* calculate the port designated vector */ 824 bp->bp_desg_pv.pv_root_id = bs->bs_root_pv.pv_root_id; 825 bp->bp_desg_pv.pv_cost = bs->bs_root_pv.pv_cost; 826 bp->bp_desg_pv.pv_dbridge_id = bs->bs_bridge_pv.pv_dbridge_id; 827 bp->bp_desg_pv.pv_dport_id = bp->bp_port_id; 828 bp->bp_desg_pv.pv_port_id = bp->bp_port_id; 829 830 /* calculate designated times */ 831 bp->bp_desg_msg_age = bs->bs_root_msg_age; 832 bp->bp_desg_max_age = bs->bs_root_max_age; 833 bp->bp_desg_fdelay = bs->bs_root_fdelay; 834 bp->bp_desg_htime = bs->bs_bridge_htime; 835 836 837 switch (bp->bp_infois) { 838 case BSTP_INFO_DISABLED: 839 bstp_set_port_role(bp, BSTP_ROLE_DISABLED); 840 break; 841 842 case BSTP_INFO_AGED: 843 bstp_set_port_role(bp, BSTP_ROLE_DESIGNATED); 844 bstp_update_info(bp); 845 break; 846 847 case BSTP_INFO_MINE: 848 bstp_set_port_role(bp, BSTP_ROLE_DESIGNATED); 849 /* update the port info if stale */ 850 if (bstp_info_cmp(&bp->bp_port_pv, 851 &bp->bp_desg_pv) != INFO_SAME || 852 (rbp != NULL && 853 (bp->bp_port_msg_age != rbp->bp_port_msg_age || 854 bp->bp_port_max_age != rbp->bp_port_max_age || 855 bp->bp_port_fdelay != rbp->bp_port_fdelay || 856 bp->bp_port_htime != rbp->bp_port_htime))) 857 bstp_update_info(bp); 858 break; 859 860 case BSTP_INFO_RECEIVED: 861 if (bp == rbp) { 862 /* 863 * root priority is derived from this 864 * port, make it the root port. 865 */ 866 bstp_set_port_role(bp, BSTP_ROLE_ROOT); 867 bs->bs_root_port = bp; 868 } else if (bstp_info_cmp(&bp->bp_port_pv, 869 &bp->bp_desg_pv) == INFO_BETTER) { 870 /* 871 * the port priority is lower than the root 872 * port. 873 */ 874 bstp_set_port_role(bp, BSTP_ROLE_DESIGNATED); 875 bstp_update_info(bp); 876 } else { 877 if (bstp_same_bridgeid( 878 bp->bp_port_pv.pv_dbridge_id, 879 bs->bs_bridge_pv.pv_dbridge_id)) { 880 /* 881 * the designated bridge refers to 882 * another port on this bridge. 883 */ 884 bstp_set_port_role(bp, 885 BSTP_ROLE_BACKUP); 886 } else { 887 /* 888 * the port is an inferior path to the 889 * root bridge. 890 */ 891 bstp_set_port_role(bp, 892 BSTP_ROLE_ALTERNATE); 893 } 894 } 895 break; 896 } 897 } 898 } 899 900 static void 901 bstp_update_state(struct bstp_state *bs, struct bstp_port *bp) 902 { 903 struct bstp_port *bp2; 904 int synced; 905 906 BSTP_LOCK_ASSERT(bs); 907 908 /* check if all the ports have syncronised again */ 909 if (!bs->bs_allsynced) { 910 synced = 1; 911 LIST_FOREACH(bp2, &bs->bs_bplist, bp_next) { 912 if (!(bp2->bp_synced || 913 bp2->bp_role == BSTP_ROLE_ROOT)) { 914 synced = 0; 915 break; 916 } 917 } 918 bs->bs_allsynced = synced; 919 } 920 921 bstp_update_roles(bs, bp); 922 bstp_update_tc(bp); 923 } 924 925 static void 926 bstp_update_roles(struct bstp_state *bs, struct bstp_port *bp) 927 { 928 switch (bp->bp_role) { 929 case BSTP_ROLE_DISABLED: 930 /* Clear any flags if set */ 931 if (bp->bp_sync || !bp->bp_synced || bp->bp_reroot) { 932 bp->bp_sync = 0; 933 bp->bp_synced = 1; 934 bp->bp_reroot = 0; 935 } 936 break; 937 938 case BSTP_ROLE_ALTERNATE: 939 case BSTP_ROLE_BACKUP: 940 if ((bs->bs_allsynced && !bp->bp_agree) || 941 (bp->bp_proposed && bp->bp_agree)) { 942 bp->bp_proposed = 0; 943 bp->bp_agree = 1; 944 bp->bp_flags |= BSTP_PORT_NEWINFO; 945 DPRINTF("%s -> ALTERNATE_AGREED\n", 946 bp->bp_ifp->if_xname); 947 } 948 949 if (bp->bp_proposed && !bp->bp_agree) { 950 bstp_set_all_sync(bs); 951 bp->bp_proposed = 0; 952 DPRINTF("%s -> ALTERNATE_PROPOSED\n", 953 bp->bp_ifp->if_xname); 954 } 955 956 /* Clear any flags if set */ 957 if (bp->bp_sync || !bp->bp_synced || bp->bp_reroot) { 958 bp->bp_sync = 0; 959 bp->bp_synced = 1; 960 bp->bp_reroot = 0; 961 DPRINTF("%s -> ALTERNATE_PORT\n", bp->bp_ifp->if_xname); 962 } 963 break; 964 965 case BSTP_ROLE_ROOT: 966 if (bp->bp_state != BSTP_IFSTATE_FORWARDING && !bp->bp_reroot) { 967 bstp_set_all_reroot(bs); 968 DPRINTF("%s -> ROOT_REROOT\n", bp->bp_ifp->if_xname); 969 } 970 971 if ((bs->bs_allsynced && !bp->bp_agree) || 972 (bp->bp_proposed && bp->bp_agree)) { 973 bp->bp_proposed = 0; 974 bp->bp_sync = 0; 975 bp->bp_agree = 1; 976 bp->bp_flags |= BSTP_PORT_NEWINFO; 977 DPRINTF("%s -> ROOT_AGREED\n", bp->bp_ifp->if_xname); 978 } 979 980 if (bp->bp_proposed && !bp->bp_agree) { 981 bstp_set_all_sync(bs); 982 bp->bp_proposed = 0; 983 DPRINTF("%s -> ROOT_PROPOSED\n", bp->bp_ifp->if_xname); 984 } 985 986 if (bp->bp_state != BSTP_IFSTATE_FORWARDING && 987 (bp->bp_forward_delay_timer.active == 0 || 988 (bstp_rerooted(bs, bp) && 989 bp->bp_recent_backup_timer.active == 0 && 990 bp->bp_protover == BSTP_PROTO_RSTP))) { 991 switch (bp->bp_state) { 992 case BSTP_IFSTATE_DISCARDING: 993 bstp_set_port_state(bp, BSTP_IFSTATE_LEARNING); 994 break; 995 case BSTP_IFSTATE_LEARNING: 996 bstp_set_port_state(bp, 997 BSTP_IFSTATE_FORWARDING); 998 break; 999 } 1000 } 1001 1002 if (bp->bp_state == BSTP_IFSTATE_FORWARDING && bp->bp_reroot) { 1003 bp->bp_reroot = 0; 1004 DPRINTF("%s -> ROOT_REROOTED\n", bp->bp_ifp->if_xname); 1005 } 1006 break; 1007 1008 case BSTP_ROLE_DESIGNATED: 1009 if (bp->bp_recent_root_timer.active == 0 && bp->bp_reroot) { 1010 bp->bp_reroot = 0; 1011 DPRINTF("%s -> DESIGNATED_RETIRED\n", 1012 bp->bp_ifp->if_xname); 1013 } 1014 1015 if ((bp->bp_state == BSTP_IFSTATE_DISCARDING && 1016 !bp->bp_synced) || (bp->bp_agreed && !bp->bp_synced) || 1017 (bp->bp_operedge && !bp->bp_synced) || 1018 (bp->bp_sync && bp->bp_synced)) { 1019 bstp_timer_stop(&bp->bp_recent_root_timer); 1020 bp->bp_synced = 1; 1021 bp->bp_sync = 0; 1022 DPRINTF("%s -> DESIGNATED_SYNCED\n", 1023 bp->bp_ifp->if_xname); 1024 } 1025 1026 if (bp->bp_state != BSTP_IFSTATE_FORWARDING && 1027 !bp->bp_agreed && !bp->bp_proposing && 1028 !bp->bp_operedge) { 1029 bp->bp_proposing = 1; 1030 bp->bp_flags |= BSTP_PORT_NEWINFO; 1031 bstp_timer_start(&bp->bp_edge_delay_timer, 1032 (bp->bp_ptp_link ? BSTP_DEFAULT_MIGRATE_DELAY : 1033 bp->bp_desg_max_age)); 1034 DPRINTF("%s -> DESIGNATED_PROPOSE\n", 1035 bp->bp_ifp->if_xname); 1036 } 1037 1038 if (bp->bp_state != BSTP_IFSTATE_FORWARDING && 1039 (bp->bp_forward_delay_timer.active == 0 || bp->bp_agreed || 1040 bp->bp_operedge) && 1041 (bp->bp_recent_root_timer.active == 0 || !bp->bp_reroot) && 1042 !bp->bp_sync) { 1043 if (bp->bp_agreed) 1044 DPRINTF("%s -> AGREED\n", bp->bp_ifp->if_xname); 1045 /* 1046 * If agreed|operedge then go straight to forwarding, 1047 * otherwise follow discard -> learn -> forward. 1048 */ 1049 if (bp->bp_agreed || bp->bp_operedge || 1050 bp->bp_state == BSTP_IFSTATE_LEARNING) { 1051 bstp_set_port_state(bp, 1052 BSTP_IFSTATE_FORWARDING); 1053 bp->bp_agreed = bp->bp_protover; 1054 } else if (bp->bp_state == BSTP_IFSTATE_DISCARDING) 1055 bstp_set_port_state(bp, BSTP_IFSTATE_LEARNING); 1056 } 1057 1058 if (((bp->bp_sync && !bp->bp_synced) || 1059 (bp->bp_reroot && bp->bp_recent_root_timer.active) || 1060 (bp->bp_flags & BSTP_PORT_DISPUTED)) && !bp->bp_operedge && 1061 bp->bp_state != BSTP_IFSTATE_DISCARDING) { 1062 bstp_set_port_state(bp, BSTP_IFSTATE_DISCARDING); 1063 bp->bp_flags &= ~BSTP_PORT_DISPUTED; 1064 bstp_timer_start(&bp->bp_forward_delay_timer, 1065 bp->bp_protover == BSTP_PROTO_RSTP ? 1066 bp->bp_desg_htime : bp->bp_desg_fdelay); 1067 DPRINTF("%s -> DESIGNATED_DISCARD\n", 1068 bp->bp_ifp->if_xname); 1069 } 1070 break; 1071 } 1072 1073 if (bp->bp_flags & BSTP_PORT_NEWINFO) 1074 bstp_transmit(bs, bp); 1075 } 1076 1077 static void 1078 bstp_update_tc(struct bstp_port *bp) 1079 { 1080 switch (bp->bp_tcstate) { 1081 case BSTP_TCSTATE_ACTIVE: 1082 if ((bp->bp_role != BSTP_ROLE_DESIGNATED && 1083 bp->bp_role != BSTP_ROLE_ROOT) || bp->bp_operedge) 1084 bstp_set_port_tc(bp, BSTP_TCSTATE_LEARNING); 1085 1086 if (bp->bp_rcvdtcn) 1087 bstp_set_port_tc(bp, BSTP_TCSTATE_TCN); 1088 if (bp->bp_rcvdtc) 1089 bstp_set_port_tc(bp, BSTP_TCSTATE_TC); 1090 1091 if (bp->bp_tc_prop && !bp->bp_operedge) 1092 bstp_set_port_tc(bp, BSTP_TCSTATE_PROPAG); 1093 1094 if (bp->bp_rcvdtca) 1095 bstp_set_port_tc(bp, BSTP_TCSTATE_ACK); 1096 break; 1097 1098 case BSTP_TCSTATE_INACTIVE: 1099 if ((bp->bp_state == BSTP_IFSTATE_LEARNING || 1100 bp->bp_state == BSTP_IFSTATE_FORWARDING) && 1101 bp->bp_fdbflush == 0) 1102 bstp_set_port_tc(bp, BSTP_TCSTATE_LEARNING); 1103 break; 1104 1105 case BSTP_TCSTATE_LEARNING: 1106 if (bp->bp_rcvdtc || bp->bp_rcvdtcn || bp->bp_rcvdtca || 1107 bp->bp_tc_prop) 1108 bstp_set_port_tc(bp, BSTP_TCSTATE_LEARNING); 1109 else if (bp->bp_role != BSTP_ROLE_DESIGNATED && 1110 bp->bp_role != BSTP_ROLE_ROOT && 1111 bp->bp_state == BSTP_IFSTATE_DISCARDING) 1112 bstp_set_port_tc(bp, BSTP_TCSTATE_INACTIVE); 1113 1114 if ((bp->bp_role == BSTP_ROLE_DESIGNATED || 1115 bp->bp_role == BSTP_ROLE_ROOT) && 1116 bp->bp_state == BSTP_IFSTATE_FORWARDING && 1117 !bp->bp_operedge) 1118 bstp_set_port_tc(bp, BSTP_TCSTATE_DETECTED); 1119 break; 1120 1121 /* these are transient states and go straight back to ACTIVE */ 1122 case BSTP_TCSTATE_DETECTED: 1123 case BSTP_TCSTATE_TCN: 1124 case BSTP_TCSTATE_TC: 1125 case BSTP_TCSTATE_PROPAG: 1126 case BSTP_TCSTATE_ACK: 1127 DPRINTF("Invalid TC state for %s\n", 1128 bp->bp_ifp->if_xname); 1129 break; 1130 } 1131 1132 } 1133 1134 static void 1135 bstp_update_info(struct bstp_port *bp) 1136 { 1137 struct bstp_state *bs = bp->bp_bs; 1138 1139 bp->bp_proposing = 0; 1140 bp->bp_proposed = 0; 1141 1142 if (bp->bp_agreed && !bstp_pdu_bettersame(bp, BSTP_INFO_MINE)) 1143 bp->bp_agreed = 0; 1144 1145 if (bp->bp_synced && !bp->bp_agreed) { 1146 bp->bp_synced = 0; 1147 bs->bs_allsynced = 0; 1148 } 1149 1150 /* copy the designated pv to the port */ 1151 bp->bp_port_pv = bp->bp_desg_pv; 1152 bp->bp_port_msg_age = bp->bp_desg_msg_age; 1153 bp->bp_port_max_age = bp->bp_desg_max_age; 1154 bp->bp_port_fdelay = bp->bp_desg_fdelay; 1155 bp->bp_port_htime = bp->bp_desg_htime; 1156 bp->bp_infois = BSTP_INFO_MINE; 1157 1158 /* Set transmit flag but do not immediately send */ 1159 bp->bp_flags |= BSTP_PORT_NEWINFO; 1160 } 1161 1162 /* set tcprop on every port other than the caller */ 1163 static void 1164 bstp_set_other_tcprop(struct bstp_port *bp) 1165 { 1166 struct bstp_state *bs = bp->bp_bs; 1167 struct bstp_port *bp2; 1168 1169 BSTP_LOCK_ASSERT(bs); 1170 1171 LIST_FOREACH(bp2, &bs->bs_bplist, bp_next) { 1172 if (bp2 == bp) 1173 continue; 1174 bp2->bp_tc_prop = 1; 1175 } 1176 } 1177 1178 static void 1179 bstp_set_all_reroot(struct bstp_state *bs) 1180 { 1181 struct bstp_port *bp; 1182 1183 BSTP_LOCK_ASSERT(bs); 1184 1185 LIST_FOREACH(bp, &bs->bs_bplist, bp_next) 1186 bp->bp_reroot = 1; 1187 } 1188 1189 static void 1190 bstp_set_all_sync(struct bstp_state *bs) 1191 { 1192 struct bstp_port *bp; 1193 1194 BSTP_LOCK_ASSERT(bs); 1195 1196 LIST_FOREACH(bp, &bs->bs_bplist, bp_next) { 1197 bp->bp_sync = 1; 1198 bp->bp_synced = 0; /* Not explicit in spec */ 1199 } 1200 1201 bs->bs_allsynced = 0; 1202 } 1203 1204 static void 1205 bstp_set_port_state(struct bstp_port *bp, int state) 1206 { 1207 if (bp->bp_state == state) 1208 return; 1209 1210 bp->bp_state = state; 1211 1212 switch (bp->bp_state) { 1213 case BSTP_IFSTATE_DISCARDING: 1214 DPRINTF("state changed to DISCARDING on %s\n", 1215 bp->bp_ifp->if_xname); 1216 break; 1217 1218 case BSTP_IFSTATE_LEARNING: 1219 DPRINTF("state changed to LEARNING on %s\n", 1220 bp->bp_ifp->if_xname); 1221 1222 bstp_timer_start(&bp->bp_forward_delay_timer, 1223 bp->bp_protover == BSTP_PROTO_RSTP ? 1224 bp->bp_desg_htime : bp->bp_desg_fdelay); 1225 break; 1226 1227 case BSTP_IFSTATE_FORWARDING: 1228 DPRINTF("state changed to FORWARDING on %s\n", 1229 bp->bp_ifp->if_xname); 1230 1231 bstp_timer_stop(&bp->bp_forward_delay_timer); 1232 /* Record that we enabled forwarding */ 1233 bp->bp_forward_transitions++; 1234 break; 1235 } 1236 1237 /* notify the parent bridge */ 1238 taskqueue_enqueue(taskqueue_swi, &bp->bp_statetask); 1239 } 1240 1241 static void 1242 bstp_set_port_role(struct bstp_port *bp, int role) 1243 { 1244 struct bstp_state *bs = bp->bp_bs; 1245 1246 if (bp->bp_role == role) 1247 return; 1248 1249 /* perform pre-change tasks */ 1250 switch (bp->bp_role) { 1251 case BSTP_ROLE_DISABLED: 1252 bstp_timer_start(&bp->bp_forward_delay_timer, 1253 bp->bp_desg_max_age); 1254 break; 1255 1256 case BSTP_ROLE_BACKUP: 1257 bstp_timer_start(&bp->bp_recent_backup_timer, 1258 bp->bp_desg_htime * 2); 1259 /* fall through */ 1260 case BSTP_ROLE_ALTERNATE: 1261 bstp_timer_start(&bp->bp_forward_delay_timer, 1262 bp->bp_desg_fdelay); 1263 bp->bp_sync = 0; 1264 bp->bp_synced = 1; 1265 bp->bp_reroot = 0; 1266 break; 1267 1268 case BSTP_ROLE_ROOT: 1269 bstp_timer_start(&bp->bp_recent_root_timer, 1270 BSTP_DEFAULT_FORWARD_DELAY); 1271 break; 1272 } 1273 1274 bp->bp_role = role; 1275 /* clear values not carried between roles */ 1276 bp->bp_proposing = 0; 1277 bs->bs_allsynced = 0; 1278 1279 /* initialise the new role */ 1280 switch (bp->bp_role) { 1281 case BSTP_ROLE_DISABLED: 1282 case BSTP_ROLE_ALTERNATE: 1283 case BSTP_ROLE_BACKUP: 1284 DPRINTF("%s role -> ALT/BACK/DISABLED\n", 1285 bp->bp_ifp->if_xname); 1286 bstp_set_port_state(bp, BSTP_IFSTATE_DISCARDING); 1287 bstp_timer_stop(&bp->bp_recent_root_timer); 1288 bstp_timer_latch(&bp->bp_forward_delay_timer); 1289 bp->bp_sync = 0; 1290 bp->bp_synced = 1; 1291 bp->bp_reroot = 0; 1292 break; 1293 1294 case BSTP_ROLE_ROOT: 1295 DPRINTF("%s role -> ROOT\n", 1296 bp->bp_ifp->if_xname); 1297 bstp_set_port_state(bp, BSTP_IFSTATE_DISCARDING); 1298 bstp_timer_latch(&bp->bp_recent_root_timer); 1299 bp->bp_proposing = 0; 1300 break; 1301 1302 case BSTP_ROLE_DESIGNATED: 1303 DPRINTF("%s role -> DESIGNATED\n", 1304 bp->bp_ifp->if_xname); 1305 bstp_timer_start(&bp->bp_hello_timer, 1306 bp->bp_desg_htime); 1307 bp->bp_agree = 0; 1308 break; 1309 } 1310 1311 /* let the TC state know that the role changed */ 1312 bstp_update_tc(bp); 1313 } 1314 1315 static void 1316 bstp_set_port_proto(struct bstp_port *bp, int proto) 1317 { 1318 struct bstp_state *bs = bp->bp_bs; 1319 1320 /* supported protocol versions */ 1321 switch (proto) { 1322 case BSTP_PROTO_STP: 1323 /* we can downgrade protocols only */ 1324 bstp_timer_stop(&bp->bp_migrate_delay_timer); 1325 /* clear unsupported features */ 1326 bp->bp_operedge = 0; 1327 /* STP compat mode only uses 16 bits of the 32 */ 1328 if (bp->bp_path_cost > 65535) 1329 bp->bp_path_cost = 65535; 1330 break; 1331 1332 case BSTP_PROTO_RSTP: 1333 bstp_timer_start(&bp->bp_migrate_delay_timer, 1334 bs->bs_migration_delay); 1335 break; 1336 1337 default: 1338 DPRINTF("Unsupported STP version %d\n", proto); 1339 return; 1340 } 1341 1342 bp->bp_protover = proto; 1343 bp->bp_flags &= ~BSTP_PORT_CANMIGRATE; 1344 } 1345 1346 static void 1347 bstp_set_port_tc(struct bstp_port *bp, int state) 1348 { 1349 struct bstp_state *bs = bp->bp_bs; 1350 1351 bp->bp_tcstate = state; 1352 1353 /* initialise the new state */ 1354 switch (bp->bp_tcstate) { 1355 case BSTP_TCSTATE_ACTIVE: 1356 DPRINTF("%s -> TC_ACTIVE\n", bp->bp_ifp->if_xname); 1357 /* nothing to do */ 1358 break; 1359 1360 case BSTP_TCSTATE_INACTIVE: 1361 bstp_timer_stop(&bp->bp_tc_timer); 1362 /* flush routes on the parent bridge */ 1363 bp->bp_fdbflush = 1; 1364 taskqueue_enqueue(taskqueue_swi, &bp->bp_rtagetask); 1365 bp->bp_tc_ack = 0; 1366 DPRINTF("%s -> TC_INACTIVE\n", bp->bp_ifp->if_xname); 1367 break; 1368 1369 case BSTP_TCSTATE_LEARNING: 1370 bp->bp_rcvdtc = 0; 1371 bp->bp_rcvdtcn = 0; 1372 bp->bp_rcvdtca = 0; 1373 bp->bp_tc_prop = 0; 1374 DPRINTF("%s -> TC_LEARNING\n", bp->bp_ifp->if_xname); 1375 break; 1376 1377 case BSTP_TCSTATE_DETECTED: 1378 bstp_set_timer_tc(bp); 1379 bstp_set_other_tcprop(bp); 1380 /* send out notification */ 1381 bp->bp_flags |= BSTP_PORT_NEWINFO; 1382 bstp_transmit(bs, bp); 1383 getmicrotime(&bs->bs_last_tc_time); 1384 DPRINTF("%s -> TC_DETECTED\n", bp->bp_ifp->if_xname); 1385 bp->bp_tcstate = BSTP_TCSTATE_ACTIVE; /* UCT */ 1386 break; 1387 1388 case BSTP_TCSTATE_TCN: 1389 bstp_set_timer_tc(bp); 1390 DPRINTF("%s -> TC_TCN\n", bp->bp_ifp->if_xname); 1391 /* fall through */ 1392 case BSTP_TCSTATE_TC: 1393 bp->bp_rcvdtc = 0; 1394 bp->bp_rcvdtcn = 0; 1395 if (bp->bp_role == BSTP_ROLE_DESIGNATED) 1396 bp->bp_tc_ack = 1; 1397 1398 bstp_set_other_tcprop(bp); 1399 DPRINTF("%s -> TC_TC\n", bp->bp_ifp->if_xname); 1400 bp->bp_tcstate = BSTP_TCSTATE_ACTIVE; /* UCT */ 1401 break; 1402 1403 case BSTP_TCSTATE_PROPAG: 1404 /* flush routes on the parent bridge */ 1405 bp->bp_fdbflush = 1; 1406 taskqueue_enqueue(taskqueue_swi, &bp->bp_rtagetask); 1407 bp->bp_tc_prop = 0; 1408 bstp_set_timer_tc(bp); 1409 DPRINTF("%s -> TC_PROPAG\n", bp->bp_ifp->if_xname); 1410 bp->bp_tcstate = BSTP_TCSTATE_ACTIVE; /* UCT */ 1411 break; 1412 1413 case BSTP_TCSTATE_ACK: 1414 bstp_timer_stop(&bp->bp_tc_timer); 1415 bp->bp_rcvdtca = 0; 1416 DPRINTF("%s -> TC_ACK\n", bp->bp_ifp->if_xname); 1417 bp->bp_tcstate = BSTP_TCSTATE_ACTIVE; /* UCT */ 1418 break; 1419 } 1420 } 1421 1422 static void 1423 bstp_set_timer_tc(struct bstp_port *bp) 1424 { 1425 struct bstp_state *bs = bp->bp_bs; 1426 1427 if (bp->bp_tc_timer.active) 1428 return; 1429 1430 switch (bp->bp_protover) { 1431 case BSTP_PROTO_RSTP: 1432 bstp_timer_start(&bp->bp_tc_timer, 1433 bp->bp_desg_htime + BSTP_TICK_VAL); 1434 bp->bp_flags |= BSTP_PORT_NEWINFO; 1435 break; 1436 1437 case BSTP_PROTO_STP: 1438 bstp_timer_start(&bp->bp_tc_timer, 1439 bs->bs_root_max_age + bs->bs_root_fdelay); 1440 break; 1441 } 1442 } 1443 1444 static void 1445 bstp_set_timer_msgage(struct bstp_port *bp) 1446 { 1447 if (bp->bp_port_msg_age + BSTP_MESSAGE_AGE_INCR <= 1448 bp->bp_port_max_age) { 1449 bstp_timer_start(&bp->bp_message_age_timer, 1450 bp->bp_port_htime * 3); 1451 } else 1452 /* expires immediately */ 1453 bstp_timer_start(&bp->bp_message_age_timer, 0); 1454 } 1455 1456 static int 1457 bstp_rerooted(struct bstp_state *bs, struct bstp_port *bp) 1458 { 1459 struct bstp_port *bp2; 1460 int rr_set = 0; 1461 1462 LIST_FOREACH(bp2, &bs->bs_bplist, bp_next) { 1463 if (bp2 == bp) 1464 continue; 1465 if (bp2->bp_recent_root_timer.active) { 1466 rr_set = 1; 1467 break; 1468 } 1469 } 1470 return (!rr_set); 1471 } 1472 1473 int 1474 bstp_set_htime(struct bstp_state *bs, int t) 1475 { 1476 /* convert seconds to ticks */ 1477 t *= BSTP_TICK_VAL; 1478 1479 /* value can only be changed in leagacy stp mode */ 1480 if (bs->bs_protover != BSTP_PROTO_STP) 1481 return (EPERM); 1482 1483 if (t < BSTP_MIN_HELLO_TIME || t > BSTP_MAX_HELLO_TIME) 1484 return (EINVAL); 1485 1486 BSTP_LOCK(bs); 1487 bs->bs_bridge_htime = t; 1488 bstp_reinit(bs); 1489 BSTP_UNLOCK(bs); 1490 return (0); 1491 } 1492 1493 int 1494 bstp_set_fdelay(struct bstp_state *bs, int t) 1495 { 1496 /* convert seconds to ticks */ 1497 t *= BSTP_TICK_VAL; 1498 1499 if (t < BSTP_MIN_FORWARD_DELAY || t > BSTP_MAX_FORWARD_DELAY) 1500 return (EINVAL); 1501 1502 BSTP_LOCK(bs); 1503 bs->bs_bridge_fdelay = t; 1504 bstp_reinit(bs); 1505 BSTP_UNLOCK(bs); 1506 return (0); 1507 } 1508 1509 int 1510 bstp_set_maxage(struct bstp_state *bs, int t) 1511 { 1512 /* convert seconds to ticks */ 1513 t *= BSTP_TICK_VAL; 1514 1515 if (t < BSTP_MIN_MAX_AGE || t > BSTP_MAX_MAX_AGE) 1516 return (EINVAL); 1517 1518 BSTP_LOCK(bs); 1519 bs->bs_bridge_max_age = t; 1520 bstp_reinit(bs); 1521 BSTP_UNLOCK(bs); 1522 return (0); 1523 } 1524 1525 int 1526 bstp_set_holdcount(struct bstp_state *bs, int count) 1527 { 1528 struct bstp_port *bp; 1529 1530 if (count < BSTP_MIN_HOLD_COUNT || 1531 count > BSTP_MAX_HOLD_COUNT) 1532 return (EINVAL); 1533 1534 BSTP_LOCK(bs); 1535 bs->bs_txholdcount = count; 1536 LIST_FOREACH(bp, &bs->bs_bplist, bp_next) 1537 bp->bp_txcount = 0; 1538 BSTP_UNLOCK(bs); 1539 return (0); 1540 } 1541 1542 int 1543 bstp_set_protocol(struct bstp_state *bs, int proto) 1544 { 1545 struct bstp_port *bp; 1546 1547 switch (proto) { 1548 /* Supported protocol versions */ 1549 case BSTP_PROTO_STP: 1550 case BSTP_PROTO_RSTP: 1551 break; 1552 1553 default: 1554 return (EINVAL); 1555 } 1556 1557 BSTP_LOCK(bs); 1558 bs->bs_protover = proto; 1559 bs->bs_bridge_htime = BSTP_DEFAULT_HELLO_TIME; 1560 LIST_FOREACH(bp, &bs->bs_bplist, bp_next) { 1561 /* reinit state */ 1562 bp->bp_infois = BSTP_INFO_DISABLED; 1563 bp->bp_txcount = 0; 1564 bstp_set_port_proto(bp, bs->bs_protover); 1565 bstp_set_port_role(bp, BSTP_ROLE_DISABLED); 1566 bstp_set_port_tc(bp, BSTP_TCSTATE_INACTIVE); 1567 bstp_timer_stop(&bp->bp_recent_backup_timer); 1568 } 1569 bstp_reinit(bs); 1570 BSTP_UNLOCK(bs); 1571 return (0); 1572 } 1573 1574 int 1575 bstp_set_priority(struct bstp_state *bs, int pri) 1576 { 1577 if (pri < 0 || pri > BSTP_MAX_PRIORITY) 1578 return (EINVAL); 1579 1580 /* Limit to steps of 4096 */ 1581 pri -= pri % 4096; 1582 1583 BSTP_LOCK(bs); 1584 bs->bs_bridge_priority = pri; 1585 bstp_reinit(bs); 1586 BSTP_UNLOCK(bs); 1587 return (0); 1588 } 1589 1590 int 1591 bstp_set_port_priority(struct bstp_port *bp, int pri) 1592 { 1593 struct bstp_state *bs = bp->bp_bs; 1594 1595 if (pri < 0 || pri > BSTP_MAX_PORT_PRIORITY) 1596 return (EINVAL); 1597 1598 /* Limit to steps of 16 */ 1599 pri -= pri % 16; 1600 1601 BSTP_LOCK(bs); 1602 bp->bp_priority = pri; 1603 bstp_reinit(bs); 1604 BSTP_UNLOCK(bs); 1605 return (0); 1606 } 1607 1608 int 1609 bstp_set_path_cost(struct bstp_port *bp, uint32_t path_cost) 1610 { 1611 struct bstp_state *bs = bp->bp_bs; 1612 1613 if (path_cost > BSTP_MAX_PATH_COST) 1614 return (EINVAL); 1615 1616 /* STP compat mode only uses 16 bits of the 32 */ 1617 if (bp->bp_protover == BSTP_PROTO_STP && path_cost > 65535) 1618 path_cost = 65535; 1619 1620 BSTP_LOCK(bs); 1621 1622 if (path_cost == 0) { /* use auto */ 1623 bp->bp_flags &= ~BSTP_PORT_ADMCOST; 1624 bp->bp_path_cost = bstp_calc_path_cost(bp); 1625 } else { 1626 bp->bp_path_cost = path_cost; 1627 bp->bp_flags |= BSTP_PORT_ADMCOST; 1628 } 1629 bstp_reinit(bs); 1630 BSTP_UNLOCK(bs); 1631 return (0); 1632 } 1633 1634 int 1635 bstp_set_edge(struct bstp_port *bp, int set) 1636 { 1637 struct bstp_state *bs = bp->bp_bs; 1638 1639 BSTP_LOCK(bs); 1640 if ((bp->bp_operedge = set) == 0) 1641 bp->bp_flags &= ~BSTP_PORT_ADMEDGE; 1642 else 1643 bp->bp_flags |= BSTP_PORT_ADMEDGE; 1644 BSTP_UNLOCK(bs); 1645 return (0); 1646 } 1647 1648 int 1649 bstp_set_autoedge(struct bstp_port *bp, int set) 1650 { 1651 struct bstp_state *bs = bp->bp_bs; 1652 1653 BSTP_LOCK(bs); 1654 if (set) { 1655 bp->bp_flags |= BSTP_PORT_AUTOEDGE; 1656 /* we may be able to transition straight to edge */ 1657 if (bp->bp_edge_delay_timer.active == 0) 1658 bstp_edge_delay_expiry(bs, bp); 1659 } else 1660 bp->bp_flags &= ~BSTP_PORT_AUTOEDGE; 1661 BSTP_UNLOCK(bs); 1662 return (0); 1663 } 1664 1665 int 1666 bstp_set_ptp(struct bstp_port *bp, int set) 1667 { 1668 struct bstp_state *bs = bp->bp_bs; 1669 1670 BSTP_LOCK(bs); 1671 bp->bp_ptp_link = set; 1672 BSTP_UNLOCK(bs); 1673 return (0); 1674 } 1675 1676 int 1677 bstp_set_autoptp(struct bstp_port *bp, int set) 1678 { 1679 struct bstp_state *bs = bp->bp_bs; 1680 1681 BSTP_LOCK(bs); 1682 if (set) { 1683 bp->bp_flags |= BSTP_PORT_AUTOPTP; 1684 if (bp->bp_role != BSTP_ROLE_DISABLED) 1685 bstp_ifupdstatus(bs, bp); 1686 } else 1687 bp->bp_flags &= ~BSTP_PORT_AUTOPTP; 1688 BSTP_UNLOCK(bs); 1689 return (0); 1690 } 1691 1692 /* 1693 * Calculate the path cost according to the link speed. 1694 */ 1695 static uint32_t 1696 bstp_calc_path_cost(struct bstp_port *bp) 1697 { 1698 struct ifnet *ifp = bp->bp_ifp; 1699 uint32_t path_cost; 1700 1701 /* If the priority has been manually set then retain the value */ 1702 if (bp->bp_flags & BSTP_PORT_ADMCOST) 1703 return bp->bp_path_cost; 1704 1705 if (ifp->if_link_state == LINK_STATE_DOWN) { 1706 /* Recalc when the link comes up again */ 1707 bp->bp_flags |= BSTP_PORT_PNDCOST; 1708 return (BSTP_DEFAULT_PATH_COST); 1709 } 1710 1711 if (ifp->if_baudrate < 1000) 1712 return (BSTP_DEFAULT_PATH_COST); 1713 1714 /* formula from section 17.14, IEEE Std 802.1D-2004 */ 1715 path_cost = 20000000000ULL / (ifp->if_baudrate / 1000); 1716 1717 if (path_cost > BSTP_MAX_PATH_COST) 1718 path_cost = BSTP_MAX_PATH_COST; 1719 1720 /* STP compat mode only uses 16 bits of the 32 */ 1721 if (bp->bp_protover == BSTP_PROTO_STP && path_cost > 65535) 1722 path_cost = 65535; 1723 1724 return (path_cost); 1725 } 1726 1727 /* 1728 * Notify the bridge that a port state has changed, we need to do this from a 1729 * taskqueue to avoid a LOR. 1730 */ 1731 static void 1732 bstp_notify_state(void *arg, int pending) 1733 { 1734 struct bstp_port *bp = (struct bstp_port *)arg; 1735 struct bstp_state *bs = bp->bp_bs; 1736 1737 if (bp->bp_active == 1 && bs->bs_state_cb != NULL) 1738 (*bs->bs_state_cb)(bp->bp_ifp, bp->bp_state); 1739 } 1740 1741 /* 1742 * Flush the routes on the bridge port, we need to do this from a 1743 * taskqueue to avoid a LOR. 1744 */ 1745 static void 1746 bstp_notify_rtage(void *arg, int pending) 1747 { 1748 struct bstp_port *bp = (struct bstp_port *)arg; 1749 struct bstp_state *bs = bp->bp_bs; 1750 int age = 0; 1751 1752 BSTP_LOCK(bs); 1753 switch (bp->bp_protover) { 1754 case BSTP_PROTO_STP: 1755 /* convert to seconds */ 1756 age = bp->bp_desg_fdelay / BSTP_TICK_VAL; 1757 break; 1758 1759 case BSTP_PROTO_RSTP: 1760 age = 0; 1761 break; 1762 } 1763 BSTP_UNLOCK(bs); 1764 1765 if (bp->bp_active == 1 && bs->bs_rtage_cb != NULL) 1766 (*bs->bs_rtage_cb)(bp->bp_ifp, age); 1767 1768 /* flush is complete */ 1769 BSTP_LOCK(bs); 1770 bp->bp_fdbflush = 0; 1771 BSTP_UNLOCK(bs); 1772 } 1773 1774 void 1775 bstp_linkstate(struct ifnet *ifp, int state) 1776 { 1777 struct bstp_state *bs; 1778 struct bstp_port *bp; 1779 1780 /* search for the stp port */ 1781 mtx_lock(&bstp_list_mtx); 1782 LIST_FOREACH(bs, &bstp_list, bs_list) { 1783 BSTP_LOCK(bs); 1784 LIST_FOREACH(bp, &bs->bs_bplist, bp_next) { 1785 if (bp->bp_ifp == ifp) { 1786 bstp_ifupdstatus(bs, bp); 1787 bstp_update_state(bs, bp); 1788 /* it only exists once so return */ 1789 BSTP_UNLOCK(bs); 1790 mtx_unlock(&bstp_list_mtx); 1791 return; 1792 } 1793 } 1794 BSTP_UNLOCK(bs); 1795 } 1796 mtx_unlock(&bstp_list_mtx); 1797 } 1798 1799 static void 1800 bstp_ifupdstatus(struct bstp_state *bs, struct bstp_port *bp) 1801 { 1802 struct ifnet *ifp = bp->bp_ifp; 1803 struct ifmediareq ifmr; 1804 int error = 0; 1805 1806 BSTP_LOCK_ASSERT(bs); 1807 1808 bzero((char *)&ifmr, sizeof(ifmr)); 1809 error = (*ifp->if_ioctl)(ifp, SIOCGIFMEDIA, (caddr_t)&ifmr); 1810 1811 if ((error == 0) && (ifp->if_flags & IFF_UP)) { 1812 if (ifmr.ifm_status & IFM_ACTIVE) { 1813 /* A full-duplex link is assumed to be point to point */ 1814 if (bp->bp_flags & BSTP_PORT_AUTOPTP) { 1815 bp->bp_ptp_link = 1816 ifmr.ifm_active & IFM_FDX ? 1 : 0; 1817 } 1818 1819 /* Calc the cost if the link was down previously */ 1820 if (bp->bp_flags & BSTP_PORT_PNDCOST) { 1821 bp->bp_path_cost = bstp_calc_path_cost(bp); 1822 bp->bp_flags &= ~BSTP_PORT_PNDCOST; 1823 } 1824 1825 if (bp->bp_role == BSTP_ROLE_DISABLED) 1826 bstp_enable_port(bs, bp); 1827 } else { 1828 if (bp->bp_role != BSTP_ROLE_DISABLED) { 1829 bstp_disable_port(bs, bp); 1830 if ((bp->bp_flags & BSTP_PORT_ADMEDGE) && 1831 bp->bp_protover == BSTP_PROTO_RSTP) 1832 bp->bp_operedge = 1; 1833 } 1834 } 1835 return; 1836 } 1837 1838 if (bp->bp_infois != BSTP_INFO_DISABLED) 1839 bstp_disable_port(bs, bp); 1840 } 1841 1842 static void 1843 bstp_enable_port(struct bstp_state *bs, struct bstp_port *bp) 1844 { 1845 bp->bp_infois = BSTP_INFO_AGED; 1846 bstp_assign_roles(bs); 1847 } 1848 1849 static void 1850 bstp_disable_port(struct bstp_state *bs, struct bstp_port *bp) 1851 { 1852 bp->bp_infois = BSTP_INFO_DISABLED; 1853 bstp_assign_roles(bs); 1854 } 1855 1856 static void 1857 bstp_tick(void *arg) 1858 { 1859 struct bstp_state *bs = arg; 1860 struct bstp_port *bp; 1861 1862 BSTP_LOCK_ASSERT(bs); 1863 1864 if (bs->bs_running == 0) 1865 return; 1866 1867 /* slow timer to catch missed link events */ 1868 if (bstp_timer_expired(&bs->bs_link_timer)) { 1869 LIST_FOREACH(bp, &bs->bs_bplist, bp_next) 1870 bstp_ifupdstatus(bs, bp); 1871 bstp_timer_start(&bs->bs_link_timer, BSTP_LINK_TIMER); 1872 } 1873 1874 LIST_FOREACH(bp, &bs->bs_bplist, bp_next) { 1875 /* no events need to happen for these */ 1876 bstp_timer_expired(&bp->bp_tc_timer); 1877 bstp_timer_expired(&bp->bp_recent_root_timer); 1878 bstp_timer_expired(&bp->bp_forward_delay_timer); 1879 bstp_timer_expired(&bp->bp_recent_backup_timer); 1880 1881 if (bstp_timer_expired(&bp->bp_hello_timer)) 1882 bstp_hello_timer_expiry(bs, bp); 1883 1884 if (bstp_timer_expired(&bp->bp_message_age_timer)) 1885 bstp_message_age_expiry(bs, bp); 1886 1887 if (bstp_timer_expired(&bp->bp_migrate_delay_timer)) 1888 bstp_migrate_delay_expiry(bs, bp); 1889 1890 if (bstp_timer_expired(&bp->bp_edge_delay_timer)) 1891 bstp_edge_delay_expiry(bs, bp); 1892 1893 /* update the various state machines for the port */ 1894 bstp_update_state(bs, bp); 1895 1896 if (bp->bp_txcount > 0) 1897 bp->bp_txcount--; 1898 } 1899 1900 callout_reset(&bs->bs_bstpcallout, hz, bstp_tick, bs); 1901 } 1902 1903 static void 1904 bstp_timer_start(struct bstp_timer *t, uint16_t v) 1905 { 1906 t->value = v; 1907 t->active = 1; 1908 t->latched = 0; 1909 } 1910 1911 static void 1912 bstp_timer_stop(struct bstp_timer *t) 1913 { 1914 t->value = 0; 1915 t->active = 0; 1916 t->latched = 0; 1917 } 1918 1919 static void 1920 bstp_timer_latch(struct bstp_timer *t) 1921 { 1922 t->latched = 1; 1923 t->active = 1; 1924 } 1925 1926 static int 1927 bstp_timer_expired(struct bstp_timer *t) 1928 { 1929 if (t->active == 0 || t->latched) 1930 return (0); 1931 t->value -= BSTP_TICK_VAL; 1932 if (t->value <= 0) { 1933 bstp_timer_stop(t); 1934 return (1); 1935 } 1936 return (0); 1937 } 1938 1939 static void 1940 bstp_hello_timer_expiry(struct bstp_state *bs, struct bstp_port *bp) 1941 { 1942 if ((bp->bp_flags & BSTP_PORT_NEWINFO) || 1943 bp->bp_role == BSTP_ROLE_DESIGNATED || 1944 (bp->bp_role == BSTP_ROLE_ROOT && 1945 bp->bp_tc_timer.active == 1)) { 1946 bstp_timer_start(&bp->bp_hello_timer, bp->bp_desg_htime); 1947 bp->bp_flags |= BSTP_PORT_NEWINFO; 1948 bstp_transmit(bs, bp); 1949 } 1950 } 1951 1952 static void 1953 bstp_message_age_expiry(struct bstp_state *bs, struct bstp_port *bp) 1954 { 1955 if (bp->bp_infois == BSTP_INFO_RECEIVED) { 1956 bp->bp_infois = BSTP_INFO_AGED; 1957 bstp_assign_roles(bs); 1958 DPRINTF("aged info on %s\n", bp->bp_ifp->if_xname); 1959 } 1960 } 1961 1962 static void 1963 bstp_migrate_delay_expiry(struct bstp_state *bs, struct bstp_port *bp) 1964 { 1965 bp->bp_flags |= BSTP_PORT_CANMIGRATE; 1966 } 1967 1968 static void 1969 bstp_edge_delay_expiry(struct bstp_state *bs, struct bstp_port *bp) 1970 { 1971 if ((bp->bp_flags & BSTP_PORT_AUTOEDGE) && 1972 bp->bp_protover == BSTP_PROTO_RSTP && bp->bp_proposing && 1973 bp->bp_role == BSTP_ROLE_DESIGNATED) { 1974 bp->bp_operedge = 1; 1975 DPRINTF("%s -> edge port\n", bp->bp_ifp->if_xname); 1976 } 1977 } 1978 1979 static int 1980 bstp_addr_cmp(const uint8_t *a, const uint8_t *b) 1981 { 1982 int i, d; 1983 1984 for (i = 0, d = 0; i < ETHER_ADDR_LEN && d == 0; i++) { 1985 d = ((int)a[i]) - ((int)b[i]); 1986 } 1987 1988 return (d); 1989 } 1990 1991 /* 1992 * compare the bridge address component of the bridgeid 1993 */ 1994 static int 1995 bstp_same_bridgeid(uint64_t id1, uint64_t id2) 1996 { 1997 u_char addr1[ETHER_ADDR_LEN]; 1998 u_char addr2[ETHER_ADDR_LEN]; 1999 2000 PV2ADDR(id1, addr1); 2001 PV2ADDR(id2, addr2); 2002 2003 if (bstp_addr_cmp(addr1, addr2) == 0) 2004 return (1); 2005 2006 return (0); 2007 } 2008 2009 void 2010 bstp_reinit(struct bstp_state *bs) 2011 { 2012 INIT_VNET_NET(curvnet); 2013 struct bstp_port *bp; 2014 struct ifnet *ifp, *mif; 2015 u_char *e_addr; 2016 static const u_char llzero[ETHER_ADDR_LEN]; /* 00:00:00:00:00:00 */ 2017 2018 BSTP_LOCK_ASSERT(bs); 2019 2020 mif = NULL; 2021 /* 2022 * Search through the Ethernet adapters and find the one with the 2023 * lowest value. The adapter which we take the MAC address from does 2024 * not need to be part of the bridge, it just needs to be a unique 2025 * value. 2026 */ 2027 IFNET_RLOCK(); 2028 TAILQ_FOREACH(ifp, &V_ifnet, if_link) { 2029 if (ifp->if_type != IFT_ETHER) 2030 continue; 2031 2032 if (bstp_addr_cmp(IF_LLADDR(ifp), llzero) == 0) 2033 continue; 2034 2035 if (mif == NULL) { 2036 mif = ifp; 2037 continue; 2038 } 2039 if (bstp_addr_cmp(IF_LLADDR(ifp), IF_LLADDR(mif)) < 0) { 2040 mif = ifp; 2041 continue; 2042 } 2043 } 2044 IFNET_RUNLOCK(); 2045 2046 if (LIST_EMPTY(&bs->bs_bplist) || mif == NULL) { 2047 /* Set the bridge and root id (lower bits) to zero */ 2048 bs->bs_bridge_pv.pv_dbridge_id = 2049 ((uint64_t)bs->bs_bridge_priority) << 48; 2050 bs->bs_bridge_pv.pv_root_id = bs->bs_bridge_pv.pv_dbridge_id; 2051 bs->bs_root_pv = bs->bs_bridge_pv; 2052 /* Disable any remaining ports, they will have no MAC address */ 2053 LIST_FOREACH(bp, &bs->bs_bplist, bp_next) { 2054 bp->bp_infois = BSTP_INFO_DISABLED; 2055 bstp_set_port_role(bp, BSTP_ROLE_DISABLED); 2056 } 2057 callout_stop(&bs->bs_bstpcallout); 2058 return; 2059 } 2060 2061 e_addr = IF_LLADDR(mif); 2062 bs->bs_bridge_pv.pv_dbridge_id = 2063 (((uint64_t)bs->bs_bridge_priority) << 48) | 2064 (((uint64_t)e_addr[0]) << 40) | 2065 (((uint64_t)e_addr[1]) << 32) | 2066 (((uint64_t)e_addr[2]) << 24) | 2067 (((uint64_t)e_addr[3]) << 16) | 2068 (((uint64_t)e_addr[4]) << 8) | 2069 (((uint64_t)e_addr[5])); 2070 2071 bs->bs_bridge_pv.pv_root_id = bs->bs_bridge_pv.pv_dbridge_id; 2072 bs->bs_bridge_pv.pv_cost = 0; 2073 bs->bs_bridge_pv.pv_dport_id = 0; 2074 bs->bs_bridge_pv.pv_port_id = 0; 2075 2076 if (bs->bs_running && callout_pending(&bs->bs_bstpcallout) == 0) 2077 callout_reset(&bs->bs_bstpcallout, hz, bstp_tick, bs); 2078 2079 LIST_FOREACH(bp, &bs->bs_bplist, bp_next) { 2080 bp->bp_port_id = (bp->bp_priority << 8) | 2081 (bp->bp_ifp->if_index & 0xfff); 2082 bstp_ifupdstatus(bs, bp); 2083 } 2084 2085 bstp_assign_roles(bs); 2086 bstp_timer_start(&bs->bs_link_timer, BSTP_LINK_TIMER); 2087 } 2088 2089 static int 2090 bstp_modevent(module_t mod, int type, void *data) 2091 { 2092 switch (type) { 2093 case MOD_LOAD: 2094 mtx_init(&bstp_list_mtx, "bridgestp list", NULL, MTX_DEF); 2095 LIST_INIT(&bstp_list); 2096 bstp_linkstate_p = bstp_linkstate; 2097 break; 2098 case MOD_UNLOAD: 2099 bstp_linkstate_p = NULL; 2100 mtx_destroy(&bstp_list_mtx); 2101 break; 2102 default: 2103 return (EOPNOTSUPP); 2104 } 2105 return (0); 2106 } 2107 2108 static moduledata_t bstp_mod = { 2109 "bridgestp", 2110 bstp_modevent, 2111 0 2112 }; 2113 2114 DECLARE_MODULE(bridgestp, bstp_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); 2115 MODULE_VERSION(bridgestp, 1); 2116 2117 void 2118 bstp_attach(struct bstp_state *bs, struct bstp_cb_ops *cb) 2119 { 2120 BSTP_LOCK_INIT(bs); 2121 callout_init_mtx(&bs->bs_bstpcallout, &bs->bs_mtx, 0); 2122 LIST_INIT(&bs->bs_bplist); 2123 2124 bs->bs_bridge_max_age = BSTP_DEFAULT_MAX_AGE; 2125 bs->bs_bridge_htime = BSTP_DEFAULT_HELLO_TIME; 2126 bs->bs_bridge_fdelay = BSTP_DEFAULT_FORWARD_DELAY; 2127 bs->bs_bridge_priority = BSTP_DEFAULT_BRIDGE_PRIORITY; 2128 bs->bs_hold_time = BSTP_DEFAULT_HOLD_TIME; 2129 bs->bs_migration_delay = BSTP_DEFAULT_MIGRATE_DELAY; 2130 bs->bs_txholdcount = BSTP_DEFAULT_HOLD_COUNT; 2131 bs->bs_protover = BSTP_PROTO_RSTP; 2132 bs->bs_state_cb = cb->bcb_state; 2133 bs->bs_rtage_cb = cb->bcb_rtage; 2134 2135 getmicrotime(&bs->bs_last_tc_time); 2136 2137 mtx_lock(&bstp_list_mtx); 2138 LIST_INSERT_HEAD(&bstp_list, bs, bs_list); 2139 mtx_unlock(&bstp_list_mtx); 2140 } 2141 2142 void 2143 bstp_detach(struct bstp_state *bs) 2144 { 2145 KASSERT(LIST_EMPTY(&bs->bs_bplist), ("bstp still active")); 2146 2147 mtx_lock(&bstp_list_mtx); 2148 LIST_REMOVE(bs, bs_list); 2149 mtx_unlock(&bstp_list_mtx); 2150 callout_drain(&bs->bs_bstpcallout); 2151 BSTP_LOCK_DESTROY(bs); 2152 } 2153 2154 void 2155 bstp_init(struct bstp_state *bs) 2156 { 2157 BSTP_LOCK(bs); 2158 callout_reset(&bs->bs_bstpcallout, hz, bstp_tick, bs); 2159 bs->bs_running = 1; 2160 bstp_reinit(bs); 2161 BSTP_UNLOCK(bs); 2162 } 2163 2164 void 2165 bstp_stop(struct bstp_state *bs) 2166 { 2167 struct bstp_port *bp; 2168 2169 BSTP_LOCK(bs); 2170 2171 LIST_FOREACH(bp, &bs->bs_bplist, bp_next) 2172 bstp_set_port_state(bp, BSTP_IFSTATE_DISCARDING); 2173 2174 bs->bs_running = 0; 2175 callout_stop(&bs->bs_bstpcallout); 2176 BSTP_UNLOCK(bs); 2177 } 2178 2179 int 2180 bstp_create(struct bstp_state *bs, struct bstp_port *bp, struct ifnet *ifp) 2181 { 2182 bzero(bp, sizeof(struct bstp_port)); 2183 2184 BSTP_LOCK(bs); 2185 bp->bp_ifp = ifp; 2186 bp->bp_bs = bs; 2187 bp->bp_priority = BSTP_DEFAULT_PORT_PRIORITY; 2188 TASK_INIT(&bp->bp_statetask, 0, bstp_notify_state, bp); 2189 TASK_INIT(&bp->bp_rtagetask, 0, bstp_notify_rtage, bp); 2190 2191 /* Init state */ 2192 bp->bp_infois = BSTP_INFO_DISABLED; 2193 bp->bp_flags = BSTP_PORT_AUTOEDGE|BSTP_PORT_AUTOPTP; 2194 bstp_set_port_state(bp, BSTP_IFSTATE_DISCARDING); 2195 bstp_set_port_proto(bp, bs->bs_protover); 2196 bstp_set_port_role(bp, BSTP_ROLE_DISABLED); 2197 bstp_set_port_tc(bp, BSTP_TCSTATE_INACTIVE); 2198 bp->bp_path_cost = bstp_calc_path_cost(bp); 2199 BSTP_UNLOCK(bs); 2200 return (0); 2201 } 2202 2203 int 2204 bstp_enable(struct bstp_port *bp) 2205 { 2206 struct bstp_state *bs = bp->bp_bs; 2207 struct ifnet *ifp = bp->bp_ifp; 2208 2209 KASSERT(bp->bp_active == 0, ("already a bstp member")); 2210 2211 switch (ifp->if_type) { 2212 case IFT_ETHER: /* These can do spanning tree. */ 2213 break; 2214 default: 2215 /* Nothing else can. */ 2216 return (EINVAL); 2217 } 2218 2219 BSTP_LOCK(bs); 2220 LIST_INSERT_HEAD(&bs->bs_bplist, bp, bp_next); 2221 bp->bp_active = 1; 2222 bp->bp_flags |= BSTP_PORT_NEWINFO; 2223 bstp_reinit(bs); 2224 bstp_update_roles(bs, bp); 2225 BSTP_UNLOCK(bs); 2226 return (0); 2227 } 2228 2229 void 2230 bstp_disable(struct bstp_port *bp) 2231 { 2232 struct bstp_state *bs = bp->bp_bs; 2233 2234 KASSERT(bp->bp_active == 1, ("not a bstp member")); 2235 2236 BSTP_LOCK(bs); 2237 bstp_disable_port(bs, bp); 2238 LIST_REMOVE(bp, bp_next); 2239 bp->bp_active = 0; 2240 bstp_reinit(bs); 2241 BSTP_UNLOCK(bs); 2242 } 2243 2244 /* 2245 * The bstp_port structure is about to be freed by the parent bridge. 2246 */ 2247 void 2248 bstp_destroy(struct bstp_port *bp) 2249 { 2250 KASSERT(bp->bp_active == 0, ("port is still attached")); 2251 taskqueue_drain(taskqueue_swi, &bp->bp_statetask); 2252 taskqueue_drain(taskqueue_swi, &bp->bp_rtagetask); 2253 } 2254