1 /* $OpenBSD: bridgestp.c,v 1.7 2001/06/27 06:07:37 kjc 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 34 /* 35 * Implementation of the spanning tree protocol as defined in 36 * ISO/IEC Final DIS 15802-3 (IEEE P802.1D/D17), May 25, 1998. 37 * (In English: IEEE 802.1D, Draft 17, 1998) 38 */ 39 40 #include "bridge.h" 41 42 #if NBRIDGE > 0 43 44 #include <sys/param.h> 45 #include <sys/systm.h> 46 #include <sys/mbuf.h> 47 #include <sys/socket.h> 48 #include <sys/ioctl.h> 49 #include <sys/device.h> 50 #include <sys/kernel.h> 51 #include <sys/timeout.h> 52 53 #include <net/if.h> 54 #include <net/if_types.h> 55 #include <net/if_llc.h> 56 #include <net/if_media.h> 57 #include <net/route.h> 58 #include <net/netisr.h> 59 60 #ifdef INET 61 #include <netinet/in.h> 62 #include <netinet/in_systm.h> 63 #include <netinet/in_var.h> 64 #include <netinet/ip.h> 65 #include <netinet/if_ether.h> 66 #endif 67 68 #if NBPFILTER > 0 69 #include <net/bpf.h> 70 #endif 71 72 #include <net/if_bridge.h> 73 74 /* BPDU message types */ 75 #define BSTP_MSGTYPE_CFG 0x00 /* Configuration */ 76 #define BSTP_MSGTYPE_TCN 0x80 /* Topology chg notification */ 77 78 /* BPDU flags */ 79 #define BSTP_FLAG_TC 0x01 /* Topology change */ 80 #define BSTP_FLAG_TCA 0x80 /* Topology change ack */ 81 82 #define BSTP_MESSAGE_AGE_INCR (1 * 256) /* in 256ths of a second */ 83 #define BSTP_TICK_VAL (1 * 256) /* in 256ths of a second */ 84 85 /* 86 * Because BPDU's do not make nicely aligned structures, two different 87 * declarations are used: bstp_?bpdu (wire representation, packed) and 88 * bstp_*_unit (internal, nicely aligned version). 89 */ 90 91 /* configuration bridge protocol data unit */ 92 struct bstp_cbpdu { 93 u_int8_t cbu_dsap; /* LLC: destination sap */ 94 u_int8_t cbu_ssap; /* LLC: source sap */ 95 u_int8_t cbu_ctl; /* LLC: control */ 96 u_int16_t cbu_protoid; /* protocol id */ 97 u_int8_t cbu_protover; /* protocol version */ 98 u_int8_t cbu_bpdutype; /* message type */ 99 u_int8_t cbu_flags; /* flags (below) */ 100 101 /* root id */ 102 u_int16_t cbu_rootpri; /* root priority */ 103 u_int8_t cbu_rootaddr[6]; /* root address */ 104 105 u_int32_t cbu_rootpathcost; /* root path cost */ 106 107 /* bridge id */ 108 u_int16_t cbu_bridgepri; /* bridge priority */ 109 u_int8_t cbu_bridgeaddr[6]; /* bridge address */ 110 111 u_int16_t cbu_portid; /* port id */ 112 u_int16_t cbu_messageage; /* current message age */ 113 u_int16_t cbu_maxage; /* maximum age */ 114 u_int16_t cbu_hellotime; /* hello time */ 115 u_int16_t cbu_forwarddelay; /* forwarding delay */ 116 } __attribute__((__packed__)); 117 118 /* topology change notification bridge protocol data unit */ 119 struct bstp_tbpdu { 120 u_int8_t tbu_dsap; /* LLC: destination sap */ 121 u_int8_t tbu_ssap; /* LLC: source sap */ 122 u_int8_t tbu_ctl; /* LLC: control */ 123 u_int16_t tbu_protoid; /* protocol id */ 124 u_int8_t tbu_protover; /* protocol version */ 125 u_int8_t tbu_bpdutype; /* message type */ 126 } __attribute__((__packed__)); 127 128 u_int8_t bstp_etheraddr[] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 }; 129 130 void bstp_initialization __P((struct bridge_softc *)); 131 void bstp_stop __P((struct bridge_softc *)); 132 void bstp_initialize_port __P((struct bridge_softc *, struct bridge_iflist *)); 133 void bstp_ifupdstatus __P((struct bridge_softc *, struct bridge_iflist *)); 134 void bstp_enable_port __P((struct bridge_softc *, struct bridge_iflist *)); 135 void bstp_disable_port __P((struct bridge_softc *, struct bridge_iflist *)); 136 void bstp_enable_change_detection __P((struct bridge_iflist *)); 137 void bstp_disable_change_detection __P((struct bridge_iflist *)); 138 int bstp_root_bridge __P((struct bridge_softc *sc)); 139 int bstp_supersedes_port_info __P((struct bridge_softc *, struct bridge_iflist *, struct bstp_config_unit *)); 140 int bstp_designated_port __P((struct bridge_softc *, struct bridge_iflist *)); 141 int bstp_designated_for_some_port __P((struct bridge_softc *)); 142 void bstp_transmit_config __P((struct bridge_softc *, struct bridge_iflist *)); 143 void bstp_transmit_tcn __P((struct bridge_softc *)); 144 struct mbuf *bstp_input __P((struct bridge_softc *, struct ifnet *, 145 struct ether_header *, struct mbuf *)); 146 void bstp_received_config_bpdu __P((struct bridge_softc *, struct bridge_iflist *, struct bstp_config_unit *)); 147 void bstp_received_tcn_bpdu __P((struct bridge_softc *, struct bridge_iflist *, struct bstp_tcn_unit *)); 148 void bstp_record_config_information __P((struct bridge_softc *, struct bridge_iflist *, struct bstp_config_unit *)); 149 void bstp_record_config_timeout_values __P((struct bridge_softc *, struct bstp_config_unit *)); 150 void bstp_config_bpdu_generation __P((struct bridge_softc *)); 151 void bstp_send_config_bpdu __P((struct bridge_iflist *, struct bstp_config_unit *)); 152 void bstp_configuration_update __P((struct bridge_softc *)); 153 void bstp_root_selection __P((struct bridge_softc *)); 154 void bstp_designated_port_selection __P((struct bridge_softc *)); 155 void bstp_become_designated_port __P((struct bridge_softc *, struct bridge_iflist *)); 156 void bstp_port_state_selection __P((struct bridge_softc *)); 157 void bstp_make_forwarding __P((struct bridge_softc *, struct bridge_iflist *)); 158 void bstp_make_blocking __P((struct bridge_softc *, struct bridge_iflist *)); 159 void bstp_set_port_state __P((struct bridge_iflist *, u_int8_t)); 160 void bstp_set_bridge_priority __P((struct bridge_softc *, u_int64_t)); 161 void bstp_set_port_priority __P((struct bridge_softc *, struct bridge_iflist *, u_int16_t)); 162 void bstp_set_path_cost __P((struct bridge_softc *, struct bridge_iflist *, u_int32_t)); 163 void bstp_topology_change_detection __P((struct bridge_softc *)); 164 void bstp_topology_change_acknowledged __P((struct bridge_softc *)); 165 void bstp_acknowledge_topology_change __P((struct bridge_softc *, struct bridge_iflist *)); 166 167 void bstp_tick __P((void *)); 168 void bstp_timer_start __P((struct bridge_timer *, u_int16_t)); 169 void bstp_timer_stop __P((struct bridge_timer *)); 170 int bstp_timer_expired __P((struct bridge_timer *, u_int16_t)); 171 172 void bstp_hold_timer_expiry __P((struct bridge_softc *, struct bridge_iflist *)); 173 void bstp_message_age_timer_expiry __P((struct bridge_softc *, struct bridge_iflist *)); 174 void bstp_forward_delay_timer_expiry __P((struct bridge_softc *, struct bridge_iflist *)); 175 void bstp_topology_change_timer_expiry __P((struct bridge_softc *)); 176 void bstp_tcn_timer_expiry __P((struct bridge_softc *)); 177 void bstp_hello_timer_expiry __P((struct bridge_softc *)); 178 179 void 180 bstp_transmit_config(sc, bif) 181 struct bridge_softc *sc; 182 struct bridge_iflist *bif; 183 { 184 if (bif->bif_hold_timer.active) { 185 bif->bif_config_pending = 1; 186 return; 187 } 188 189 bif->bif_config_bpdu.cu_message_type = BSTP_MSGTYPE_CFG; 190 bif->bif_config_bpdu.cu_rootid = sc->sc_designated_root; 191 bif->bif_config_bpdu.cu_root_path_cost = sc->sc_root_path_cost; 192 bif->bif_config_bpdu.cu_bridge_id = sc->sc_bridge_id; 193 bif->bif_config_bpdu.cu_port_id = bif->bif_port_id; 194 195 if (bstp_root_bridge(sc)) 196 bif->bif_config_bpdu.cu_message_age = 0; 197 else 198 bif->bif_config_bpdu.cu_message_age = 199 sc->sc_root_port->bif_message_age_timer.value + 200 BSTP_MESSAGE_AGE_INCR; 201 202 bif->bif_config_bpdu.cu_max_age = sc->sc_max_age; 203 bif->bif_config_bpdu.cu_hello_time = sc->sc_hello_time; 204 bif->bif_config_bpdu.cu_forward_delay = sc->sc_forward_delay; 205 bif->bif_config_bpdu.cu_topology_change_acknowledgment 206 = bif->bif_topology_change_acknowledge; 207 bif->bif_config_bpdu.cu_topology_change = sc->sc_topology_change; 208 209 if (bif->bif_config_bpdu.cu_message_age < sc->sc_max_age) { 210 bif->bif_topology_change_acknowledge = 0; 211 bif->bif_config_pending = 0; 212 bstp_send_config_bpdu(bif, &bif->bif_config_bpdu); 213 bstp_timer_start(&bif->bif_hold_timer, 0); 214 } 215 } 216 217 void 218 bstp_send_config_bpdu(bif, cu) 219 struct bridge_iflist *bif; 220 struct bstp_config_unit *cu; 221 { 222 struct arpcom *arp; 223 struct ifnet *ifp; 224 struct mbuf *m; 225 struct ether_header eh; 226 struct bstp_cbpdu bpdu; 227 int s, error; 228 229 s = splimp(); 230 ifp = bif->ifp; 231 arp = (struct arpcom *)ifp; 232 233 if ((ifp->if_flags & IFF_RUNNING) == 0) { 234 splx(s); 235 return; 236 } 237 #ifdef ALTQ 238 if (!ALTQ_IS_ENABLED(&ifp->if_snd)) 239 #endif 240 if (IF_QFULL(&ifp->if_snd)) { 241 splx(s); 242 return; 243 } 244 245 MGETHDR(m, M_DONTWAIT, MT_DATA); 246 if (m == NULL) { 247 splx(s); 248 return; 249 } 250 m->m_pkthdr.rcvif = ifp; 251 m->m_pkthdr.len = sizeof(eh) + sizeof(bpdu); 252 m->m_len = m->m_pkthdr.len; 253 254 bpdu.cbu_ssap = bpdu.cbu_dsap = LLC_8021D_LSAP; 255 bpdu.cbu_ctl = LLC_UI; 256 bpdu.cbu_protoid = htons(0); 257 bpdu.cbu_protover = 0; 258 bpdu.cbu_bpdutype = cu->cu_message_type; 259 bpdu.cbu_flags = (cu->cu_topology_change ? BSTP_FLAG_TC : 0) | 260 (cu->cu_topology_change_acknowledgment ? BSTP_FLAG_TCA : 0); 261 262 bpdu.cbu_rootpri = htons(cu->cu_rootid >> 48); 263 bpdu.cbu_rootaddr[0] = cu->cu_rootid >> 40; 264 bpdu.cbu_rootaddr[1] = cu->cu_rootid >> 32; 265 bpdu.cbu_rootaddr[2] = cu->cu_rootid >> 24; 266 bpdu.cbu_rootaddr[3] = cu->cu_rootid >> 16; 267 bpdu.cbu_rootaddr[4] = cu->cu_rootid >> 8; 268 bpdu.cbu_rootaddr[5] = cu->cu_rootid >> 0; 269 270 bpdu.cbu_rootpathcost = htonl(cu->cu_root_path_cost); 271 272 bpdu.cbu_bridgepri = htons(cu->cu_rootid >> 48); 273 bpdu.cbu_bridgeaddr[0] = cu->cu_rootid >> 40; 274 bpdu.cbu_bridgeaddr[1] = cu->cu_rootid >> 32; 275 bpdu.cbu_bridgeaddr[2] = cu->cu_rootid >> 24; 276 bpdu.cbu_bridgeaddr[3] = cu->cu_rootid >> 16; 277 bpdu.cbu_bridgeaddr[4] = cu->cu_rootid >> 8; 278 bpdu.cbu_bridgeaddr[5] = cu->cu_rootid >> 0; 279 280 bpdu.cbu_portid = htons(cu->cu_port_id); 281 bpdu.cbu_messageage = htons(cu->cu_message_age); 282 bpdu.cbu_maxage = htons(cu->cu_max_age); 283 bpdu.cbu_hellotime = htons(cu->cu_hello_time); 284 bpdu.cbu_forwarddelay = htons(cu->cu_forward_delay); 285 286 bcopy(arp->ac_enaddr, eh.ether_shost, ETHER_ADDR_LEN); 287 bcopy(bstp_etheraddr, eh.ether_dhost, ETHER_ADDR_LEN); 288 eh.ether_type = htons(sizeof(bpdu)); 289 290 bcopy(&eh, m->m_data, sizeof(eh)); 291 bcopy(&bpdu, m->m_data + sizeof(eh), sizeof(bpdu)); 292 293 IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error); 294 if (error == 0 && (ifp->if_flags & IFF_OACTIVE) == 0) 295 (*ifp->if_start)(ifp); 296 splx(s); 297 } 298 299 int 300 bstp_root_bridge(sc) 301 struct bridge_softc *sc; 302 { 303 return (sc->sc_designated_root == sc->sc_bridge_id); 304 } 305 306 int 307 bstp_supersedes_port_info(sc, bif, cu) 308 struct bridge_softc *sc; 309 struct bridge_iflist *bif; 310 struct bstp_config_unit *cu; 311 { 312 if (cu->cu_rootid < bif->bif_designated_root) 313 return (1); 314 if (cu->cu_rootid > bif->bif_designated_root) 315 return (0); 316 317 if (cu->cu_root_path_cost < bif->bif_designated_cost) 318 return (1); 319 if (cu->cu_root_path_cost > bif->bif_designated_cost) 320 return (0); 321 322 if (cu->cu_bridge_id < bif->bif_designated_bridge) 323 return (1); 324 if (cu->cu_bridge_id > bif->bif_designated_bridge) 325 return (0); 326 327 if (sc->sc_bridge_id != cu->cu_bridge_id) 328 return (1); 329 if (cu->cu_port_id <= bif->bif_designated_port) 330 return (1); 331 return (0); 332 } 333 334 void 335 bstp_record_config_information(sc, bif, cu) 336 struct bridge_softc *sc; 337 struct bridge_iflist *bif; 338 struct bstp_config_unit *cu; 339 { 340 bif->bif_designated_root = cu->cu_rootid; 341 bif->bif_designated_cost = cu->cu_root_path_cost; 342 bif->bif_designated_bridge = cu->cu_bridge_id; 343 bif->bif_designated_port = cu->cu_port_id; 344 bstp_timer_start(&bif->bif_message_age_timer, cu->cu_message_age); 345 } 346 347 void 348 bstp_record_config_timeout_values(sc, config) 349 struct bridge_softc *sc; 350 struct bstp_config_unit *config; 351 { 352 sc->sc_max_age = config->cu_max_age; 353 sc->sc_hello_time = config->cu_hello_time; 354 sc->sc_forward_delay = config->cu_forward_delay; 355 sc->sc_topology_change = config->cu_topology_change; 356 } 357 358 void 359 bstp_config_bpdu_generation(sc) 360 struct bridge_softc *sc; 361 { 362 struct bridge_iflist *bif; 363 364 LIST_FOREACH(bif, &sc->sc_iflist, next) { 365 if (!(bif->bif_flags & IFBIF_STP)) 366 continue; 367 if (bstp_designated_port(sc, bif) && 368 (bif->bif_state != BSTP_IFSTATE_DISABLED)) 369 bstp_transmit_config(sc, bif); 370 } 371 } 372 373 int 374 bstp_designated_port(sc, bif) 375 struct bridge_softc *sc; 376 struct bridge_iflist *bif; 377 { 378 return ((bif->bif_designated_bridge == sc->sc_bridge_id) 379 && (bif->bif_designated_port == bif->bif_port_id)); 380 } 381 382 void 383 bstp_transmit_tcn(sc) 384 struct bridge_softc *sc; 385 { 386 struct bstp_tbpdu bpdu; 387 struct bridge_iflist *bif = sc->sc_root_port; 388 struct ifnet *ifp = bif->ifp; 389 struct arpcom *arp = (struct arpcom *)ifp; 390 struct ether_header *eh; 391 struct mbuf *m; 392 int s, error; 393 394 MGETHDR(m, M_DONTWAIT, MT_DATA); 395 if (m == NULL) 396 return; 397 m->m_pkthdr.rcvif = ifp; 398 m->m_pkthdr.len = sizeof(eh) + sizeof(bpdu); 399 m->m_len = m->m_pkthdr.len; 400 401 eh = mtod(m, struct ether_header *); 402 bcopy(arp->ac_enaddr, eh->ether_shost, ETHER_ADDR_LEN); 403 bcopy(bstp_etheraddr, eh->ether_dhost, ETHER_ADDR_LEN); 404 eh->ether_type = htons(sizeof(bpdu)); 405 406 bpdu.tbu_ssap = bpdu.tbu_dsap = LLC_8021D_LSAP; 407 bpdu.tbu_ctl = LLC_UI; 408 bpdu.tbu_protoid = 0; 409 bpdu.tbu_protover = 0; 410 bpdu.tbu_bpdutype = BSTP_MSGTYPE_TCN; 411 bcopy(&bpdu, m->m_data + sizeof(eh), sizeof(bpdu)); 412 413 s = splimp(); 414 if ((ifp->if_flags & IFF_RUNNING) == 0) 415 goto out; 416 IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error); 417 if (error == 0 && (ifp->if_flags & IFF_OACTIVE) == 0) 418 (*ifp->if_start)(ifp); 419 m = NULL; 420 421 out: 422 splx(s); 423 if (m != NULL) 424 m_freem(m); 425 } 426 427 void 428 bstp_configuration_update(sc) 429 struct bridge_softc *sc; 430 { 431 bstp_root_selection(sc); 432 bstp_designated_port_selection(sc); 433 } 434 435 void 436 bstp_root_selection(sc) 437 struct bridge_softc *sc; 438 { 439 struct bridge_iflist *root_port = NULL, *bif; 440 441 LIST_FOREACH(bif, &sc->sc_iflist, next) { 442 if (!(bif->bif_flags & IFBIF_STP)) 443 continue; 444 if (bstp_designated_port(sc, bif)) 445 continue; 446 if (bif->bif_state == BSTP_IFSTATE_DISABLED) 447 continue; 448 if (bif->bif_designated_root >= sc->sc_bridge_id) 449 continue; 450 if (root_port == NULL) 451 goto set_port; 452 453 if (bif->bif_designated_root < root_port->bif_designated_root) 454 goto set_port; 455 if (bif->bif_designated_root > root_port->bif_designated_root) 456 continue; 457 458 if ((bif->bif_designated_cost + bif->bif_path_cost) < 459 (root_port->bif_designated_cost + root_port->bif_path_cost)) 460 goto set_port; 461 if ((bif->bif_designated_cost + bif->bif_path_cost) > 462 (root_port->bif_designated_cost + root_port->bif_path_cost)) 463 continue; 464 465 if (bif->bif_designated_bridge < root_port->bif_designated_bridge) 466 goto set_port; 467 if (bif->bif_designated_bridge > root_port->bif_designated_bridge) 468 continue; 469 470 if (bif->bif_designated_port < root_port->bif_designated_port) 471 goto set_port; 472 if (bif->bif_designated_port > root_port->bif_designated_port) 473 continue; 474 475 if (bif->bif_port_id >= root_port->bif_port_id) 476 continue; 477 set_port: 478 root_port = bif; 479 } 480 481 sc->sc_root_port = root_port; 482 if (root_port == NULL) { 483 sc->sc_designated_root = sc->sc_bridge_id; 484 sc->sc_root_path_cost = 0; 485 } else { 486 sc->sc_designated_root = root_port->bif_designated_root; 487 sc->sc_root_path_cost = root_port->bif_designated_cost + 488 root_port->bif_path_cost; 489 } 490 } 491 492 void 493 bstp_designated_port_selection(sc) 494 struct bridge_softc *sc; 495 { 496 struct bridge_iflist *bif; 497 498 LIST_FOREACH(bif, &sc->sc_iflist, next) { 499 if (!(bif->bif_flags & IFBIF_STP)) 500 continue; 501 if (bstp_designated_port(sc, bif)) 502 goto designated; 503 if (bif->bif_designated_root != sc->sc_designated_root) 504 goto designated; 505 506 if (sc->sc_root_path_cost < bif->bif_designated_cost) 507 goto designated; 508 if (sc->sc_root_path_cost > bif->bif_designated_cost) 509 continue; 510 511 if (sc->sc_bridge_id < bif->bif_designated_bridge) 512 goto designated; 513 if (sc->sc_bridge_id > bif->bif_designated_bridge) 514 continue; 515 516 if (bif->bif_port_id > bif->bif_designated_port) 517 continue; 518 designated: 519 bstp_become_designated_port(sc, bif); 520 } 521 } 522 523 void 524 bstp_become_designated_port(sc, bif) 525 struct bridge_softc *sc; 526 struct bridge_iflist *bif; 527 { 528 bif->bif_designated_root = sc->sc_designated_root; 529 bif->bif_designated_cost = sc->sc_root_path_cost; 530 bif->bif_designated_bridge = sc->sc_bridge_id; 531 bif->bif_designated_port = bif->bif_port_id; 532 } 533 534 void 535 bstp_port_state_selection(sc) 536 struct bridge_softc *sc; 537 { 538 struct bridge_iflist *bif; 539 540 LIST_FOREACH(bif, &sc->sc_iflist, next) { 541 if (!(bif->bif_flags & IFBIF_STP)) 542 continue; 543 if (bif == sc->sc_root_port) { 544 bif->bif_config_pending = 0; 545 bif->bif_topology_change_acknowledge = 0; 546 bstp_make_forwarding(sc, bif); 547 } else if (bstp_designated_port(sc, bif)) { 548 bstp_timer_stop(&bif->bif_message_age_timer); 549 bstp_make_forwarding(sc, bif); 550 } else { 551 bif->bif_config_pending = 0; 552 bif->bif_topology_change_acknowledge = 0; 553 bstp_make_blocking(sc, bif); 554 } 555 } 556 } 557 558 void 559 bstp_make_forwarding(sc, bif) 560 struct bridge_softc *sc; 561 struct bridge_iflist *bif; 562 { 563 if (bif->bif_state == BSTP_IFSTATE_BLOCKING) { 564 bstp_set_port_state(bif, BSTP_IFSTATE_LISTENING); 565 bstp_timer_start(&bif->bif_forward_delay_timer, 0); 566 } 567 } 568 569 void 570 bstp_make_blocking(sc, bif) 571 struct bridge_softc *sc; 572 struct bridge_iflist *bif; 573 { 574 if ((bif->bif_state != BSTP_IFSTATE_DISABLED) && 575 (bif->bif_state != BSTP_IFSTATE_BLOCKING)) { 576 if ((bif->bif_state == BSTP_IFSTATE_FORWARDING) || 577 (bif->bif_state == BSTP_IFSTATE_LEARNING)) { 578 if (bif->bif_change_detection_enabled) { 579 bstp_topology_change_detection(sc); 580 } 581 } 582 bstp_set_port_state(bif, BSTP_IFSTATE_BLOCKING); 583 bstp_timer_stop(&bif->bif_forward_delay_timer); 584 } 585 } 586 587 void 588 bstp_set_port_state(bif, state) 589 struct bridge_iflist *bif; 590 u_int8_t state; 591 { 592 bif->bif_state = state; 593 } 594 595 void 596 bstp_topology_change_detection(sc) 597 struct bridge_softc *sc; 598 { 599 if (bstp_root_bridge(sc)) { 600 sc->sc_topology_change = 1; 601 bstp_timer_start(&sc->sc_topology_change_timer, 0); 602 } else if (!sc->sc_topology_change_detected) { 603 bstp_transmit_tcn(sc); 604 bstp_timer_start(&sc->sc_tcn_timer, 0); 605 } 606 sc->sc_topology_change_detected = 1; 607 } 608 609 void 610 bstp_topology_change_acknowledged(sc) 611 struct bridge_softc *sc; 612 { 613 sc->sc_topology_change_detected = 0; 614 bstp_timer_stop(&sc->sc_tcn_timer); 615 } 616 617 void 618 bstp_acknowledge_topology_change(sc, bif) 619 struct bridge_softc *sc; 620 struct bridge_iflist *bif; 621 { 622 bif->bif_topology_change_acknowledge = 1; 623 bstp_transmit_config(sc, bif); 624 } 625 626 struct mbuf * 627 bstp_input(sc, ifp, eh, m) 628 struct bridge_softc *sc; 629 struct ifnet *ifp; 630 struct ether_header *eh; 631 struct mbuf *m; 632 { 633 struct bridge_iflist *bif = NULL; 634 struct bstp_tbpdu tpdu; 635 struct bstp_cbpdu cpdu; 636 struct bstp_config_unit cu; 637 struct bstp_tcn_unit tu; 638 u_int16_t len; 639 640 LIST_FOREACH(bif, &sc->sc_iflist, next) { 641 if (!(bif->bif_flags & IFBIF_STP)) 642 continue; 643 if (bif->ifp == ifp) 644 break; 645 } 646 if (bif == NULL) 647 goto out; 648 649 len = ntohs(eh->ether_type); 650 if (len < sizeof(tpdu)) 651 goto out; 652 if (m->m_pkthdr.len > len) 653 m_adj(m, len - m->m_pkthdr.len); 654 if ((m = m_pullup(m, sizeof(tpdu))) == NULL) 655 goto out; 656 bcopy(mtod(m, struct tpdu *), &tpdu, sizeof(tpdu)); 657 658 if (tpdu.tbu_dsap != LLC_8021D_LSAP || 659 tpdu.tbu_ssap != LLC_8021D_LSAP || 660 tpdu.tbu_ctl != LLC_UI) 661 goto out; 662 if (tpdu.tbu_protoid != 0 || tpdu.tbu_protover != 0) 663 goto out; 664 665 switch (tpdu.tbu_bpdutype) { 666 case BSTP_MSGTYPE_TCN: 667 tu.tu_message_type = tpdu.tbu_bpdutype; 668 bstp_received_tcn_bpdu(sc, bif, &tu); 669 break; 670 case BSTP_MSGTYPE_CFG: 671 if ((m = m_pullup(m, sizeof(cpdu))) == NULL) 672 goto out; 673 bcopy(mtod(m, struct bstp_cpdu *), &cpdu, sizeof(cpdu)); 674 675 cu.cu_rootid = 676 (((u_int64_t)ntohs(cpdu.cbu_rootpri)) << 48) | 677 (((u_int64_t)cpdu.cbu_rootaddr[0]) << 40) | 678 (((u_int64_t)cpdu.cbu_rootaddr[1]) << 32) | 679 (((u_int64_t)cpdu.cbu_rootaddr[2]) << 24) | 680 (((u_int64_t)cpdu.cbu_rootaddr[3]) << 16) | 681 (((u_int64_t)cpdu.cbu_rootaddr[4]) << 8) | 682 (((u_int64_t)cpdu.cbu_rootaddr[5]) << 0); 683 684 cu.cu_bridge_id = 685 (((u_int64_t)ntohs(cpdu.cbu_bridgepri)) << 48) | 686 (((u_int64_t)cpdu.cbu_bridgeaddr[0]) << 40) | 687 (((u_int64_t)cpdu.cbu_bridgeaddr[1]) << 32) | 688 (((u_int64_t)cpdu.cbu_bridgeaddr[2]) << 24) | 689 (((u_int64_t)cpdu.cbu_bridgeaddr[3]) << 16) | 690 (((u_int64_t)cpdu.cbu_bridgeaddr[4]) << 8) | 691 (((u_int64_t)cpdu.cbu_bridgeaddr[5]) << 0); 692 693 cu.cu_root_path_cost = ntohl(cpdu.cbu_rootpathcost); 694 cu.cu_message_age = ntohs(cpdu.cbu_messageage); 695 cu.cu_max_age = ntohs(cpdu.cbu_maxage); 696 cu.cu_hello_time = ntohs(cpdu.cbu_hellotime); 697 cu.cu_forward_delay = ntohs(cpdu.cbu_forwarddelay); 698 cu.cu_port_id = ntohs(cpdu.cbu_portid); 699 cu.cu_message_type = cpdu.cbu_bpdutype; 700 cu.cu_topology_change_acknowledgment = 701 (cpdu.cbu_flags & BSTP_FLAG_TCA) ? 1 : 0; 702 cu.cu_topology_change = 703 (cpdu.cbu_flags & BSTP_FLAG_TC) ? 1 : 0; 704 bstp_received_config_bpdu(sc, bif, &cu); 705 break; 706 default: 707 goto out; 708 } 709 710 out: 711 if (m) 712 m_freem(m); 713 return (NULL); 714 } 715 716 void 717 bstp_received_config_bpdu(sc, bif, cu) 718 struct bridge_softc *sc; 719 struct bridge_iflist *bif; 720 struct bstp_config_unit *cu; 721 { 722 int root; 723 724 root = bstp_root_bridge(sc); 725 726 if (bif->bif_state != BSTP_IFSTATE_DISABLED) { 727 if (bstp_supersedes_port_info(sc, bif, cu)) { 728 bstp_record_config_information(sc, bif, cu); 729 bstp_configuration_update(sc); 730 bstp_port_state_selection(sc); 731 732 if ((!bstp_root_bridge(sc)) && root) { 733 bstp_timer_stop(&sc->sc_hello_timer); 734 735 if (sc->sc_topology_change_detected) { 736 bstp_timer_stop(&sc->sc_topology_change_timer); 737 bstp_transmit_tcn(sc); 738 bstp_timer_start(&sc->sc_tcn_timer, 0); 739 } 740 } 741 742 if (bif == sc->sc_root_port) { 743 bstp_record_config_timeout_values(sc, cu); 744 bstp_config_bpdu_generation(sc); 745 746 if (cu->cu_topology_change_acknowledgment) 747 bstp_topology_change_acknowledged(sc); 748 } 749 } 750 else if (bstp_designated_port(sc, bif)) 751 bstp_transmit_config(sc, bif); 752 } 753 } 754 755 void 756 bstp_received_tcn_bpdu(sc, bif, tcn) 757 struct bridge_softc *sc; 758 struct bridge_iflist *bif; 759 struct bstp_tcn_unit *tcn; 760 { 761 if (bif->bif_state != BSTP_IFSTATE_DISABLED && 762 bstp_designated_port(sc, bif)) { 763 bstp_topology_change_detection(sc); 764 bstp_acknowledge_topology_change(sc, bif); 765 } 766 } 767 768 void 769 bstp_hello_timer_expiry(sc) 770 struct bridge_softc *sc; 771 { 772 bstp_config_bpdu_generation(sc); 773 bstp_timer_start(&sc->sc_hello_timer, 0); 774 } 775 776 void 777 bstp_message_age_timer_expiry(sc, bif) 778 struct bridge_softc *sc; 779 struct bridge_iflist *bif; 780 { 781 int root; 782 783 root = bstp_root_bridge(sc); 784 bstp_become_designated_port(sc, bif); 785 bstp_configuration_update(sc); 786 bstp_port_state_selection(sc); 787 788 if ((bstp_root_bridge(sc)) && (!root)) { 789 sc->sc_max_age = sc->sc_bridge_max_age; 790 sc->sc_hello_time = sc->sc_bridge_hello_time; 791 sc->sc_forward_delay = sc->sc_bridge_forward_delay; 792 793 bstp_topology_change_detection(sc); 794 bstp_timer_stop(&sc->sc_tcn_timer); 795 bstp_config_bpdu_generation(sc); 796 bstp_timer_start(&sc->sc_hello_timer, 0); 797 } 798 } 799 800 void 801 bstp_forward_delay_timer_expiry(sc, bif) 802 struct bridge_softc *sc; 803 struct bridge_iflist *bif; 804 { 805 if (bif->bif_state == BSTP_IFSTATE_LISTENING) { 806 bstp_set_port_state(bif, BSTP_IFSTATE_LEARNING); 807 bstp_timer_start(&bif->bif_forward_delay_timer, 0); 808 } else if (bif->bif_state == BSTP_IFSTATE_LEARNING) { 809 bstp_set_port_state(bif, BSTP_IFSTATE_FORWARDING); 810 if (bstp_designated_for_some_port(sc) && 811 bif->bif_change_detection_enabled) 812 bstp_topology_change_detection(sc); 813 } 814 } 815 816 int 817 bstp_designated_for_some_port(sc) 818 struct bridge_softc *sc; 819 { 820 821 struct bridge_iflist *bif; 822 823 LIST_FOREACH(bif, &sc->sc_iflist, next) { 824 if (!(bif->bif_flags & IFBIF_STP)) 825 continue; 826 if (bif->bif_designated_bridge == sc->sc_bridge_id) 827 return (1); 828 } 829 return (0); 830 } 831 832 void 833 bstp_tcn_timer_expiry(sc) 834 struct bridge_softc *sc; 835 { 836 bstp_transmit_tcn(sc); 837 bstp_timer_start(&sc->sc_tcn_timer, 0); 838 } 839 840 void 841 bstp_topology_change_timer_expiry(sc) 842 struct bridge_softc *sc; 843 { 844 sc->sc_topology_change_detected = 0; 845 sc->sc_topology_change = 0; 846 } 847 848 void 849 bstp_hold_timer_expiry(sc, bif) 850 struct bridge_softc *sc; 851 struct bridge_iflist *bif; 852 { 853 if (bif->bif_config_pending) 854 bstp_transmit_config(sc, bif); 855 } 856 857 void 858 bstp_initialization(sc) 859 struct bridge_softc *sc; 860 { 861 struct bridge_iflist *bif, *mif; 862 struct arpcom *ac, *mac; 863 864 mif = NULL; mac = NULL; 865 LIST_FOREACH(bif, &sc->sc_iflist, next) { 866 if (!(bif->bif_flags & IFBIF_STP)) 867 continue; 868 if (bif->ifp->if_type != IFT_ETHER) 869 continue; 870 bif->bif_port_id = (bif->bif_priority << 8) | 871 (bif->ifp->if_index & 0xff); 872 873 if (mif == NULL) { 874 mif = bif; 875 mac = (struct arpcom *)bif->ifp; 876 continue; 877 } 878 ac = (struct arpcom *)bif->ifp; 879 if (memcmp(ac->ac_enaddr, mac->ac_enaddr, ETHER_ADDR_LEN) < 0) { 880 mif = bif; 881 mac = (struct arpcom *)bif->ifp; 882 continue; 883 } 884 } 885 if (mif == NULL) { 886 bstp_stop(sc); 887 return; 888 } 889 890 sc->sc_bridge_id = 891 (((u_int64_t)sc->sc_bridge_priority) << 48) | 892 (((u_int64_t)mac->ac_enaddr[0]) << 40) | 893 (((u_int64_t)mac->ac_enaddr[1]) << 32) | 894 (mac->ac_enaddr[2] << 24) | (mac->ac_enaddr[3] << 16) | 895 (mac->ac_enaddr[4] << 8) | (mac->ac_enaddr[5]); 896 897 sc->sc_designated_root = sc->sc_bridge_id; 898 sc->sc_root_path_cost = 0; 899 sc->sc_root_port = NULL; 900 901 sc->sc_max_age = sc->sc_bridge_max_age; 902 sc->sc_hello_time = sc->sc_bridge_hello_time; 903 sc->sc_forward_delay = sc->sc_bridge_forward_delay; 904 sc->sc_topology_change_detected = 0; 905 sc->sc_topology_change = 0; 906 bstp_timer_stop(&sc->sc_tcn_timer); 907 bstp_timer_stop(&sc->sc_topology_change_timer); 908 909 if (!timeout_initialized(&sc->sc_bstptimeout)) 910 timeout_set(&sc->sc_bstptimeout, bstp_tick, sc); 911 if (!timeout_pending(&sc->sc_bstptimeout)) 912 timeout_add(&sc->sc_bstptimeout, hz); 913 914 LIST_FOREACH(bif, &sc->sc_iflist, next) { 915 if (bif->bif_flags & IFBIF_STP) 916 bstp_enable_port(sc, bif); 917 else 918 bstp_disable_port(sc, bif); 919 } 920 921 bstp_port_state_selection(sc); 922 bstp_config_bpdu_generation(sc); 923 bstp_timer_start(&sc->sc_hello_timer, 0); 924 } 925 926 void 927 bstp_stop(sc) 928 struct bridge_softc *sc; 929 { 930 931 struct bridge_iflist *bif; 932 933 LIST_FOREACH(bif, &sc->sc_iflist, next) { 934 bstp_set_port_state(bif, BSTP_IFSTATE_DISABLED); 935 bstp_timer_stop(&bif->bif_hold_timer); 936 bstp_timer_stop(&bif->bif_message_age_timer); 937 bstp_timer_stop(&bif->bif_forward_delay_timer); 938 } 939 940 if (timeout_initialized(&sc->sc_bstptimeout) && 941 timeout_pending(&sc->sc_bstptimeout)) 942 timeout_del(&sc->sc_bstptimeout); 943 944 bstp_timer_stop(&sc->sc_topology_change_timer); 945 bstp_timer_stop(&sc->sc_tcn_timer); 946 bstp_timer_stop(&sc->sc_hello_timer); 947 948 } 949 950 void 951 bstp_initialize_port(sc, bif) 952 struct bridge_softc *sc; 953 struct bridge_iflist *bif; 954 { 955 bstp_become_designated_port(sc, bif); 956 bstp_set_port_state(bif, BSTP_IFSTATE_BLOCKING); 957 bif->bif_topology_change_acknowledge = 0; 958 bif->bif_config_pending = 0; 959 bif->bif_change_detection_enabled = 1; 960 bstp_timer_stop(&bif->bif_message_age_timer); 961 bstp_timer_stop(&bif->bif_forward_delay_timer); 962 bstp_timer_stop(&bif->bif_hold_timer); 963 } 964 965 void 966 bstp_enable_port(sc, bif) 967 struct bridge_softc *sc; 968 struct bridge_iflist *bif; 969 { 970 bstp_initialize_port(sc, bif); 971 bstp_port_state_selection(sc); 972 } 973 974 void 975 bstp_disable_port(sc, bif) 976 struct bridge_softc *sc; 977 struct bridge_iflist *bif; 978 { 979 int root; 980 981 root = bstp_root_bridge(sc); 982 bstp_become_designated_port(sc, bif); 983 bstp_set_port_state(bif, BSTP_IFSTATE_DISABLED); 984 bif->bif_topology_change_acknowledge = 0; 985 bif->bif_config_pending = 0; 986 bstp_timer_stop(&bif->bif_message_age_timer); 987 bstp_timer_stop(&bif->bif_forward_delay_timer); 988 bstp_configuration_update(sc); 989 bstp_port_state_selection(sc); 990 991 if (bstp_root_bridge(sc) && (!root)) { 992 sc->sc_max_age = sc->sc_bridge_max_age; 993 sc->sc_hello_time = sc->sc_bridge_hello_time; 994 sc->sc_forward_delay = sc->sc_bridge_forward_delay; 995 996 bstp_topology_change_detection(sc); 997 bstp_timer_stop(&sc->sc_tcn_timer); 998 bstp_config_bpdu_generation(sc); 999 bstp_timer_start(&sc->sc_hello_timer, 0); 1000 } 1001 } 1002 1003 void 1004 bstp_set_bridge_priority(sc, new_bridge_id) 1005 struct bridge_softc *sc; 1006 u_int64_t new_bridge_id; 1007 { 1008 int root; 1009 struct bridge_iflist *bif; 1010 1011 root = bstp_root_bridge(sc); 1012 1013 LIST_FOREACH(bif, &sc->sc_iflist, next) { 1014 if (!(bif->bif_flags & IFBIF_STP)) 1015 continue; 1016 if (bstp_designated_port(sc, bif)) 1017 bif->bif_designated_bridge = new_bridge_id; 1018 } 1019 1020 sc->sc_bridge_id = new_bridge_id; 1021 1022 bstp_configuration_update(sc); 1023 bstp_port_state_selection(sc); 1024 1025 if (bstp_root_bridge(sc) && (!root)) { 1026 sc->sc_max_age = sc->sc_bridge_max_age; 1027 sc->sc_hello_time = sc->sc_bridge_hello_time; 1028 sc->sc_forward_delay = sc->sc_bridge_forward_delay; 1029 1030 bstp_topology_change_detection(sc); 1031 bstp_timer_stop(&sc->sc_tcn_timer); 1032 bstp_config_bpdu_generation(sc); 1033 bstp_timer_start(&sc->sc_hello_timer, 0); 1034 } 1035 } 1036 1037 void 1038 bstp_set_port_priority(sc, bif, new_port_id) 1039 struct bridge_softc *sc; 1040 struct bridge_iflist *bif; 1041 u_int16_t new_port_id; 1042 { 1043 if (bstp_designated_port(sc, bif)) 1044 bif->bif_designated_port = new_port_id; 1045 1046 bif->bif_port_id = new_port_id; 1047 1048 if ((sc->sc_bridge_id == bif->bif_designated_bridge) && 1049 (bif->bif_port_id < bif->bif_designated_port)) { 1050 bstp_become_designated_port(sc, bif); 1051 bstp_port_state_selection(sc); 1052 } 1053 } 1054 1055 void 1056 bstp_set_path_cost(sc, bif, path_cost) 1057 struct bridge_softc *sc; 1058 struct bridge_iflist *bif; 1059 u_int32_t path_cost; 1060 { 1061 bif->bif_path_cost = path_cost; 1062 bstp_configuration_update(sc); 1063 bstp_port_state_selection(sc); 1064 } 1065 1066 void 1067 bstp_enable_change_detection(bif) 1068 struct bridge_iflist *bif; 1069 { 1070 bif->bif_change_detection_enabled = 1; 1071 } 1072 1073 void 1074 bstp_disable_change_detection(bif) 1075 struct bridge_iflist *bif; 1076 { 1077 bif->bif_change_detection_enabled = 0; 1078 } 1079 1080 void 1081 bstp_ifupdstatus(sc, bif) 1082 struct bridge_softc *sc; 1083 struct bridge_iflist *bif; 1084 { 1085 struct ifnet *ifp = bif->ifp; 1086 struct ifmediareq ifmr; 1087 int err; 1088 1089 if (ifp->if_flags & IFF_UP) { 1090 ifmr.ifm_count = 0; 1091 err = (*ifp->if_ioctl)(ifp, SIOCGIFMEDIA, (caddr_t)&ifmr); 1092 if (err) { 1093 if (bif->bif_state == BSTP_IFSTATE_DISABLED) 1094 bstp_enable_port(sc, bif); 1095 return; 1096 } 1097 1098 if (!(ifmr.ifm_status & IFM_AVALID)) { 1099 if (bif->bif_state == BSTP_IFSTATE_DISABLED) 1100 bstp_enable_port(sc, bif); 1101 return; 1102 } 1103 1104 if (ifmr.ifm_status & IFM_ACTIVE) { 1105 if (bif->bif_state == BSTP_IFSTATE_DISABLED) 1106 bstp_enable_port(sc, bif); 1107 return; 1108 } 1109 1110 if (bif->bif_state != BSTP_IFSTATE_DISABLED) 1111 bstp_disable_port(sc, bif); 1112 1113 return; 1114 } 1115 1116 if (bif->bif_state != BSTP_IFSTATE_DISABLED) 1117 bstp_disable_port(sc, bif); 1118 } 1119 1120 void 1121 bstp_tick(vsc) 1122 void *vsc; 1123 { 1124 struct bridge_softc *sc = vsc; 1125 struct bridge_iflist *bif; 1126 int s; 1127 1128 s = splnet(); 1129 1130 LIST_FOREACH(bif, &sc->sc_iflist, next) { 1131 if (!(bif->bif_flags & IFBIF_STP)) 1132 continue; 1133 bstp_ifupdstatus(sc, bif); 1134 } 1135 1136 if (bstp_timer_expired(&sc->sc_hello_timer, sc->sc_hello_time)) 1137 bstp_hello_timer_expiry(sc); 1138 1139 if (bstp_timer_expired(&sc->sc_tcn_timer, sc->sc_bridge_hello_time)) 1140 bstp_tcn_timer_expiry(sc); 1141 1142 if (bstp_timer_expired(&sc->sc_topology_change_timer, 1143 sc->sc_topology_change_time)) 1144 bstp_topology_change_timer_expiry(sc); 1145 1146 LIST_FOREACH(bif, &sc->sc_iflist, next) { 1147 if (!(bif->bif_flags & IFBIF_STP)) 1148 continue; 1149 if (bstp_timer_expired(&bif->bif_message_age_timer, 1150 sc->sc_max_age)) 1151 bstp_message_age_timer_expiry(sc, bif); 1152 } 1153 1154 LIST_FOREACH(bif, &sc->sc_iflist, next) { 1155 if (!(bif->bif_flags & IFBIF_STP)) 1156 continue; 1157 if (bstp_timer_expired(&bif->bif_forward_delay_timer, 1158 sc->sc_forward_delay)) 1159 bstp_forward_delay_timer_expiry(sc, bif); 1160 1161 if (bstp_timer_expired(&bif->bif_hold_timer, 1162 sc->sc_hold_time)) 1163 bstp_hold_timer_expiry(sc, bif); 1164 } 1165 1166 if (sc->sc_if.if_flags & IFF_RUNNING) 1167 timeout_add(&sc->sc_bstptimeout, hz); 1168 1169 splx(s); 1170 } 1171 1172 void 1173 bstp_timer_start(t, v) 1174 struct bridge_timer *t; 1175 u_int16_t v; 1176 { 1177 t->value = v; 1178 t->active = 1; 1179 } 1180 1181 void 1182 bstp_timer_stop(t) 1183 struct bridge_timer *t; 1184 { 1185 t->value = 0; 1186 t->active = 0; 1187 } 1188 1189 int 1190 bstp_timer_expired(t, v) 1191 struct bridge_timer *t; 1192 u_int16_t v; 1193 { 1194 if (!t->active) 1195 return (0); 1196 t->value += BSTP_TICK_VAL; 1197 if (t->value >= v) { 1198 bstp_timer_stop(t); 1199 return (1); 1200 } 1201 return (0); 1202 1203 } 1204 1205 int 1206 bstp_ioctl(ifp, cmd, data) 1207 struct ifnet *ifp; 1208 u_long cmd; 1209 caddr_t data; 1210 { 1211 struct bridge_softc *sc = (struct bridge_softc *)ifp; 1212 struct ifbrparam *bp = (struct ifbrparam *)data; 1213 int r = 0, err = 0; 1214 1215 switch (cmd) { 1216 case SIOCBRDGGPRI: 1217 bp->ifbrp_prio = sc->sc_bridge_priority; 1218 break; 1219 case SIOCBRDGGMA: 1220 bp->ifbrp_maxage = sc->sc_bridge_max_age >> 8; 1221 break; 1222 case SIOCBRDGGHT: 1223 bp->ifbrp_hellotime = sc->sc_bridge_hello_time >> 8; 1224 break; 1225 case SIOCBRDGGFD: 1226 bp->ifbrp_fwddelay = sc->sc_bridge_forward_delay >> 8; 1227 break; 1228 case SIOCBRDGSPRI: 1229 sc->sc_bridge_priority = bp->ifbrp_prio; 1230 r = 1; 1231 break; 1232 case SIOCBRDGSMA: 1233 if (bp->ifbrp_maxage == 0) { 1234 err = EINVAL; 1235 break; 1236 } 1237 sc->sc_bridge_max_age = bp->ifbrp_maxage << 8; 1238 r = 1; 1239 break; 1240 case SIOCBRDGSHT: 1241 if (bp->ifbrp_hellotime == 0) { 1242 err = EINVAL; 1243 break; 1244 } 1245 sc->sc_bridge_hello_time = bp->ifbrp_hellotime << 8; 1246 r = 1; 1247 break; 1248 case SIOCBRDGSFD: 1249 if (bp->ifbrp_fwddelay == 0) { 1250 err = EINVAL; 1251 break; 1252 } 1253 sc->sc_bridge_forward_delay = bp->ifbrp_fwddelay << 8; 1254 r = 1; 1255 break; 1256 case SIOCBRDGADD: 1257 case SIOCBRDGDEL: 1258 case SIOCBRDGSIFFLGS: 1259 case SIOCBRDGSIFPRIO: 1260 r = 1; 1261 break; 1262 default: 1263 break; 1264 } 1265 1266 if (r) 1267 bstp_initialization(sc); 1268 1269 return (err); 1270 } 1271 1272 #endif /* NBRIDGE */ 1273