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