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 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Jason L. Wright 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 30 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 * 33 * OpenBSD: bridgestp.c,v 1.5 2001/03/22 03:48:29 jason Exp 34 */ 35 36 /* 37 * Implementation of the spanning tree protocol as defined in 38 * ISO/IEC Final DIS 15802-3 (IEEE P802.1D/D17), May 25, 1998. 39 * (In English: IEEE 802.1D, Draft 17, 1998) 40 */ 41 42 #include <sys/cdefs.h> 43 __FBSDID("$FreeBSD$"); 44 45 #include <sys/param.h> 46 #include <sys/systm.h> 47 #include <sys/mbuf.h> 48 #include <sys/socket.h> 49 #include <sys/sockio.h> 50 #include <sys/kernel.h> 51 #include <sys/callout.h> 52 #include <sys/module.h> 53 #include <sys/proc.h> 54 #include <sys/lock.h> 55 #include <sys/mutex.h> 56 57 #include <net/if.h> 58 #include <net/if_dl.h> 59 #include <net/if_types.h> 60 #include <net/if_llc.h> 61 #include <net/if_media.h> 62 63 #include <netinet/in.h> 64 #include <netinet/in_systm.h> 65 #include <netinet/in_var.h> 66 #include <netinet/if_ether.h> 67 #include <net/bridgestp.h> 68 69 const uint8_t bstp_etheraddr[] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 }; 70 71 LIST_HEAD(, bstp_state) bstp_list; 72 static struct mtx bstp_list_mtx; 73 74 static void bstp_initialize_port(struct bstp_state *, 75 struct bstp_port *); 76 static void bstp_ifupdstatus(struct bstp_state *, struct bstp_port *); 77 static void bstp_enable_port(struct bstp_state *, struct bstp_port *); 78 static void bstp_disable_port(struct bstp_state *, 79 struct bstp_port *); 80 #ifdef notused 81 static void bstp_enable_change_detection(struct bstp_port *); 82 static void bstp_disable_change_detection(struct bstp_port *); 83 #endif /* notused */ 84 static int bstp_root_bridge(struct bstp_state *bs); 85 static int bstp_supersedes_port_info(struct bstp_state *, 86 struct bstp_port *, struct bstp_config_unit *); 87 static int bstp_designated_port(struct bstp_state *, 88 struct bstp_port *); 89 static int bstp_designated_for_some_port(struct bstp_state *); 90 static void bstp_transmit_config(struct bstp_state *, 91 struct bstp_port *); 92 static void bstp_transmit_tcn(struct bstp_state *); 93 static void bstp_received_config_bpdu(struct bstp_state *, 94 struct bstp_port *, struct bstp_config_unit *); 95 static void bstp_received_tcn_bpdu(struct bstp_state *, 96 struct bstp_port *, struct bstp_tcn_unit *); 97 static void bstp_record_config_information(struct bstp_state *, 98 struct bstp_port *, struct bstp_config_unit *); 99 static void bstp_record_config_timeout_values(struct bstp_state *, 100 struct bstp_config_unit *); 101 static void bstp_config_bpdu_generation(struct bstp_state *); 102 static void bstp_send_config_bpdu(struct bstp_state *, 103 struct bstp_port *, struct bstp_config_unit *); 104 static void bstp_configuration_update(struct bstp_state *); 105 static void bstp_root_selection(struct bstp_state *); 106 static void bstp_designated_port_selection(struct bstp_state *); 107 static void bstp_become_designated_port(struct bstp_state *, 108 struct bstp_port *); 109 static void bstp_port_state_selection(struct bstp_state *); 110 static void bstp_make_forwarding(struct bstp_state *, 111 struct bstp_port *); 112 static void bstp_make_blocking(struct bstp_state *, 113 struct bstp_port *); 114 static void bstp_set_port_state(struct bstp_port *, uint8_t); 115 #ifdef notused 116 static void bstp_set_bridge_priority(struct bstp_state *, uint64_t); 117 static void bstp_set_port_priority(struct bstp_state *, 118 struct bstp_port *, uint16_t); 119 static void bstp_set_path_cost(struct bstp_state *, 120 struct bstp_port *, uint32_t); 121 #endif /* notused */ 122 static void bstp_topology_change_detection(struct bstp_state *); 123 static void bstp_topology_change_acknowledged(struct bstp_state *); 124 static void bstp_acknowledge_topology_change(struct bstp_state *, 125 struct bstp_port *); 126 127 static void bstp_enqueue(struct ifnet *, struct mbuf *); 128 static void bstp_tick(void *); 129 static void bstp_timer_start(struct bstp_timer *, uint16_t); 130 static void bstp_timer_stop(struct bstp_timer *); 131 static int bstp_timer_expired(struct bstp_timer *, uint16_t); 132 133 static void bstp_hold_timer_expiry(struct bstp_state *, 134 struct bstp_port *); 135 static void bstp_message_age_timer_expiry(struct bstp_state *, 136 struct bstp_port *); 137 static void bstp_forward_delay_timer_expiry(struct bstp_state *, 138 struct bstp_port *); 139 static void bstp_topology_change_timer_expiry(struct bstp_state *); 140 static void bstp_tcn_timer_expiry(struct bstp_state *); 141 static void bstp_hello_timer_expiry(struct bstp_state *); 142 static int bstp_addr_cmp(const uint8_t *, const uint8_t *); 143 144 static void 145 bstp_transmit_config(struct bstp_state *bs, struct bstp_port *bp) 146 { 147 BSTP_LOCK_ASSERT(bs); 148 149 if (bp->bp_hold_timer.active) { 150 bp->bp_config_pending = 1; 151 return; 152 } 153 154 bp->bp_config_bpdu.cu_message_type = BSTP_MSGTYPE_CFG; 155 bp->bp_config_bpdu.cu_rootid = bs->bs_designated_root; 156 bp->bp_config_bpdu.cu_root_path_cost = bs->bs_root_path_cost; 157 bp->bp_config_bpdu.cu_bridge_id = bs->bs_bridge_id; 158 bp->bp_config_bpdu.cu_port_id = bp->bp_port_id; 159 160 if (bstp_root_bridge(bs)) 161 bp->bp_config_bpdu.cu_message_age = 0; 162 else 163 bp->bp_config_bpdu.cu_message_age = 164 bs->bs_root_port->bp_message_age_timer.value + 165 BSTP_MESSAGE_AGE_INCR; 166 167 bp->bp_config_bpdu.cu_max_age = bs->bs_max_age; 168 bp->bp_config_bpdu.cu_hello_time = bs->bs_hello_time; 169 bp->bp_config_bpdu.cu_forward_delay = bs->bs_forward_delay; 170 bp->bp_config_bpdu.cu_topology_change_acknowledgment 171 = bp->bp_topology_change_acknowledge; 172 bp->bp_config_bpdu.cu_topology_change = bs->bs_topology_change; 173 174 if (bp->bp_config_bpdu.cu_message_age < bs->bs_max_age) { 175 bp->bp_topology_change_acknowledge = 0; 176 bp->bp_config_pending = 0; 177 bstp_send_config_bpdu(bs, bp, &bp->bp_config_bpdu); 178 bstp_timer_start(&bp->bp_hold_timer, 0); 179 } 180 } 181 182 static void 183 bstp_send_config_bpdu(struct bstp_state *bs, struct bstp_port *bp, 184 struct bstp_config_unit *cu) 185 { 186 struct ifnet *ifp; 187 struct mbuf *m; 188 struct ether_header *eh; 189 struct bstp_cbpdu bpdu; 190 191 BSTP_LOCK_ASSERT(bs); 192 193 ifp = bp->bp_ifp; 194 195 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) 196 return; 197 198 MGETHDR(m, M_DONTWAIT, MT_DATA); 199 if (m == NULL) 200 return; 201 202 eh = mtod(m, struct ether_header *); 203 204 m->m_pkthdr.rcvif = ifp; 205 m->m_pkthdr.len = sizeof(*eh) + sizeof(bpdu); 206 m->m_len = m->m_pkthdr.len; 207 208 bpdu.cbu_ssap = bpdu.cbu_dsap = LLC_8021D_LSAP; 209 bpdu.cbu_ctl = LLC_UI; 210 bpdu.cbu_protoid = htons(0); 211 bpdu.cbu_protover = 0; 212 bpdu.cbu_bpdutype = cu->cu_message_type; 213 bpdu.cbu_flags = (cu->cu_topology_change ? BSTP_FLAG_TC : 0) | 214 (cu->cu_topology_change_acknowledgment ? BSTP_FLAG_TCA : 0); 215 216 bpdu.cbu_rootpri = htons(cu->cu_rootid >> 48); 217 bpdu.cbu_rootaddr[0] = cu->cu_rootid >> 40; 218 bpdu.cbu_rootaddr[1] = cu->cu_rootid >> 32; 219 bpdu.cbu_rootaddr[2] = cu->cu_rootid >> 24; 220 bpdu.cbu_rootaddr[3] = cu->cu_rootid >> 16; 221 bpdu.cbu_rootaddr[4] = cu->cu_rootid >> 8; 222 bpdu.cbu_rootaddr[5] = cu->cu_rootid >> 0; 223 224 bpdu.cbu_rootpathcost = htonl(cu->cu_root_path_cost); 225 226 bpdu.cbu_bridgepri = htons(cu->cu_bridge_id >> 48); 227 bpdu.cbu_bridgeaddr[0] = cu->cu_bridge_id >> 40; 228 bpdu.cbu_bridgeaddr[1] = cu->cu_bridge_id >> 32; 229 bpdu.cbu_bridgeaddr[2] = cu->cu_bridge_id >> 24; 230 bpdu.cbu_bridgeaddr[3] = cu->cu_bridge_id >> 16; 231 bpdu.cbu_bridgeaddr[4] = cu->cu_bridge_id >> 8; 232 bpdu.cbu_bridgeaddr[5] = cu->cu_bridge_id >> 0; 233 234 bpdu.cbu_portid = htons(cu->cu_port_id); 235 bpdu.cbu_messageage = htons(cu->cu_message_age); 236 bpdu.cbu_maxage = htons(cu->cu_max_age); 237 bpdu.cbu_hellotime = htons(cu->cu_hello_time); 238 bpdu.cbu_forwarddelay = htons(cu->cu_forward_delay); 239 240 memcpy(eh->ether_shost, IF_LLADDR(ifp), ETHER_ADDR_LEN); 241 memcpy(eh->ether_dhost, bstp_etheraddr, ETHER_ADDR_LEN); 242 eh->ether_type = htons(sizeof(bpdu)); 243 244 memcpy(mtod(m, caddr_t) + sizeof(*eh), &bpdu, sizeof(bpdu)); 245 246 bstp_enqueue(ifp, m); 247 } 248 249 static int 250 bstp_root_bridge(struct bstp_state *bs) 251 { 252 return (bs->bs_designated_root == bs->bs_bridge_id); 253 } 254 255 static int 256 bstp_supersedes_port_info(struct bstp_state *bs, struct bstp_port *bp, 257 struct bstp_config_unit *cu) 258 { 259 if (cu->cu_rootid < bp->bp_designated_root) 260 return (1); 261 if (cu->cu_rootid > bp->bp_designated_root) 262 return (0); 263 264 if (cu->cu_root_path_cost < bp->bp_designated_cost) 265 return (1); 266 if (cu->cu_root_path_cost > bp->bp_designated_cost) 267 return (0); 268 269 if (cu->cu_bridge_id < bp->bp_designated_bridge) 270 return (1); 271 if (cu->cu_bridge_id > bp->bp_designated_bridge) 272 return (0); 273 274 if (bs->bs_bridge_id != cu->cu_bridge_id) 275 return (1); 276 if (cu->cu_port_id <= bp->bp_designated_port) 277 return (1); 278 return (0); 279 } 280 281 static void 282 bstp_record_config_information(struct bstp_state *bs, 283 struct bstp_port *bp, struct bstp_config_unit *cu) 284 { 285 BSTP_LOCK_ASSERT(bs); 286 287 bp->bp_designated_root = cu->cu_rootid; 288 bp->bp_designated_cost = cu->cu_root_path_cost; 289 bp->bp_designated_bridge = cu->cu_bridge_id; 290 bp->bp_designated_port = cu->cu_port_id; 291 bstp_timer_start(&bp->bp_message_age_timer, cu->cu_message_age); 292 } 293 294 static void 295 bstp_record_config_timeout_values(struct bstp_state *bs, 296 struct bstp_config_unit *config) 297 { 298 BSTP_LOCK_ASSERT(bs); 299 300 bs->bs_max_age = config->cu_max_age; 301 bs->bs_hello_time = config->cu_hello_time; 302 bs->bs_forward_delay = config->cu_forward_delay; 303 bs->bs_topology_change = config->cu_topology_change; 304 } 305 306 static void 307 bstp_config_bpdu_generation(struct bstp_state *bs) 308 { 309 struct bstp_port *bp; 310 311 BSTP_LOCK_ASSERT(bs); 312 313 LIST_FOREACH(bp, &bs->bs_bplist, bp_next) { 314 if (bstp_designated_port(bs, bp) && 315 (bp->bp_state != BSTP_IFSTATE_DISABLED)) 316 bstp_transmit_config(bs, bp); 317 } 318 } 319 320 static int 321 bstp_designated_port(struct bstp_state *bs, struct bstp_port *bp) 322 { 323 return ((bp->bp_designated_bridge == bs->bs_bridge_id) 324 && (bp->bp_designated_port == bp->bp_port_id)); 325 } 326 327 static void 328 bstp_transmit_tcn(struct bstp_state *bs) 329 { 330 struct bstp_tbpdu bpdu; 331 struct bstp_port *bp = bs->bs_root_port; 332 struct ifnet *ifp = bp->bp_ifp; 333 struct ether_header *eh; 334 struct mbuf *m; 335 336 BSTP_LOCK_ASSERT(bs); 337 338 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) 339 return; 340 341 MGETHDR(m, M_DONTWAIT, MT_DATA); 342 if (m == NULL) 343 return; 344 345 m->m_pkthdr.rcvif = ifp; 346 m->m_pkthdr.len = sizeof(*eh) + sizeof(bpdu); 347 m->m_len = m->m_pkthdr.len; 348 349 eh = mtod(m, struct ether_header *); 350 351 memcpy(eh->ether_shost, IF_LLADDR(ifp), ETHER_ADDR_LEN); 352 memcpy(eh->ether_dhost, bstp_etheraddr, ETHER_ADDR_LEN); 353 eh->ether_type = htons(sizeof(bpdu)); 354 355 bpdu.tbu_ssap = bpdu.tbu_dsap = LLC_8021D_LSAP; 356 bpdu.tbu_ctl = LLC_UI; 357 bpdu.tbu_protoid = 0; 358 bpdu.tbu_protover = 0; 359 bpdu.tbu_bpdutype = BSTP_MSGTYPE_TCN; 360 361 memcpy(mtod(m, caddr_t) + sizeof(*eh), &bpdu, sizeof(bpdu)); 362 363 bstp_enqueue(ifp, m); 364 } 365 366 static void 367 bstp_configuration_update(struct bstp_state *bs) 368 { 369 BSTP_LOCK_ASSERT(bs); 370 371 bstp_root_selection(bs); 372 bstp_designated_port_selection(bs); 373 } 374 375 static void 376 bstp_root_selection(struct bstp_state *bs) 377 { 378 struct bstp_port *root_port = NULL, *bp; 379 380 BSTP_LOCK_ASSERT(bs); 381 382 LIST_FOREACH(bp, &bs->bs_bplist, bp_next) { 383 if (bstp_designated_port(bs, bp)) 384 continue; 385 if (bp->bp_state == BSTP_IFSTATE_DISABLED) 386 continue; 387 if (bp->bp_designated_root >= bs->bs_bridge_id) 388 continue; 389 if (root_port == NULL) 390 goto set_port; 391 392 if (bp->bp_designated_root < root_port->bp_designated_root) 393 goto set_port; 394 if (bp->bp_designated_root > root_port->bp_designated_root) 395 continue; 396 397 if ((bp->bp_designated_cost + bp->bp_path_cost) < 398 (root_port->bp_designated_cost + root_port->bp_path_cost)) 399 goto set_port; 400 if ((bp->bp_designated_cost + bp->bp_path_cost) > 401 (root_port->bp_designated_cost + root_port->bp_path_cost)) 402 continue; 403 404 if (bp->bp_designated_bridge < 405 root_port->bp_designated_bridge) 406 goto set_port; 407 if (bp->bp_designated_bridge > 408 root_port->bp_designated_bridge) 409 continue; 410 411 if (bp->bp_designated_port < root_port->bp_designated_port) 412 goto set_port; 413 if (bp->bp_designated_port > root_port->bp_designated_port) 414 continue; 415 416 if (bp->bp_port_id >= root_port->bp_port_id) 417 continue; 418 set_port: 419 root_port = bp; 420 } 421 422 bs->bs_root_port = root_port; 423 if (root_port == NULL) { 424 bs->bs_designated_root = bs->bs_bridge_id; 425 bs->bs_root_path_cost = 0; 426 } else { 427 bs->bs_designated_root = root_port->bp_designated_root; 428 bs->bs_root_path_cost = root_port->bp_designated_cost + 429 root_port->bp_path_cost; 430 } 431 } 432 433 static void 434 bstp_designated_port_selection(struct bstp_state *bs) 435 { 436 struct bstp_port *bp; 437 438 BSTP_LOCK_ASSERT(bs); 439 440 LIST_FOREACH(bp, &bs->bs_bplist, bp_next) { 441 if (bstp_designated_port(bs, bp)) 442 goto designated; 443 if (bp->bp_designated_root != bs->bs_designated_root) 444 goto designated; 445 446 if (bs->bs_root_path_cost < bp->bp_designated_cost) 447 goto designated; 448 if (bs->bs_root_path_cost > bp->bp_designated_cost) 449 continue; 450 451 if (bs->bs_bridge_id < bp->bp_designated_bridge) 452 goto designated; 453 if (bs->bs_bridge_id > bp->bp_designated_bridge) 454 continue; 455 456 if (bp->bp_port_id > bp->bp_designated_port) 457 continue; 458 designated: 459 bstp_become_designated_port(bs, bp); 460 } 461 } 462 463 static void 464 bstp_become_designated_port(struct bstp_state *bs, struct bstp_port *bp) 465 { 466 BSTP_LOCK_ASSERT(bs); 467 468 bp->bp_designated_root = bs->bs_designated_root; 469 bp->bp_designated_cost = bs->bs_root_path_cost; 470 bp->bp_designated_bridge = bs->bs_bridge_id; 471 bp->bp_designated_port = bp->bp_port_id; 472 } 473 474 static void 475 bstp_port_state_selection(struct bstp_state *bs) 476 { 477 struct bstp_port *bp; 478 479 BSTP_LOCK_ASSERT(bs); 480 481 LIST_FOREACH(bp, &bs->bs_bplist, bp_next) { 482 if (bp == bs->bs_root_port) { 483 bp->bp_config_pending = 0; 484 bp->bp_topology_change_acknowledge = 0; 485 bstp_make_forwarding(bs, bp); 486 } else if (bstp_designated_port(bs, bp)) { 487 bstp_timer_stop(&bp->bp_message_age_timer); 488 bstp_make_forwarding(bs, bp); 489 } else { 490 bp->bp_config_pending = 0; 491 bp->bp_topology_change_acknowledge = 0; 492 bstp_make_blocking(bs, bp); 493 } 494 } 495 } 496 497 static void 498 bstp_make_forwarding(struct bstp_state *bs, struct bstp_port *bp) 499 { 500 BSTP_LOCK_ASSERT(bs); 501 502 if (bp->bp_state == BSTP_IFSTATE_BLOCKING) { 503 bstp_set_port_state(bp, BSTP_IFSTATE_LISTENING); 504 bstp_timer_start(&bp->bp_forward_delay_timer, 0); 505 } 506 } 507 508 static void 509 bstp_make_blocking(struct bstp_state *bs, struct bstp_port *bp) 510 { 511 BSTP_LOCK_ASSERT(bs); 512 513 if ((bp->bp_state != BSTP_IFSTATE_DISABLED) && 514 (bp->bp_state != BSTP_IFSTATE_BLOCKING)) { 515 if ((bp->bp_state == BSTP_IFSTATE_FORWARDING) || 516 (bp->bp_state == BSTP_IFSTATE_LEARNING)) { 517 if (bp->bp_change_detection_enabled) { 518 bstp_topology_change_detection(bs); 519 } 520 } 521 bstp_set_port_state(bp, BSTP_IFSTATE_BLOCKING); 522 /* XXX bridge_rtdelete(bs, bp->bp_ifp, IFBF_FLUSHDYN); */ 523 bstp_timer_stop(&bp->bp_forward_delay_timer); 524 } 525 } 526 527 static void 528 bstp_set_port_state(struct bstp_port *bp, uint8_t state) 529 { 530 bp->bp_state = state; 531 } 532 533 static void 534 bstp_topology_change_detection(struct bstp_state *bs) 535 { 536 BSTP_LOCK_ASSERT(bs); 537 538 if (bstp_root_bridge(bs)) { 539 bs->bs_topology_change = 1; 540 bstp_timer_start(&bs->bs_topology_change_timer, 0); 541 } else if (!bs->bs_topology_change_detected) { 542 bstp_transmit_tcn(bs); 543 bstp_timer_start(&bs->bs_tcn_timer, 0); 544 } 545 bs->bs_topology_change_detected = 1; 546 } 547 548 static void 549 bstp_topology_change_acknowledged(struct bstp_state *bs) 550 { 551 BSTP_LOCK_ASSERT(bs); 552 553 bs->bs_topology_change_detected = 0; 554 bstp_timer_stop(&bs->bs_tcn_timer); 555 } 556 557 static void 558 bstp_acknowledge_topology_change(struct bstp_state *bs, 559 struct bstp_port *bp) 560 { 561 BSTP_LOCK_ASSERT(bs); 562 563 bp->bp_topology_change_acknowledge = 1; 564 bstp_transmit_config(bs, bp); 565 } 566 567 struct mbuf * 568 bstp_input(struct bstp_port *bp, struct ifnet *ifp, struct mbuf *m) 569 { 570 struct bstp_state *bs = bp->bp_bs; 571 struct ether_header *eh; 572 struct bstp_tbpdu tpdu; 573 struct bstp_cbpdu cpdu; 574 struct bstp_config_unit cu; 575 struct bstp_tcn_unit tu; 576 uint16_t len; 577 578 if (bp->bp_active == 0) { 579 m_freem(m); 580 return (NULL); 581 } 582 583 BSTP_LOCK(bs); 584 585 eh = mtod(m, struct ether_header *); 586 587 len = ntohs(eh->ether_type); 588 if (len < sizeof(tpdu)) 589 goto out; 590 591 m_adj(m, ETHER_HDR_LEN); 592 593 if (m->m_pkthdr.len > len) 594 m_adj(m, len - m->m_pkthdr.len); 595 if (m->m_len < sizeof(tpdu) && 596 (m = m_pullup(m, sizeof(tpdu))) == NULL) 597 goto out; 598 599 memcpy(&tpdu, mtod(m, caddr_t), sizeof(tpdu)); 600 601 if (tpdu.tbu_dsap != LLC_8021D_LSAP || 602 tpdu.tbu_ssap != LLC_8021D_LSAP || 603 tpdu.tbu_ctl != LLC_UI) 604 goto out; 605 if (tpdu.tbu_protoid != 0 || tpdu.tbu_protover != 0) 606 goto out; 607 608 switch (tpdu.tbu_bpdutype) { 609 case BSTP_MSGTYPE_TCN: 610 tu.tu_message_type = tpdu.tbu_bpdutype; 611 bstp_received_tcn_bpdu(bs, bp, &tu); 612 break; 613 case BSTP_MSGTYPE_CFG: 614 if (m->m_len < sizeof(cpdu) && 615 (m = m_pullup(m, sizeof(cpdu))) == NULL) 616 goto out; 617 memcpy(&cpdu, mtod(m, caddr_t), sizeof(cpdu)); 618 619 cu.cu_rootid = 620 (((uint64_t)ntohs(cpdu.cbu_rootpri)) << 48) | 621 (((uint64_t)cpdu.cbu_rootaddr[0]) << 40) | 622 (((uint64_t)cpdu.cbu_rootaddr[1]) << 32) | 623 (((uint64_t)cpdu.cbu_rootaddr[2]) << 24) | 624 (((uint64_t)cpdu.cbu_rootaddr[3]) << 16) | 625 (((uint64_t)cpdu.cbu_rootaddr[4]) << 8) | 626 (((uint64_t)cpdu.cbu_rootaddr[5]) << 0); 627 628 cu.cu_bridge_id = 629 (((uint64_t)ntohs(cpdu.cbu_bridgepri)) << 48) | 630 (((uint64_t)cpdu.cbu_bridgeaddr[0]) << 40) | 631 (((uint64_t)cpdu.cbu_bridgeaddr[1]) << 32) | 632 (((uint64_t)cpdu.cbu_bridgeaddr[2]) << 24) | 633 (((uint64_t)cpdu.cbu_bridgeaddr[3]) << 16) | 634 (((uint64_t)cpdu.cbu_bridgeaddr[4]) << 8) | 635 (((uint64_t)cpdu.cbu_bridgeaddr[5]) << 0); 636 637 cu.cu_root_path_cost = ntohl(cpdu.cbu_rootpathcost); 638 cu.cu_message_age = ntohs(cpdu.cbu_messageage); 639 cu.cu_max_age = ntohs(cpdu.cbu_maxage); 640 cu.cu_hello_time = ntohs(cpdu.cbu_hellotime); 641 cu.cu_forward_delay = ntohs(cpdu.cbu_forwarddelay); 642 cu.cu_port_id = ntohs(cpdu.cbu_portid); 643 cu.cu_message_type = cpdu.cbu_bpdutype; 644 cu.cu_topology_change_acknowledgment = 645 (cpdu.cbu_flags & BSTP_FLAG_TCA) ? 1 : 0; 646 cu.cu_topology_change = 647 (cpdu.cbu_flags & BSTP_FLAG_TC) ? 1 : 0; 648 bstp_received_config_bpdu(bs, bp, &cu); 649 break; 650 default: 651 goto out; 652 } 653 654 out: 655 BSTP_UNLOCK(bs); 656 if (m) 657 m_freem(m); 658 return (NULL); 659 } 660 661 static void 662 bstp_received_config_bpdu(struct bstp_state *bs, struct bstp_port *bp, 663 struct bstp_config_unit *cu) 664 { 665 int root; 666 667 BSTP_LOCK_ASSERT(bs); 668 669 root = bstp_root_bridge(bs); 670 671 if (bp->bp_state != BSTP_IFSTATE_DISABLED) { 672 if (bstp_supersedes_port_info(bs, bp, cu)) { 673 bstp_record_config_information(bs, bp, cu); 674 bstp_configuration_update(bs); 675 bstp_port_state_selection(bs); 676 677 if ((bstp_root_bridge(bs) == 0) && root) { 678 bstp_timer_stop(&bs->bs_hello_timer); 679 680 if (bs->bs_topology_change_detected) { 681 bstp_timer_stop( 682 &bs->bs_topology_change_timer); 683 bstp_transmit_tcn(bs); 684 bstp_timer_start(&bs->bs_tcn_timer, 0); 685 } 686 } 687 688 if (bp == bs->bs_root_port) { 689 bstp_record_config_timeout_values(bs, cu); 690 bstp_config_bpdu_generation(bs); 691 692 if (cu->cu_topology_change_acknowledgment) 693 bstp_topology_change_acknowledged(bs); 694 } 695 } else if (bstp_designated_port(bs, bp)) 696 bstp_transmit_config(bs, bp); 697 } 698 } 699 700 static void 701 bstp_received_tcn_bpdu(struct bstp_state *bs, struct bstp_port *bp, 702 struct bstp_tcn_unit *tcn) 703 { 704 if (bp->bp_state != BSTP_IFSTATE_DISABLED && 705 bstp_designated_port(bs, bp)) { 706 bstp_topology_change_detection(bs); 707 bstp_acknowledge_topology_change(bs, bp); 708 } 709 } 710 711 static void 712 bstp_hello_timer_expiry(struct bstp_state *bs) 713 { 714 bstp_config_bpdu_generation(bs); 715 bstp_timer_start(&bs->bs_hello_timer, 0); 716 } 717 718 static void 719 bstp_message_age_timer_expiry(struct bstp_state *bs, 720 struct bstp_port *bp) 721 { 722 int root; 723 724 BSTP_LOCK_ASSERT(bs); 725 726 root = bstp_root_bridge(bs); 727 bstp_become_designated_port(bs, bp); 728 bstp_configuration_update(bs); 729 bstp_port_state_selection(bs); 730 731 if ((bstp_root_bridge(bs)) && (root == 0)) { 732 bs->bs_max_age = bs->bs_bridge_max_age; 733 bs->bs_hello_time = bs->bs_bridge_hello_time; 734 bs->bs_forward_delay = bs->bs_bridge_forward_delay; 735 736 bstp_topology_change_detection(bs); 737 bstp_timer_stop(&bs->bs_tcn_timer); 738 bstp_config_bpdu_generation(bs); 739 bstp_timer_start(&bs->bs_hello_timer, 0); 740 } 741 } 742 743 static void 744 bstp_forward_delay_timer_expiry(struct bstp_state *bs, 745 struct bstp_port *bp) 746 { 747 if (bp->bp_state == BSTP_IFSTATE_LISTENING) { 748 bstp_set_port_state(bp, BSTP_IFSTATE_LEARNING); 749 bstp_timer_start(&bp->bp_forward_delay_timer, 0); 750 } else if (bp->bp_state == BSTP_IFSTATE_LEARNING) { 751 bstp_set_port_state(bp, BSTP_IFSTATE_FORWARDING); 752 if (bstp_designated_for_some_port(bs) && 753 bp->bp_change_detection_enabled) 754 bstp_topology_change_detection(bs); 755 } 756 } 757 758 static int 759 bstp_designated_for_some_port(struct bstp_state *bs) 760 { 761 762 struct bstp_port *bp; 763 764 BSTP_LOCK_ASSERT(bs); 765 766 LIST_FOREACH(bp, &bs->bs_bplist, bp_next) { 767 if (bp->bp_designated_bridge == bs->bs_bridge_id) 768 return (1); 769 } 770 return (0); 771 } 772 773 static void 774 bstp_tcn_timer_expiry(struct bstp_state *bs) 775 { 776 BSTP_LOCK_ASSERT(bs); 777 778 bstp_transmit_tcn(bs); 779 bstp_timer_start(&bs->bs_tcn_timer, 0); 780 } 781 782 static void 783 bstp_topology_change_timer_expiry(struct bstp_state *bs) 784 { 785 BSTP_LOCK_ASSERT(bs); 786 787 bs->bs_topology_change_detected = 0; 788 bs->bs_topology_change = 0; 789 } 790 791 static void 792 bstp_hold_timer_expiry(struct bstp_state *bs, struct bstp_port *bp) 793 { 794 if (bp->bp_config_pending) 795 bstp_transmit_config(bs, bp); 796 } 797 798 static int 799 bstp_addr_cmp(const uint8_t *a, const uint8_t *b) 800 { 801 int i, d; 802 803 for (i = 0, d = 0; i < ETHER_ADDR_LEN && d == 0; i++) { 804 d = ((int)a[i]) - ((int)b[i]); 805 } 806 807 return (d); 808 } 809 810 void 811 bstp_reinit(struct bstp_state *bs) 812 { 813 struct bstp_port *bp, *mbp; 814 u_char *e_addr; 815 816 BSTP_LOCK(bs); 817 818 mbp = NULL; 819 LIST_FOREACH(bp, &bs->bs_bplist, bp_next) { 820 bp->bp_port_id = (bp->bp_priority << 8) | 821 (bp->bp_ifp->if_index & 0xff); 822 823 if (mbp == NULL) { 824 mbp = bp; 825 continue; 826 } 827 if (bstp_addr_cmp(IF_LLADDR(bp->bp_ifp), 828 IF_LLADDR(mbp->bp_ifp)) < 0) { 829 mbp = bp; 830 continue; 831 } 832 } 833 if (mbp == NULL) { 834 BSTP_UNLOCK(bs); 835 bstp_stop(bs); 836 return; 837 } 838 839 e_addr = IF_LLADDR(mbp->bp_ifp); 840 bs->bs_bridge_id = 841 (((uint64_t)bs->bs_bridge_priority) << 48) | 842 (((uint64_t)e_addr[0]) << 40) | 843 (((uint64_t)e_addr[1]) << 32) | 844 (((uint64_t)e_addr[2]) << 24) | 845 (((uint64_t)e_addr[3]) << 16) | 846 (((uint64_t)e_addr[4]) << 8) | 847 (((uint64_t)e_addr[5])); 848 849 bs->bs_designated_root = bs->bs_bridge_id; 850 bs->bs_root_path_cost = 0; 851 bs->bs_root_port = NULL; 852 853 bs->bs_max_age = bs->bs_bridge_max_age; 854 bs->bs_hello_time = bs->bs_bridge_hello_time; 855 bs->bs_forward_delay = bs->bs_bridge_forward_delay; 856 bs->bs_topology_change_detected = 0; 857 bs->bs_topology_change = 0; 858 bstp_timer_stop(&bs->bs_tcn_timer); 859 bstp_timer_stop(&bs->bs_topology_change_timer); 860 861 if (callout_pending(&bs->bs_bstpcallout) == 0) 862 callout_reset(&bs->bs_bstpcallout, hz, 863 bstp_tick, bs); 864 865 LIST_FOREACH(bp, &bs->bs_bplist, bp_next) 866 bstp_ifupdstatus(bs, bp); 867 868 bstp_port_state_selection(bs); 869 bstp_config_bpdu_generation(bs); 870 bstp_timer_start(&bs->bs_hello_timer, 0); 871 bstp_timer_start(&bs->bs_link_timer, 0); 872 BSTP_UNLOCK(bs); 873 } 874 875 static int 876 bstp_modevent(module_t mod, int type, void *data) 877 { 878 879 switch (type) { 880 case MOD_LOAD: 881 mtx_init(&bstp_list_mtx, "bridgestp list", NULL, MTX_DEF); 882 LIST_INIT(&bstp_list); 883 bstp_linkstate_p = bstp_linkstate; 884 break; 885 case MOD_UNLOAD: 886 mtx_destroy(&bstp_list_mtx); 887 break; 888 default: 889 return (EOPNOTSUPP); 890 } 891 return (0); 892 } 893 894 static moduledata_t bstp_mod = { 895 "bridgestp", 896 bstp_modevent, 897 0 898 }; 899 900 DECLARE_MODULE(bridgestp, bstp_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); 901 902 void 903 bstp_attach(struct bstp_state *bs) 904 { 905 BSTP_LOCK_INIT(bs); 906 callout_init_mtx(&bs->bs_bstpcallout, &bs->bs_mtx, 0); 907 LIST_INIT(&bs->bs_bplist); 908 909 bs->bs_bridge_max_age = BSTP_DEFAULT_MAX_AGE; 910 bs->bs_bridge_hello_time = BSTP_DEFAULT_HELLO_TIME; 911 bs->bs_bridge_forward_delay = BSTP_DEFAULT_FORWARD_DELAY; 912 bs->bs_bridge_priority = BSTP_DEFAULT_BRIDGE_PRIORITY; 913 bs->bs_hold_time = BSTP_DEFAULT_HOLD_TIME; 914 915 mtx_lock(&bstp_list_mtx); 916 LIST_INSERT_HEAD(&bstp_list, bs, bs_list); 917 mtx_unlock(&bstp_list_mtx); 918 } 919 920 void 921 bstp_detach(struct bstp_state *bs) 922 { 923 KASSERT(LIST_EMPTY(&bs->bs_bplist), ("bstp still active")); 924 925 mtx_lock(&bstp_list_mtx); 926 LIST_REMOVE(bs, bs_list); 927 mtx_unlock(&bstp_list_mtx); 928 BSTP_LOCK_DESTROY(bs); 929 } 930 931 void 932 bstp_init(struct bstp_state *bs) 933 { 934 callout_reset(&bs->bs_bstpcallout, hz, bstp_tick, bs); 935 bstp_reinit(bs); 936 } 937 938 void 939 bstp_stop(struct bstp_state *bs) 940 { 941 struct bstp_port *bp; 942 943 BSTP_LOCK(bs); 944 945 LIST_FOREACH(bp, &bs->bs_bplist, bp_next) { 946 bstp_set_port_state(bp, BSTP_IFSTATE_DISABLED); 947 bstp_timer_stop(&bp->bp_hold_timer); 948 bstp_timer_stop(&bp->bp_message_age_timer); 949 bstp_timer_stop(&bp->bp_forward_delay_timer); 950 } 951 952 callout_drain(&bs->bs_bstpcallout); 953 callout_stop(&bs->bs_bstpcallout); 954 955 bstp_timer_stop(&bs->bs_topology_change_timer); 956 bstp_timer_stop(&bs->bs_tcn_timer); 957 bstp_timer_stop(&bs->bs_hello_timer); 958 959 BSTP_UNLOCK(bs); 960 } 961 962 static void 963 bstp_initialize_port(struct bstp_state *bs, struct bstp_port *bp) 964 { 965 BSTP_LOCK_ASSERT(bs); 966 967 bstp_become_designated_port(bs, bp); 968 bstp_set_port_state(bp, BSTP_IFSTATE_BLOCKING); 969 bp->bp_topology_change_acknowledge = 0; 970 bp->bp_config_pending = 0; 971 bp->bp_change_detection_enabled = 1; 972 bstp_timer_stop(&bp->bp_message_age_timer); 973 bstp_timer_stop(&bp->bp_forward_delay_timer); 974 bstp_timer_stop(&bp->bp_hold_timer); 975 } 976 977 static void 978 bstp_enable_port(struct bstp_state *bs, struct bstp_port *bp) 979 { 980 bstp_initialize_port(bs, bp); 981 bstp_port_state_selection(bs); 982 } 983 984 static void 985 bstp_disable_port(struct bstp_state *bs, struct bstp_port *bp) 986 { 987 int root; 988 989 BSTP_LOCK_ASSERT(bs); 990 991 root = bstp_root_bridge(bs); 992 bstp_become_designated_port(bs, bp); 993 bstp_set_port_state(bp, BSTP_IFSTATE_DISABLED); 994 bp->bp_topology_change_acknowledge = 0; 995 bp->bp_config_pending = 0; 996 bstp_timer_stop(&bp->bp_message_age_timer); 997 bstp_timer_stop(&bp->bp_forward_delay_timer); 998 bstp_configuration_update(bs); 999 bstp_port_state_selection(bs); 1000 /* XXX bridge_rtdelete(bs, bp->bp_ifp, IFBF_FLUSHDYN); */ 1001 1002 if (bstp_root_bridge(bs) && (root == 0)) { 1003 bs->bs_max_age = bs->bs_bridge_max_age; 1004 bs->bs_hello_time = bs->bs_bridge_hello_time; 1005 bs->bs_forward_delay = bs->bs_bridge_forward_delay; 1006 1007 bstp_topology_change_detection(bs); 1008 bstp_timer_stop(&bs->bs_tcn_timer); 1009 bstp_config_bpdu_generation(bs); 1010 bstp_timer_start(&bs->bs_hello_timer, 0); 1011 } 1012 } 1013 1014 #ifdef notused 1015 static void 1016 bstp_set_bridge_priority(struct bstp_state *bs, uint64_t new_bridge_id) 1017 { 1018 struct bstp_port *bp; 1019 int root; 1020 1021 BSTP_LOCK_ASSERT(bs); 1022 1023 root = bstp_root_bridge(bs); 1024 1025 LIST_FOREACH(bp, &bs->bs_bplist, bp_next) { 1026 if (bstp_designated_port(bs, bp)) 1027 bp->bp_designated_bridge = new_bridge_id; 1028 } 1029 1030 bs->bs_bridge_id = new_bridge_id; 1031 1032 bstp_configuration_update(bs); 1033 bstp_port_state_selection(bs); 1034 1035 if (bstp_root_bridge(bs) && (root == 0)) { 1036 bs->bs_max_age = bs->bs_bridge_max_age; 1037 bs->bs_hello_time = bs->bs_bridge_hello_time; 1038 bs->bs_forward_delay = bs->bs_bridge_forward_delay; 1039 1040 bstp_topology_change_detection(bs); 1041 bstp_timer_stop(&bs->bs_tcn_timer); 1042 bstp_config_bpdu_generation(bs); 1043 bstp_timer_start(&bs->bs_hello_timer, 0); 1044 } 1045 } 1046 1047 static void 1048 bstp_set_port_priority(struct bstp_state *bs, struct bstp_port *bp, 1049 uint16_t new_port_id) 1050 { 1051 if (bstp_designated_port(bs, bp)) 1052 bp->bp_designated_port = new_port_id; 1053 1054 bp->bp_port_id = new_port_id; 1055 1056 if ((bs->bs_bridge_id == bp->bp_designated_bridge) && 1057 (bp->bp_port_id < bp->bp_designated_port)) { 1058 bstp_become_designated_port(bs, bp); 1059 bstp_port_state_selection(bs); 1060 } 1061 } 1062 1063 static void 1064 bstp_set_path_cost(struct bstp_state *bs, struct bstp_port *bp, 1065 uint32_t path_cost) 1066 { 1067 bp->bp_path_cost = path_cost; 1068 bstp_configuration_update(bs); 1069 bstp_port_state_selection(bs); 1070 } 1071 1072 static void 1073 bstp_enable_change_detection(struct bstp_port *bp) 1074 { 1075 bp->bp_change_detection_enabled = 1; 1076 } 1077 1078 static void 1079 bstp_disable_change_detection(struct bstp_port *bp) 1080 { 1081 bp->bp_change_detection_enabled = 0; 1082 } 1083 #endif /* notused */ 1084 1085 static void 1086 bstp_enqueue(struct ifnet *dst_ifp, struct mbuf *m) 1087 { 1088 int err = 0; 1089 1090 IFQ_ENQUEUE(&dst_ifp->if_snd, m, err); 1091 1092 if ((dst_ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) 1093 (*dst_ifp->if_start)(dst_ifp); 1094 } 1095 1096 void 1097 bstp_linkstate(struct ifnet *ifp, int state) 1098 { 1099 struct bstp_state *bs; 1100 struct bstp_port *bp; 1101 1102 /* 1103 * It would be nice if the ifnet had a pointer to the bstp_port so we 1104 * didnt need to search for it, but that may be an overkill. In reality 1105 * this is fast and doesnt get called often. 1106 */ 1107 mtx_lock(&bstp_list_mtx); 1108 LIST_FOREACH(bs, &bstp_list, bs_list) { 1109 BSTP_LOCK(bs); 1110 LIST_FOREACH(bp, &bs->bs_bplist, bp_next) { 1111 if (bp->bp_ifp == ifp) { 1112 bstp_ifupdstatus(bs, bp); 1113 /* it only exists once so return */ 1114 BSTP_UNLOCK(bs); 1115 mtx_unlock(&bstp_list_mtx); 1116 return; 1117 } 1118 } 1119 BSTP_UNLOCK(bs); 1120 } 1121 mtx_unlock(&bstp_list_mtx); 1122 } 1123 1124 static void 1125 bstp_ifupdstatus(struct bstp_state *bs, struct bstp_port *bp) 1126 { 1127 struct ifnet *ifp = bp->bp_ifp; 1128 struct ifmediareq ifmr; 1129 int error = 0; 1130 1131 BSTP_LOCK_ASSERT(bs); 1132 1133 bzero((char *)&ifmr, sizeof(ifmr)); 1134 error = (*ifp->if_ioctl)(ifp, SIOCGIFMEDIA, (caddr_t)&ifmr); 1135 1136 if ((error == 0) && (ifp->if_flags & IFF_UP)) { 1137 if (ifmr.ifm_status & IFM_ACTIVE) { 1138 if (bp->bp_state == BSTP_IFSTATE_DISABLED) 1139 bstp_enable_port(bs, bp); 1140 1141 } else { 1142 if (bp->bp_state != BSTP_IFSTATE_DISABLED) 1143 bstp_disable_port(bs, bp); 1144 } 1145 return; 1146 } 1147 1148 if (bp->bp_state != BSTP_IFSTATE_DISABLED) 1149 bstp_disable_port(bs, bp); 1150 } 1151 1152 static void 1153 bstp_tick(void *arg) 1154 { 1155 struct bstp_state *bs = arg; 1156 struct bstp_port *bp; 1157 1158 BSTP_LOCK_ASSERT(bs); 1159 1160 /* slow timer to catch missed link events */ 1161 if (bstp_timer_expired(&bs->bs_link_timer, BSTP_LINK_TIMER)) { 1162 LIST_FOREACH(bp, &bs->bs_bplist, bp_next) { 1163 bstp_ifupdstatus(bs, bp); 1164 } 1165 bstp_timer_start(&bs->bs_link_timer, 0); 1166 } 1167 1168 if (bstp_timer_expired(&bs->bs_hello_timer, bs->bs_hello_time)) 1169 bstp_hello_timer_expiry(bs); 1170 1171 if (bstp_timer_expired(&bs->bs_tcn_timer, bs->bs_bridge_hello_time)) 1172 bstp_tcn_timer_expiry(bs); 1173 1174 if (bstp_timer_expired(&bs->bs_topology_change_timer, 1175 bs->bs_topology_change_time)) 1176 bstp_topology_change_timer_expiry(bs); 1177 1178 LIST_FOREACH(bp, &bs->bs_bplist, bp_next) { 1179 if (bstp_timer_expired(&bp->bp_message_age_timer, 1180 bs->bs_max_age)) 1181 bstp_message_age_timer_expiry(bs, bp); 1182 } 1183 1184 LIST_FOREACH(bp, &bs->bs_bplist, bp_next) { 1185 if (bstp_timer_expired(&bp->bp_forward_delay_timer, 1186 bs->bs_forward_delay)) 1187 bstp_forward_delay_timer_expiry(bs, bp); 1188 1189 if (bstp_timer_expired(&bp->bp_hold_timer, 1190 bs->bs_hold_time)) 1191 bstp_hold_timer_expiry(bs, bp); 1192 } 1193 1194 callout_reset(&bs->bs_bstpcallout, hz, bstp_tick, bs); 1195 } 1196 1197 static void 1198 bstp_timer_start(struct bstp_timer *t, uint16_t v) 1199 { 1200 t->value = v; 1201 t->active = 1; 1202 } 1203 1204 static void 1205 bstp_timer_stop(struct bstp_timer *t) 1206 { 1207 t->value = 0; 1208 t->active = 0; 1209 } 1210 1211 static int 1212 bstp_timer_expired(struct bstp_timer *t, uint16_t v) 1213 { 1214 if (t->active == 0) 1215 return (0); 1216 t->value += BSTP_TICK_VAL; 1217 if (t->value >= v) { 1218 bstp_timer_stop(t); 1219 return (1); 1220 } 1221 return (0); 1222 1223 } 1224 1225 int 1226 bstp_add(struct bstp_state *bs, struct bstp_port *bp, struct ifnet *ifp) 1227 { 1228 KASSERT(bp->bp_active == 0, ("already a bstp member")); 1229 1230 switch (ifp->if_type) { 1231 case IFT_ETHER: /* These can do spanning tree. */ 1232 break; 1233 default: 1234 /* Nothing else can. */ 1235 return (EINVAL); 1236 } 1237 1238 BSTP_LOCK(bs); 1239 bp->bp_ifp = ifp; 1240 bp->bp_bs = bs; 1241 bp->bp_active = 1; 1242 bp->bp_priority = BSTP_DEFAULT_PORT_PRIORITY; 1243 bp->bp_path_cost = BSTP_DEFAULT_PATH_COST; 1244 1245 LIST_INSERT_HEAD(&bs->bs_bplist, bp, bp_next); 1246 BSTP_UNLOCK(bs); 1247 bstp_reinit(bs); 1248 1249 return (0); 1250 } 1251 1252 void 1253 bstp_delete(struct bstp_port *bp) 1254 { 1255 struct bstp_state *bs = bp->bp_bs; 1256 1257 KASSERT(bp->bp_active == 1, ("not a bstp member")); 1258 1259 BSTP_LOCK(bs); 1260 LIST_REMOVE(bp, bp_next); 1261 BSTP_UNLOCK(bs); 1262 bp->bp_bs = NULL; 1263 bp->bp_active = 0; 1264 1265 bstp_reinit(bs); 1266 } 1267