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  -  FREEBSD10  -  FREEBSD9  -  FREEBSD92  -  FREEBSD91  -  FREEBSD90  -  FREEBSD8  -  FREEBSD82  -  FREEBSD81  -  FREEBSD80  -  FREEBSD7  -  FREEBSD74  -  FREEBSD73  -  FREEBSD72  -  FREEBSD71  -  FREEBSD70  -  FREEBSD6  -  FREEBSD64  -  FREEBSD63  -  FREEBSD62  -  FREEBSD61  -  FREEBSD60  -  FREEBSD5  -  FREEBSD55  -  FREEBSD54  -  FREEBSD53  -  FREEBSD52  -  FREEBSD51  -  FREEBSD50  -  FREEBSD4  -  FREEBSD3  -  FREEBSD22  -  cheribsd  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1  -  FREEBSD-LIBC  -  FREEBSD8-LIBC  -  FREEBSD7-LIBC  -  FREEBSD6-LIBC  -  GLIBC27 
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: src/sys/net/bridgestp.c,v 1.6.2.4 2006/03/03 21:37:01 thompsa Exp $");
   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 #define sc_if ifb_ac.ac_if
   69 
   70 /* BPDU message types */
   71 #define BSTP_MSGTYPE_CFG        0x00            /* Configuration */
   72 #define BSTP_MSGTYPE_TCN        0x80            /* Topology chg notification */
   73 
   74 /* BPDU flags */
   75 #define BSTP_FLAG_TC            0x01            /* Topology change */
   76 #define BSTP_FLAG_TCA           0x80            /* Topology change ack */
   77 
   78 #define BSTP_MESSAGE_AGE_INCR   (1 * 256)       /* in 256ths of a second */
   79 #define BSTP_TICK_VAL           (1 * 256)       /* in 256ths of a second */
   80 
   81 /*
   82  * Because BPDU's do not make nicely aligned structures, two different
   83  * declarations are used: bstp_?bpdu (wire representation, packed) and
   84  * bstp_*_unit (internal, nicely aligned version).
   85  */
   86 
   87 /* configuration bridge protocol data unit */
   88 struct bstp_cbpdu {
   89         uint8_t         cbu_dsap;               /* LLC: destination sap */
   90         uint8_t         cbu_ssap;               /* LLC: source sap */
   91         uint8_t         cbu_ctl;                /* LLC: control */
   92         uint16_t        cbu_protoid;            /* protocol id */
   93         uint8_t         cbu_protover;           /* protocol version */
   94         uint8_t         cbu_bpdutype;           /* message type */
   95         uint8_t         cbu_flags;              /* flags (below) */
   96 
   97         /* root id */
   98         uint16_t        cbu_rootpri;            /* root priority */
   99         uint8_t cbu_rootaddr[6];        /* root address */
  100 
  101         uint32_t        cbu_rootpathcost;       /* root path cost */
  102 
  103         /* bridge id */
  104         uint16_t        cbu_bridgepri;          /* bridge priority */
  105         uint8_t         cbu_bridgeaddr[6];      /* bridge address */
  106 
  107         uint16_t        cbu_portid;             /* port id */
  108         uint16_t        cbu_messageage;         /* current message age */
  109         uint16_t        cbu_maxage;             /* maximum age */
  110         uint16_t        cbu_hellotime;          /* hello time */
  111         uint16_t        cbu_forwarddelay;       /* forwarding delay */
  112 } __attribute__((__packed__));
  113 
  114 /* topology change notification bridge protocol data unit */
  115 struct bstp_tbpdu {
  116         uint8_t         tbu_dsap;               /* LLC: destination sap */
  117         uint8_t         tbu_ssap;               /* LLC: source sap */
  118         uint8_t         tbu_ctl;                /* LLC: control */
  119         uint16_t        tbu_protoid;            /* protocol id */
  120         uint8_t         tbu_protover;           /* protocol version */
  121         uint8_t         tbu_bpdutype;           /* message type */
  122 } __attribute__((__packed__));
  123 
  124 const uint8_t bstp_etheraddr[] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 };
  125 
  126 static void     bstp_initialize_port(struct bridge_softc *,
  127                     struct bridge_iflist *);
  128 static void     bstp_ifupdstatus(struct bridge_softc *, struct bridge_iflist *);
  129 static void     bstp_enable_port(struct bridge_softc *, struct bridge_iflist *);
  130 static void     bstp_disable_port(struct bridge_softc *,
  131                     struct bridge_iflist *);
  132 #ifdef notused
  133 static void     bstp_enable_change_detection(struct bridge_iflist *);
  134 static void     bstp_disable_change_detection(struct bridge_iflist *);
  135 #endif /* notused */
  136 static int      bstp_root_bridge(struct bridge_softc *sc);
  137 static int      bstp_supersedes_port_info(struct bridge_softc *,
  138                     struct bridge_iflist *, struct bstp_config_unit *);
  139 static int      bstp_designated_port(struct bridge_softc *,
  140                     struct bridge_iflist *);
  141 static int      bstp_designated_for_some_port(struct bridge_softc *);
  142 static void     bstp_transmit_config(struct bridge_softc *,
  143                     struct bridge_iflist *);
  144 static void     bstp_transmit_tcn(struct bridge_softc *);
  145 static void     bstp_received_config_bpdu(struct bridge_softc *,
  146                     struct bridge_iflist *, struct bstp_config_unit *);
  147 static void     bstp_received_tcn_bpdu(struct bridge_softc *,
  148                     struct bridge_iflist *, struct bstp_tcn_unit *);
  149 static void     bstp_record_config_information(struct bridge_softc *,
  150                     struct bridge_iflist *, struct bstp_config_unit *);
  151 static void     bstp_record_config_timeout_values(struct bridge_softc *,
  152                     struct bstp_config_unit *);
  153 static void     bstp_config_bpdu_generation(struct bridge_softc *);
  154 static void     bstp_send_config_bpdu(struct bridge_softc *,
  155                     struct bridge_iflist *, struct bstp_config_unit *);
  156 static void     bstp_configuration_update(struct bridge_softc *);
  157 static void     bstp_root_selection(struct bridge_softc *);
  158 static void     bstp_designated_port_selection(struct bridge_softc *);
  159 static void     bstp_become_designated_port(struct bridge_softc *,
  160                     struct bridge_iflist *);
  161 static void     bstp_port_state_selection(struct bridge_softc *);
  162 static void     bstp_make_forwarding(struct bridge_softc *,
  163                     struct bridge_iflist *);
  164 static void     bstp_make_blocking(struct bridge_softc *,
  165                     struct bridge_iflist *);
  166 static void     bstp_set_port_state(struct bridge_iflist *, uint8_t);
  167 #ifdef notused
  168 static void     bstp_set_bridge_priority(struct bridge_softc *, uint64_t);
  169 static void     bstp_set_port_priority(struct bridge_softc *,
  170                     struct bridge_iflist *, uint16_t);
  171 static void     bstp_set_path_cost(struct bridge_softc *,
  172                     struct bridge_iflist *, uint32_t);
  173 #endif /* notused */
  174 static void     bstp_topology_change_detection(struct bridge_softc *);
  175 static void     bstp_topology_change_acknowledged(struct bridge_softc *);
  176 static void     bstp_acknowledge_topology_change(struct bridge_softc *,
  177                     struct bridge_iflist *);
  178 
  179 static void     bstp_tick(void *);
  180 static void     bstp_timer_start(struct bridge_timer *, uint16_t);
  181 static void     bstp_timer_stop(struct bridge_timer *);
  182 static int      bstp_timer_expired(struct bridge_timer *, uint16_t);
  183 
  184 static void     bstp_hold_timer_expiry(struct bridge_softc *,
  185                     struct bridge_iflist *);
  186 static void     bstp_message_age_timer_expiry(struct bridge_softc *,
  187                     struct bridge_iflist *);
  188 static void     bstp_forward_delay_timer_expiry(struct bridge_softc *,
  189                     struct bridge_iflist *);
  190 static void     bstp_topology_change_timer_expiry(struct bridge_softc *);
  191 static void     bstp_tcn_timer_expiry(struct bridge_softc *);
  192 static void     bstp_hello_timer_expiry(struct bridge_softc *);
  193 static int      bstp_addr_cmp(const uint8_t *, const uint8_t *);
  194 
  195 static void
  196 bstp_transmit_config(struct bridge_softc *sc, struct bridge_iflist *bif)
  197 {
  198         if (bif->bif_hold_timer.active) {
  199                 bif->bif_config_pending = 1;
  200                 return;
  201         }
  202 
  203         bif->bif_config_bpdu.cu_message_type = BSTP_MSGTYPE_CFG;
  204         bif->bif_config_bpdu.cu_rootid = sc->sc_designated_root;
  205         bif->bif_config_bpdu.cu_root_path_cost = sc->sc_root_path_cost;
  206         bif->bif_config_bpdu.cu_bridge_id = sc->sc_bridge_id;
  207         bif->bif_config_bpdu.cu_port_id = bif->bif_port_id;
  208 
  209         if (bstp_root_bridge(sc))
  210                 bif->bif_config_bpdu.cu_message_age = 0;
  211         else
  212                 bif->bif_config_bpdu.cu_message_age =
  213                     sc->sc_root_port->bif_message_age_timer.value +
  214                     BSTP_MESSAGE_AGE_INCR;
  215 
  216         bif->bif_config_bpdu.cu_max_age = sc->sc_max_age;
  217         bif->bif_config_bpdu.cu_hello_time = sc->sc_hello_time;
  218         bif->bif_config_bpdu.cu_forward_delay = sc->sc_forward_delay;
  219         bif->bif_config_bpdu.cu_topology_change_acknowledgment
  220             = bif->bif_topology_change_acknowledge;
  221         bif->bif_config_bpdu.cu_topology_change = sc->sc_topology_change;
  222 
  223         if (bif->bif_config_bpdu.cu_message_age < sc->sc_max_age) {
  224                 bif->bif_topology_change_acknowledge = 0;
  225                 bif->bif_config_pending = 0;
  226                 bstp_send_config_bpdu(sc, bif, &bif->bif_config_bpdu);
  227                 bstp_timer_start(&bif->bif_hold_timer, 0);
  228         }
  229 }
  230 
  231 static void
  232 bstp_send_config_bpdu(struct bridge_softc *sc, struct bridge_iflist *bif,
  233     struct bstp_config_unit *cu)
  234 {
  235         struct ifnet *ifp;
  236         struct mbuf *m;
  237         struct ether_header *eh;
  238         struct bstp_cbpdu bpdu;
  239 
  240         BRIDGE_LOCK_ASSERT(sc);
  241 
  242         ifp = bif->bif_ifp;
  243 
  244         if ((ifp->if_flags & IFF_RUNNING) == 0)
  245                 return;
  246 
  247         MGETHDR(m, M_DONTWAIT, MT_DATA);
  248         if (m == NULL)
  249                 return;
  250 
  251         eh = mtod(m, struct ether_header *);
  252 
  253         m->m_pkthdr.rcvif = ifp;
  254         m->m_pkthdr.len = sizeof(*eh) + sizeof(bpdu);
  255         m->m_len = m->m_pkthdr.len;
  256 
  257         bpdu.cbu_ssap = bpdu.cbu_dsap = LLC_8021D_LSAP;
  258         bpdu.cbu_ctl = LLC_UI;
  259         bpdu.cbu_protoid = htons(0);
  260         bpdu.cbu_protover = 0;
  261         bpdu.cbu_bpdutype = cu->cu_message_type;
  262         bpdu.cbu_flags = (cu->cu_topology_change ? BSTP_FLAG_TC : 0) |
  263             (cu->cu_topology_change_acknowledgment ? BSTP_FLAG_TCA : 0);
  264 
  265         bpdu.cbu_rootpri = htons(cu->cu_rootid >> 48);
  266         bpdu.cbu_rootaddr[0] = cu->cu_rootid >> 40;
  267         bpdu.cbu_rootaddr[1] = cu->cu_rootid >> 32;
  268         bpdu.cbu_rootaddr[2] = cu->cu_rootid >> 24;
  269         bpdu.cbu_rootaddr[3] = cu->cu_rootid >> 16;
  270         bpdu.cbu_rootaddr[4] = cu->cu_rootid >> 8;
  271         bpdu.cbu_rootaddr[5] = cu->cu_rootid >> 0;
  272 
  273         bpdu.cbu_rootpathcost = htonl(cu->cu_root_path_cost);
  274 
  275         bpdu.cbu_bridgepri = htons(cu->cu_bridge_id >> 48);
  276         bpdu.cbu_bridgeaddr[0] = cu->cu_bridge_id >> 40;
  277         bpdu.cbu_bridgeaddr[1] = cu->cu_bridge_id >> 32;
  278         bpdu.cbu_bridgeaddr[2] = cu->cu_bridge_id >> 24;
  279         bpdu.cbu_bridgeaddr[3] = cu->cu_bridge_id >> 16;
  280         bpdu.cbu_bridgeaddr[4] = cu->cu_bridge_id >> 8;
  281         bpdu.cbu_bridgeaddr[5] = cu->cu_bridge_id >> 0;
  282 
  283         bpdu.cbu_portid = htons(cu->cu_port_id);
  284         bpdu.cbu_messageage = htons(cu->cu_message_age);
  285         bpdu.cbu_maxage = htons(cu->cu_max_age);
  286         bpdu.cbu_hellotime = htons(cu->cu_hello_time);
  287         bpdu.cbu_forwarddelay = htons(cu->cu_forward_delay);
  288 
  289         memcpy(eh->ether_shost, IF_LLADDR(ifp), ETHER_ADDR_LEN);
  290         memcpy(eh->ether_dhost, bstp_etheraddr, ETHER_ADDR_LEN);
  291         eh->ether_type = htons(sizeof(bpdu));
  292 
  293         memcpy(mtod(m, caddr_t) + sizeof(*eh), &bpdu, sizeof(bpdu));
  294 
  295         /* XXX: safe here?!? */
  296         BRIDGE_UNLOCK(sc);
  297         bridge_enqueue(sc, ifp, m);
  298         BRIDGE_LOCK(sc);
  299 }
  300 
  301 static int
  302 bstp_root_bridge(struct bridge_softc *sc)
  303 {
  304         return (sc->sc_designated_root == sc->sc_bridge_id);
  305 }
  306 
  307 static int
  308 bstp_supersedes_port_info(struct bridge_softc *sc, struct bridge_iflist *bif,
  309     struct bstp_config_unit *cu)
  310 {
  311         if (cu->cu_rootid < bif->bif_designated_root)
  312                 return (1);
  313         if (cu->cu_rootid > bif->bif_designated_root)
  314                 return (0);
  315 
  316         if (cu->cu_root_path_cost < bif->bif_designated_cost)
  317                 return (1);
  318         if (cu->cu_root_path_cost > bif->bif_designated_cost)
  319                 return (0);
  320 
  321         if (cu->cu_bridge_id < bif->bif_designated_bridge)
  322                 return (1);
  323         if (cu->cu_bridge_id > bif->bif_designated_bridge)
  324                 return (0);
  325 
  326         if (sc->sc_bridge_id != cu->cu_bridge_id)
  327                 return (1);
  328         if (cu->cu_port_id <= bif->bif_designated_port)
  329                 return (1);
  330         return (0);
  331 }
  332 
  333 static void
  334 bstp_record_config_information(struct bridge_softc *sc,
  335     struct bridge_iflist *bif, struct bstp_config_unit *cu)
  336 {
  337         bif->bif_designated_root = cu->cu_rootid;
  338         bif->bif_designated_cost = cu->cu_root_path_cost;
  339         bif->bif_designated_bridge = cu->cu_bridge_id;
  340         bif->bif_designated_port = cu->cu_port_id;
  341         bstp_timer_start(&bif->bif_message_age_timer, cu->cu_message_age);
  342 }
  343 
  344 static void
  345 bstp_record_config_timeout_values(struct bridge_softc *sc,
  346     struct bstp_config_unit *config)
  347 {
  348         sc->sc_max_age = config->cu_max_age;
  349         sc->sc_hello_time = config->cu_hello_time;
  350         sc->sc_forward_delay = config->cu_forward_delay;
  351         sc->sc_topology_change = config->cu_topology_change;
  352 }
  353 
  354 static void
  355 bstp_config_bpdu_generation(struct bridge_softc *sc)
  356 {
  357         struct bridge_iflist *bif;
  358 
  359         LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
  360                 if ((bif->bif_flags & IFBIF_STP) == 0)
  361                         continue;
  362                 if (bstp_designated_port(sc, bif) &&
  363                     (bif->bif_state != BSTP_IFSTATE_DISABLED))
  364                         bstp_transmit_config(sc, bif);
  365         }
  366 }
  367 
  368 static int
  369 bstp_designated_port(struct bridge_softc *sc, struct bridge_iflist *bif)
  370 {
  371         return ((bif->bif_designated_bridge == sc->sc_bridge_id)
  372             && (bif->bif_designated_port == bif->bif_port_id));
  373 }
  374 
  375 static void
  376 bstp_transmit_tcn(struct bridge_softc *sc)
  377 {
  378         struct bstp_tbpdu bpdu;
  379         struct bridge_iflist *bif = sc->sc_root_port;
  380         struct ifnet *ifp = bif->bif_ifp;
  381         struct ether_header *eh;
  382         struct mbuf *m;
  383 
  384         BRIDGE_LOCK_ASSERT(sc);
  385 
  386         if ((ifp->if_flags & IFF_RUNNING) == 0)
  387                 return;
  388 
  389         MGETHDR(m, M_DONTWAIT, MT_DATA);
  390         if (m == NULL)
  391                 return;
  392 
  393         m->m_pkthdr.rcvif = ifp;
  394         m->m_pkthdr.len = sizeof(*eh) + sizeof(bpdu);
  395         m->m_len = m->m_pkthdr.len;
  396 
  397         eh = mtod(m, struct ether_header *);
  398 
  399         memcpy(eh->ether_shost, IF_LLADDR(ifp), ETHER_ADDR_LEN);
  400         memcpy(eh->ether_dhost, bstp_etheraddr, ETHER_ADDR_LEN);
  401         eh->ether_type = htons(sizeof(bpdu));
  402 
  403         bpdu.tbu_ssap = bpdu.tbu_dsap = LLC_8021D_LSAP;
  404         bpdu.tbu_ctl = LLC_UI;
  405         bpdu.tbu_protoid = 0;
  406         bpdu.tbu_protover = 0;
  407         bpdu.tbu_bpdutype = BSTP_MSGTYPE_TCN;
  408 
  409         memcpy(mtod(m, caddr_t) + sizeof(*eh), &bpdu, sizeof(bpdu));
  410 
  411         /* XXX: safe here?!? */
  412         BRIDGE_UNLOCK(sc);
  413         bridge_enqueue(sc, ifp, m);
  414         BRIDGE_LOCK(sc);
  415 }
  416 
  417 static void
  418 bstp_configuration_update(struct bridge_softc *sc)
  419 {
  420         BRIDGE_LOCK_ASSERT(sc);
  421 
  422         bstp_root_selection(sc);
  423         bstp_designated_port_selection(sc);
  424 }
  425 
  426 static void
  427 bstp_root_selection(struct bridge_softc *sc)
  428 {
  429         struct bridge_iflist *root_port = NULL, *bif;
  430 
  431         BRIDGE_LOCK_ASSERT(sc);
  432 
  433         LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
  434                 if ((bif->bif_flags & IFBIF_STP) == 0)
  435                         continue;
  436                 if (bstp_designated_port(sc, bif))
  437                         continue;
  438                 if (bif->bif_state == BSTP_IFSTATE_DISABLED)
  439                         continue;
  440                 if (bif->bif_designated_root >= sc->sc_bridge_id)
  441                         continue;
  442                 if (root_port == NULL)
  443                         goto set_port;
  444 
  445                 if (bif->bif_designated_root < root_port->bif_designated_root)
  446                         goto set_port;
  447                 if (bif->bif_designated_root > root_port->bif_designated_root)
  448                         continue;
  449 
  450                 if ((bif->bif_designated_cost + bif->bif_path_cost) <
  451                     (root_port->bif_designated_cost + root_port->bif_path_cost))
  452                         goto set_port;
  453                 if ((bif->bif_designated_cost + bif->bif_path_cost) >
  454                     (root_port->bif_designated_cost + root_port->bif_path_cost))
  455                         continue;
  456 
  457                 if (bif->bif_designated_bridge <
  458                     root_port->bif_designated_bridge)
  459                         goto set_port;
  460                 if (bif->bif_designated_bridge >
  461                     root_port->bif_designated_bridge)
  462                         continue;
  463 
  464                 if (bif->bif_designated_port < root_port->bif_designated_port)
  465                         goto set_port;
  466                 if (bif->bif_designated_port > root_port->bif_designated_port)
  467                         continue;
  468 
  469                 if (bif->bif_port_id >= root_port->bif_port_id)
  470                         continue;
  471 set_port:
  472                 root_port = bif;
  473         }
  474 
  475         sc->sc_root_port = root_port;
  476         if (root_port == NULL) {
  477                 sc->sc_designated_root = sc->sc_bridge_id;
  478                 sc->sc_root_path_cost = 0;
  479         } else {
  480                 sc->sc_designated_root = root_port->bif_designated_root;
  481                 sc->sc_root_path_cost = root_port->bif_designated_cost +
  482                     root_port->bif_path_cost;
  483         }
  484 }
  485 
  486 static void
  487 bstp_designated_port_selection(struct bridge_softc *sc)
  488 {
  489         struct bridge_iflist *bif;
  490 
  491         BRIDGE_LOCK_ASSERT(sc);
  492 
  493         LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
  494                 if ((bif->bif_flags & IFBIF_STP) == 0)
  495                         continue;
  496                 if (bstp_designated_port(sc, bif))
  497                         goto designated;
  498                 if (bif->bif_designated_root != sc->sc_designated_root)
  499                         goto designated;
  500 
  501                 if (sc->sc_root_path_cost < bif->bif_designated_cost)
  502                         goto designated;
  503                 if (sc->sc_root_path_cost > bif->bif_designated_cost)
  504                         continue;
  505 
  506                 if (sc->sc_bridge_id < bif->bif_designated_bridge)
  507                         goto designated;
  508                 if (sc->sc_bridge_id > bif->bif_designated_bridge)
  509                         continue;
  510 
  511                 if (bif->bif_port_id > bif->bif_designated_port)
  512                         continue;
  513 designated:
  514                 bstp_become_designated_port(sc, bif);
  515         }
  516 }
  517 
  518 static void
  519 bstp_become_designated_port(struct bridge_softc *sc, struct bridge_iflist *bif)
  520 {
  521         bif->bif_designated_root = sc->sc_designated_root;
  522         bif->bif_designated_cost = sc->sc_root_path_cost;
  523         bif->bif_designated_bridge = sc->sc_bridge_id;
  524         bif->bif_designated_port = bif->bif_port_id;
  525 }
  526 
  527 static void
  528 bstp_port_state_selection(struct bridge_softc *sc)
  529 {
  530         struct bridge_iflist *bif;
  531 
  532         LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
  533                 if ((bif->bif_flags & IFBIF_STP) == 0)
  534                         continue;
  535                 if (bif == sc->sc_root_port) {
  536                         bif->bif_config_pending = 0;
  537                         bif->bif_topology_change_acknowledge = 0;
  538                         bstp_make_forwarding(sc, bif);
  539                 } else if (bstp_designated_port(sc, bif)) {
  540                         bstp_timer_stop(&bif->bif_message_age_timer);
  541                         bstp_make_forwarding(sc, bif);
  542                 } else {
  543                         bif->bif_config_pending = 0;
  544                         bif->bif_topology_change_acknowledge = 0;
  545                         bstp_make_blocking(sc, bif);
  546                 }
  547         }
  548 }
  549 
  550 static void
  551 bstp_make_forwarding(struct bridge_softc *sc, struct bridge_iflist *bif)
  552 {
  553         if (bif->bif_state == BSTP_IFSTATE_BLOCKING) {
  554                 bstp_set_port_state(bif, BSTP_IFSTATE_LISTENING);
  555                 bstp_timer_start(&bif->bif_forward_delay_timer, 0);
  556         }
  557 }
  558 
  559 static void
  560 bstp_make_blocking(struct bridge_softc *sc, struct bridge_iflist *bif)
  561 {
  562         BRIDGE_LOCK_ASSERT(sc);
  563 
  564         if ((bif->bif_state != BSTP_IFSTATE_DISABLED) &&
  565             (bif->bif_state != BSTP_IFSTATE_BLOCKING)) {
  566                 if ((bif->bif_state == BSTP_IFSTATE_FORWARDING) ||
  567                     (bif->bif_state == BSTP_IFSTATE_LEARNING)) {
  568                         if (bif->bif_change_detection_enabled) {
  569                                 bstp_topology_change_detection(sc);
  570                         }
  571                 }
  572                 bstp_set_port_state(bif, BSTP_IFSTATE_BLOCKING);
  573                 bridge_rtdelete(sc, bif->bif_ifp, IFBF_FLUSHDYN);
  574                 bstp_timer_stop(&bif->bif_forward_delay_timer);
  575         }
  576 }
  577 
  578 static void
  579 bstp_set_port_state(struct bridge_iflist *bif, uint8_t state)
  580 {
  581         bif->bif_state = state;
  582 }
  583 
  584 static void
  585 bstp_topology_change_detection(struct bridge_softc *sc)
  586 {
  587         if (bstp_root_bridge(sc)) {
  588                 sc->sc_topology_change = 1;
  589                 bstp_timer_start(&sc->sc_topology_change_timer, 0);
  590         } else if (!sc->sc_topology_change_detected) {
  591                 bstp_transmit_tcn(sc);
  592                 bstp_timer_start(&sc->sc_tcn_timer, 0);
  593         }
  594         sc->sc_topology_change_detected = 1;
  595 }
  596 
  597 static void
  598 bstp_topology_change_acknowledged(struct bridge_softc *sc)
  599 {
  600         sc->sc_topology_change_detected = 0;
  601         bstp_timer_stop(&sc->sc_tcn_timer);
  602 }
  603 
  604 static void
  605 bstp_acknowledge_topology_change(struct bridge_softc *sc,
  606     struct bridge_iflist *bif)
  607 {
  608         bif->bif_topology_change_acknowledge = 1;
  609         bstp_transmit_config(sc, bif);
  610 }
  611 
  612 struct mbuf *
  613 bstp_input(struct ifnet *ifp, struct mbuf *m)
  614 {
  615         struct bridge_softc *sc = ifp->if_bridge;
  616         struct bridge_iflist *bif = NULL;
  617         struct ether_header *eh;
  618         struct bstp_tbpdu tpdu;
  619         struct bstp_cbpdu cpdu;
  620         struct bstp_config_unit cu;
  621         struct bstp_tcn_unit tu;
  622         uint16_t len;
  623 
  624         BRIDGE_LOCK_ASSERT(sc);
  625 
  626         eh = mtod(m, struct ether_header *);
  627 
  628         LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
  629                 if ((bif->bif_flags & IFBIF_STP) == 0)
  630                         continue;
  631                 if (bif->bif_ifp == ifp)
  632                         break;
  633         }
  634         if (bif == NULL)
  635                 goto out;
  636 
  637         len = ntohs(eh->ether_type);
  638         if (len < sizeof(tpdu))
  639                 goto out;
  640 
  641         m_adj(m, ETHER_HDR_LEN);
  642 
  643         if (m->m_pkthdr.len > len)
  644                 m_adj(m, len - m->m_pkthdr.len);
  645         if (m->m_len < sizeof(tpdu) &&
  646             (m = m_pullup(m, sizeof(tpdu))) == NULL)
  647                 goto out;
  648 
  649         memcpy(&tpdu, mtod(m, caddr_t), sizeof(tpdu));
  650 
  651         if (tpdu.tbu_dsap != LLC_8021D_LSAP ||
  652             tpdu.tbu_ssap != LLC_8021D_LSAP ||
  653             tpdu.tbu_ctl != LLC_UI)
  654                 goto out;
  655         if (tpdu.tbu_protoid != 0 || tpdu.tbu_protover != 0)
  656                 goto out;
  657 
  658         switch (tpdu.tbu_bpdutype) {
  659         case BSTP_MSGTYPE_TCN:
  660                 tu.tu_message_type = tpdu.tbu_bpdutype;
  661                 bstp_received_tcn_bpdu(sc, bif, &tu);
  662                 break;
  663         case BSTP_MSGTYPE_CFG:
  664                 if (m->m_len < sizeof(cpdu) &&
  665                     (m = m_pullup(m, sizeof(cpdu))) == NULL)
  666                         goto out;
  667                 memcpy(&cpdu, mtod(m, caddr_t), sizeof(cpdu));
  668 
  669                 cu.cu_rootid =
  670                     (((uint64_t)ntohs(cpdu.cbu_rootpri)) << 48) |
  671                     (((uint64_t)cpdu.cbu_rootaddr[0]) << 40) |
  672                     (((uint64_t)cpdu.cbu_rootaddr[1]) << 32) |
  673                     (((uint64_t)cpdu.cbu_rootaddr[2]) << 24) |
  674                     (((uint64_t)cpdu.cbu_rootaddr[3]) << 16) |
  675                     (((uint64_t)cpdu.cbu_rootaddr[4]) << 8) |
  676                     (((uint64_t)cpdu.cbu_rootaddr[5]) << 0);
  677 
  678                 cu.cu_bridge_id =
  679                     (((uint64_t)ntohs(cpdu.cbu_bridgepri)) << 48) |
  680                     (((uint64_t)cpdu.cbu_bridgeaddr[0]) << 40) |
  681                     (((uint64_t)cpdu.cbu_bridgeaddr[1]) << 32) |
  682                     (((uint64_t)cpdu.cbu_bridgeaddr[2]) << 24) |
  683                     (((uint64_t)cpdu.cbu_bridgeaddr[3]) << 16) |
  684                     (((uint64_t)cpdu.cbu_bridgeaddr[4]) << 8) |
  685                     (((uint64_t)cpdu.cbu_bridgeaddr[5]) << 0);
  686 
  687                 cu.cu_root_path_cost = ntohl(cpdu.cbu_rootpathcost);
  688                 cu.cu_message_age = ntohs(cpdu.cbu_messageage);
  689                 cu.cu_max_age = ntohs(cpdu.cbu_maxage);
  690                 cu.cu_hello_time = ntohs(cpdu.cbu_hellotime);
  691                 cu.cu_forward_delay = ntohs(cpdu.cbu_forwarddelay);
  692                 cu.cu_port_id = ntohs(cpdu.cbu_portid);
  693                 cu.cu_message_type = cpdu.cbu_bpdutype;
  694                 cu.cu_topology_change_acknowledgment =
  695                     (cpdu.cbu_flags & BSTP_FLAG_TCA) ? 1 : 0;
  696                 cu.cu_topology_change =
  697                     (cpdu.cbu_flags & BSTP_FLAG_TC) ? 1 : 0;
  698                 bstp_received_config_bpdu(sc, bif, &cu);
  699                 break;
  700         default:
  701                 goto out;
  702         }
  703 
  704 out:
  705         if (m)
  706                 m_freem(m);
  707         return (NULL);
  708 }
  709 
  710 static void
  711 bstp_received_config_bpdu(struct bridge_softc *sc, struct bridge_iflist *bif,
  712     struct bstp_config_unit *cu)
  713 {
  714         int root;
  715 
  716         BRIDGE_LOCK_ASSERT(sc);
  717 
  718         root = bstp_root_bridge(sc);
  719 
  720         if (bif->bif_state != BSTP_IFSTATE_DISABLED) {
  721                 if (bstp_supersedes_port_info(sc, bif, cu)) {
  722                         bstp_record_config_information(sc, bif, cu);
  723                         bstp_configuration_update(sc);
  724                         bstp_port_state_selection(sc);
  725 
  726                         if ((bstp_root_bridge(sc) == 0) && root) {
  727                                 bstp_timer_stop(&sc->sc_hello_timer);
  728 
  729                                 if (sc->sc_topology_change_detected) {
  730                                         bstp_timer_stop(
  731                                             &sc->sc_topology_change_timer);
  732                                         bstp_transmit_tcn(sc);
  733                                         bstp_timer_start(&sc->sc_tcn_timer, 0);
  734                                 }
  735                         }
  736 
  737                         if (bif == sc->sc_root_port) {
  738                                 bstp_record_config_timeout_values(sc, cu);
  739                                 bstp_config_bpdu_generation(sc);
  740 
  741                                 if (cu->cu_topology_change_acknowledgment)
  742                                         bstp_topology_change_acknowledged(sc);
  743                         }
  744                 } else if (bstp_designated_port(sc, bif))
  745                         bstp_transmit_config(sc, bif);
  746         }
  747 }
  748 
  749 static void
  750 bstp_received_tcn_bpdu(struct bridge_softc *sc, struct bridge_iflist *bif,
  751     struct bstp_tcn_unit *tcn)
  752 {
  753         if (bif->bif_state != BSTP_IFSTATE_DISABLED &&
  754             bstp_designated_port(sc, bif)) {
  755                 bstp_topology_change_detection(sc);
  756                 bstp_acknowledge_topology_change(sc, bif);
  757         }
  758 }
  759 
  760 static void
  761 bstp_hello_timer_expiry(struct bridge_softc *sc)
  762 {
  763         bstp_config_bpdu_generation(sc);
  764         bstp_timer_start(&sc->sc_hello_timer, 0);
  765 }
  766 
  767 static void
  768 bstp_message_age_timer_expiry(struct bridge_softc *sc,
  769     struct bridge_iflist *bif)
  770 {
  771         int root;
  772 
  773         root = bstp_root_bridge(sc);
  774         bstp_become_designated_port(sc, bif);
  775         bstp_configuration_update(sc);
  776         bstp_port_state_selection(sc);
  777 
  778         if ((bstp_root_bridge(sc)) && (root == 0)) {
  779                 sc->sc_max_age = sc->sc_bridge_max_age;
  780                 sc->sc_hello_time = sc->sc_bridge_hello_time;
  781                 sc->sc_forward_delay = sc->sc_bridge_forward_delay;
  782 
  783                 bstp_topology_change_detection(sc);
  784                 bstp_timer_stop(&sc->sc_tcn_timer);
  785                 bstp_config_bpdu_generation(sc);
  786                 bstp_timer_start(&sc->sc_hello_timer, 0);
  787         }
  788 }
  789 
  790 static void
  791 bstp_forward_delay_timer_expiry(struct bridge_softc *sc,
  792     struct bridge_iflist *bif)
  793 {
  794         if (bif->bif_state == BSTP_IFSTATE_LISTENING) {
  795                 bstp_set_port_state(bif, BSTP_IFSTATE_LEARNING);
  796                 bstp_timer_start(&bif->bif_forward_delay_timer, 0);
  797         } else if (bif->bif_state == BSTP_IFSTATE_LEARNING) {
  798                 bstp_set_port_state(bif, BSTP_IFSTATE_FORWARDING);
  799                 if (bstp_designated_for_some_port(sc) &&
  800                     bif->bif_change_detection_enabled)
  801                         bstp_topology_change_detection(sc);
  802         }
  803 }
  804 
  805 static int
  806 bstp_designated_for_some_port(struct bridge_softc *sc)
  807 {
  808 
  809         struct bridge_iflist *bif;
  810 
  811         LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
  812                 if ((bif->bif_flags & IFBIF_STP) == 0)
  813                         continue;
  814                 if (bif->bif_designated_bridge == sc->sc_bridge_id)
  815                         return (1);
  816         }
  817         return (0);
  818 }
  819 
  820 static void
  821 bstp_tcn_timer_expiry(struct bridge_softc *sc)
  822 {
  823         bstp_transmit_tcn(sc);
  824         bstp_timer_start(&sc->sc_tcn_timer, 0);
  825 }
  826 
  827 static void
  828 bstp_topology_change_timer_expiry(struct bridge_softc *sc)
  829 {
  830         sc->sc_topology_change_detected = 0;
  831         sc->sc_topology_change = 0;
  832 }
  833 
  834 static void
  835 bstp_hold_timer_expiry(struct bridge_softc *sc, struct bridge_iflist *bif)
  836 {
  837         if (bif->bif_config_pending)
  838                 bstp_transmit_config(sc, bif);
  839 }
  840 
  841 static int
  842 bstp_addr_cmp(const uint8_t *a, const uint8_t *b)
  843 {
  844         int i, d;
  845 
  846         for (i = 0, d = 0; i < ETHER_ADDR_LEN && d == 0; i++) {
  847                 d = ((int)a[i]) - ((int)b[i]);
  848         }
  849 
  850         return (d);
  851 }
  852 
  853 void
  854 bstp_initialization(struct bridge_softc *sc)
  855 {
  856         struct bridge_iflist *bif, *mif;
  857         u_char *e_addr;
  858 
  859         BRIDGE_LOCK_ASSERT(sc);
  860 
  861         mif = NULL;
  862         LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
  863                 if ((bif->bif_flags & IFBIF_STP) == 0)
  864                         continue;
  865                 if (bif->bif_ifp->if_type != IFT_ETHER)
  866                         continue;
  867                 bif->bif_port_id = (bif->bif_priority << 8) |
  868                     (bif->bif_ifp->if_index & 0xff);
  869 
  870                 if (mif == NULL) {
  871                         mif = bif;
  872                         continue;
  873                 }
  874                 if (bstp_addr_cmp(IF_LLADDR(bif->bif_ifp),
  875                     IF_LLADDR(mif->bif_ifp)) < 0) {
  876                         mif = bif;
  877                         continue;
  878                 }
  879         }
  880         if (mif == NULL) {
  881                 bstp_stop(sc);
  882                 return;
  883         }
  884 
  885         e_addr = IF_LLADDR(mif->bif_ifp);
  886         sc->sc_bridge_id =
  887             (((uint64_t)sc->sc_bridge_priority) << 48) |
  888             (((uint64_t)e_addr[0]) << 40) |
  889             (((uint64_t)e_addr[1]) << 32) |
  890             (((uint64_t)e_addr[2]) << 24) |
  891             (((uint64_t)e_addr[3]) << 16) |
  892             (((uint64_t)e_addr[4]) << 8) |
  893             (((uint64_t)e_addr[5]));
  894 
  895         sc->sc_designated_root = sc->sc_bridge_id;
  896         sc->sc_root_path_cost = 0;
  897         sc->sc_root_port = NULL;
  898 
  899         sc->sc_max_age = sc->sc_bridge_max_age;
  900         sc->sc_hello_time = sc->sc_bridge_hello_time;
  901         sc->sc_forward_delay = sc->sc_bridge_forward_delay;
  902         sc->sc_topology_change_detected = 0;
  903         sc->sc_topology_change = 0;
  904         bstp_timer_stop(&sc->sc_tcn_timer);
  905         bstp_timer_stop(&sc->sc_topology_change_timer);
  906 
  907         if (callout_pending(&sc->sc_bstpcallout) == 0)
  908                 callout_reset(&sc->sc_bstpcallout, hz,
  909                     bstp_tick, sc);
  910 
  911         LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
  912                 if (bif->bif_flags & IFBIF_STP)
  913                         bstp_enable_port(sc, bif);
  914                 else
  915                         bstp_disable_port(sc, bif);
  916         }
  917 
  918         bstp_port_state_selection(sc);
  919         bstp_config_bpdu_generation(sc);
  920         bstp_timer_start(&sc->sc_hello_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 static void
 1069 bstp_ifupdstatus(struct bridge_softc *sc, struct bridge_iflist *bif)
 1070 {
 1071         struct ifnet *ifp = bif->bif_ifp;
 1072         struct ifmediareq ifmr;
 1073         int error = 0;
 1074 
 1075         BRIDGE_LOCK_ASSERT(sc);
 1076 
 1077         bzero((char *)&ifmr, sizeof(ifmr));
 1078         error = (*ifp->if_ioctl)(ifp, SIOCGIFMEDIA, (caddr_t)&ifmr);
 1079 
 1080         if ((error == 0) && (ifp->if_flags & IFF_UP)) {
 1081                 if (ifmr.ifm_status & IFM_ACTIVE) {
 1082                         if (bif->bif_state == BSTP_IFSTATE_DISABLED)
 1083                                 bstp_enable_port(sc, bif);
 1084 
 1085                 } else {
 1086                         if (bif->bif_state != BSTP_IFSTATE_DISABLED)
 1087                                 bstp_disable_port(sc, bif);
 1088                 }
 1089                 return;
 1090         }
 1091 
 1092         if (bif->bif_state != BSTP_IFSTATE_DISABLED)
 1093                 bstp_disable_port(sc, bif);
 1094 }
 1095 
 1096 static void
 1097 bstp_tick(void *arg)
 1098 {
 1099         struct bridge_softc *sc = arg;
 1100         struct bridge_iflist *bif;
 1101 
 1102         BRIDGE_LOCK(sc);
 1103 
 1104         LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
 1105                 if ((bif->bif_flags & IFBIF_STP) == 0)
 1106                         continue;
 1107                 /*
 1108                  * XXX This can cause a lag in "link does away"
 1109                  * XXX and "spanning tree gets updated".  We need
 1110                  * XXX come sort of callback from the link state
 1111                  * XXX update code to kick spanning tree.
 1112                  * XXX --thorpej@NetBSD.org
 1113                  */
 1114                 bstp_ifupdstatus(sc, bif);
 1115         }
 1116 
 1117         if (bstp_timer_expired(&sc->sc_hello_timer, sc->sc_hello_time))
 1118                 bstp_hello_timer_expiry(sc);
 1119 
 1120         if (bstp_timer_expired(&sc->sc_tcn_timer, sc->sc_bridge_hello_time))
 1121                 bstp_tcn_timer_expiry(sc);
 1122 
 1123         if (bstp_timer_expired(&sc->sc_topology_change_timer,
 1124             sc->sc_topology_change_time))
 1125                 bstp_topology_change_timer_expiry(sc);
 1126 
 1127         LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
 1128                 if ((bif->bif_flags & IFBIF_STP) == 0)
 1129                         continue;
 1130                 if (bstp_timer_expired(&bif->bif_message_age_timer,
 1131                     sc->sc_max_age))
 1132                         bstp_message_age_timer_expiry(sc, bif);
 1133         }
 1134 
 1135         LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
 1136                 if ((bif->bif_flags & IFBIF_STP) == 0)
 1137                         continue;
 1138                 if (bstp_timer_expired(&bif->bif_forward_delay_timer,
 1139                     sc->sc_forward_delay))
 1140                         bstp_forward_delay_timer_expiry(sc, bif);
 1141 
 1142                 if (bstp_timer_expired(&bif->bif_hold_timer,
 1143                     sc->sc_hold_time))
 1144                         bstp_hold_timer_expiry(sc, bif);
 1145         }
 1146 
 1147         if (sc->sc_if.if_flags & IFF_RUNNING)
 1148                 callout_reset(&sc->sc_bstpcallout, hz, bstp_tick, sc);
 1149 
 1150         BRIDGE_UNLOCK(sc);
 1151 }
 1152 
 1153 static void
 1154 bstp_timer_start(struct bridge_timer *t, uint16_t v)
 1155 {
 1156         t->value = v;
 1157         t->active = 1;
 1158 }
 1159 
 1160 static void
 1161 bstp_timer_stop(struct bridge_timer *t)
 1162 {
 1163         t->value = 0;
 1164         t->active = 0;
 1165 }
 1166 
 1167 static int
 1168 bstp_timer_expired(struct bridge_timer *t, uint16_t v)
 1169 {
 1170         if (t->active == 0)
 1171                 return (0);
 1172         t->value += BSTP_TICK_VAL;
 1173         if (t->value >= v) {
 1174                 bstp_timer_stop(t);
 1175                 return (1);
 1176         }
 1177         return (0);
 1178 
 1179 }

Cache object: 286fa8fcf43267206c5bbfbb1cd918b9


[ 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.