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