The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/net/bridgestp.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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: releng/6.1/sys/net/bridgestp.c 156471 2006-03-09 08:21:19Z thompsa $");
   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 }

Cache object: 9926369c8e323cb342a3b5149e30a987


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.