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