changeset 1408:ea17952ce26b

* src/sys/net/bridgestp.c: Code for Spanning Tree Protocol (STP). * cdl/openbsd_net.cdl: Changes make provisions for STP code. * doc/openbsd.sgml: Same. * include/net/if.h: Same. * include/net/if_bridge.h: Same. * include/net/if_llc.h: Same. * include/sys/sockio.h: Same. * src/sys/net/if_bridge.c: Same. * doc/openbsd-manpages-stp.sgml: Documentation for OpenBSD specific code * doc/openbsd-manpages-netintro.sgml: Same. * doc/openbsd-manpages-bridge.sgml: Same.
author asl
date Thu, 27 Nov 2003 15:25:16 +0000
parents 661c5743f848
children 6799a1e89127
files packages/net/tcpip/current/ChangeLog packages/net/tcpip/current/cdl/openbsd_net.cdl packages/net/tcpip/current/doc/openbsd-manpages-bridge.sgml packages/net/tcpip/current/doc/openbsd-manpages-netintro.sgml packages/net/tcpip/current/doc/openbsd-manpages-stp.sgml packages/net/tcpip/current/doc/openbsd.sgml packages/net/tcpip/current/include/net/if.h packages/net/tcpip/current/include/net/if_bridge.h packages/net/tcpip/current/include/net/if_llc.h packages/net/tcpip/current/include/sys/sockio.h packages/net/tcpip/current/src/sys/net/bridgestp.c packages/net/tcpip/current/src/sys/net/if_bridge.c
diffstat 12 files changed, 3266 insertions(+), 271 deletions(-) [+]
line wrap: on
line diff
--- a/packages/net/tcpip/current/ChangeLog
+++ b/packages/net/tcpip/current/ChangeLog
@@ -1,3 +1,18 @@
+2003-11-25  Manu Sharma <manu.sharma@ascom.com>
+        * src/sys/net/bridgestp.c: Code for Spanning Tree Protocol (STP).
+
+        * cdl/openbsd_net.cdl: Changes make provisions for STP code.
+        * doc/openbsd.sgml:         Same.
+        * include/net/if.h:         Same.
+        * include/net/if_bridge.h:  Same.
+        * include/net/if_llc.h:     Same.
+        * include/sys/sockio.h:     Same.
+        * src/sys/net/if_bridge.c:  Same.
+
+        * doc/openbsd-manpages-stp.sgml: Documentation for OpenBSD specific code
+        * doc/openbsd-manpages-netintro.sgml: Same.
+        * doc/openbsd-manpages-bridge.sgml:   Same.
+
 2003-09-22  Reinhard Jessich  <Reinhard.Jessich@frequentis.com>
 
 	* include/net/if.h: Define macro IF_IS_EMPTY needed by eth_drv.c
--- a/packages/net/tcpip/current/cdl/openbsd_net.cdl
+++ b/packages/net/tcpip/current/cdl/openbsd_net.cdl
@@ -186,7 +186,8 @@ cdl_package CYGPKG_NET_OPENBSD_STACK {
          description   "
              This option controls whether to include the built-in code for
              the Ethernet bridge."
-     compile sys/net/if_bridge.c
+     compile sys/net/if_bridge.c \
+             sys/net/bridgestp.c
 
          cdl_option CYGNUM_NET_BRIDGES {
              display "Number of Ethernet bridges"
@@ -194,6 +195,14 @@ cdl_package CYGPKG_NET_OPENBSD_STACK {
              default_value 1
              legal_values 1 to 999999
          }
+
+         cdl_option CYGPKG_NET_BRIDGE_STP_CODE {
+             display "Include code for Spanning Tree Protocol"
+             default_value 0
+             description "
+                 This option controls whether to include the code for
+                 the Spanning Tree Protocol on Ethernet bridge."
+         }
     }
 
     cdl_interface CYGINT_NET_BRIDGE_HANDLER {
new file mode 100644
--- /dev/null
+++ b/packages/net/tcpip/current/doc/openbsd-manpages-bridge.sgml
@@ -0,0 +1,452 @@
+<!-- {{{ Banner                         -->
+<!-- All of the documentation and software included in the second BSD Networking     -->
+<!-- Software Release is copyrighted by The Regents of the University of California. -->
+
+<!-- Copyright 1979, 1980, 1983, 1986, 1988, 1989, 1991 The Regents of the           -->
+<!-- University of California.                                                       -->
+<!-- All rights reserved.                                                            -->
+
+<!-- Redistribution and use in source and binary forms, with or without              -->
+<!-- modification, are permitted provided that the following conditions              -->
+<!-- are met:                                                                        -->
+<!-- 1. Redistributions of source code must retain the above copyright               -->
+<!--    notice, this list of conditions and the following disclaimer.                -->
+<!-- 2. Redistributions in binary form must reproduce the above copyright            -->
+<!--    notice, this list of conditions and the following disclaimer in the          -->
+<!--    documentation and/or other materials provided with the distribution.         -->
+<!-- 3. Neither the name of the University nor the names of its contributors         -->
+<!--    may be used to endorse or promote products derived from this software        -->
+<!--    without specific prior written permission.                                   -->
+
+<!-- THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND         -->
+<!-- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE           -->
+<!-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE      -->
+<!-- ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE        -->
+<!-- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL      -->
+<!-- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS         -->
+<!-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)           -->
+<!-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT      -->
+<!-- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY       -->
+<!-- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF          -->
+<!-- SUCH DAMAGE.                                                                    -->
+
+<!-- =============================================================== -->
+<!--                                                                 -->
+<!--     openbsd_bridge.sgml                                         -->
+<!--                                                                 -->
+<!--     eCos TCP/IP Stacks                                          -->
+<!--                                                                 -->
+<!-- =============================================================== -->
+<!-- ####COPYRIGHTBEGIN####                                          -->
+<!--                                                                 -->
+<!-- =============================================================== -->
+<!-- Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.  -->
+<!-- This material may be distributed only subject to the terms      -->
+<!-- and conditions set forth in the Open Publication License, v1.0  -->
+<!-- or later (the latest version is presently available at          -->
+<!-- http://www.opencontent.org/openpub/)                            -->
+<!-- Distribution of the work or derivative of the work in any       -->
+<!-- standard (paper) book form is prohibited unless prior           -->
+<!-- permission obtained from the copyright holder                   -->
+<!-- =============================================================== -->
+<!--                                                                 -->
+<!-- ####COPYRIGHTEND####                                            -->
+<!-- =============================================================== -->
+<!-- #####DESCRIPTIONBEGIN####                                       -->
+<!--                                                                 -->
+<!-- ####DESCRIPTIONEND####                                          -->
+<!-- =============================================================== -->
+
+<!-- }}} -->
+
+<SECT1 id="openbsd-manpages-bridge">
+<TITLE>Bridging</TITLE>
+<SCREEN>
+
+NAME
+     bridge - Ethernet bridge interface
+
+SYNOPSIS
+     pseudo-device bridge
+
+DESCRIPTION
+     The bridge device creates a logical link between two or more Ethernet 
+     interfaces.  This link between the interfaces selectively forwards 
+     frames from each interface on the bridge to every other interface on 
+     the bridge.  A bridge can serve several services, including isolation 
+     of traffic between sets of machines so that traffic local to one set of
+     machines is not available on the wire of another set of machines, and 
+     it can act as a transparent filter for ip4 datagrams.
+
+     The bridges provided by this interface are learning bridges with filter-
+     ing.  In general a bridge works like a hub, forwarding traffic from one 
+     interface to another. It differs from a hub in that it will "learn" which
+     machines are on each of its attached segments by actively listening to 
+     incoming traffic and examining the headers of each frame. A table is 
+     built containing the MAC address and segment to which the MAC address is 
+     attached. This allows a bridge to be more selective about what it 
+     forwards, which can be used to reduce traffic on a set of segments and 
+     also to provide an IP firewall without changing the topology of the 
+     network.
+
+     The algorithm works as follows by default, but can be modified via ioctl.
+     When a frame comes in, the origin segment and the source address are 
+     recorded.  If the bridge has no knowledge about where the destination is 
+     to be found, the bridge will forward the frame to all attached segments. 
+     If the destination is known to be on a different segment from its origin, 
+     the bridge will forward the packet only to the destination segment. If the 
+     destination is on the same segment as the origin segment, the bridge will
+     drop the packet because the receiver has already had a chance to see the
+     frame.
+
+IOCTLS
+     A bridge interface responds to all of the ioctl calls specific to oth-
+     er interfaces listed in <link linkend="openbsd-manpages-netintro">netintro</link>.  The following ioctl calls are
+     specific to bridge devices.  They are defined in &lt;sys/sockio.h>.
+
+     SIOCBRDGIFS      (struct ifbifconf) Retrieve member interface list from a
+                      bridge.  This request takes an ifbifconf structure (see
+                      below) as a value-result parameter.  The ifbic_len field
+                      should be initially set to the size of the buffer point-
+                      ed to by ifbic_buf.  On return it will contain the
+                      length, in bytes, of the configuration list.  Alterna-
+                      tively, if the ifbic_len passed in is set to 0,
+                      SIOCBRDGIFS will set ifbic_len to the size that
+                      ifbic_buf needs to be to fit the entire configuration
+                      list, and will not fill in the other parameters.  This
+                      is useful for determining the exact size that ifbic_buf
+                      needs to be in advance.
+
+                      The argument structure is defined as follows:
+
+                            struct ifbreq {
+                                    char ifbr_name[IFNAMSIZ];    /* brdg nam */
+                                    char ifbr_ifsname[IFNAMSIZ]; /* if name */
+                                    u_int32_t ifbr_ifsflags;     /* if flags */
+                                    u_int8_t  ifbr_state;        /* member stp state */
+                                    u_int8_t  ifbr_priority;     /* member stp priority */
+                                    u_int8_t  ifbr_portno;       /* member port number */
+                                    u_int32_t ifbr_path_cost;    /* member stp path cost */
+                            };
+                            /* SIOCBRDGIFFLGS, SIOCBRDGIFFLGS */
+                            #define IFBIF_LEARNING    0x0001 /* ifs can learn */
+                            #define IFBIF_DISCOVER    0x0002 /* ifs sends packets w/unknown dest */
+                            #define IFBIF_BLOCKNONIP  0x0004 /* ifs blocks non-IP/ARP in/out */
+                            #define IFBIF_STP         0x0008 /* ifs participates in spanning tree */
+                            #define IFBIF_SPAN        0x0100 /* ifs is a span port (ro) */
+                            #define IFBIF_RO_MASK     0xff00 /* read only bits */
+
+                            struct ifbifconf {
+                                    char ifbic_name[IFNAMSIZ]; /* brdg name */
+                                    u_int32_t       ifbic_len; /* buf size */
+                                    union {
+                                            caddr_t ifbicu_buf; /* buffer */
+                                            struct  ifbreq *ifbicu_req;
+                                    } ifbic_ifbicu;
+                            #define ifbic_buf       ifbic_ifbicu.ifbicu_buf
+                            #define ifbic_req       ifbic_ifbicu.ifbicu_req
+                            };
+
+     SIOCBRDGADD      (struct ifbreq) Add the interface named in ifbr_ifsname
+                      to the bridge named in ifbr_name.
+
+     SIOCBRDGDEL      (struct ifbreq) Delete the interface named in
+                      ifbr_ifsname from the bridge named in ifbr_name.
+
+     SIOCBRDGADDS     (struct ifbreq) Add the interface named in ifbr_ifsname
+                      as a span port to the bridge named in ifbr_name.
+
+     SIOCBRDGDELS     (struct ifbreq) Delete the interface named in
+                      ifbr_ifsname from the list of span ports of the bridge
+                      named in ifbr_name.
+
+     SIOCBRDGSIFFLGS  (struct ifbreq) Set the bridge member interface flags
+                      for the interface named in ifbr_ifsname attached to the
+                      bridge ifbr_name.  If the flag IFBIF_LEARNING is set on
+                      an interface, source addresses from frames received on
+                      the interface are recorded in the address cache.  If the
+                      flag IFBIF_DISCOVER is set, the interface will receive
+                      packets destined for unknown destinations, otherwise a
+                      frame that has a destination not found in the address
+                      cache is not forwarded to this interface.  The default
+                      for newly added interfaces has both flags set.  If the
+                      flag IFBIF_BLOCKNONIP is set, packets that are one of
+                      ip(4), ip6(4), arp(4), or Reverse ARP, will not be
+                      bridged from and to the interface.
+
+     SIOCBRDGGIFFLGS  Retrieve the bridge member interface flags for the in-
+                      terface named in ifbr_ifsname attached to the bridge
+                      ifbr_name.
+
+     SIOCBRDGRTS      (struct ifbaconf) Retrieve the address cache of the
+                      bridge named in ifbac_name.  This request takes an
+                      ifbaconf structure (see below) as a value result parame-
+                      ter.  The ifbac_len field should be initially set to the
+                      size of the buffer pointed to by ifbac_buf.  On return,
+                      it will contain the length, in bytes, of the configura-
+                      tion list.  Alternatively, if the ifbac_len passed in is
+                      set to 0, SIOCBRDGRTS will set it to the size that
+                      ifbac_buf needs to be to fit the entire configuration
+                      list and not fill in the other parameters.  As with
+                      SIOCBRDGIFS, this is useful for determining the exact
+                      size that ifbac_buf needs to be in advance.
+
+                      The argument structure is defined as follows:
+
+                            struct ifbareq {
+                                    char ifba_name[IFNAMSIZ];   /* brdg nam */
+                                    char ifba_ifsname[IFNAMSIZ];/* dest ifs */
+                                    u_int8_t ifba_age;          /* addr age */
+                                    u_int8_t ifba_flags;        /* addr flag */
+                                    struct ether_addr ifba_dst; /* dst addr */
+                            };
+
+                            #define IFBAF_TYPEMASK 0x03  /* addr type mask */
+                            #define IFBAF_DYNAMIC  0x00  /* dynamic addr */
+                            #define IFBAF_STATIC   0x01  /* static address */
+
+                            struct ifbaconf {
+                                    char ifbac_name[IFNAMSIZ]; /* brdg name */
+                                    u_int32_t ifbac_len;       /* buf size */
+                                    union {
+                                            caddr_t ifbacu_buf;     /* buf */
+                                            struct ifbareq *ifbacu_req;
+                                    } ifbac_ifbacu;
+                            #define ifbac_buf       ifbac_ifbacu.ifbacu_buf
+                            #define ifbac_req       ifbac_ifbacu.ifbacu_req
+                            };
+                      Address cache entries with the type set to IFBAF_DYNAMIC
+                      in ifba_flags are entries learned by the bridge.  En-
+                      tries with the type set to IFBAF_STATIC are manually
+                      added entries.
+
+     SIOCBRDGSADDR    (struct ifbareq) Add an entry, manually, to the address
+                      cache for the bridge named in ifba_name.  The address
+                      and its associated interface and flags are set in the
+                      ifba_dst, ifba_ifsname, and ifba_flags fields, respec-
+                      tively.
+
+     SIOCBRDGDADDR    (struct ifbareq) Delete an entry from the address cache
+                      of the bridge named in ifba_name.  Entries are deleted
+                      strictly based on the address field ifba_dst.
+
+     SIOCBRDGSCACHE   (struct ifbcachereq) Set the maximum address cache size
+                      for the bridge named in ifbc_name to ifbc_size entries.
+
+                      The argument structure is as follows:
+
+                            struct ifbcachereq {
+                                    char ifbc_name[IFNAMSIZ]; /* bridge */
+                                    u_int32_t ifbc_size;      /* size */
+                            };
+
+     SIOCBRDGGCACHE   (struct ifbcachereq) Retrieve the maximum size of the
+                      address cache for the bridge ifbc_name.
+
+     SIOCBRDGSTO      (struct ifbcachetoreq) Set the time, in seconds, that
+                      addresses which have not been seen on the network
+                      (transmitted a packet) remain in the cache.  If the time
+                      is set to zero, no aging is performed on the address
+                      cache.  The argument structure is as follows:
+
+                            struct ifbcachetoreq {
+                                    char ifbct_name[IFNAMSIZ]; /* bridge */
+                                    u_int32_t ifbct_time;      /* time */
+                            };
+
+     SIOCBRDGGTO      (struct ifbcachetoreq) Retrieve the address cache expi-
+                      ration time (see above).
+
+     SIOCBRDGFLUSH    (struct ifbreq) Flush addresses from the cache.
+                      ifbr_name contains the name of the bridge device, and
+                      ifbr_ifsflags should be set to IFBF_FLUSHALL to flush
+                      all addresses from the cache or IFBF_FLUSHDYN to flush
+                      only the dynamically learned addresses from the cache.
+
+     SIOCBRDGARL      (struct ifbrlreq) Add an Ethernet address filtering rule
+                      to the bridge on a specific interface.  ifbr_name con-
+                      tains the name of the bridge device, and ifbr_ifsname
+                      contains the name of the bridge member interface.  The
+                      ifbr_action field is one of BRL_ACTION_PASS or
+                      BRL_ACTION_BLOCK, to pass or block matching frames re-
+                      spectively.  The ifbr_flags specifies whether the rule
+                      should match on input, output, or both be using the
+                      flags BRL_FLAG_IN and BRL_FLAG_OUT.  It also specifies
+                      whether either (or both) of the source and destination
+                      addresses should be matched by using the
+                      BRL_FLAG_SRCVALID and BRL_FLAG_DSTVALID flags.  The
+                      ifbr_src field is the source address that triggers the
+                      rule (only considered if ifbr_flags has the
+                      BRL_FLAG_SRCVALID bit set).  The ifbr_src field is the
+                      destination address that triggers the rule (only consid-
+                      ered if ifbr_flags has the BRL_FLAG_DSTVALID bit set).
+
+                      The argument structure is as follows:
+
+                            struct ifbrlreq {
+                                    char ifbr_name[IFNAMSIZ];
+                                    char ifbr_ifsname[IFNAMSIZ];
+                                    u_int8_t ifbr_action;
+                                    u_int8_t ifbr_flags;
+                                    struct ether_addr ifbr_src;
+                                    struct ether_addr ifbr_dst;
+                                    char ifbr_tagname[PF_TAG_NAME_SIZE];
+                            };
+                            #define BRL_ACTION_BLOCK 0x01
+                            #define BRL_ACTION_PASS  0x02
+                            #define BRL_FLAG_IN      0x08
+                            #define BRL_FLAG_OUT     0x04
+
+     SIOCBRDGFRL      (struct ifbrlreq) Remove all filtering rules from a
+                      bridge interface member.  ifbr_name contains the name of
+                      the bridge device, and ifbr_ifsname contains the name of
+                      the bridge member interface.
+
+     SIOCBRDGGRL      (struct ifbrlconf) Retrieve all of the rules from the
+                      bridge, ifbrl_name, for the member interface,
+                      ifbrl_ifsname.  This request takes an ifbrlconf struc-
+                      ture (see below) as a value result parameter.  The
+                      ifbrl_len field should be initially set to the size of
+                      the buffer pointed to by ifbrl_buf.  On return, it will
+                      contain the length, in bytes, of the configuration list.
+                      Alternatively, if the ifbrl_len passed in is set to 0,
+                      SIOCBRDGGRL will set it to the size that ifbrl_buf needs
+                      to be to fit the entire configuration list and not fill
+                      in the other parameters.  As with SIOCBRDGIFS, this is
+                      useful for determining the exact size that ifbrl_buf
+                      needs to be in advance.
+
+                      The argument structure is defined as follows:
+
+                            struct ifbrlconf {
+                                    char ifbrl_name[IFNAMSIZ];   /* brdg nam */
+                                    char ifbrl_ifsname[IFNAMSIZ];/* ifs name */
+                                    u_int32_t ifbr_len;         /* buf len */
+                                    union {
+                                            caddr_t ifbrlu_buf;
+                                            struct ifbrlreq *ifbrlu_req;
+                                    } ifrl_ifbrlu;
+                            #define ifbrl_buf ifbrl_ifbrlu.ifbrlu_buf
+                            #define ifbrl_req ifbrl_ifbrlu.ifbrlu_req
+                            };
+
+     SIOCBRDGARL      (struct ifbrlreq) Add a filtering rule to the bridge
+                      named in ifbr_name on the interface named in
+                      ifbr_ifsname.  The argument structure is as follows:
+
+                            struct ifbrlreq {
+                                    char ifbr_name[IFNAMSIZ];    /* bridge */
+                                    char ifbr_ifsname[IFNAMSIZ]; /* ifs */
+                                    u_int8_t ifbr_action;        /* handling */
+                                    u_int8_t ifbr_flags;         /* flags */
+                                    struct ether_addr ifbr_src;  /* src mac */
+                                    struct ether_addr ifbr_dst;  /* dst mac */
+                            };
+                            #define BRL_ACTION_BLOCK        0x01
+                            #define BRL_ACTION_PASS         0x02
+                            #define BRL_FLAG_IN             0x08
+                            #define BRL_FLAG_OUT            0x04
+                            #define BRL_FLAG_SRCVALID       0x02
+                            #define BRL_FLAG_DSTVALID       0x01
+
+                      Rules are applied in the order in which they were added
+                      to the bridge, and the first matching rule's action pa-
+                      rameter determines the fate of the packet.  The
+                      ifbr_action parameter specifies whether a frame matching
+                      the rule is to be blocked or passed.
+
+                      If the BRL_FLAG_IN bit is set in ifbr_flags, then the
+                      rule applies to frames received by the interface.  If
+                      the BRL_FLAG_OUT bit is set, then the rule applies to
+                      frame transmitted by the interface.  At least one of
+                      BRL_FLAG_IN or BRL_FLAG_OUT must be set.
+
+                      The source Ethernet address in ifbr_src is checked if
+                      the BRL_FLAG_SRCVALID bit is set in ifbr_flags.  The
+                      destination address in ifbr_dst is checked if the
+                      BRL_FLAG_DSTVALID bit is set.  If neither bit is set,
+                      the rule matches all frames.
+
+     SIOCBRDGFRL      (struct ifbrlreq) Flush rules from the bridge ifbr_name
+                      on the interface ifbr_ifsname.
+
+     SIOCBRDGGRL      (struct ifbrlconf) Retrieve an array of rules from the
+                      bridge for a particular interface.  This request takes
+                      an ifbrlconf structure (see below) as a value-result pa-
+                      rameter.  The ifbrl_len field should be initially set to
+                      the size of the buffer pointed to by ifbrl_buf.  On re-
+                      turn it will contain the length, in bytes, of the rule
+                      list.  Alternatively, if the ifbrl_len passed in is set
+                      to 0, SIOCBRDGGRL will set ifbrl_len to the size that
+                      ifbrl_buf needs to be to fit the entire configuration
+                      list, and will not fill in the other parameters.  This
+                      is useful for determining the exact size that ifbrl_buf
+                      needs to be in advance.
+
+                      The argument structure is as follows:
+
+                            struct ifbrlconf {
+                                    char ifbrl_name[IFNAMSIZ];   /* bridge */
+                                    char ifbrl_ifsname[IFNAMSIZ];/* member */
+                                    u_int32_t ifbrl_len;         /* buflen */
+                                    union {
+                                            caddr_t ifbrlu_buf;
+                                            struct  ifbrlreq *ifbrlu_req;
+                                    } ifbrl_ifbrlu;
+                            #define ifbrl_buf ifbrl_ifbrlu.ifbrlu_buf
+                            #define ifbrl_req ifbrl_ifbrlu.ifbrlu_req
+                            };
+
+ERRORS
+     If the ioctl call fails, errno is set to one of the following values:
+
+     [ENOENT]      For an add request, this means that the named interface is
+                   not configured into the system.  For a delete operation, it
+                   means that the named interface is not a member of the
+                   bridge.  For an address cache deletion, the address was not
+                   found in the table.
+
+     [ENOMEM]      Memory could not be allocated for an interface or cache en-
+                   try to be added to the bridge.
+
+     [EEXIST]      The named interface is already a member of the bridge.
+
+     [EBUSY]       The named interface is already a member of another bridge.
+
+     [EINVAL]      The named interface is not an Ethernet interface or an in-
+                   valid ioctl was performed on the bridge.
+
+     [ENETDOWN]    Address cache operation (flush, add, delete) on a bridge
+                   that is in the down state.
+
+     [ESRCH]       No such member interface in the bridge.
+
+SEE ALSO
+     <link linkend="openbsd-manpages-netintro">netintro</link>, <link linkend="openbsd-manpages-stp">spanning-tree</link>
+
+AUTHORS
+     The bridge kernel interface was written by Jason L. Wright 
+     &lt;jason@thought.net> as part of an undergraduate independent study at 
+     the University of North Carolina at Greensboro.
+
+</SCREEN>
+</SECT1>
+
+<!-- Keep this comment at the end of the file
+Local variables:
+mode: sgml
+sgml-omittag:nil
+sgml-shorttag:t
+sgml-namecase-general:t
+sgml-general-insert-case:lower
+sgml-minimize-attributes:nil
+sgml-always-quote-attributes:t
+sgml-indent-step:2
+sgml-indent-data:t
+sgml-parent-document:("tcpip.sgml" "book" "chapter")
+sgml-exposed-tags:nil
+sgml-local-catalogs:nil
+sgml-local-ecat-files:nil
+sgml-doctype:"book"
+End:
+-->
new file mode 100644
--- /dev/null
+++ b/packages/net/tcpip/current/doc/openbsd-manpages-netintro.sgml
@@ -0,0 +1,310 @@
+<!-- {{{ Banner                         -->
+
+<!-- All of the documentation and software included in the second BSD Networking     -->
+<!-- Software Release is copyrighted by The Regents of the University of California. -->
+
+<!-- Copyright 1979, 1980, 1983, 1986, 1988, 1989, 1991 The Regents of the           -->
+<!-- University of California.                                                       -->
+<!-- All rights reserved.                                                            -->
+
+<!-- Redistribution and use in source and binary forms, with or without              -->
+<!-- modification, are permitted provided that the following conditions              -->
+<!-- are met:                                                                        -->
+<!-- 1. Redistributions of source code must retain the above copyright               -->
+<!--    notice, this list of conditions and the following disclaimer.                -->
+<!-- 2. Redistributions in binary form must reproduce the above copyright            -->
+<!--    notice, this list of conditions and the following disclaimer in the          -->
+<!--    documentation and/or other materials provided with the distribution.         -->
+<!-- 3. Neither the name of the University nor the names of its contributors         -->
+<!--    may be used to endorse or promote products derived from this software        -->
+<!--    without specific prior written permission.                                   -->
+
+<!-- THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND         -->
+<!-- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE           -->
+<!-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE      -->
+<!-- ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE        -->
+<!-- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL      -->
+<!-- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS         -->
+<!-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)           -->
+<!-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT      -->
+<!-- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY       -->
+<!-- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF          --> 
+<!-- SUCH DAMAGE.                                                                    -->
+
+<!-- =============================================================== -->
+<!--                                                                 -->
+<!--     openbsd_netintro.sgml                                       -->
+<!--                                                                 -->
+<!--     eCos TCP/IP Stacks                                          -->
+<!--                                                                 -->
+<!-- =============================================================== -->
+<!-- ####COPYRIGHTBEGIN####                                          -->
+<!--                                                                 -->
+<!-- =============================================================== -->
+<!-- Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.  -->
+<!-- This material may be distributed only subject to the terms      -->
+<!-- and conditions set forth in the Open Publication License, v1.0  -->
+<!-- or later (the latest version is presently available at          -->
+<!-- http://www.opencontent.org/openpub/)                            -->
+<!-- Distribution of the work or derivative of the work in any       -->
+<!-- standard (paper) book form is prohibited unless prior           -->
+<!-- permission obtained from the copyright holder                   -->
+<!-- =============================================================== -->
+<!--                                                                 -->
+<!-- ####COPYRIGHTEND####                                            -->
+<!-- =============================================================== -->
+<!-- #####DESCRIPTIONBEGIN####                                       -->
+<!--                                                                 -->
+<!-- ####DESCRIPTIONEND####                                          -->
+<!-- =============================================================== -->
+
+<!-- }}} -->
+
+<SECT1 id="openbsd-manpages-netintro">
+<TITLE>OpenBSD networking facilities</TITLE>
+<SCREEN>
+
+NAME
+     networking - introduction to networking facilities
+
+SYNOPSIS
+     #include &lt;sys/socket.h>
+     #include &lt;net/route.h>
+     #include &lt;net/if.h>
+
+DESCRIPTION
+     This section is a general introduction to the networking facilities
+     available in the system.  The general introduction on this page is 
+     broken up into three areas: protocol families (domains), protocols, 
+     and network interfaces.
+
+     All network protocols are associated with a specific protocol family. A
+     protocol family provides basic services to the protocol implementation 
+     to allow it to function within a specific network environment.  These 
+     services may include packet fragmentation and reassembly, routing, 
+     addressing, and basic transport.  A protocol family may support multiple 
+     methods of addressing, though the current protocol implementations do not.
+     A protocol family is normally comprised of a number of protocols, one per
+     <link linkend="net-common-tcpip-manpages-socket">socket</link> type. It is not required that a protocol family support all
+     socket types.  A protocol family may contain multiple protocols support-
+     ing the same socket abstraction.
+
+     A protocol supports one of the socket abstractions detailed in <link linkend="net-common-tcpip-manpages-socket">socket</link>.
+     A specific protocol may be accessed either by creating a socket of the
+     appropriate type and protocol family, or by requesting the protocol ex-
+     plicitly when creating a socket.  Protocols normally accept only one type
+     of address format, usually determined by the addressing structure inher-
+     ent in the design of the protocol family/network architecture.  Certain
+     semantics of the basic socket abstractions are protocol specific.  All
+     protocols are expected to support the basic model for their particular
+     socket type, but may, in addition, provide non-standard facilities or ex-
+     tensions to a mechanism.  For example, a protocol supporting the
+     SOCK_STREAM abstraction may allow more than one byte of out-of-band data
+     to be transmitted per out-of-band message.
+
+     A network interface is similar to a device interface.  Network interfaces
+     comprise the lowest layer of the networking subsystem, interacting with
+     the actual transport hardware.  An interface may support one or more pro-
+     tocol families and/or address formats. 
+
+PROTOCOL
+     The system currently supports the Internet protocols. Raw socket interfaces
+     are provided to the IP protocol layer of the Internet. 
+
+ADDRESSING
+     Associated with each protocol family is an address format.  All network
+     addresses adhere to a general structure, called a sockaddr, described be-
+     low.  However, each protocol imposes a finer, more specific structure,
+     generally renaming the variant, which is discussed in the protocol family
+     manual page alluded to above.
+
+           struct sockaddr {
+                   u_int8_t        sa_len;
+                   sa_family_t     sa_family;
+                   char            sa_data[14];
+           };
+
+     The field sa_len contains the total length of the structure, which may
+     exceed 16 bytes.  The following address values for sa_family are known to
+     the system (and additional formats are defined for possible future imple-
+     mentation):
+
+     #define    AF_UNIX      1    /* local to host (pipes, portals) */
+     #define    AF_INET      2    /* internetwork: UDP, TCP, etc. */
+     #define    AF_NS        6    /* Xerox NS protocols */
+     #define    AF_CCITT     10   /* CCITT protocols, X.25 etc */
+     #define    AF_HYLINK    15   /* NSC Hyperchannel */
+     #define    AF_APPLETALK 16   /* AppleTalk */
+     #define    AF_ISO       18   /* ISO protocols */
+     #define    AF_IPX       23   /* Novell Internet Protocol */
+     #define    AF_INET6     24   /* IPv6 */
+     #define    AF_NATM      27   /* native ATM access */
+
+ROUTING
+     OpenBSD provides some packet routing facilities.  The kernel maintains a
+     routing information database, which is used in selecting the appropriate
+     network interface when transmitting packets.
+
+     This facility is however, untested in eCos ports.
+
+INTERFACES
+     Each network interface in a system corresponds to a path through which
+     messages may be sent and received.  A network interface usually has a
+     hardware device associated with it, though certain interfaces such as the
+     loopback interface, lo, do not.
+
+     The following ioctl calls may be used to manipulate network interfaces
+     The ioctl is made on a socket (typically of type SOCK_DGRAM) in the desired
+     domain.  Most of the requests supported in earlier releases take an ifreq 
+     structure as its parameter.  This structure has the form
+
+     struct  ifreq {
+     #define    IFNAMSIZ    16
+             char    ifr_name[IFNAMSIZ];         /* if name, e.g. "en0" */
+             union {
+                     struct    sockaddr ifru_addr;
+                     struct    sockaddr ifru_dstaddr;
+                     struct    sockaddr ifru_broadaddr;
+                     short     ifru_flags;
+                     int       ifru_metric;
+                     caddr_t   ifru_data;
+             } ifr_ifru;
+     #define ifr_addr      ifr_ifru.ifru_addr    /* address */
+     #define ifr_dstaddr   ifr_ifru.ifru_dstaddr /* other end of p-to-p link */
+     #define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */
+     #define ifr_flags     ifr_ifru.ifru_flags   /* flags */
+     #define ifr_metric    ifr_ifru.ifru_metric  /* metric */
+     #define ifr_media     ifr_ifru.ifru_metric  /* media options (overload) */
+     #define ifr_data      ifr_ifru.ifru_data    /* for use by interface */
+     };
+
+     Calls which are now deprecated are:
+
+     SIOCSIFADDR     Set interface address for protocol family.  Following the
+                     address assignment, the ``initialization'' routine for
+                     the interface is called.
+
+     SIOCSIFDSTADDR  Set point to point address for protocol family and inter-
+                     face.
+
+     SIOCSIFBRDADDR  Set broadcast address for protocol family and interface.
+
+     ioctl requests to obtain addresses and requests both to set and retrieve
+     other data are still fully supported and use the ifreq structure:
+
+     SIOCGIFADDR     Get interface address for protocol family.
+
+     SIOCGIFDSTADDR  Get point to point address for protocol family and inter-
+                     face.
+
+     SIOCGIFBRDADDR  Get broadcast address for protocol family and interface.
+
+     SIOCSIFFLAGS    Set interface flags field.  If the interface is marked
+                     down, any processes currently routing packets through the
+                     interface are notified; some interfaces may be reset so
+                     that incoming packets are no longer received.  When
+                     marked up again, the interface is reinitialized.
+
+     SIOCGIFFLAGS    Get interface flags.
+
+     SIOCSIFMEDIA    Set interface media.  See ifmedia(4) for possible values.
+
+     SIOCGIFMEDIA    Get interface media.  See ifmedia(4) for interpreting
+                     this value.
+
+     SIOCSIFMETRIC   Set interface routing metric.  The metric is used only by
+                     user-level routers.
+
+     SIOCGIFMETRIC   Get interface metric.
+
+     There are two requests that make use of a new structure:
+
+     SIOCAIFADDR     An interface may have more than one address associated
+                     with it in some protocols.  This request provides a means
+                     to add additional addresses (or modify characteristics of
+                     the primary address if the default address for the ad-
+                     dress family is specified).  Rather than making separate
+                     calls to set destination or broadcast addresses, or net-
+                     work masks (now an integral feature of multiple proto-
+                     cols) a separate structure is used to specify all three
+                     facets simultaneously (see below).  One would use a
+                     slightly tailored version of this struct specific to each
+                     family (replacing each sockaddr by one of the family-spe-
+                     cific type).  Where the sockaddr itself is larger than
+                     the default size, one needs to modify the ioctl(2) iden-
+                     tifier itself to include the total size, as described in
+                     ioctl(2).
+
+     SIOCDIFADDR     This request deletes the specified address from the list
+                     associated with an interface.  It also uses the
+                     if_aliasreq structure to allow for the possibility of
+                     protocols allowing multiple masks or destination address-
+                     es, and also adopts the convention that specification of
+                     the default address means to delete the first address for
+                     the interface belonging to the address family in which
+                     the original socket was opened.
+
+     SIOCGIFCONF     Get interface configuration list.  This request takes an
+                     ifconf structure (see below) as a value-result parameter.
+                     The ifc_len field should be initially set to the size of
+                     the buffer pointed to by ifc_buf.  On return it will con-
+                     tain the length, in bytes, of the configuration list.
+                     Alternately, if the ifc_len passed in is set to 0,
+                     SIOCGIFCONF will set ifc_len to the size that ifc_buf
+                     needs to be to fit the entire configuration list and not
+                     fill in the other parameters.  This is useful for deter-
+                     mining the exact size that ifc_buf needs to be in ad-
+                     vance.  Note, however, that this is an extension that not
+                     all operating systems support.
+
+     /*
+     * Structure used in SIOCAIFADDR request.
+     */
+     struct ifaliasreq {
+             char    ifra_name[IFNAMSIZ];   /* if name, e.g. "en0" */
+             struct  sockaddr        ifra_addr;
+             struct  sockaddr        ifra_broadaddr;
+             struct  sockaddr        ifra_mask;
+     };
+
+     /*
+     * Structure used in SIOCGIFCONF request.
+     * Used to retrieve interface configuration
+     * for machine (useful for programs which
+     * must know all networks accessible).
+     */
+     struct ifconf {
+             int   ifc_len;          /* size of associated buffer */
+             union {
+                     caddr_t    ifcu_buf;
+                     struct     ifreq *ifcu_req;
+             } ifc_ifcu;
+     #define ifc_buf ifc_ifcu.ifcu_buf /* buffer address */
+     #define ifc_req ifc_ifcu.ifcu_req /* array of structures returned */
+     };
+
+SEE ALSO
+     <link linkend="openbsd-manpages-bridge">bridge</link>, <link linkend="openbsd-manpages-stp">spanning-tree</link>
+
+</SCREEN>
+</SECT1>
+
+<!-- Keep this comment at the end of the file
+Local variables:
+mode: sgml
+sgml-omittag:nil
+sgml-shorttag:t
+sgml-namecase-general:t
+sgml-general-insert-case:lower
+sgml-minimize-attributes:nil
+sgml-always-quote-attributes:t
+sgml-indent-step:2
+sgml-indent-data:t
+sgml-parent-document:("tcpip.sgml" "book" "chapter")
+sgml-exposed-tags:nil
+sgml-local-catalogs:nil
+sgml-local-ecat-files:nil
+sgml-doctype:"book"
+End:
+-->
+
new file mode 100644
--- /dev/null
+++ b/packages/net/tcpip/current/doc/openbsd-manpages-stp.sgml
@@ -0,0 +1,137 @@
+<!-- {{{ Banner                         -->
+
+<!-- =============================================================== -->
+<!--                                                                 -->
+<!--     openbsd-manpages-stp.sgml                                   -->
+<!--                                                                 -->
+<!--     eCos TCP/IP Stacks                                          -->
+<!--                                                                 -->
+<!-- =============================================================== -->
+<!-- ####COPYRIGHTBEGIN####                                          -->
+<!--                                                                 -->
+<!-- =============================================================== -->
+<!-- Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.  -->
+<!-- This material may be distributed only subject to the terms      -->
+<!-- and conditions set forth in the Open Publication License, v1.0  -->
+<!-- or later (the latest version is presently available at          -->
+<!-- http://www.opencontent.org/openpub/)                            -->
+<!-- Distribution of the work or derivative of the work in any       -->
+<!-- standard (paper) book form is prohibited unless prior           -->
+<!-- permission obtained from the copyright holder                   -->
+<!-- =============================================================== -->
+<!--                                                                 -->
+<!-- ####COPYRIGHTEND####                                            -->
+<!-- =============================================================== -->
+<!-- #####DESCRIPTIONBEGIN####                                       -->
+<!--                                                                 -->
+<!-- ####DESCRIPTIONEND####                                          -->
+<!-- =============================================================== -->
+
+<!-- }}} -->
+
+<SECT1 id="openbsd-manpages-stp">
+<TITLE>Spanning Tree Protocol</TITLE>
+<SCREEN>
+NAME
+     stp - Spanning Tree Protocol
+
+SYNOPSIS
+
+
+DESCRIPTION
+     Spanning Tree (STP) is a layer 2 protocol designed to run on bridges. The
+     main purpose of STP is to ensure that there are no loop situations when
+     redundant paths are provisioned in the network. STP detects and disables
+     creation of network loops by blocking certain ports on some of the bridges
+     in the network. The process of selection of blocking ports (on occurance
+     of redundant paths) is governed by the following three parameters :
+
+     - Relative priority of each bridge. A higher value means lower priority.
+     - Relative priority of each port within a bridge. A higher value means
+       lower priority.
+     - Path cost (based on physical media type) associated with each port.
+
+     A given port/interface participates in STP if the flag IFBIF_STP is 
+     set for the interface. A possible time for setting this flag is at the 
+     time when the interface in context is added to bridge. 
+
+IOCTLS
+     The STP code is invoked for all ioctl calls specified in <link linkend="openbsd-manpages-bridge">bridge</link> section.
+     The following ioctl calls are specific to STP functionality. They are
+     defined in &lt;sys/sockio.h>.
+
+     SIOCBRDGGPRI         (struct ifbrparam) Get the configured priority of this
+                          bridge. The priority value could vary from 0 to 65535.
+                          0 being the highest priority and 65535 the lowest. The
+                          configured value is returned in field ifbrp_prio.
+
+     SIOCBRDGSPRI         (struct ifbrparam) Set priority of this bridge to the
+                          value specified in field ifbrp_prio.
+
+     SIOCBRDGGHT          (struct ifbrparam) Get the configured frequency of
+                          transmission of hello packets from non-blocking
+                          interfaces on this bridge. The configured frequency is
+                          returned in field ifbrp_hellotime.  
+
+     SIOCBRDGSHT          (struct ifbrparam) Set the frequency of transmission
+                          of hello packets to the value specified in field
+                          ifbrp_hellotime. The specified value should be greater
+                          than 0, else EINVAL is returned.
+
+     SIOCBRDGGFD          (struct ifbrparam) Get the forwarding delay time 
+                          associated with ports/interfaces on this bridge. The
+                          forwarding delay time is the time taken by a port
+                          to transit from one state to other (for eg. from 
+                          LEARNING state to FORWARDING state). The configured
+                          value if returned in field ifbrp_fwddelay.
+
+     SIOCBRDGSFD          (struct ifbrparam) Set the forwarding delay for ports
+                          attached to this bridge to a value specified in 
+                          field ifbrp_fwddelay. The specified value should be
+                          greater than 0, else EINVAL is returned.
+
+     SIOCBRDGGMA          (struct ifbrparam) Get aging timeout values of 
+                          spanning data. The timeout value is returned in field
+                          ifbrp_maxage. 
+
+     SIOCBRDGSMA          (struct ifbrparam) Set the aging timeout value of 
+                          BPDUs to the value specified in ifbrp_maxage. The 
+                          specified value should be greater than 0, else 
+                          EINVAL is returned.
+
+     SIOCBRDGSIFPRIO      (struct ifbreq) Set the priority of specified 
+                          interface to the value given in field ifbr_priority.
+
+     SIOCBRDGSIFCOST      (struct ifbreq) Set the cost associated with the 
+                          given interface to the value specified in field 
+                          ifbr_path_cost.
+
+
+ERRORS
+     Same as the ones specified for <link linkend="openbsd-manpages-bridge">bridge</link>.
+
+SEE ALSO
+     <link linkend="openbsd-manpages-netintro">netintro</link>, <link linkend="openbsd-manpages-bridge">bridge</link>
+
+</SCREEN>
+</SECT1>
+
+<!-- Keep this comment at the end of the file
+Local variables:
+mode: sgml
+sgml-omittag:nil
+sgml-shorttag:t
+sgml-namecase-general:t
+sgml-general-insert-case:lower
+sgml-minimize-attributes:nil
+sgml-always-quote-attributes:t
+sgml-indent-step:2
+sgml-indent-data:t
+sgml-parent-document:("tcpip.sgml" "book" "chapter")
+sgml-exposed-tags:nil
+sgml-local-catalogs:nil
+sgml-local-ecat-files:nil
+sgml-doctype:"book"
+End:
+-->
+
--- a/packages/net/tcpip/current/doc/openbsd.sgml
+++ b/packages/net/tcpip/current/doc/openbsd.sgml
@@ -42,6 +42,8 @@
 
 <CHAPTER id="tcpip-openbsd-networking-stack-features">
 <TITLE>Networking Stack Features</TITLE>
+<SECT1 id="tcpip-openbsd-tcpip-features">
+<TITLE>Introduction</TITLE>
 <PARA>Since this networking package is based on BSD code, it is
 very complete and robust.  The eCos implementation includes support
 for the following protocols:   </PARA>
@@ -52,14 +54,18 @@ for the following protocols:   </PARA>
 <LISTITEM><PARA>ICMP</para></listitem>
 <LISTITEM><PARA>raw packet interface</para></listitem>
 </itemizedlist>
-<PARA>These additional features are also present in the package,
+<PARA>Along with support for the above mentioned protocols, the OpenBSD
+stack also supports ethernet bridging.
+</PARA>
+<PARA>The following additional features are also present in the package,
 	but are not supported:</PARA>
 <itemizedlist>
 <LISTITEM><PARA>Berkeley Packet Filter   </PARA></LISTITEM>
-<LISTITEM><PARA>Multi-cast and uni-cast support, including multi-casting
+<LISTITEM><PARA>Multi-cast and uni-cast support, including multi-cast
 routing   </PARA></LISTITEM>
 <LISTITEM><PARA>IPv6 </PARA></LISTITEM>
       </itemizedlist>
+</SECT1>
 </CHAPTER>
 <CHAPTER id="tcpip-openbsd-stack-port">
 <TITLE>OpenBSD TCP/IP stack port</TITLE>
@@ -113,6 +119,25 @@ networking tests (demo programs)&rdquo; 
 support build options&rdquo;.</PARA>
 </NOTE>
 </SECT1>
+<SECT1 id="tcpip-openbsd-building-the-bridge-code">
+<TITLE>Inclusion of bridge code</TITLE>
+
+<PARA>The OpenBSD stack does not by default result in the inclusion of
+the bridge code. To include bridging functionality the CDL option
+CYGPKG_NET_BRIDGE must be enable . It is also possible to enable more
+than one concurrent bridge. The number of bridges active in a device
+is configured by the CDL option CYGNUM_NET_BRIDGES, which has a
+default value of 1.</PARA>
+
+<PARA>The default behavior of a bridge is to operate without the
+spanning tree protocol. When devices are operated in this default mode
+it must be ensured the network topology is loop-free. Any loops will
+cause broadcast storms and general mayhem on the network.  Including
+spanning tree code during the build process will allow the bridge to
+communicate with other bridges. They can then detect such loops and by
+disabling selected interfaces break the loop. To enable spanning tree enable
+the CDL option CYGPKG_NET_BRIDGE_STP_CODE.</PARA>
+</SECT1>
 </CHAPTER>
 <CHAPTER id="tcpip-openbsd-tcpip-apis">
 <TITLE>APIs</TITLE>
@@ -189,5 +214,8 @@ void <function>cyg_select_abort</functio
 <function>cyg_select_with_abort()</function> call
 to cease waiting and continue execution.</PARA>
 </SECT1>
+&net-tcpip-openbsd-manpages-netintro-sgml
+&net-tcpip-openbsd-manpages-bridge-sgml
+&net-tcpip-openbsd-manpages-stp-sgml
 </CHAPTER>
 </PART>
--- a/packages/net/tcpip/current/include/net/if.h
+++ b/packages/net/tcpip/current/include/net/if.h
@@ -256,6 +256,19 @@ struct ifnet {				/* and the entries */
 }
 #define	IF_IS_EMPTY(ifq)	((ifq)->ifq_len == 0)
 
+#define IFQ_ENQUEUE(ifq, m, pattr, err)                                 \
+do {                                                                    \
+        if (IF_QFULL((ifq))) {                                          \
+                m_freem((m));                                           \
+                (err) = ENOBUFS;                                        \
+        } else {                                                        \
+                IF_ENQUEUE((ifq), (m));                                 \
+                (err) = 0;                                              \
+        }                                                               \
+        if ((err))                                                      \
+                (ifq)->ifq_drops++;                                     \
+} while (0)
+
 #define	IFQ_MAXLEN	50
 #define	IFNET_SLOWHZ	1		/* granularity is 1 second */
 
--- a/packages/net/tcpip/current/include/net/if_bridge.h
+++ b/packages/net/tcpip/current/include/net/if_bridge.h
@@ -19,7 +19,7 @@
 //#####DESCRIPTIONBEGIN####
 //
 // Author(s):    Jason L. Wright (jason@thought.net)
-// Contributors: andrew.lunn@ascom.ch (Andrew Lunn), hmt
+// Contributors: andrew.lunn@ascom.ch (Andrew Lunn), hmt, manu.sharma@ascom.ch
 // Date:         2000-07-18
 // Purpose:      Ethernet bridge
 // Description:  
@@ -29,8 +29,7 @@
 //
 //==========================================================================
 
-
-/*	$OpenBSD: if_bridge.h,v 1.12 2000/01/25 22:06:27 jason Exp $	*/
+/*      $OpenBSD: if_bridge.h,v 1.25 2003/07/15 03:41:15 jason Exp $        */
 
 /*
  * Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net)
@@ -44,11 +43,6 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by Jason L. Wright
- * 4. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
@@ -61,64 +55,101 @@
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Effort sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F30602-01-2-0537.
+ *
  */
 
 /*
  * Bridge control request: add/delete member interfaces.
  */
 struct ifbreq {
-	char		ifbr_name[IFNAMSIZ];	/* bridge ifs name */
-	char		ifbr_ifsname[IFNAMSIZ];	/* member ifs name */
-	u_int32_t	ifbr_ifsflags;		/* member ifs flags */
+        char            ifbr_name[IFNAMSIZ];       /* bridge ifs name */
+        char            ifbr_ifsname[IFNAMSIZ];    /* member ifs name */
+        u_int32_t       ifbr_ifsflags;             /* member ifs flags */
+        u_int8_t        ifbr_state;                /* member stp state */
+        u_int8_t        ifbr_priority;             /* member stp priority */
+        u_int8_t        ifbr_portno;               /* member port number */
+        u_int32_t       ifbr_path_cost;            /* member stp path cost */
 };
 /* SIOCBRDGIFFLGS, SIOCBRDGIFFLGS */
-#define	IFBIF_LEARNING	0x1	/* ifs can learn */
-#define	IFBIF_DISCOVER	0x2	/* ifs sends packets w/unknown dest */
-#define IFBIF_BLOCKNONIP 0x04	/* ifs blocks non-IP/ARP traffic in/out */
+#define IFBIF_LEARNING          0x0001        /* ifs can learn */
+#define IFBIF_DISCOVER          0x0002        /* ifs sends packets w/unknown dest */
+#define IFBIF_BLOCKNONIP        0x0004        /* ifs blocks non-IP/ARP in/out */
+#define IFBIF_STP               0x0008        /* ifs participates in spanning tree */
+#define IFBIF_SPAN              0x0100        /* ifs is a span port (ro) */
+#define IFBIF_RO_MASK           0xff00        /* read only bits */
 /* SIOCBRDGFLUSH */
-#define	IFBF_FLUSHDYN	0x0	/* flush dynamic addresses only */
-#define	IFBF_FLUSHALL	0x1	/* flush all addresses from cache */
+#define IFBF_FLUSHDYN        0x0        /* flush dynamic addresses only */
+#define IFBF_FLUSHALL        0x1        /* flush all addresses from cache */
+
+/* port states */
+#define BSTP_IFSTATE_DISABLED        0
+#define BSTP_IFSTATE_LISTENING       1
+#define BSTP_IFSTATE_LEARNING        2
+#define BSTP_IFSTATE_FORWARDING      3
+#define BSTP_IFSTATE_BLOCKING        4
 
 /*
  * Interface list structure
  */
 struct ifbifconf {
-	char		ifbic_name[IFNAMSIZ];	/* bridge ifs name */
-	u_int32_t	ifbic_len;		/* buffer size */
-	union {
-		caddr_t	ifbicu_buf;
-		struct	ifbreq *ifbicu_req;
-	} ifbic_ifbicu;
-#define	ifbic_buf	ifbic_ifbicu.ifbicu_buf
-#define	ifbic_req	ifbic_ifbicu.ifbicu_req
+        char             ifbic_name[IFNAMSIZ];        /* bridge ifs name */
+        u_int32_t        ifbic_len;                /* buffer size */
+        union {
+                caddr_t       ifbicu_buf;
+                struct        ifbreq *ifbicu_req;
+        } ifbic_ifbicu;
+#define ifbic_buf        ifbic_ifbicu.ifbicu_buf
+#define ifbic_req        ifbic_ifbicu.ifbicu_req
 };
 
 /*
  * Bridge address request
  */
 struct ifbareq {
-	char			ifba_name[IFNAMSIZ];	/* bridge name */
-	char			ifba_ifsname[IFNAMSIZ];	/* destination ifs */
-	u_int8_t		ifba_age;		/* address age */
-	u_int8_t		ifba_flags;		/* address flags */
-	struct ether_addr	ifba_dst;		/* destination addr */
+        char                    ifba_name[IFNAMSIZ];     /* bridge name */
+        char                    ifba_ifsname[IFNAMSIZ];  /* destination ifs */
+        u_int8_t                ifba_age;                /* address age */
+        u_int8_t                ifba_flags;              /* address flags */
+        struct ether_addr       ifba_dst;                /* destination addr */
 };
 
-#define	IFBAF_TYPEMASK		0x03		/* address type mask */
-#define	IFBAF_DYNAMIC		0x00		/* dynamically learned */
-#define	IFBAF_STATIC		0x01		/* static address */
+#define IFBAF_TYPEMASK              0x03                /* address type mask */
+#define IFBAF_DYNAMIC               0x00                /* dynamically learned */
+#define IFBAF_STATIC                0x01                /* static address */
 
 struct ifbaconf {
-	char			ifbac_name[IFNAMSIZ];	/* bridge ifs name */
-	u_int32_t		ifbac_len;		/* buffer size */
-	union {
-		caddr_t	ifbacu_buf;			/* buffer */
-		struct ifbareq *ifbacu_req;		/* request pointer */
-	} ifbac_ifbacu;
-#define	ifbac_buf	ifbac_ifbacu.ifbacu_buf
-#define	ifbac_req	ifbac_ifbacu.ifbacu_req
+        char                     ifbac_name[IFNAMSIZ];     /* bridge ifs name */
+        u_int32_t                ifbac_len;                /* buffer size */
+        union {
+                caddr_t        ifbacu_buf;                 /* buffer */
+                struct ifbareq *ifbacu_req;                /* request pointer */
+        } ifbac_ifbacu;
+#define ifbac_buf        ifbac_ifbacu.ifbacu_buf
+#define ifbac_req        ifbac_ifbacu.ifbacu_req
 };
 
+struct ifbrparam {
+        char                        ifbrp_name[IFNAMSIZ];
+        union {
+                u_int32_t       ifbrpu_csize;           /* cache size */
+                int             ifbrpu_ctime;           /* cache time (sec) */
+                u_int16_t       ifbrpu_prio;            /* bridge priority */
+                u_int8_t        ifbrpu_hellotime;       /* hello time (sec) */
+                u_int8_t        ifbrpu_fwddelay;        /* fwd delay (sec) */
+                u_int8_t        ifbrpu_maxage;          /* max age (sec) */
+        } ifbrp_ifbrpu;
+};
+#define ifbrp_csize       ifbrp_ifbrpu.ifbrpu_csize
+#define ifbrp_ctime       ifbrp_ifbrpu.ifbrpu_ctime
+#define ifbrp_prio        ifbrp_ifbrpu.ifbrpu_prio
+#define ifbrp_hellotime   ifbrp_ifbrpu.ifbrpu_hellotime
+#define ifbrp_fwddelay    ifbrp_ifbrpu.ifbrpu_fwddelay
+#define ifbrp_maxage      ifbrp_ifbrpu.ifbrpu_maxage
+
 /*
  * Bridge cache size get/set
  */
@@ -139,36 +170,153 @@ struct ifbcachetoreq {
  * Bridge mac rules
  */
 struct ifbrlreq {
-	char			ifbr_name[IFNAMSIZ];	/* bridge ifs name */
-	char			ifbr_ifsname[IFNAMSIZ];	/* member ifs name */
-	u_int8_t		ifbr_action;		/* disposition */
-	u_int8_t		ifbr_flags;		/* flags */
-	struct ether_addr	ifbr_src;		/* source mac */
-	struct ether_addr	ifbr_dst;		/* destination mac */
+        char                    ifbr_name[IFNAMSIZ];     /* bridge ifs name */
+        char                    ifbr_ifsname[IFNAMSIZ];  /* member ifs name */
+        u_int8_t                ifbr_action;             /* disposition */
+        u_int8_t                ifbr_flags;              /* flags */
+        struct ether_addr       ifbr_src;                /* source mac */
+        struct ether_addr       ifbr_dst;                /* destination mac */
 };
-#define	BRL_ACTION_BLOCK	0x01			/* block frame */
-#define	BRL_ACTION_PASS		0x02			/* pass frame */
-#define	BRL_FLAG_IN		0x08			/* input rule */
-#define	BRL_FLAG_OUT		0x04			/* output rule */
-#define	BRL_FLAG_SRCVALID	0x02			/* src valid */
-#define	BRL_FLAG_DSTVALID	0x01			/* dst valid */
+#define BRL_ACTION_BLOCK         0x01                        /* block frame */
+#define BRL_ACTION_PASS          0x02                        /* pass frame */
+#define BRL_FLAG_IN              0x08                        /* input rule */
+#define BRL_FLAG_OUT             0x04                        /* output rule */
+#define BRL_FLAG_SRCVALID        0x02                        /* src valid */
+#define BRL_FLAG_DSTVALID        0x01                        /* dst valid */
 
 struct ifbrlconf {
-	char		ifbrl_name[IFNAMSIZ];	/* bridge ifs name */
-	char		ifbrl_ifsname[IFNAMSIZ];/* member ifs name */
-	u_int32_t	ifbrl_len;		/* buffer size */
-	union {
-		caddr_t	ifbrlu_buf;
-		struct	ifbrlreq *ifbrlu_req;
-	} ifbrl_ifbrlu;
-#define	ifbrl_buf	ifbrl_ifbrlu.ifbrlu_buf
-#define	ifbrl_req	ifbrl_ifbrlu.ifbrlu_req
+        char             ifbrl_name[IFNAMSIZ];    /* bridge ifs name */
+        char             ifbrl_ifsname[IFNAMSIZ]; /* member ifs name */
+        u_int32_t        ifbrl_len;               /* buffer size */
+        union {
+                caddr_t        ifbrlu_buf;
+                struct        ifbrlreq *ifbrlu_req;
+        } ifbrl_ifbrlu;
+#define ifbrl_buf        ifbrl_ifbrlu.ifbrlu_buf
+#define ifbrl_req        ifbrl_ifbrlu.ifbrlu_req
+};
+
+/*
+ * Bridge filtering rules
+ */
+SIMPLEQ_HEAD(brl_head, brl_node);
+
+struct brl_node {
+        SIMPLEQ_ENTRY(brl_node)        brl_next;        /* next rule */
+        struct ether_addr        brl_src;        /* source mac address */
+        struct ether_addr        brl_dst;        /* destination mac address */
+        u_int16_t                brl_tag;        /* pf tag ID */
+        u_int8_t                brl_action;        /* what to do with match */
+        u_int8_t                brl_flags;        /* comparision flags */
+};
+
+struct bridge_timer {
+        u_int16_t active;
+        u_int16_t value;
+};
+
+struct bstp_config_unit {
+        u_int64_t        cu_rootid;
+        u_int64_t        cu_bridge_id;
+        u_int32_t        cu_root_path_cost;
+        u_int16_t        cu_message_age;
+        u_int16_t        cu_max_age;
+        u_int16_t        cu_hello_time;
+        u_int16_t        cu_forward_delay;
+        u_int16_t        cu_port_id;
+        u_int8_t        cu_message_type;
+        u_int8_t        cu_topology_change_acknowledgment;
+        u_int8_t        cu_topology_change;
+};
+
+struct bstp_tcn_unit {
+        u_int8_t        tu_message_type;
+};
+
+/*
+ * Bridge interface list
+ */
+struct bridge_iflist {
+        LIST_ENTRY(bridge_iflist)        next;                /* next in list */
+        u_int64_t                        bif_designated_root;
+        u_int64_t                        bif_designated_bridge;
+        u_int32_t                        bif_path_cost;
+        u_int32_t                        bif_designated_cost;
+        struct bridge_timer                bif_hold_timer;
+        struct bridge_timer                bif_message_age_timer;
+        struct bridge_timer                bif_forward_delay_timer;
+        struct bstp_config_unit                bif_config_bpdu;
+        u_int16_t                        bif_port_id;
+        u_int16_t                        bif_designated_port;
+        u_int8_t                        bif_state;
+        u_int8_t                        bif_topology_change_acknowledge;
+        u_int8_t                        bif_config_pending;
+        u_int8_t                        bif_change_detection_enabled;
+        u_int8_t                        bif_priority;
+        struct brl_head                        bif_brlin;        /* input rules */
+        struct brl_head                        bif_brlout;        /* output rules */
+        struct                                ifnet *ifp;        /* member interface */
+        u_int32_t                        bif_flags;        /* member flags */
+};
+
+/*
+ * Bridge route node
+ */
+struct bridge_rtnode {
+        LIST_ENTRY(bridge_rtnode)        brt_next;        /* next in list */
+        struct                                ifnet *brt_if;        /* destination ifs */
+        u_int8_t                        brt_flags;        /* address flags */
+        u_int8_t                        brt_age;        /* age counter */
+        struct                                ether_addr brt_addr;        /* dst addr */
+};
+
+/*
+ * Software state for each bridge
+ */
+struct bridge_softc {
+        struct                     ifnet sc_if;        /* the interface */
+        u_int64_t                  sc_designated_root;
+        u_int64_t                  sc_bridge_id;
+        struct bridge_iflist       *sc_root_port;
+        u_int32_t                  sc_root_path_cost;
+        u_int16_t                  sc_max_age;
+        u_int16_t                  sc_hello_time;
+        u_int16_t                  sc_forward_delay;
+        u_int16_t                  sc_bridge_max_age;
+        u_int16_t                  sc_bridge_hello_time;
+        u_int16_t                  sc_bridge_forward_delay;
+        u_int16_t                  sc_topology_change_time;
+        u_int16_t                  sc_hold_time;
+        u_int16_t                  sc_bridge_priority;
+        u_int8_t                   sc_topology_change_detected;
+        u_int8_t                   sc_topology_change;
+        struct bridge_timer        sc_hello_timer;
+        struct bridge_timer        sc_topology_change_timer;
+        struct bridge_timer        sc_tcn_timer;
+        u_int32_t                  sc_brtmax;        /* max # addresses */
+        u_int32_t                  sc_brtcnt;        /* current # addrs */
+        int                        sc_brttimeout;        /* timeout ticks */
+        u_int32_t                  sc_hashkey;        /* hash key */
+#ifndef __ECOS
+        struct timeout             sc_brtimeout;        /* timeout state */
+        struct timeout             sc_bstptimeout;        /* stp timeout */
+#endif
+        LIST_HEAD(, bridge_iflist)        sc_iflist;        /* interface list */
+        LIST_HEAD(bridge_rthead, bridge_rtnode)        *sc_rts;/* hash table */
+        LIST_HEAD(, bridge_iflist)        sc_spanlist;        /* span ports */
 };
 
 #ifdef _KERNEL
-void	bridge_ifdetach __P((struct ifnet *));
-struct mbuf *bridge_input __P((struct ifnet *, struct ether_header *,
-    struct mbuf *));
-int	bridge_output __P((struct ifnet *, struct mbuf *, struct sockaddr *,
-    struct rtentry *rt));
+extern u_int8_t bstp_etheraddr[];
+
+void    bridge_ifdetach(struct ifnet *);
+struct mbuf *bridge_input(struct ifnet *, struct ether_header *,
+                    struct mbuf *);
+int     bridge_output(struct ifnet *, struct mbuf *, struct sockaddr *,
+                    struct rtentry *);
+struct mbuf *bstp_input(struct bridge_softc *, struct ifnet *,
+                    struct ether_header *, struct mbuf *);
+void    bstp_initialization(struct bridge_softc *);
+int     bstp_ioctl(struct ifnet *, u_long, caddr_t);
+void    bridge_rtdelete(struct bridge_softc *, struct ifnet *, int);
 #endif /* _KERNEL */
--- a/packages/net/tcpip/current/include/net/if_llc.h
+++ b/packages/net/tcpip/current/include/net/if_llc.h
@@ -30,12 +30,12 @@
 //==========================================================================
 
 
-/*	$OpenBSD: if_llc.h,v 1.3 1999/07/28 20:02:41 fgsch Exp $	*/
-/*	$NetBSD: if_llc.h,v 1.6 1995/03/08 02:56:57 cgd Exp $	*/
+/*      $OpenBSD: if_llc.h,v 1.3 1999/07/28 20:02:41 fgsch Exp $        */
+/*      $NetBSD: if_llc.h,v 1.6 1995/03/08 02:56:57 cgd Exp $   */
 
 /*
  * Copyright (c) 1988, 1993
- *	The Regents of the University of California.  All rights reserved.
+ *      The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -47,8 +47,8 @@
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
+ *      This product includes software developed by the University of
+ *      California, Berkeley and its contributors.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
@@ -65,7 +65,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)if_llc.h	8.1 (Berkeley) 6/10/93
+ *      @(#)if_llc.h    8.1 (Berkeley) 6/10/93
  */
 
 #ifndef _NET_IF_LLC_H_
@@ -80,101 +80,102 @@
  */
 
 struct llc {
-	u_int8_t llc_dsap;
-	u_int8_t llc_ssap;
-	union {
-	    struct {
-		u_int8_t control;
-		u_int8_t format_id;
-		u_int8_t class;
-		u_int8_t window_x2;
-	    } type_u;
-	    struct {
-		u_int8_t num_snd_x2;
-		u_int8_t num_rcv_x2;
-	    } type_i;
-	    struct {
-		u_int8_t control;
-		u_int8_t num_rcv_x2;
-	    } type_s;
-	    struct {
-	        u_int8_t control;
-		struct frmrinfo {
-			u_int8_t rej_pdu_0;
-			u_int8_t rej_pdu_1;
-			u_int8_t frmr_control;
-			u_int8_t frmr_control_ext;
-			u_int8_t frmr_cause;
-		} frmrinfo;
-	    } type_frmr;
-	    struct {
-		u_int8_t  control;
-		u_int8_t  org_code[3];
-		u_int16_t ether_type;
-	    } type_snap;
-	    struct {
-		u_int8_t control;
-		u_int8_t control_ext;
-	    } type_raw;
-	} llc_un;
+        u_int8_t llc_dsap;
+        u_int8_t llc_ssap;
+        union {
+            struct {
+                u_int8_t control;
+                u_int8_t format_id;
+                u_int8_t class;
+                u_int8_t window_x2;
+            } type_u;
+            struct {
+                u_int8_t num_snd_x2;
+                u_int8_t num_rcv_x2;
+            } type_i;
+            struct {
+                u_int8_t control;
+                u_int8_t num_rcv_x2;
+            } type_s;
+            struct {
+                u_int8_t control;
+                struct frmrinfo {
+                        u_int8_t rej_pdu_0;
+                        u_int8_t rej_pdu_1;
+                        u_int8_t frmr_control;
+                        u_int8_t frmr_control_ext;
+                        u_int8_t frmr_cause;
+                } frmrinfo;
+            } type_frmr;
+            struct {
+                u_int8_t  control;
+                u_int8_t  org_code[3];
+                u_int16_t ether_type;
+            } type_snap;
+            struct {
+                u_int8_t control;
+                u_int8_t control_ext;
+            } type_raw;
+        } llc_un;
 };
-#define	llc_control            llc_un.type_u.control
-#define	llc_control_ext        llc_un.type_raw.control_ext
-#define	llc_fid                llc_un.type_u.format_id
-#define	llc_class              llc_un.type_u.class
-#define	llc_window             llc_un.type_u.window_x2
-#define	llc_frmrinfo           llc_un.type_frmr.frmrinfo
-#define	llc_frmr_pdu0          llc_un.type_frmr.frmrinfo.rej_pdu0
-#define	llc_frmr_pdu1          llc_un.type_frmr.frmrinfo.rej_pdu1
-#define	llc_frmr_control       llc_un.type_frmr.frmrinfo.frmr_control
-#define	llc_frmr_control_ext   llc_un.type_frmr.frmrinfo.frmr_control_ext
-#define	llc_frmr_cause         llc_un.type_frmr.frmrinfo.frmr_control_ext
+#define llc_control            llc_un.type_u.control
+#define llc_control_ext        llc_un.type_raw.control_ext
+#define llc_fid                llc_un.type_u.format_id
+#define llc_class              llc_un.type_u.class
+#define llc_window             llc_un.type_u.window_x2
+#define llc_frmrinfo           llc_un.type_frmr.frmrinfo
+#define llc_frmr_pdu0          llc_un.type_frmr.frmrinfo.rej_pdu0
+#define llc_frmr_pdu1          llc_un.type_frmr.frmrinfo.rej_pdu1
+#define llc_frmr_control       llc_un.type_frmr.frmrinfo.frmr_control
+#define llc_frmr_control_ext   llc_un.type_frmr.frmrinfo.frmr_control_ext
+#define llc_frmr_cause         llc_un.type_frmr.frmrinfo.frmr_control_ext
 
 /*
  * Don't use sizeof(struct llc_un) for LLC header sizes
  */
-#define	LLC_UFRAMELEN		3
-#define	LLC_ISFRAMELEN		4
-#define	LLC_FRMRLEN		7
-#define	LLC_SNAPFRAMELEN	8
+#define LLC_UFRAMELEN           3
+#define LLC_ISFRAMELEN          4
+#define LLC_FRMRLEN             7
+#define LLC_SNAPFRAMELEN        8
 
 /*
  * Unnumbered LLC format commands
  */
-#define	LLC_UI		0x3
-#define	LLC_UI_P	0x13
-#define	LLC_DISC	0x43
-#define	LLC_DISC_P	0x53
-#define	LLC_UA		0x63
-#define	LLC_UA_P	0x73
-#define	LLC_TEST	0xe3
-#define	LLC_TEST_P	0xf3
-#define	LLC_FRMR	0x87
-#define	LLC_FRMR_P	0x97
-#define	LLC_DM		0x0f
-#define	LLC_DM_P	0x1f
-#define	LLC_XID		0xaf
-#define	LLC_XID_P	0xbf
-#define	LLC_SABME	0x6f
-#define	LLC_SABME_P	0x7f
+#define LLC_UI          0x3
+#define LLC_UI_P        0x13
+#define LLC_DISC        0x43
+#define LLC_DISC_P      0x53
+#define LLC_UA          0x63
+#define LLC_UA_P        0x73
+#define LLC_TEST        0xe3
+#define LLC_TEST_P      0xf3
+#define LLC_FRMR        0x87
+#define LLC_FRMR_P      0x97
+#define LLC_DM          0x0f
+#define LLC_DM_P        0x1f
+#define LLC_XID         0xaf
+#define LLC_XID_P       0xbf
+#define LLC_SABME       0x6f
+#define LLC_SABME_P     0x7f
 
 /*
  * Supervisory LLC commands
  */
-#define	LLC_RR		0x01
-#define	LLC_RNR		0x05
-#define	LLC_REJ		0x09
+#define LLC_RR          0x01
+#define LLC_RNR         0x05
+#define LLC_REJ         0x09
 
 /*
  * Info format - dummy only
  */
-#define	LLC_INFO	0x00
+#define LLC_INFO        0x00
 
 /*
  * ISO PDTR 10178 contains among others
  */
-#define	LLC_X25_LSAP	0x7e
-#define	LLC_SNAP_LSAP	0xaa
-#define	LLC_ISO_LSAP	0xfe
+#define LLC_8021D_LSAP  0x42
+#define LLC_X25_LSAP    0x7e
+#define LLC_SNAP_LSAP   0xaa
+#define LLC_ISO_LSAP    0xfe
 
 #endif // _NET_IF_LLC_H_
--- a/packages/net/tcpip/current/include/sys/sockio.h
+++ b/packages/net/tcpip/current/include/sys/sockio.h
@@ -30,12 +30,12 @@
 //==========================================================================
 
 
-/*	$OpenBSD: sockio.h,v 1.10 1999/12/08 06:50:24 itojun Exp $	*/
-/*	$NetBSD: sockio.h,v 1.5 1995/08/23 00:40:47 thorpej Exp $	*/
+/*      $OpenBSD: sockio.h,v 1.10 1999/12/08 06:50:24 itojun Exp $      */
+/*      $NetBSD: sockio.h,v 1.5 1995/08/23 00:40:47 thorpej Exp $       */
 
 /*-
  * Copyright (c) 1982, 1986, 1990, 1993, 1994
- *	The Regents of the University of California.  All rights reserved.
+ *      The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -47,8 +47,8 @@
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
+ *      This product includes software developed by the University of
+ *      California, Berkeley and its contributors.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
@@ -65,100 +65,113 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)sockio.h	8.1 (Berkeley) 3/28/94
+ *      @(#)sockio.h    8.1 (Berkeley) 3/28/94
  */
 
-#ifndef	_SYS_SOCKIO_H_
-#define	_SYS_SOCKIO_H_
+#ifndef _SYS_SOCKIO_H_
+#define _SYS_SOCKIO_H_
 
 #include <sys/ioccom.h>
 
 /* Socket ioctl's. */
-#define	SIOCSHIWAT	 _IOW('s',  0, int)		/* set high watermark */
-#define	SIOCGHIWAT	 _IOR('s',  1, int)		/* get high watermark */
-#define	SIOCSLOWAT	 _IOW('s',  2, int)		/* set low watermark */
-#define	SIOCGLOWAT	 _IOR('s',  3, int)		/* get low watermark */
-#define	SIOCATMARK	 _IOR('s',  7, int)		/* at oob mark? */
-#define	SIOCSPGRP	 _IOW('s',  8, int)		/* set process group */
-#define	SIOCGPGRP	 _IOR('s',  9, int)		/* get process group */
+#define SIOCSHIWAT       _IOW('s',  0, int)             /* set high watermark */
+#define SIOCGHIWAT       _IOR('s',  1, int)             /* get high watermark */
+#define SIOCSLOWAT       _IOW('s',  2, int)             /* set low watermark */
+#define SIOCGLOWAT       _IOR('s',  3, int)             /* get low watermark */
+#define SIOCATMARK       _IOR('s',  7, int)             /* at oob mark? */
+#define SIOCSPGRP        _IOW('s',  8, int)             /* set process group */
+#define SIOCGPGRP        _IOR('s',  9, int)             /* get process group */
 
 #ifdef __ECOS
-#define	SIOCADDRT	 _IOW('r', 10, struct ecos_rtentry)	/* add route */
-#define	SIOCDELRT	 _IOW('r', 11, struct ecos_rtentry)	/* delete route */
+#define SIOCADDRT        _IOW('r', 10, struct ecos_rtentry)     /* add route */
+#define SIOCDELRT        _IOW('r', 11, struct ecos_rtentry)     /* delete route */
 #else
-#define	SIOCADDRT	 _IOW('r', 10, struct ortentry)	/* add route */
-#define	SIOCDELRT	 _IOW('r', 11, struct ortentry)	/* delete route */
+#define SIOCADDRT        _IOW('r', 10, struct ortentry) /* add route */
+#define SIOCDELRT        _IOW('r', 11, struct ortentry) /* delete route */
 #endif
 
-#define	SIOCSIFADDR	 _IOW('i', 12, struct ifreq)	/* set ifnet address */
-#define	OSIOCGIFADDR	_IOWR('i', 13, struct ifreq)	/* get ifnet address */
-#define	SIOCGIFADDR	_IOWR('i', 33, struct ifreq)	/* get ifnet address */
-#define	SIOCGIFHWADDR	_IOWR('i', 15, struct ifreq)	/* get MAC address */
+#define SIOCSIFADDR      _IOW('i', 12, struct ifreq)    /* set ifnet address */
+#define OSIOCGIFADDR    _IOWR('i', 13, struct ifreq)    /* get ifnet address */
+#define SIOCGIFADDR     _IOWR('i', 33, struct ifreq)    /* get ifnet address */
+#define SIOCGIFHWADDR   _IOWR('i', 15, struct ifreq)    /* get MAC address */
 #ifdef __ECOS
-#define	SIOCSIFHWADDR	 _IOW('i',101, struct ifreq)	/* set MAC address */
+#define SIOCSIFHWADDR    _IOW('i',101, struct ifreq)    /* set MAC address */
 /* NB these two take a struct ifreq followed by the useful data */
 #define SIOCGIFSTATSUD  _IOWR('i',102, struct ifreq)    /* get uptodate if stats */
 #define SIOCGIFSTATS    _IOWR('i',103, struct ifreq)    /* get interface stats */
 #endif
-#define	SIOCSIFDSTADDR	 _IOW('i', 14, struct ifreq)	/* set p-p address */
-#define	OSIOCGIFDSTADDR	_IOWR('i', 15, struct ifreq)	/* get p-p address */
-#define	SIOCGIFDSTADDR	_IOWR('i', 34, struct ifreq)	/* get p-p address */
-#define	SIOCSIFFLAGS	 _IOW('i', 16, struct ifreq)	/* set ifnet flags */
-#define	SIOCGIFFLAGS	_IOWR('i', 17, struct ifreq)	/* get ifnet flags */
-#define	OSIOCGIFBRDADDR	_IOWR('i', 18, struct ifreq)	/* get broadcast addr */
-#define	SIOCGIFBRDADDR	_IOWR('i', 35, struct ifreq)	/* get broadcast addr */
-#define	SIOCSIFBRDADDR	 _IOW('i', 19, struct ifreq)	/* set broadcast addr */
-#define	OSIOCGIFCONF	_IOWR('i', 20, struct ifconf)	/* get ifnet list */
-#define	SIOCGIFCONF	_IOWR('i', 36, struct ifconf)	/* get ifnet list */
-#define	OSIOCGIFNETMASK	_IOWR('i', 21, struct ifreq)	/* get net addr mask */
-#define	SIOCGIFNETMASK	_IOWR('i', 37, struct ifreq)	/* get net addr mask */
-#define	SIOCSIFNETMASK	 _IOW('i', 22, struct ifreq)	/* set net addr mask */
-#define	SIOCGIFMETRIC	_IOWR('i', 23, struct ifreq)	/* get IF metric */
-#define	SIOCSIFMETRIC	 _IOW('i', 24, struct ifreq)	/* set IF metric */
-#define	SIOCDIFADDR	 _IOW('i', 25, struct ifreq)	/* delete IF addr */
-#define	SIOCAIFADDR	 _IOW('i', 26, struct ifaliasreq)/* add/chg IF alias */
-#define	SIOCGIFDATA	_IOWR('i', 27, struct ifreq)	/* get if_data */
+#define SIOCSIFDSTADDR   _IOW('i', 14, struct ifreq)    /* set p-p address */
+#define OSIOCGIFDSTADDR _IOWR('i', 15, struct ifreq)    /* get p-p address */
+#define SIOCGIFDSTADDR  _IOWR('i', 34, struct ifreq)    /* get p-p address */
+#define SIOCSIFFLAGS     _IOW('i', 16, struct ifreq)    /* set ifnet flags */
+#define SIOCGIFFLAGS    _IOWR('i', 17, struct ifreq)    /* get ifnet flags */
+#define OSIOCGIFBRDADDR _IOWR('i', 18, struct ifreq)    /* get broadcast addr */
+#define SIOCGIFBRDADDR  _IOWR('i', 35, struct ifreq)    /* get broadcast addr */
+#define SIOCSIFBRDADDR   _IOW('i', 19, struct ifreq)    /* set broadcast addr */
+#define OSIOCGIFCONF    _IOWR('i', 20, struct ifconf)   /* get ifnet list */
+#define SIOCGIFCONF     _IOWR('i', 36, struct ifconf)   /* get ifnet list */
+#define OSIOCGIFNETMASK _IOWR('i', 21, struct ifreq)    /* get net addr mask */
+#define SIOCGIFNETMASK  _IOWR('i', 37, struct ifreq)    /* get net addr mask */
+#define SIOCSIFNETMASK   _IOW('i', 22, struct ifreq)    /* set net addr mask */
+#define SIOCGIFMETRIC   _IOWR('i', 23, struct ifreq)    /* get IF metric */
+#define SIOCSIFMETRIC    _IOW('i', 24, struct ifreq)    /* set IF metric */
+#define SIOCDIFADDR      _IOW('i', 25, struct ifreq)    /* delete IF addr */
+#define SIOCAIFADDR      _IOW('i', 26, struct ifaliasreq)/* add/chg IF alias */
+#define SIOCGIFDATA     _IOWR('i', 27, struct ifreq)    /* get if_data */
 
 /* KAME IPv6 */
 /* SIOCAIFALIAS? */
-#define SIOCALIFADDR	 _IOW('i', 28, struct if_laddrreq) /* add IF addr */
-#define SIOCGLIFADDR	_IOWR('i', 29, struct if_laddrreq) /* get IF addr */
-#define SIOCDLIFADDR	 _IOW('i', 30, struct if_laddrreq) /* delete IF addr */
+#define SIOCALIFADDR     _IOW('i', 28, struct if_laddrreq) /* add IF addr */
+#define SIOCGLIFADDR    _IOWR('i', 29, struct if_laddrreq) /* get IF addr */
+#define SIOCDLIFADDR     _IOW('i', 30, struct if_laddrreq) /* delete IF addr */
 
-#define	SIOCADDMULTI	 _IOW('i', 49, struct ifreq)	/* add m'cast addr */
-#define	SIOCDELMULTI	 _IOW('i', 50, struct ifreq)	/* del m'cast addr */
-#define	SIOCGETVIFCNT	_IOWR('u', 51, struct sioc_vif_req)/* vif pkt cnt */
-#define	SIOCGETSGCNT	_IOWR('u', 52, struct sioc_sg_req) /* sg pkt cnt */
+#define SIOCADDMULTI     _IOW('i', 49, struct ifreq)    /* add m'cast addr */
+#define SIOCDELMULTI     _IOW('i', 50, struct ifreq)    /* del m'cast addr */
+#define SIOCGETVIFCNT   _IOWR('u', 51, struct sioc_vif_req)/* vif pkt cnt */
+#define SIOCGETSGCNT    _IOWR('u', 52, struct sioc_sg_req) /* sg pkt cnt */
 
-#define	SIOCSIFMEDIA	_IOWR('i', 53, struct ifreq)	/* set net media */
-#define	SIOCGIFMEDIA	_IOWR('i', 54, struct ifmediareq) /* get net media */
+#define SIOCSIFMEDIA    _IOWR('i', 53, struct ifreq)    /* set net media */
+#define SIOCGIFMEDIA    _IOWR('i', 54, struct ifmediareq) /* get net media */
 
 #define SIOCSIFPHYADDR   _IOW('i', 70, struct ifaliasreq) /* set gif addres */
-#define	SIOCGIFPSRCADDR	_IOWR('i', 71, struct ifreq)	/* get gif psrc addr */
-#define	SIOCGIFPDSTADDR	_IOWR('i', 72, struct ifreq)	/* get gif pdst addr */
+#define SIOCGIFPSRCADDR _IOWR('i', 71, struct ifreq)    /* get gif psrc addr */
+#define SIOCGIFPDSTADDR _IOWR('i', 72, struct ifreq)    /* get gif pdst addr */
 
-#define	SIOCBRDGADD	_IOWR('i', 60, struct ifbreq)	/* add bridge ifs */
-#define	SIOCBRDGDEL	_IOWR('i', 61, struct ifbreq)	/* del bridge ifs */
-#define	SIOCBRDGGIFFLGS	_IOWR('i', 62, struct ifbreq)	/* get brdg if flags */
-#define	SIOCBRDGSIFFLGS	_IOWR('i', 63, struct ifbreq)	/* set brdg if flags */
-#define	SIOCBRDGSCACHE	_IOWR('i', 64, struct ifbcachereq) /* set cache size */
-#define	SIOCBRDGGCACHE	_IOWR('i', 65, struct ifbcachereq) /* get cache size */
-#define	SIOCBRDGIFS	_IOWR('i', 66, struct ifbreq)	/* get member ifs */
-#define	SIOCBRDGRTS	_IOWR('i', 67, struct ifbaconf)	/* get addresses */
-#define	SIOCBRDGSADDR	_IOWR('i', 68, struct ifbareq)	/* set addr flags */
-#define	SIOCBRDGSTO	_IOWR('i', 69, struct ifbcachetoreq) /* cache timeout */
-#define	SIOCBRDGGTO	_IOWR('i', 70, struct ifbcachetoreq) /* cache timeout */
-#define	SIOCBRDGDADDR	_IOWR('i', 71, struct ifbareq)	/* delete addr */
-#define	SIOCBRDGFLUSH	_IOWR('i', 72, struct ifbreq)	/* flush addr cache */
+#define SIOCBRDGADD     _IOWR('i', 60, struct ifbreq)   /* add bridge ifs */
+#define SIOCBRDGDEL     _IOWR('i', 61, struct ifbreq)   /* del bridge ifs */
+#define SIOCBRDGGIFFLGS _IOWR('i', 62, struct ifbreq)   /* get brdg if flags */
+#define SIOCBRDGSIFFLGS _IOWR('i', 63, struct ifbreq)   /* set brdg if flags */
+#define SIOCBRDGSCACHE  _IOWR('i', 64, struct ifbcachereq) /* set cache size */
+#define SIOCBRDGGCACHE  _IOWR('i', 65, struct ifbcachereq) /* get cache size */
+#define SIOCBRDGADDS     _IOW('i', 65, struct ifbreq)   /* add span port */
+#define SIOCBRDGIFS     _IOWR('i', 66, struct ifbreq)   /* get member ifs */
+#define SIOCBRDGDELS     _IOW('i', 66, struct ifbreq)   /* del span port */
+#define SIOCBRDGRTS     _IOWR('i', 67, struct ifbaconf) /* get addresses */
+#define SIOCBRDGSADDR   _IOWR('i', 68, struct ifbareq)  /* set addr flags */
+#define SIOCBRDGSTO     _IOWR('i', 69, struct ifbcachetoreq) /* cache timeout */
+#define SIOCBRDGGTO     _IOWR('i', 70, struct ifbcachetoreq) /* cache timeout */
+#define SIOCBRDGDADDR   _IOWR('i', 71, struct ifbareq)  /* delete addr */
+#define SIOCBRDGFLUSH   _IOWR('i', 72, struct ifbreq)   /* flush addr cache */
 
 #define SIOCBRDGARL     _IOWR('i', 77, struct ifbrlreq) /* add bridge rule */
 #define SIOCBRDGFRL     _IOWR('i', 78, struct ifbrlreq) /* flush brdg rules */
 #define SIOCBRDGGRL     _IOWR('i', 79, struct ifbrlconf)/* get bridge rules */
 
-#define	SIOCSIFMTU	 _IOW('i', 127, struct ifreq)	/* set ifnet mtu */
-#define	SIOCGIFMTU	_IOWR('i', 126, struct ifreq)	/* get ifnet mtu */
-#define	SIOCSIFASYNCMAP  _IOW('i', 125, struct ifreq)	/* set ppp asyncmap */
-#define	SIOCGIFASYNCMAP _IOWR('i', 124, struct ifreq)	/* get ppp asyncmap */
+#define SIOCBRDGGPRI    _IOWR('i', 80, struct ifbrparam) /* get priority */
+#define SIOCBRDGSPRI     _IOW('i', 80, struct ifbrparam) /* set priority */
+#define SIOCBRDGGHT     _IOWR('i', 81, struct ifbrparam) /* get hello time */
+#define SIOCBRDGSHT      _IOW('i', 81, struct ifbrparam) /* set hello time */
+#define SIOCBRDGGFD     _IOWR('i', 82, struct ifbrparam) /* get forward delay */
+#define SIOCBRDGSFD      _IOW('i', 82, struct ifbrparam) /* set forward delay */
+#define SIOCBRDGGMA     _IOWR('i', 83, struct ifbrparam) /* get max age */
+#define SIOCBRDGSMA      _IOW('i', 83, struct ifbrparam) /* set max age */
+#define SIOCBRDGSIFPRIO _IOWR('i', 84, struct ifbreq)   /* set if priority */
+#define SIOCBRDGSIFCOST _IOWR('i', 85, struct ifbreq)   /* set if cost */
+
+#define SIOCSIFMTU       _IOW('i', 127, struct ifreq)   /* set ifnet mtu */
+#define SIOCGIFMTU      _IOWR('i', 126, struct ifreq)   /* get ifnet mtu */
+#define SIOCSIFASYNCMAP  _IOW('i', 125, struct ifreq)   /* set ppp asyncmap */
+#define SIOCGIFASYNCMAP _IOWR('i', 124, struct ifreq)   /* get ppp asyncmap */
 
 #ifdef __ECOS
 #define FIONBIO          _IOW('s', 80, int)             /* set non-blocking I/O */
new file mode 100644
--- /dev/null
+++ b/packages/net/tcpip/current/src/sys/net/bridgestp.c
@@ -0,0 +1,1537 @@
+//==========================================================================
+//
+//      sys/net/bridgestp.c
+//
+//     
+//
+//==========================================================================
+//####COPYRIGHTBEGIN####
+//                                                                          
+// -------------------------------------------                              
+// The contents of this file are subject to the Red Hat eCos Public License 
+// Version 1.1 (the "License"); you may not use this file except in         
+// compliance with the License.  You may obtain a copy of the License at    
+// http://www.redhat.com/                                                   
+//                                                                          
+// Software distributed under the License is distributed on an "AS IS"      
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the 
+// License for the specific language governing rights and limitations under 
+// the License.                                                             
+//                                                                          
+// The Original Code is eCos - Embedded Configurable Operating System,      
+// released September 30, 1998.                                             
+//                                                                          
+// The Initial Developer of the Original Code is Red Hat.                   
+// Portions created by Red Hat are                                          
+// Copyright (C) 1998, 1999, 2000 Red Hat, Inc.                             
+// All Rights Reserved.                                                     
+// -------------------------------------------                              
+//                                                                          
+//####COPYRIGHTEND####
+//####BSDCOPYRIGHTBEGIN####
+//
+// -------------------------------------------
+//
+// Portions of this software may have been derived from OpenBSD or other sources,
+// and are covered by the appropriate copyright disclaimers included herein.
+//
+// -------------------------------------------
+//
+//####BSDCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    Jason L. Wright (jason@thought.net)  
+// Contributors: Manu Sharma (manu.sharma@ascom.com)
+// Date:         2000-07-18
+// Purpose:      Implementation of the spanning tree protocol as defined in
+//               ISO/IEC Final DIS 15802-3 (IEEE P802.1D/D17), May 25, 1998.
+//               (In English: IEEE 802.1D, Draft 17, 1998)
+// Description:  
+//              
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+//
+/*	$OpenBSD: bridgestp.c,v 1.15 2002/12/10 13:22:55 markus Exp $	*/
+
+/*
+ * Copyright (c) 2000 Jason L. Wright (jason@thought.net)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Implementation of the spanning tree protocol as defined in
+ * ISO/IEC Final DIS 15802-3 (IEEE P802.1D/D17), May 25, 1998.
+ * (In English: IEEE 802.1D, Draft 17, 1998)
+ */
+
+#ifdef __ECOS
+#include <pkgconf/net.h>
+#include <stdio.h>
+#else
+#include "bridge.h"
+#endif
+
+#ifdef CYGPKG_NET_BRIDGE_STP_CODE
+#if NBRIDGE 
+
+#include <sys/param.h>
+#ifndef __ECOS
+#include <sys/systm.h>
+#endif
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#ifndef __ECOS
+#include <sys/device.h>
+#endif
+#include <sys/kernel.h>
+
+#include <net/if.h>
+#include <net/if_types.h>
+#include <net/if_llc.h>
+#include <net/netisr.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#include <netinet/if_ether.h>
+#endif
+
+#if NBPFILTER > 0
+#include <net/bpf.h>
+#endif
+
+#include <net/if_bridge.h>
+
+#define STP_DEBUG
+#define STP_DETAILED_DEBUG
+#ifdef STP_DEBUG
+#define STPLOG(x) diag_printf x
+#else
+#define STPLOG(x)
+#endif
+
+#ifdef STP_DETAILED_DEBUG
+#define STP_OPERATION_LOG(x) diag_printf x
+#else
+#define STP_OPERATION_LOG(x)
+#endif
+
+/* BPDU message types */
+#define	BSTP_MSGTYPE_CFG	0x00		/* Configuration */
+#define	BSTP_MSGTYPE_TCN	0x80		/* Topology chg notification */
+
+/* BPDU flags */
+#define	BSTP_FLAG_TC		0x01		/* Topology change */
+#define	BSTP_FLAG_TCA		0x80		/* Topology change ack */
+
+#define	BSTP_MESSAGE_AGE_INCR	(1 * 256)	/* in 256ths of a second */
+#define	BSTP_TICK_VAL		(1 * 256)	/* in 256ths of a second */
+
+/*
+ * Because BPDU's do not make nicely aligned structures, two different
+ * declarations are used: bstp_?bpdu (wire representation, packed) and
+ * bstp_*_unit (internal, nicely aligned version).
+ */
+
+/* configuration bridge protocol data unit */
+struct bstp_cbpdu {
+	u_int8_t	cbu_dsap;		/* LLC: destination sap */
+	u_int8_t	cbu_ssap;		/* LLC: source sap */
+	u_int8_t	cbu_ctl;		/* LLC: control */
+	u_int16_t	cbu_protoid;		/* protocol id */
+	u_int8_t	cbu_protover;		/* protocol version */
+	u_int8_t	cbu_bpdutype;		/* message type */
+	u_int8_t	cbu_flags;		/* flags (below) */
+
+	/* root id */
+	u_int16_t	cbu_rootpri;		/* root priority */
+	u_int8_t	cbu_rootaddr[6];	/* root address */
+
+	u_int32_t	cbu_rootpathcost;	/* root path cost */
+
+	/* bridge id */
+	u_int16_t	cbu_bridgepri;		/* bridge priority */
+	u_int8_t	cbu_bridgeaddr[6];	/* bridge address */
+
+	u_int16_t	cbu_portid;		/* port id */
+	u_int16_t	cbu_messageage;		/* current message age */
+	u_int16_t	cbu_maxage;		/* maximum age */
+	u_int16_t	cbu_hellotime;		/* hello time */
+	u_int16_t	cbu_forwarddelay;	/* forwarding delay */
+} __attribute__((__packed__));
+
+/* topology change notification bridge protocol data unit */
+struct bstp_tbpdu {
+	u_int8_t	tbu_dsap;		/* LLC: destination sap */
+	u_int8_t	tbu_ssap;		/* LLC: source sap */
+	u_int8_t	tbu_ctl;		/* LLC: control */
+	u_int16_t	tbu_protoid;		/* protocol id */
+	u_int8_t	tbu_protover;		/* protocol version */
+	u_int8_t	tbu_bpdutype;		/* message type */
+} __attribute__((__packed__));
+
+u_int8_t bstp_etheraddr[] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 };
+u_int8_t bstp_init_done;
+
+void bstp_initialization(struct bridge_softc *);
+void bstp_stop(struct bridge_softc *);
+void bstp_initialize_port(struct bridge_softc *, struct bridge_iflist *);
+void bstp_ifupdstatus(struct bridge_softc *, struct bridge_iflist *);
+void bstp_enable_port(struct bridge_softc *, struct bridge_iflist *);
+void bstp_disable_port(struct bridge_softc *, struct bridge_iflist *);
+void bstp_enable_change_detection(struct bridge_iflist *);
+void bstp_disable_change_detection(struct bridge_iflist *);
+int bstp_root_bridge(struct bridge_softc *sc);
+int bstp_supersedes_port_info(struct bridge_softc *, struct bridge_iflist *,
+    struct bstp_config_unit *);
+int bstp_designated_port(struct bridge_softc *, struct bridge_iflist *);
+int bstp_designated_for_some_port(struct bridge_softc *);
+void bstp_transmit_config(struct bridge_softc *, struct bridge_iflist *);
+void bstp_transmit_tcn(struct bridge_softc *);
+struct mbuf *bstp_input(struct bridge_softc *, struct ifnet *,
+    struct ether_header *, struct mbuf *);
+void bstp_received_config_bpdu(struct bridge_softc *, struct bridge_iflist *,
+    struct bstp_config_unit *);
+void bstp_received_tcn_bpdu(struct bridge_softc *, struct bridge_iflist *,
+    struct bstp_tcn_unit *);
+void bstp_record_config_information(struct bridge_softc *,
+    struct bridge_iflist *, struct bstp_config_unit *);
+void bstp_record_config_timeout_values(struct bridge_softc *,
+    struct bstp_config_unit *);
+void bstp_config_bpdu_generation(struct bridge_softc *);
+void bstp_send_config_bpdu(struct bridge_iflist *, struct bstp_config_unit *);
+void bstp_configuration_update(struct bridge_softc *);
+void bstp_root_selection(struct bridge_softc *);
+void bstp_designated_port_selection(struct bridge_softc *);
+void bstp_become_designated_port(struct bridge_softc *, struct bridge_iflist *);
+void bstp_port_state_selection(struct bridge_softc *);
+void bstp_make_forwarding(struct bridge_softc *, struct bridge_iflist *);
+void bstp_make_blocking(struct bridge_softc *, struct bridge_iflist *);
+void bstp_set_port_state(struct bridge_iflist *, u_int8_t);
+void bstp_set_bridge_priority(struct bridge_softc *, u_int64_t);
+void bstp_set_port_priority(struct bridge_softc *, struct bridge_iflist *,
+    u_int16_t);
+void bstp_set_path_cost(struct bridge_softc *, struct bridge_iflist *,
+    u_int32_t);
+void bstp_topology_change_detection(struct bridge_softc *);
+void bstp_topology_change_acknowledged(struct bridge_softc *);
+void bstp_acknowledge_topology_change(struct bridge_softc *,
+    struct bridge_iflist *);
+
+void bstp_tick(void *);
+void bstp_timer_start(struct bridge_timer *, u_int16_t);
+void bstp_timer_stop(struct bridge_timer *);
+int bstp_timer_expired(struct bridge_timer *, u_int16_t);
+
+void bstp_hold_timer_expiry(struct bridge_softc *, struct bridge_iflist *);
+void bstp_message_age_timer_expiry(struct bridge_softc *,
+    struct bridge_iflist *);
+void bstp_forward_delay_timer_expiry(struct bridge_softc *,
+    struct bridge_iflist *);
+void bstp_topology_change_timer_expiry(struct bridge_softc *);
+void bstp_tcn_timer_expiry(struct bridge_softc *);
+void bstp_hello_timer_expiry(struct bridge_softc *);
+
+char stp_buf [32];
+char *
+stp_port_state (unsigned int state) {
+        memset (stp_buf, 0x0, 32);
+        switch (state) {
+                case BSTP_IFSTATE_DISABLED   : sprintf (stp_buf, " Disabled "); break;
+                case BSTP_IFSTATE_LISTENING  : sprintf (stp_buf, " Listn'ng "); break;
+                case BSTP_IFSTATE_LEARNING   : sprintf (stp_buf, " Lrn'ng "); break;
+                case BSTP_IFSTATE_FORWARDING : sprintf (stp_buf, " Fwd'ng "); break;
+                case BSTP_IFSTATE_BLOCKING   : sprintf (stp_buf, " Blk'ng "); break;
+                default: sprintf (stp_buf, " UNKNOWN "); break;
+        }
+        return stp_buf;
+}
+
+void
+bstp_transmit_config(sc, bif)
+	struct bridge_softc *sc;
+	struct bridge_iflist *bif;
+{
+	if (bif->bif_hold_timer.active) {
+		bif->bif_config_pending = 1;
+		return;
+	}
+
+	bif->bif_config_bpdu.cu_message_type = BSTP_MSGTYPE_CFG;
+	bif->bif_config_bpdu.cu_rootid = sc->sc_designated_root;
+	bif->bif_config_bpdu.cu_root_path_cost = sc->sc_root_path_cost;
+	bif->bif_config_bpdu.cu_bridge_id = sc->sc_bridge_id;
+	bif->bif_config_bpdu.cu_port_id = bif->bif_port_id;
+
+	if (bstp_root_bridge(sc))
+		bif->bif_config_bpdu.cu_message_age = 0;
+	else
+		bif->bif_config_bpdu.cu_message_age =
+		    sc->sc_root_port->bif_message_age_timer.value +
+		    BSTP_MESSAGE_AGE_INCR;
+
+	bif->bif_config_bpdu.cu_max_age = sc->sc_max_age;
+	bif->bif_config_bpdu.cu_hello_time = sc->sc_hello_time;
+	bif->bif_config_bpdu.cu_forward_delay = sc->sc_forward_delay;
+	bif->bif_config_bpdu.cu_topology_change_acknowledgment
+	    = bif->bif_topology_change_acknowledge;
+	bif->bif_config_bpdu.cu_topology_change = sc->sc_topology_change;
+
+	if (bif->bif_config_bpdu.cu_message_age < sc->sc_max_age) {
+		bif->bif_topology_change_acknowledge = 0;
+		bif->bif_config_pending = 0;
+		bstp_send_config_bpdu(bif, &bif->bif_config_bpdu);
+		bstp_timer_start(&bif->bif_hold_timer, 0);
+	}
+}
+
+void
+bstp_send_config_bpdu(bif, cu)
+	struct bridge_iflist *bif;
+	struct bstp_config_unit *cu;
+{
+	struct arpcom *arp;
+	struct ifnet *ifp;
+	struct mbuf *m;
+	struct ether_header eh;
+	struct bstp_cbpdu bpdu;
+	int s, error;
+
+	s = splimp();
+	ifp = bif->ifp;
+	arp = (struct arpcom *)ifp;
+
+	if ((ifp->if_flags & IFF_RUNNING) == 0) {
+		splx(s);
+		return;
+	}
+#ifdef ALTQ
+	if (!ALTQ_IS_ENABLED(&ifp->if_snd))
+#endif
+	if (IF_QFULL(&ifp->if_snd)) {
+		splx(s);
+		return;
+	}
+
+	MGETHDR(m, M_DONTWAIT, MT_DATA);
+	if (m == NULL) {
+		splx(s);
+		return;
+	}
+	m->m_pkthdr.rcvif = ifp;
+	m->m_pkthdr.len = sizeof(eh) + sizeof(bpdu);
+	m->m_len = m->m_pkthdr.len;
+
+	bpdu.cbu_ssap = bpdu.cbu_dsap = LLC_8021D_LSAP;
+	bpdu.cbu_ctl = LLC_UI;
+	bpdu.cbu_protoid = htons(0);
+	bpdu.cbu_protover = 0;
+	bpdu.cbu_bpdutype = cu->cu_message_type;
+	bpdu.cbu_flags = (cu->cu_topology_change ? BSTP_FLAG_TC : 0) |
+	    (cu->cu_topology_change_acknowledgment ? BSTP_FLAG_TCA : 0);
+
+	bpdu.cbu_rootpri = htons(cu->cu_rootid >> 48);
+	bpdu.cbu_rootaddr[0] = cu->cu_rootid >> 40;
+	bpdu.cbu_rootaddr[1] = cu->cu_rootid >> 32;
+	bpdu.cbu_rootaddr[2] = cu->cu_rootid >> 24;
+	bpdu.cbu_rootaddr[3] = cu->cu_rootid >> 16;
+	bpdu.cbu_rootaddr[4] = cu->cu_rootid >> 8;
+	bpdu.cbu_rootaddr[5] = cu->cu_rootid >> 0;
+
+	bpdu.cbu_rootpathcost = htonl(cu->cu_root_path_cost);
+
+	bpdu.cbu_bridgepri = htons(cu->cu_rootid >> 48);
+	bpdu.cbu_bridgeaddr[0] = cu->cu_rootid >> 40;
+	bpdu.cbu_bridgeaddr[1] = cu->cu_rootid >> 32;
+	bpdu.cbu_bridgeaddr[2] = cu->cu_rootid >> 24;
+	bpdu.cbu_bridgeaddr[3] = cu->cu_rootid >> 16;
+	bpdu.cbu_bridgeaddr[4] = cu->cu_rootid >> 8;
+	bpdu.cbu_bridgeaddr[5] = cu->cu_rootid >> 0;
+
+	bpdu.cbu_portid = htons(cu->cu_port_id);
+	bpdu.cbu_messageage = htons(cu->cu_message_age);
+	bpdu.cbu_maxage = htons(cu->cu_max_age);
+	bpdu.cbu_hellotime = htons(cu->cu_hello_time);
+	bpdu.cbu_forwarddelay = htons(cu->cu_forward_delay);
+
+	bcopy(arp->ac_enaddr, eh.ether_shost, ETHER_ADDR_LEN);
+	bcopy(bstp_etheraddr, eh.ether_dhost, ETHER_ADDR_LEN);
+	eh.ether_type = htons(sizeof(bpdu));
+
+	bcopy(&eh, m->m_data, sizeof(eh));
+	bcopy(&bpdu, m->m_data + sizeof(eh), sizeof(bpdu));
+
+        STPLOG (("        - <%s>: Tx with Port 0x%x; Age %d; Flags %d\n", bif->ifp->if_xname,
+                  cu->cu_port_id, cu->cu_message_age, bpdu.cbu_flags));
+
+	IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error);
+	if (error == 0 && (ifp->if_flags & IFF_OACTIVE) == 0)
+		(*ifp->if_start)(ifp);
+	splx(s);
+}
+
+int
+bstp_root_bridge(sc)
+	struct bridge_softc *sc;
+{
+	return (sc->sc_designated_root == sc->sc_bridge_id);
+}
+
+int
+bstp_supersedes_port_info(sc, bif, cu)
+	struct bridge_softc *sc;
+	struct bridge_iflist *bif;
+	struct bstp_config_unit *cu;
+{
+	if (cu->cu_rootid < bif->bif_designated_root) {
+		return (1);
+        }
+	if (cu->cu_rootid > bif->bif_designated_root) {
+		return (0);
+        }
+
+	if (cu->cu_root_path_cost < bif->bif_designated_cost) {
+		return (1);
+        }
+	if (cu->cu_root_path_cost > bif->bif_designated_cost) {
+		return (0);
+        }
+
+	if (cu->cu_bridge_id < bif->bif_designated_bridge) {
+		return (1);
+        }
+	if (cu->cu_bridge_id > bif->bif_designated_bridge) {
+		return (0);
+        }
+
+	if (sc->sc_bridge_id != cu->cu_bridge_id) {
+		return (1);
+        }
+	if (cu->cu_port_id <= bif->bif_designated_port) {
+		return (1); 
+        }
+	return (0);
+}
+
+void
+bstp_record_config_information(sc, bif, cu)
+	struct bridge_softc *sc;
+	struct bridge_iflist *bif;
+	struct bstp_config_unit *cu;
+{
+	bif->bif_designated_root = cu->cu_rootid;
+	bif->bif_designated_cost = cu->cu_root_path_cost;
+	bif->bif_designated_bridge = cu->cu_bridge_id;
+	bif->bif_designated_port = cu->cu_port_id;
+	bstp_timer_start(&bif->bif_message_age_timer, cu->cu_message_age);
+}
+
+void
+bstp_record_config_timeout_values(sc, config)
+	struct bridge_softc *sc;
+	struct bstp_config_unit *config;
+{
+	sc->sc_max_age = config->cu_max_age;
+	sc->sc_hello_time = config->cu_hello_time;
+	sc->sc_forward_delay = config->cu_forward_delay;
+	sc->sc_topology_change = config->cu_topology_change;
+}
+
+void
+bstp_config_bpdu_generation(sc)
+	struct bridge_softc *sc;
+{
+	struct bridge_iflist *bif;
+
+        STPLOG (("STP : Tx Hello BPDU ...\n"));
+	LIST_FOREACH(bif, &sc->sc_iflist, next) {
+		if (!(bif->bif_flags & IFBIF_STP))
+			continue;
+		if (bstp_designated_port(sc, bif) &&
+		    (bif->bif_state != BSTP_IFSTATE_DISABLED)) {
+			bstp_transmit_config(sc, bif);
+                } else {
+                        STPLOG (("        - <%s>: No Tx\n", bif->ifp->if_xname));
+                }
+	}
+}
+
+int
+bstp_designated_port(sc, bif)
+	struct bridge_softc *sc;
+	struct bridge_iflist *bif;
+{
+	return ((bif->bif_designated_bridge == sc->sc_bridge_id)
+	    && (bif->bif_designated_port == bif->bif_port_id));
+}
+
+void
+bstp_transmit_tcn(sc)
+	struct bridge_softc *sc;
+{
+	struct bstp_tbpdu bpdu;
+	struct bridge_iflist *bif = sc->sc_root_port;
+	struct ifnet *ifp = bif->ifp;
+	struct arpcom *arp = (struct arpcom *)ifp;
+	struct ether_header *eh;
+	struct mbuf *m;
+	int s, error;
+
+	if ((ifp->if_flags & IFF_RUNNING) == 0)
+		return;
+
+	MGETHDR(m, M_DONTWAIT, MT_DATA);
+	if (m == NULL)
+		return;
+
+        STPLOG (("STP : Tx TCN BPDU on <%s> ...\n", ifp->if_xname));
+
+	m->m_pkthdr.rcvif = ifp;
+	m->m_pkthdr.len = sizeof(*eh) + sizeof(bpdu);
+	m->m_len = m->m_pkthdr.len;
+
+	eh = mtod(m, struct ether_header *);
+	bcopy(arp->ac_enaddr, eh->ether_shost, ETHER_ADDR_LEN);
+	bcopy(bstp_etheraddr, eh->ether_dhost, ETHER_ADDR_LEN);
+	eh->ether_type = htons(sizeof(bpdu));
+
+	bpdu.tbu_ssap = bpdu.tbu_dsap = LLC_8021D_LSAP;
+	bpdu.tbu_ctl = LLC_UI;
+	bpdu.tbu_protoid = 0;
+	bpdu.tbu_protover = 0;
+	bpdu.tbu_bpdutype = BSTP_MSGTYPE_TCN;
+	bcopy(&bpdu, m->m_data + sizeof(*eh), sizeof(bpdu));
+
+	s = splimp();
+	IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error);
+	if (error == 0 && (ifp->if_flags & IFF_OACTIVE) == 0)
+		(*ifp->if_start)(ifp);
+	m = NULL;
+
+	splx(s);
+	if (m != NULL)
+		m_freem(m);
+}
+
+void
+bstp_configuration_update(sc)
+	struct bridge_softc *sc;
+{
+        STP_OPERATION_LOG (("   %s \n", __FUNCTION__));
+	bstp_root_selection(sc);
+	bstp_designated_port_selection(sc);
+}
+
+void
+bstp_root_selection(sc)
+	struct bridge_softc *sc;
+{
+	struct bridge_iflist *root_port = NULL, *bif;
+
+        STP_OPERATION_LOG (("   => Root Port selection ...\n", __FUNCTION__));
+	LIST_FOREACH(bif, &sc->sc_iflist, next) {
+                STP_OPERATION_LOG (("      - <%s>", bif->ifp->if_xname));
+		if (!(bif->bif_flags & IFBIF_STP)) {
+                        STP_OPERATION_LOG ((" STP not configured\n"));
+			continue;
+                }
+		if (bstp_designated_port(sc, bif)) {
+                        STP_OPERATION_LOG ((" dsgntd port\n"));
+			continue;
+                }
+		if (bif->bif_state == BSTP_IFSTATE_DISABLED) {
+                        STP_OPERATION_LOG ((" .. in state DISABLED \n"));
+			continue;
+                }
+		if (bif->bif_designated_root >= sc->sc_bridge_id) {
+                        STP_OPERATION_LOG ((" root: ifp dsgntd >= sc\n"));
+			continue;
+                }
+		if (root_port == NULL) {
+                        STP_OPERATION_LOG ((" Set as Root Port\n"));
+			goto set_port;
+                }
+
+		if (bif->bif_designated_root < root_port->bif_designated_root) {
+                        STP_OPERATION_LOG ((" ifp dsgntd < root dsgntd; Set as Root Port \n"));
+			goto set_port;
+                }
+		if (bif->bif_designated_root > root_port->bif_designated_root) {
+                        STP_OPERATION_LOG ((" root: ifp dsgntd > root dsgntd \n"));
+			continue;
+                }
+
+		if ((bif->bif_designated_cost + bif->bif_path_cost) <
+		    (root_port->bif_designated_cost + root_port->bif_path_cost)) {
+                        STP_OPERATION_LOG ((" (dsgntd_cost+path_cost): ifp < root; Set as Root Port \n"));
+			goto set_port;
+                }
+		if ((bif->bif_designated_cost + bif->bif_path_cost) >
+		    (root_port->bif_designated_cost + root_port->bif_path_cost)) {
+                        STP_OPERATION_LOG ((" (dsgntd_cost+path_cost): ifp > root \n"));
+			continue;
+                }
+
+		if (bif->bif_designated_bridge < root_port->bif_designated_bridge) {
+                        STP_OPERATION_LOG ((" bridge: ifp dsgntd < root dsgntd; Set as Root Port \n"));
+			goto set_port;
+                }
+		if (bif->bif_designated_bridge > root_port->bif_designated_bridge) {
+                        STP_OPERATION_LOG ((" bridge: ifp dsgntd > root dsgntd \n"));
+			continue;
+                }
+
+		if (bif->bif_designated_port < root_port->bif_designated_port) {
+                        STP_OPERATION_LOG ((" port: ifp dsgntd (%d) < root dsgntd (%d); Set as Root Port\n",
+                                 bif->bif_designated_port, root_port->bif_designated_port));
+			goto set_port;
+                }
+		if (bif->bif_designated_port > root_port->bif_designated_port) {
+                        STP_OPERATION_LOG ((" port: ifp dsgntd (%d) > root dsgntd (%d)\n",
+                                 bif->bif_designated_port, root_port->bif_designated_port));
+			continue;
+                }
+
+		if (bif->bif_port_id >= root_port->bif_port_id) {
+                        STP_OPERATION_LOG ((" ifp port_id (%d) >= root port_id (%d) 8 \n",
+                                 bif->bif_port_id, root_port->bif_port_id));
+			continue;
+                }
+set_port:
+		root_port = bif;
+	}
+
+	sc->sc_root_port = root_port;
+	if (root_port == NULL) {
+		sc->sc_designated_root = sc->sc_bridge_id;
+		sc->sc_root_path_cost = 0;
+                STPLOG (("      Root Port : <SELF ROOT>, Path Cost : 0\n"));
+	} else {
+		sc->sc_designated_root = root_port->bif_designated_root;
+		sc->sc_root_path_cost = root_port->bif_designated_cost +
+		    root_port->bif_path_cost;
+                STPLOG (("      Root Port : <%s>, Path Cost : 0\n", 
+                          root_port->ifp->if_xname, sc->sc_root_path_cost));
+	}
+}
+
+void
+bstp_designated_port_selection(sc)
+	struct bridge_softc *sc;
+{
+	struct bridge_iflist *bif;
+
+        STP_OPERATION_LOG (("   => Designated Port selection ...\n"));
+	LIST_FOREACH(bif, &sc->sc_iflist, next) {
+		if (!(bif->bif_flags & IFBIF_STP))
+			continue;
+		if (bstp_designated_port(sc, bif)) {
+                        STPLOG (("      - <%s>: already designated \n", bif->ifp->if_xname));
+			goto designated;
+                }
+		if (bif->bif_designated_root != sc->sc_designated_root) {
+                        STPLOG (("      - <%s>: becomes designated\n", bif->ifp->if_xname));
+			goto designated;
+                }
+
+                /* 
+                 * PLC network is special, we cannot go as per standards because of
+                 * our network topology and behavior
+                 *
+		if (sc->sc_root_path_cost < bif->bif_designated_cost) {
+                        STPLOG (("        - <%s>: becomes designated path cost (1)\n", bif->ifp->if_xname));
+			goto designated;
+                }
+		if (sc->sc_root_path_cost > bif->bif_designated_cost) {
+                        STPLOG (("        - <%s>: Cannot be designated; Root cost (%d) > Desig cost (%d) \n", 
+                                 bif->ifp->if_xname, sc->sc_root_path_cost, bif->bif_designated_cost));
+			continue;
+                }
+                */
+
+		if (sc->sc_bridge_id < bif->bif_designated_bridge) {
+                        STPLOG (("      - <%s>: becomes dsgntd (self-brdgid < dsgntd-brdgid); \n", bif->ifp->if_xname));
+			goto designated;
+                }
+		if (sc->sc_bridge_id > bif->bif_designated_bridge) {
+                        STPLOG (("      - <%s>: Cannot be dsgntd (self-brdgid > dsgntd-brdgid); \n", bif->ifp->if_xname));
+			continue;
+                }
+
+		if (bif->bif_port_id > bif->bif_designated_port) {
+                        STPLOG (("      - <%s>: Cannot be dsgntd (self-portid > bsgntd-portid); \n", bif->ifp->if_xname));
+			continue;
+                }
+
+                /* 
+                 * PLC network is special, we cannot go as per standards because of
+                 * our network topology and behavior
+                 */
+		if (sc->sc_root_path_cost < bif->bif_designated_cost) {
+                        STPLOG (("      - <%s>: becomes dsgntd path cost (1)\n", bif->ifp->if_xname));
+			goto designated;
+                }
+		if (sc->sc_root_path_cost > bif->bif_designated_cost) {
+                        STPLOG (("      - <%s>: Cannot be dsgntd; Root cost (%d) > Desig cost (%d) \n", 
+                                 bif->ifp->if_xname, sc->sc_root_path_cost, bif->bif_designated_cost));
+			continue;
+                }
+designated:
+		bstp_become_designated_port(sc, bif);
+	}
+}
+
+void
+bstp_become_designated_port(sc, bif)
+	struct bridge_softc *sc;
+	struct bridge_iflist *bif;
+{
+	bif->bif_designated_root = sc->sc_designated_root;
+	bif->bif_designated_cost = sc->sc_root_path_cost;
+	bif->bif_designated_bridge = sc->sc_bridge_id;
+	bif->bif_designated_port = bif->bif_port_id;
+
+        STP_OPERATION_LOG (("               => %s values (cost:%d, port:0x%x)\n", 
+                            __FUNCTION__, bif->ifp->if_xname, bif->bif_designated_cost, bif->bif_designated_port));
+        //STP_OPERATION_LOG (("(cost:%d, port:0x%x)\n", bif->bif_designated_cost, bif->bif_designated_port));
+}
+
+void
+bstp_port_state_selection(sc)
+	struct bridge_softc *sc;
+{
+	struct bridge_iflist *bif;
+
+	LIST_FOREACH(bif, &sc->sc_iflist, next) {
+		if (!(bif->bif_flags & IFBIF_STP))
+			continue;
+		if (bif == sc->sc_root_port) {
+			bif->bif_config_pending = 0;
+			bif->bif_topology_change_acknowledge = 0;
+			bstp_make_forwarding(sc, bif);
+		} else if (bstp_designated_port(sc, bif)) {
+			bstp_timer_stop(&bif->bif_message_age_timer);
+			bstp_make_forwarding(sc, bif);
+		} else {
+			bif->bif_config_pending = 0;
+			bif->bif_topology_change_acknowledge = 0;
+			bstp_make_blocking(sc, bif);
+		}
+	}
+}
+
+void
+bstp_make_forwarding(sc, bif)
+	struct bridge_softc *sc;
+	struct bridge_iflist *bif;
+{
+	if (bif->bif_state == BSTP_IFSTATE_BLOCKING) {
+		bstp_set_port_state(bif, BSTP_IFSTATE_LISTENING);
+		bstp_timer_start(&bif->bif_forward_delay_timer, 0);
+	}
+}
+
+void
+bstp_make_blocking(sc, bif)
+	struct bridge_softc *sc;
+	struct bridge_iflist *bif;
+{
+	if ((bif->bif_state != BSTP_IFSTATE_DISABLED) &&
+	    (bif->bif_state != BSTP_IFSTATE_BLOCKING)) {
+		if ((bif->bif_state == BSTP_IFSTATE_FORWARDING) ||
+		    (bif->bif_state == BSTP_IFSTATE_LEARNING)) {
+			if (bif->bif_change_detection_enabled) {
+				bstp_topology_change_detection(sc);
+			}
+			bridge_rtdelete(sc, bif->ifp, 1);
+		}
+		bstp_set_port_state(bif, BSTP_IFSTATE_BLOCKING);
+		bstp_timer_stop(&bif->bif_forward_delay_timer);
+	}
+}
+
+void
+bstp_set_port_state(bif, state)
+	struct bridge_iflist *bif;
+	u_int8_t state;
+{
+	bif->bif_state = state;
+}
+
+void
+bstp_topology_change_detection(sc)
+	struct bridge_softc *sc;
+{
+	if (bstp_root_bridge(sc)) {
+                STPLOG (("   -> %s : Root Bridge\n", __FUNCTION__));
+		sc->sc_topology_change = 1;
+		bstp_timer_start(&sc->sc_topology_change_timer, 0);
+	} else if (!sc->sc_topology_change_detected) {
+                STPLOG (("   -> %s : NOT Root Bridge, Tx TCN\n", __FUNCTION__));
+		bstp_transmit_tcn(sc);
+		bstp_timer_start(&sc->sc_tcn_timer, 0);
+	}
+	sc->sc_topology_change_detected = 1;
+}
+
+void
+bstp_topology_change_acknowledged(sc)
+	struct bridge_softc *sc;
+{
+	sc->sc_topology_change_detected = 0;
+	bstp_timer_stop(&sc->sc_tcn_timer);
+}
+
+void
+bstp_acknowledge_topology_change(sc, bif)
+	struct bridge_softc *sc;
+	struct bridge_iflist *bif;
+{
+	bif->bif_topology_change_acknowledge = 1;
+	bstp_transmit_config(sc, bif);
+}
+
+struct mbuf *
+bstp_input(sc, ifp, eh, m)
+	struct bridge_softc *sc;
+	struct ifnet *ifp;
+	struct ether_header *eh;
+	struct mbuf *m;
+{
+	struct bridge_iflist *bif = NULL;
+	struct bstp_tbpdu tpdu;
+	struct bstp_cbpdu cpdu;
+	struct bstp_config_unit cu;
+	struct bstp_tcn_unit tu;
+	u_int16_t len;
+
+	LIST_FOREACH(bif, &sc->sc_iflist, next) {
+		if (!(bif->bif_flags & IFBIF_STP))
+			continue;
+		if (bif->ifp == ifp)
+			break;
+	}
+
+	if (bif == NULL)
+		goto out;
+
+	len = ntohs(eh->ether_type);
+	if (len < sizeof(tpdu)) {
+		goto out;
+        }
+	if (m->m_pkthdr.len > len)
+		m_adj(m, len - m->m_pkthdr.len);
+	if ((m = m_pullup(m, sizeof(tpdu))) == NULL) {
+		goto out;
+        }
+	bcopy(mtod(m, struct tpdu *), &tpdu, sizeof(tpdu));
+
+	if (tpdu.tbu_dsap != LLC_8021D_LSAP ||
+	    tpdu.tbu_ssap != LLC_8021D_LSAP ||
+	    tpdu.tbu_ctl != LLC_UI) {
+		goto out;
+        }
+	if (tpdu.tbu_protoid != 0 || tpdu.tbu_protover != 0) {
+		goto out;
+         }
+
+	switch (tpdu.tbu_bpdutype) {
+	case BSTP_MSGTYPE_TCN:
+
+                STPLOG (("STP : Rx TCN on <%s> from %02X:%02X:%02X:%02X:%02X:%02X \n", bif->ifp->if_xname,
+                      eh->ether_shost[0], eh->ether_shost[1], eh->ether_shost[2],
+                      eh->ether_shost[3], eh->ether_shost[4], eh->ether_shost[5]));
+
+		tu.tu_message_type = tpdu.tbu_bpdutype;
+		bstp_received_tcn_bpdu(sc, bif, &tu);
+		break;
+
+	case BSTP_MSGTYPE_CFG:
+
+                STPLOG (("STP : Rx CFG on <%s> from %02X:%02X:%02X:%02X:%02X:%02X \n", bif->ifp->if_xname,
+                      eh->ether_shost[0], eh->ether_shost[1], eh->ether_shost[2],
+                      eh->ether_shost[3], eh->ether_shost[4], eh->ether_shost[5]));
+
+		if ((m = m_pullup(m, sizeof(cpdu))) == NULL)
+			goto out;
+		bcopy(mtod(m, struct bstp_cpdu *), &cpdu, sizeof(cpdu));
+
+		cu.cu_rootid =
+		    (((u_int64_t)ntohs(cpdu.cbu_rootpri)) << 48) |
+		    (((u_int64_t)cpdu.cbu_rootaddr[0]) << 40) |
+		    (((u_int64_t)cpdu.cbu_rootaddr[1]) << 32) |
+		    (((u_int64_t)cpdu.cbu_rootaddr[2]) << 24) |
+		    (((u_int64_t)cpdu.cbu_rootaddr[3]) << 16) |
+		    (((u_int64_t)cpdu.cbu_rootaddr[4]) << 8) |
+		    (((u_int64_t)cpdu.cbu_rootaddr[5]) << 0);
+
+		cu.cu_bridge_id =
+		    (((u_int64_t)ntohs(cpdu.cbu_bridgepri)) << 48) |
+		    (((u_int64_t)cpdu.cbu_bridgeaddr[0]) << 40) |
+		    (((u_int64_t)cpdu.cbu_bridgeaddr[1]) << 32) |
+		    (((u_int64_t)cpdu.cbu_bridgeaddr[2]) << 24) |
+		    (((u_int64_t)cpdu.cbu_bridgeaddr[3]) << 16) |
+		    (((u_int64_t)cpdu.cbu_bridgeaddr[4]) << 8) |
+		    (((u_int64_t)cpdu.cbu_bridgeaddr[5]) << 0);
+
+		cu.cu_root_path_cost = ntohl(cpdu.cbu_rootpathcost);
+		cu.cu_message_age = ntohs(cpdu.cbu_messageage);
+		cu.cu_max_age = ntohs(cpdu.cbu_maxage);
+		cu.cu_hello_time = ntohs(cpdu.cbu_hellotime);
+		cu.cu_forward_delay = ntohs(cpdu.cbu_forwarddelay);
+		cu.cu_port_id = ntohs(cpdu.cbu_portid);
+		cu.cu_message_type = cpdu.cbu_bpdutype;
+		cu.cu_topology_change_acknowledgment =
+		    (cpdu.cbu_flags & BSTP_FLAG_TCA) ? 1 : 0;
+		cu.cu_topology_change =
+		    (cpdu.cbu_flags & BSTP_FLAG_TC) ? 1 : 0;
+		bstp_received_config_bpdu(sc, bif, &cu);
+		break;
+	default:
+		goto out;
+	}
+
+out:
+	if (m)
+		m_freem(m);
+	return (NULL);
+}
+
+void
+bstp_received_config_bpdu(sc, bif, cu)
+	struct bridge_softc *sc;
+	struct bridge_iflist *bif;
+	struct bstp_config_unit *cu;
+{
+	int root;
+
+	root = bstp_root_bridge(sc);
+
+	if (bif->bif_state != BSTP_IFSTATE_DISABLED) {
+		if (bstp_supersedes_port_info(sc, bif, cu)) {
+                        STPLOG (("   Rx CFG on <%s> superseds port info; RE-Evaluating...\n", bif->ifp->if_xname));
+			bstp_record_config_information(sc, bif, cu);
+			bstp_configuration_update(sc);
+			bstp_port_state_selection(sc);
+
+			if ((!bstp_root_bridge(sc)) && root) {
+				bstp_timer_stop(&sc->sc_hello_timer);
+
+				if (sc->sc_topology_change_detected) {
+					bstp_timer_stop(&sc->sc_topology_change_timer);
+					bstp_transmit_tcn(sc);
+					bstp_timer_start(&sc->sc_tcn_timer, 0);
+				}
+			}
+
+			if (bif == sc->sc_root_port) {
+				bstp_record_config_timeout_values(sc, cu);
+				bstp_config_bpdu_generation(sc);
+
+				if (cu->cu_topology_change_acknowledgment) {
+					bstp_topology_change_acknowledged(sc);
+                                }
+			}
+		} else if (bstp_designated_port(sc, bif)) {
+                        STPLOG (("   Port <%s> supersedes Rx CFG info\n", bif->ifp->if_xname));
+			bstp_transmit_config(sc, bif);
+                }
+	}
+}
+
+void
+bstp_received_tcn_bpdu(sc, bif, tcn)
+	struct bridge_softc *sc;
+	struct bridge_iflist *bif;
+	struct bstp_tcn_unit *tcn;
+{
+	if (bif->bif_state != BSTP_IFSTATE_DISABLED &&
+	    bstp_designated_port(sc, bif)) {
+		bstp_topology_change_detection(sc);
+		bstp_acknowledge_topology_change(sc, bif);
+	}
+}
+
+void
+bstp_hello_timer_expiry(sc)
+	struct bridge_softc *sc;
+{
+	bstp_config_bpdu_generation(sc);
+	bstp_timer_start(&sc->sc_hello_timer, 0);
+}
+
+void
+bstp_message_age_timer_expiry(sc, bif)
+	struct bridge_softc *sc;
+	struct bridge_iflist *bif;
+{
+	int root;
+
+	root = bstp_root_bridge(sc);
+	bstp_become_designated_port(sc, bif);
+	bstp_configuration_update(sc);
+	bstp_port_state_selection(sc);
+
+	if ((bstp_root_bridge(sc)) && (!root)) {
+		sc->sc_max_age = sc->sc_bridge_max_age;
+		sc->sc_hello_time = sc->sc_bridge_hello_time;
+		sc->sc_forward_delay = sc->sc_bridge_forward_delay;
+		bstp_topology_change_detection(sc);
+		bstp_timer_stop(&sc->sc_tcn_timer);
+		bstp_config_bpdu_generation(sc);
+		bstp_timer_start(&sc->sc_hello_timer, 0);
+	}
+}
+
+void
+bstp_forward_delay_timer_expiry(sc, bif)
+	struct bridge_softc *sc;
+	struct bridge_iflist *bif;
+{
+	if (bif->bif_state == BSTP_IFSTATE_LISTENING) {
+		bstp_set_port_state(bif, BSTP_IFSTATE_LEARNING);
+		bstp_timer_start(&bif->bif_forward_delay_timer, 0);
+	} else if (bif->bif_state == BSTP_IFSTATE_LEARNING) {
+		bstp_set_port_state(bif, BSTP_IFSTATE_FORWARDING);
+		if (bstp_designated_for_some_port(sc) &&
+		    bif->bif_change_detection_enabled)
+			bstp_topology_change_detection(sc);
+	}
+}
+
+int
+bstp_designated_for_some_port(sc)
+	struct bridge_softc *sc;
+{
+
+	struct bridge_iflist *bif;
+
+	LIST_FOREACH(bif, &sc->sc_iflist, next) {
+		if (!(bif->bif_flags & IFBIF_STP))
+			continue;
+		if (bif->bif_designated_bridge == sc->sc_bridge_id)
+			return (1);
+	}
+	return (0);
+}
+
+void
+bstp_tcn_timer_expiry(sc)
+	struct bridge_softc *sc;
+{
+        STPLOG (("  STP: tcn timer expired \n"));
+	bstp_transmit_tcn(sc);
+	bstp_timer_start(&sc->sc_tcn_timer, 0);
+}
+
+void
+bstp_topology_change_timer_expiry(sc)
+	struct bridge_softc *sc;
+{
+        STPLOG (("  STP: topology change timer expired \n"));
+	sc->sc_topology_change_detected = 0;
+	sc->sc_topology_change = 0;
+}
+
+void
+bstp_hold_timer_expiry(sc, bif)
+	struct bridge_softc *sc;
+	struct bridge_iflist *bif;
+{
+	if (bif->bif_config_pending)
+		bstp_transmit_config(sc, bif);
+}
+
+void
+bstp_initialization(sc)
+	struct bridge_softc *sc;
+{
+	struct bridge_iflist *bif, *mif;
+	struct arpcom *ac, *mac;
+
+	mif = NULL; mac = NULL;
+        /* Browse through the ethernet address of each interface and pick the
+         * one which has lowest value
+         */
+	LIST_FOREACH(bif, &sc->sc_iflist, next) {
+		if (!(bif->bif_flags & IFBIF_STP)) {
+			continue;
+                }
+		if (bif->ifp->if_type != IFT_ETHER) {
+			continue;
+                }
+		bif->bif_port_id = (bif->bif_priority << 8) |
+		    (bif->ifp->if_index & 0xff);
+
+		if (mif == NULL) {
+			mif = bif;
+			mac = (struct arpcom *)bif->ifp;
+			continue;
+		}
+		ac = (struct arpcom *)bif->ifp;
+		if (memcmp(ac->ac_enaddr, mac->ac_enaddr, ETHER_ADDR_LEN) < 0) {
+			mif = bif;
+			mac = (struct arpcom *)bif->ifp;
+			continue;
+		}
+	}
+
+	if (mif == NULL) {
+		bstp_stop(sc);
+		return;
+	}
+
+        /* Configure bridge-id as specified in standards
+         */
+	sc->sc_bridge_id =
+	    (((u_int64_t)sc->sc_bridge_priority) << 48) |
+	    (((u_int64_t)mac->ac_enaddr[0]) << 40) |
+	    (((u_int64_t)mac->ac_enaddr[1]) << 32) |
+	    (mac->ac_enaddr[2] << 24) | (mac->ac_enaddr[3] << 16) |
+	    (mac->ac_enaddr[4] << 8) | (mac->ac_enaddr[5]);
+
+        /* Configure self as root bridge
+         */
+	sc->sc_designated_root = sc->sc_bridge_id;
+	sc->sc_root_path_cost = 0;
+	sc->sc_root_port = NULL;
+
+	sc->sc_max_age = sc->sc_bridge_max_age;
+	sc->sc_hello_time = sc->sc_bridge_hello_time;
+	sc->sc_forward_delay = sc->sc_bridge_forward_delay;
+	sc->sc_topology_change_detected = 0;
+	sc->sc_topology_change = 0;
+	bstp_timer_stop(&sc->sc_tcn_timer);
+	bstp_timer_stop(&sc->sc_topology_change_timer);
+
+        /* If there is a timeout already set on this, cancel it and restart.
+         * The intent is to avoid setting duplicate timeouts. If the timeout
+         * is already set, untimeout would cancel it.
+         */
+#ifdef __ECOS
+        if (!bstp_init_done) {
+          untimeout(bstp_tick, sc);
+          timeout(bstp_tick, sc, hz);
+          bstp_init_done = 1;
+        }
+#else
+	if (!timeout_initialized(&sc->sc_bstptimeout))
+		timeout_set(&sc->sc_bstptimeout, bstp_tick, sc);
+	if (!timeout_pending(&sc->sc_bstptimeout))
+		timeout_add(&sc->sc_bstptimeout, hz);
+#endif // __ECOS
+
+	LIST_FOREACH(bif, &sc->sc_iflist, next) {
+		if (bif->bif_flags & IFBIF_STP) {
+                        STPLOG (("%s:%s ..(en). \n", __FUNCTION__, bif->ifp->if_xname));
+			bstp_enable_port(sc, bif);
+                }
+		else {
+                        STPLOG (("%s:%s ..(dis). \n", __FUNCTION__, bif->ifp->if_xname));
+			bstp_disable_port(sc, bif);
+                }
+	}
+
+	bstp_port_state_selection(sc);
+	bstp_config_bpdu_generation(sc);
+	bstp_timer_start(&sc->sc_hello_timer, 0);
+}
+
+void
+bstp_stop(sc)
+	struct bridge_softc *sc;
+{
+
+	struct bridge_iflist *bif;
+
+        STPLOG (("        %s\n", __FUNCTION__));
+	LIST_FOREACH(bif, &sc->sc_iflist, next) {
+		bstp_set_port_state(bif, BSTP_IFSTATE_DISABLED);
+		bstp_timer_stop(&bif->bif_hold_timer);
+		bstp_timer_stop(&bif->bif_message_age_timer);
+		bstp_timer_stop(&bif->bif_forward_delay_timer);
+	}
+
+#ifdef __ECOS
+        if (bstp_init_done) {
+          STPLOG (("##### untimeout ##### loc 1\n"));
+          untimeout(bstp_tick, sc);
+          bstp_init_done = 0;
+        }
+#else
+	if (timeout_initialized(&sc->sc_bstptimeout) &&
+	    timeout_pending(&sc->sc_bstptimeout))
+		timeout_del(&sc->sc_bstptimeout);
+#endif   //__ECOS
+
+	bstp_timer_stop(&sc->sc_topology_change_timer);
+	bstp_timer_stop(&sc->sc_tcn_timer);
+	bstp_timer_stop(&sc->sc_hello_timer);
+
+}
+
+void
+bstp_initialize_port(sc, bif)
+	struct bridge_softc *sc;
+	struct bridge_iflist *bif;
+{
+	bstp_become_designated_port(sc, bif);
+	bstp_set_port_state(bif, BSTP_IFSTATE_BLOCKING);
+	bif->bif_topology_change_acknowledge = 0;
+	bif->bif_config_pending = 0;
+	bstp_enable_change_detection(bif);
+	bstp_timer_stop(&bif->bif_message_age_timer);
+	bstp_timer_stop(&bif->bif_forward_delay_timer);
+	bstp_timer_stop(&bif->bif_hold_timer);
+}
+
+void
+bstp_enable_port(sc, bif)
+	struct bridge_softc *sc;
+	struct bridge_iflist *bif;
+{
+	bstp_initialize_port(sc, bif);
+	bstp_port_state_selection(sc);
+}
+
+void
+bstp_disable_port(sc, bif)
+	struct bridge_softc *sc;
+	struct bridge_iflist *bif;
+{
+	int root;
+
+	root = bstp_root_bridge(sc);
+	bstp_become_designated_port(sc, bif);
+	bstp_set_port_state(bif, BSTP_IFSTATE_DISABLED);
+	bif->bif_topology_change_acknowledge = 0;
+	bif->bif_config_pending = 0;
+	bstp_timer_stop(&bif->bif_message_age_timer);
+	bstp_timer_stop(&bif->bif_forward_delay_timer);
+	bstp_configuration_update(sc);
+	bridge_rtdelete(sc, bif->ifp, 1);
+
+	if (bstp_root_bridge(sc) && (!root))	{
+		sc->sc_max_age = sc->sc_bridge_max_age;
+		sc->sc_hello_time = sc->sc_bridge_hello_time;
+		sc->sc_forward_delay = sc->sc_bridge_forward_delay;
+		bstp_topology_change_detection(sc);
+		bstp_timer_stop(&sc->sc_tcn_timer);
+		bstp_config_bpdu_generation(sc);
+		bstp_timer_start(&sc->sc_hello_timer, 0);
+	}
+}
+
+void
+bstp_set_bridge_priority(sc, new_bridge_id)
+	struct bridge_softc *sc;
+	u_int64_t new_bridge_id;
+{
+	int root;
+	struct bridge_iflist *bif;
+
+	root = bstp_root_bridge(sc);
+
+	LIST_FOREACH(bif, &sc->sc_iflist, next) {
+		if (!(bif->bif_flags & IFBIF_STP))
+			continue;
+		if (bstp_designated_port(sc, bif))
+			bif->bif_designated_bridge = new_bridge_id;
+	}
+
+	sc->sc_bridge_id = new_bridge_id;
+
+	bstp_configuration_update(sc);
+	bstp_port_state_selection(sc);
+
+	if (bstp_root_bridge(sc) && (!root)) {
+		sc->sc_max_age = sc->sc_bridge_max_age;
+		sc->sc_hello_time = sc->sc_bridge_hello_time;
+		sc->sc_forward_delay = sc->sc_bridge_forward_delay;
+		bstp_topology_change_detection(sc);
+		bstp_timer_stop(&sc->sc_tcn_timer);
+		bstp_config_bpdu_generation(sc);
+		bstp_timer_start(&sc->sc_hello_timer, 0);
+	}
+}
+
+void
+bstp_set_port_priority(sc, bif, new_port_id)
+	struct bridge_softc *sc;
+	struct bridge_iflist *bif;
+	u_int16_t new_port_id;
+{
+	if (bstp_designated_port(sc, bif))
+		bif->bif_designated_port = new_port_id;
+
+	bif->bif_port_id = new_port_id;
+
+	if ((sc->sc_bridge_id == bif->bif_designated_bridge) &&
+	    (bif->bif_port_id < bif->bif_designated_port)) {
+		bstp_become_designated_port(sc, bif);
+		bstp_port_state_selection(sc);
+	}
+}
+
+void
+bstp_set_path_cost(sc, bif, path_cost)
+	struct bridge_softc *sc;
+	struct bridge_iflist *bif;
+	u_int32_t path_cost;
+{
+	bif->bif_path_cost = path_cost;
+	bstp_configuration_update(sc);
+	bstp_port_state_selection(sc);
+}
+
+void
+bstp_enable_change_detection(bif)
+	struct bridge_iflist *bif;
+{
+	bif->bif_change_detection_enabled = 1;
+}
+
+void
+bstp_disable_change_detection(bif)
+	struct bridge_iflist *bif;
+{
+	bif->bif_change_detection_enabled = 0;
+}
+
+void
+bstp_ifupdstatus(sc, bif)
+	struct bridge_softc *sc;
+	struct bridge_iflist *bif;
+{
+	struct ifnet *ifp = bif->ifp;
+#ifndef __ECOS
+	struct ifmediareq ifmr;
+#endif
+	int err = EOPNOTSUPP;
+
+	if (ifp->if_flags & IFF_UP) {
+#ifndef __ECOS
+		ifmr.ifm_count = 0;
+		err = (*ifp->if_ioctl)(ifp, SIOCGIFMEDIA, (caddr_t)&ifmr);
+#endif
+		if (err) {
+			if (bif->bif_state == BSTP_IFSTATE_DISABLED)
+				bstp_enable_port(sc, bif);
+                        STPLOG (("<%s:%s> ", bif->ifp->if_xname, stp_port_state(bif->bif_state)));
+			return;
+		}
+#ifndef __ECOS
+		if (!(ifmr.ifm_status & IFM_AVALID)) {
+			if (bif->bif_state == BSTP_IFSTATE_DISABLED)
+				bstp_enable_port(sc, bif);
+			return;
+		}
+
+		if (ifmr.ifm_status & IFM_ACTIVE) {
+			if (bif->bif_state == BSTP_IFSTATE_DISABLED)
+				bstp_enable_port(sc, bif);
+			return;
+		}
+#endif
+
+		if (bif->bif_state != BSTP_IFSTATE_DISABLED) {
+			bstp_disable_port(sc, bif);
+                }
+
+		return;
+	}
+
+	if (bif->bif_state != BSTP_IFSTATE_DISABLED)
+		bstp_disable_port(sc, bif);
+}
+
+void
+bstp_tick(vsc)
+	void *vsc;
+{
+	struct bridge_softc *sc = vsc;
+	struct bridge_iflist *bif;
+	int s;
+
+	s = splnet();
+
+        STPLOG (("Port Status: ")); 
+	LIST_FOREACH(bif, &sc->sc_iflist, next) {
+		if (!(bif->bif_flags & IFBIF_STP))
+			continue;
+		bstp_ifupdstatus(sc, bif);
+	}
+        STPLOG (("\n"));
+
+	if (bstp_timer_expired(&sc->sc_hello_timer, sc->sc_hello_time))
+		bstp_hello_timer_expiry(sc);
+
+	if (bstp_timer_expired(&sc->sc_tcn_timer, sc->sc_bridge_hello_time))
+		bstp_tcn_timer_expiry(sc);
+
+	if (bstp_timer_expired(&sc->sc_topology_change_timer,
+                               sc->sc_topology_change_time))
+                bstp_topology_change_timer_expiry(sc);
+
+	LIST_FOREACH(bif, &sc->sc_iflist, next) {
+		if (!(bif->bif_flags & IFBIF_STP))
+			continue;
+		if (bstp_timer_expired(&bif->bif_message_age_timer,
+		    sc->sc_max_age))
+			bstp_message_age_timer_expiry(sc, bif);
+	}
+
+	LIST_FOREACH(bif, &sc->sc_iflist, next) {
+		if (!(bif->bif_flags & IFBIF_STP))
+			continue;
+		if (bstp_timer_expired(&bif->bif_forward_delay_timer,
+		    sc->sc_forward_delay))
+			bstp_forward_delay_timer_expiry(sc, bif);
+
+		if (bstp_timer_expired(&bif->bif_hold_timer,
+		    sc->sc_hold_time))
+			bstp_hold_timer_expiry(sc, bif);
+	}
+
+#ifdef __ECOS
+	if (sc->sc_if.if_flags & IFF_RUNNING) {
+                timeout (bstp_tick, sc, hz);
+        }
+#else
+        if (sc->sc_if.if_flags & IFF_RUNNING)
+             timeout_add(&sc->sc_bstptimeout, hz);
+#endif   //__ECOS
+
+	splx(s);
+}
+
+void
+bstp_timer_start(t, v)
+	struct bridge_timer *t;
+	u_int16_t v;
+{
+	t->value = v;
+	t->active = 1;
+}
+
+void
+bstp_timer_stop(t)
+	struct bridge_timer *t;
+{
+	t->value = 0;
+	t->active = 0;
+}
+
+int
+bstp_timer_expired(t, v)
+	struct bridge_timer *t;
+	u_int16_t v;
+{
+	if (!t->active)
+		return (0);
+	t->value += BSTP_TICK_VAL;
+	if (t->value >= v) {
+		bstp_timer_stop(t);
+		return (1);
+	}
+	return (0);
+
+}
+
+int
+bstp_ioctl(ifp, cmd, data)
+	struct ifnet *ifp;
+	u_long cmd;
+	caddr_t	data;
+{
+	struct ifbrparam *bp = (struct ifbrparam *)data;
+	struct bridge_softc *sc = (struct bridge_softc *)ifp;
+	int r = 0, err = 0;
+
+	switch (cmd) {
+	case SIOCBRDGGPRI:
+		bp->ifbrp_prio = sc->sc_bridge_priority;
+		break;
+	case SIOCBRDGGMA:
+		bp->ifbrp_maxage = sc->sc_bridge_max_age >> 8;
+		break;
+	case SIOCBRDGGHT:
+		bp->ifbrp_hellotime = sc->sc_bridge_hello_time >> 8;
+		break;
+	case SIOCBRDGGFD:
+		bp->ifbrp_fwddelay = sc->sc_bridge_forward_delay >> 8;
+		break;
+	case SIOCBRDGSPRI:
+		sc->sc_bridge_priority = bp->ifbrp_prio;
+		r = 1;
+		break;
+	case SIOCBRDGSMA:
+		if (bp->ifbrp_maxage == 0) {
+			err = EINVAL;
+			break;
+		}
+		sc->sc_bridge_max_age = bp->ifbrp_maxage << 8;
+		r = 1;
+		break;
+	case SIOCBRDGSHT:
+		if (bp->ifbrp_hellotime == 0) {
+			err = EINVAL;
+			break;
+		}
+		sc->sc_bridge_hello_time = bp->ifbrp_hellotime << 8;
+		r = 1;
+		break;
+	case SIOCBRDGSFD:
+		if (bp->ifbrp_fwddelay == 0) {
+			err = EINVAL;
+			break;
+		}
+		sc->sc_bridge_forward_delay = bp->ifbrp_fwddelay << 8;
+		r = 1;
+		break;
+	case SIOCBRDGSIFCOST:
+	case SIOCBRDGSIFPRIO:
+	case SIOCBRDGSIFFLGS:
+	case SIOCBRDGADD:
+	case SIOCBRDGDEL:
+                r = 1;
+		break;
+	default:
+		break;
+	}
+
+	if (r)
+		bstp_initialization(sc);
+
+	return (err);
+}
+
+#endif   /* NBRIDGE */
+#endif   /* CYGPKG_NET_BRIDGE_STP_CODE */
--- a/packages/net/tcpip/current/src/sys/net/if_bridge.c
+++ b/packages/net/tcpip/current/src/sys/net/if_bridge.c
@@ -19,7 +19,7 @@
 //#####DESCRIPTIONBEGIN####
 //
 // Author(s):    Jason L. Wright (jason@thought.net)  
-// Contributors: andrew.lunn@ascom.ch (Andrew Lunn), hmt
+// Contributors: andrew.lunn@ascom.ch (Andrew Lunn), hmt, manu.sharma@ascom.com
 // Date:         2000-07-18
 // Purpose:      Ethernet bridge
 // Description:  
@@ -136,52 +136,16 @@
 #define BRIDGE_RTABLE_TIMEOUT	300
 #endif
 
-extern int ifqmaxlen;
-
-/*
- * Bridge filtering rules
- */
-struct brl_node {
-	SIMPLEQ_ENTRY(brl_node)	brl_next;	/* next rule */
-	struct ether_addr	brl_src;	/* source mac address */
-	struct ether_addr	brl_dst;	/* destination mac address */
-	u_int8_t		brl_action;	/* what to do with match */
-	u_int8_t		brl_flags;	/* comparision flags */
-};
+/* Spanning tree defaults */
+#define BSTP_DEFAULT_MAX_AGE            (20 * 256)
+#define BSTP_DEFAULT_HELLO_TIME         (2 * 256)
+#define BSTP_DEFAULT_FORWARD_DELAY      (15 * 256)
+#define BSTP_DEFAULT_HOLD_TIME          (1 * 256)
+#define BSTP_DEFAULT_BRIDGE_PRIORITY    0x8000
+#define BSTP_DEFAULT_PORT_PRIORITY      0x80
+#define BSTP_DEFAULT_PATH_COST          55
 
-/*
- * Bridge interface list
- */
-struct bridge_iflist {
-	LIST_ENTRY(bridge_iflist)	next;		/* next in list */
-	SIMPLEQ_HEAD(, brl_node)	bif_brlin;	/* input rules */
-	SIMPLEQ_HEAD(, brl_node)	bif_brlout;	/* output rules */
-	struct				ifnet *ifp;	/* member interface */
-	u_int32_t			bif_flags;	/* member flags */
-};
-
-/*
- * Bridge route node
- */
-struct bridge_rtnode {
-	LIST_ENTRY(bridge_rtnode)	brt_next;	/* next in list */
-	struct				ifnet *brt_if;	/* destination ifs */
-	u_int8_t			brt_flags;	/* address flags */
-	u_int8_t			brt_age;	/* age counter */
-	struct				ether_addr brt_addr;	/* dst addr */
-};
-
-/*
- * Software state for each bridge
- */
-struct bridge_softc {
-	struct				ifnet sc_if;	/* the interface */
-	u_int32_t			sc_brtmax;	/* max # addresses */
-	u_int32_t			sc_brtcnt;	/* current # addrs */
-	u_int32_t			sc_brttimeout;	/* timeout ticks */
-	LIST_HEAD(, bridge_iflist)	sc_iflist;	/* interface list */
-	LIST_HEAD(bridge_rthead, bridge_rtnode)	*sc_rts;/* hash table */
-};
+extern int ifqmaxlen;
 
 /* SNAP LLC header */
 struct snap {
@@ -207,7 +171,6 @@ int	bridge_bifconf __P((struct bridge_so
 int	bridge_rtfind __P((struct bridge_softc *, struct ifbaconf *));
 void	bridge_rtage __P((void *));
 void	bridge_rttrim __P((struct bridge_softc *));
-void	bridge_rtdelete __P((struct bridge_softc *, struct ifnet *));
 int	bridge_rtdaddr __P((struct bridge_softc *, struct ether_addr *));
 int	bridge_rtflush __P((struct bridge_softc *, int));
 struct ifnet *	bridge_rtupdate __P((struct bridge_softc *,
@@ -221,6 +184,11 @@ int		bridge_addrule __P((struct bridge_i
 int		bridge_flushrule __P((struct bridge_iflist *));
 int	bridge_brlconf __P((struct bridge_softc *, struct ifbrlconf *));
 u_int8_t bridge_filterrule __P((struct brl_node *, struct ether_header *));
+int     bridge_ifenqueue __P((struct bridge_softc *, struct ifnet *, struct mbuf *));
+
+#ifdef CYGPKG_NET_BRIDGE_STP_CODE
+void bridge_span (struct bridge_softc *, struct ether_header *, struct mbuf *);
+#endif
 
 #define	ETHERADDR_IS_IP_MCAST(a) \
 	/* struct etheraddr *a;	*/				\
@@ -247,7 +215,13 @@ bridgeattach(unused)
 	for (i = 0; i < CYGNUM_NET_BRIDGES; i++) {
 		bridgectl[i].sc_brtmax = BRIDGE_RTABLE_MAX;
 		bridgectl[i].sc_brttimeout = (BRIDGE_RTABLE_TIMEOUT * hz) / 2;
+                bridgectl[i].sc_bridge_max_age = BSTP_DEFAULT_MAX_AGE;
+                bridgectl[i].sc_bridge_hello_time = BSTP_DEFAULT_HELLO_TIME;
+                bridgectl[i].sc_bridge_forward_delay= BSTP_DEFAULT_FORWARD_DELAY;
+                bridgectl[i].sc_bridge_priority = BSTP_DEFAULT_BRIDGE_PRIORITY;
+                bridgectl[i].sc_hold_time = BSTP_DEFAULT_HOLD_TIME;
 		LIST_INIT(&bridgectl[i].sc_iflist);
+		LIST_INIT(&bridgectl[i].sc_spanlist);
 		ifp = &bridgectl[i].sc_if;
 		sprintf(ifp->if_xname, "bridge%d", i);
 		ifp->if_softc = &bridgectl[i];
@@ -310,6 +284,19 @@ bridge_ioctl(ifp, cmd, data)
 			break;
 		}
 
+#ifdef CYGPKG_NET_BRIDGE_STP_CODE
+                /* If it's in the span list, it can't be a member. */
+                LIST_FOREACH(p, &sc->sc_spanlist, next) {
+                        if (p->ifp == ifs)
+                                break;
+                }
+                if (p != LIST_END(&sc->sc_spanlist)) {
+                        error = EBUSY;
+                        break;
+                }
+#endif
+
+
 		if (ifs->if_type == IFT_ETHER) {
 			if ((ifs->if_flags & IFF_UP) == 0) {
 				/*
@@ -373,6 +360,8 @@ bridge_ioctl(ifp, cmd, data)
 
 		p->ifp = ifs;
 		p->bif_flags = IFBIF_LEARNING | IFBIF_DISCOVER;
+                p->bif_priority = BSTP_DEFAULT_PORT_PRIORITY;
+                p->bif_path_cost = BSTP_DEFAULT_PATH_COST;
 		SIMPLEQ_INIT(&p->bif_brlin);
 		SIMPLEQ_INIT(&p->bif_brlout);
 		LIST_INSERT_HEAD(&sc->sc_iflist, p, next);
@@ -392,7 +381,7 @@ bridge_ioctl(ifp, cmd, data)
 				error = ifpromisc(p->ifp, 0);
 
 				LIST_REMOVE(p, next);
-				bridge_rtdelete(sc, p->ifp);
+				bridge_rtdelete(sc, p->ifp, 0);
 				bridge_flushrule(p);
 				free(p, M_DEVBUF);
 				break;
@@ -407,6 +396,67 @@ bridge_ioctl(ifp, cmd, data)
 	case SIOCBRDGIFS:
 		error = bridge_bifconf(sc, bifconf);
 		break;
+#ifdef CYGPKG_NET_BRIDGE_STP_CODE
+        case SIOCBRDGADDS:
+#ifndef __ECOS
+                if ((error = suser(prc->p_ucred, &prc->p_acflag)) != 0)
+                        break;
+#endif
+
+                ifs = ifunit(req->ifbr_ifsname);
+                if (ifs == NULL) {                      /* no such interface */
+                        error = ENOENT;
+                        break;
+                }
+                if (ifs->if_bridge == (caddr_t)sc) {
+                        error = EEXIST;
+                        break;
+                }
+                if (ifs->if_bridge != NULL) {
+                        error = EBUSY;
+                        break;
+                }
+                LIST_FOREACH(p, &sc->sc_spanlist, next) {
+                        if (p->ifp == ifs)
+                        break;
+                }
+                if (p != LIST_END(&sc->sc_spanlist)) {
+                        error = EBUSY;
+                        break;
+                }
+                p = (struct bridge_iflist *)malloc(
+                    sizeof(struct bridge_iflist), M_DEVBUF, M_NOWAIT);
+                if (p == NULL) {
+                       error = ENOMEM;
+                       break;
+                }
+                bzero(p, sizeof(struct bridge_iflist));
+                p->ifp = ifs;
+                SIMPLEQ_INIT(&p->bif_brlin);
+                SIMPLEQ_INIT(&p->bif_brlout);
+                LIST_INSERT_HEAD(&sc->sc_spanlist, p, next);
+                break;
+                                                                                                                                                                                                           case SIOCBRDGDELS:
+#ifndef __ECOS
+                if ((error = suser(prc->p_ucred, &prc->p_acflag)) != 0)
+                       break;
+#endif
+
+                LIST_FOREACH(p, &sc->sc_spanlist, next) {
+                       if (strncmp(p->ifp->if_xname, req->ifbr_ifsname,
+                          sizeof(p->ifp->if_xname)) == 0) {
+                              LIST_REMOVE(p, next);
+                              free(p, M_DEVBUF);
+                              break;
+                       }
+                }
+                if (p == LIST_END(&sc->sc_spanlist)) {
+                       error = ENOENT;
+                       break;
+                }
+                break;
+#endif
+
 	case SIOCBRDGGIFFLGS:
 		ifs = ifunit(req->ifbr_ifsname);
 		if (ifs == NULL) {
@@ -426,6 +476,10 @@ bridge_ioctl(ifp, cmd, data)
 			break;
 		}
 		req->ifbr_ifsflags = p->bif_flags;
+                req->ifbr_state = p->bif_state;
+                req->ifbr_priority = p->bif_priority;
+                req->ifbr_path_cost = p->bif_path_cost;
+                req->ifbr_portno = p->ifp->if_index & 0xff;
 		break;
 	case SIOCBRDGSIFFLGS:
 #ifndef __ECOS
@@ -451,6 +505,39 @@ bridge_ioctl(ifp, cmd, data)
 		}
 		p->bif_flags = req->ifbr_ifsflags;
 		break;
+        case SIOCBRDGSIFPRIO:
+        case SIOCBRDGSIFCOST:
+#ifndef __ECOS
+                if ((error = suser(prc->p_ucred, &prc->p_acflag)) != 0)
+                        break;
+#endif
+
+                ifs = ifunit(req->ifbr_ifsname);
+                if (ifs == NULL) {
+                        error = ENOENT;
+                        break;
+                }
+                if ((caddr_t)sc != ifs->if_bridge) {
+                        error = ESRCH;
+                        break;
+                }
+                LIST_FOREACH(p, &sc->sc_iflist, next) {
+                        if (p->ifp == ifs)
+                        break;
+                }
+                if (p == LIST_END(&sc->sc_iflist)) {
+                        error = ESRCH;
+                        break;
+                }
+                if (cmd == SIOCBRDGSIFPRIO)
+                        p->bif_priority = req->ifbr_priority;
+                else {
+                        if (req->ifbr_path_cost < 1)
+                                error = EINVAL;
+                        else
+                                p->bif_path_cost = req->ifbr_path_cost;
+                }
+                break;
 	case SIOCBRDGRTS:
 		error = bridge_rtfind(sc, baconf);
 		break;
@@ -590,9 +677,27 @@ bridge_ioctl(ifp, cmd, data)
 	case SIOCBRDGGRL:
 		error = bridge_brlconf(sc, brlconf);
 		break;
+        case SIOCBRDGGPRI:
+        case SIOCBRDGGMA:
+        case SIOCBRDGGHT:
+        case SIOCBRDGGFD:
+                break;
+        case SIOCBRDGSPRI:
+        case SIOCBRDGSFD:
+        case SIOCBRDGSMA:
+        case SIOCBRDGSHT:
+#ifndef __ECOS
+                error = suser(prc->p_ucred, &prc->p_acflag);
+#endif
+                break;
 	default:
 		error = EINVAL;
 	}
+
+#ifdef CYGPKG_NET_BRIDGE_STP_CODE
+        if (!error)
+                error = bstp_ioctl(ifp, cmd, data);
+#endif
 	splx(s);
 	return (error);
 }
@@ -609,7 +714,7 @@ bridge_ifdetach(ifp)
 	    bif = LIST_NEXT(bif, next))
 		if (bif->ifp == ifp) {
 			LIST_REMOVE(bif, next);
-			bridge_rtdelete(bsc, ifp);
+			bridge_rtdelete(bsc, ifp, 0);
 			bridge_flushrule(bif);
 			free(bif, M_DEVBUF);
 			ifp->if_bridge = NULL;
@@ -624,6 +729,9 @@ bridge_bifconf(sc, bifc)
 {
 	struct bridge_iflist *p;
 	u_int32_t total = 0, i;
+#ifdef CYGPKG_NET_BRIDGE_STP_CODE
+        u_int32_t j;
+#endif
 	int error = 0;
 	struct ifbreq breq;
 
@@ -633,6 +741,14 @@ bridge_bifconf(sc, bifc)
 		p = LIST_NEXT(p, next);
 	}
 
+#ifdef CYGPKG_NET_BRIDGE_STP_CODE
+        p = LIST_FIRST(&sc->sc_spanlist);
+        while (p != NULL) {
+                total++;
+                p = LIST_NEXT(p, next);
+        }
+#endif
+
 	if (bifc->ifbic_len == 0) {
 		i = total;
 		goto done;
@@ -648,6 +764,10 @@ bridge_bifconf(sc, bifc)
 		    sizeof(breq.ifbr_ifsname)-1);
 		breq.ifbr_ifsname[sizeof(breq.ifbr_ifsname) - 1] = '\0';
 		breq.ifbr_ifsflags = p->bif_flags;
+                breq.ifbr_state = p->bif_state;
+                breq.ifbr_priority = p->bif_priority;
+                breq.ifbr_path_cost = p->bif_path_cost;
+                breq.ifbr_portno = p->ifp->if_index & 0xff;
 		error = copyout((caddr_t)&breq,
 		    (caddr_t)(bifc->ifbic_req + i), sizeof(breq));
 		if (error)
@@ -656,6 +776,31 @@ bridge_bifconf(sc, bifc)
 		i++;
 		bifc->ifbic_len -= sizeof(breq);
 	}
+
+#ifdef CYGPKG_NET_BRIDGE_STP_CODE
+        p = LIST_FIRST(&sc->sc_spanlist);
+        j = 0;
+        while (p != NULL && bifc->ifbic_len > j * sizeof(breq)) {
+                strncpy(breq.ifbr_name, sc->sc_if.if_xname,
+                        sizeof(breq.ifbr_name)-1);
+                breq.ifbr_name[sizeof(breq.ifbr_name) - 1] = '\0';
+                strncpy(breq.ifbr_ifsname, p->ifp->if_xname,
+                    sizeof(breq.ifbr_ifsname)-1);
+                breq.ifbr_ifsname[sizeof(breq.ifbr_ifsname) - 1] = '\0';
+                 breq.ifbr_ifsflags = p->bif_flags | IFBIF_SPAN;
+                breq.ifbr_state = p->bif_state;
+                breq.ifbr_priority = p->bif_priority;
+                breq.ifbr_path_cost = p->bif_path_cost;
+                breq.ifbr_portno = p->ifp->if_index & 0xff;
+                error = copyout((caddr_t)&breq,
+                    (caddr_t)(bifc->ifbic_req + j), sizeof(breq));
+                if (error)
+                        goto done;
+                p = LIST_NEXT(p, next);
+                j++;
+                bifc->ifbic_len -= sizeof(breq);
+        }
+#endif
 done:
 	bifc->ifbic_len = i * sizeof(breq);
 	return (error);
@@ -774,7 +919,7 @@ bridge_init(sc)
 	ifp->if_flags |= IFF_RUNNING;
 	splx(s);
 
-	if (sc->sc_brttimeout != 0)
+	if (sc->sc_brttimeout != 0) 
 		timeout(bridge_rtage, sc, sc->sc_brttimeout);
 }
 
@@ -849,6 +994,10 @@ bridge_output(ifp, m, sa, rt)
 		struct mbuf *mc;
 		int used = 0;
 
+#ifdef CYGPKG_NET_BRIDGE_STP_CODE
+                bridge_span(sc, NULL, m);
+#endif
+
 		for (p = LIST_FIRST(&sc->sc_iflist); p != NULL;
 		     p = LIST_NEXT(p, next)) {
 			if ((p->ifp->if_flags & IFF_RUNNING) == 0)
@@ -958,6 +1107,23 @@ bridgeintr_frame(sc, m)
 
 	src_if = m->m_pkthdr.rcvif;
 
+        /* 
+         * Pick out 802.1D packets.
+         *                   */
+#ifdef CYGPKG_NET_BRIDGE_STP_CODE
+#ifdef __ECOS
+        if (m->m_flags & (M_BCAST | M_MCAST)) {
+                if (bcmp (mtod(m,struct ether_header *), bstp_etheraddr, ETHER_ADDR_LEN) == 0) {
+                        m_copydata(m, 0, sizeof(struct ether_header), (caddr_t)&eh);
+                        m_adj (m, sizeof(struct ether_header));
+                        m = bstp_input(sc, src_if, &eh, m);
+                        if (m == NULL)
+                                return;
+                 }
+        }
+#endif   // __ECOS
+#endif
+
 #if NBPFILTER > 0
 	if (sc->sc_if.if_bpf)
 		bpf_mtap(sc->sc_if.if_bpf, m);
@@ -976,6 +1142,16 @@ bridgeintr_frame(sc, m)
 		return;
 	}
 
+#ifdef CYGPKG_NET_BRIDGE_STP_CODE
+        if ((ifl->bif_flags & IFBIF_STP) &&
+            (ifl->bif_state == BSTP_IFSTATE_BLOCKING ||
+            ifl->bif_state == BSTP_IFSTATE_LISTENING ||
+            ifl->bif_state == BSTP_IFSTATE_DISABLED)) {
+                m_freem(m);
+                return;
+        }
+#endif
+
 	if (m->m_pkthdr.len < sizeof(eh)) {
 		m_freem(m);
 		return;
@@ -998,6 +1174,18 @@ bridgeintr_frame(sc, m)
 	      eh.ether_shost[5] == 0))
 		bridge_rtupdate(sc, src, src_if, 0, IFBAF_DYNAMIC);
 
+#ifdef CYGPKG_NET_BRIDGE_STP_CODE
+        if ((ifl->bif_flags & IFBIF_STP) &&
+            (ifl->bif_state == BSTP_IFSTATE_LEARNING)) {
+                m_freem(m);
+                return;
+        }
+#endif
+        /*
+         * At this point, the port either does not participate in stp or
+         * it is in forwarding state.
+         */
+
 	/*
 	 * If packet is unicast, destined for someone on "this"
 	 * side of the bridge, drop it.
@@ -1082,6 +1270,15 @@ bridgeintr_frame(sc, m)
 	ifl = LIST_FIRST(&sc->sc_iflist);
 	while (ifl != NULL && ifl->ifp != dst_if)
 		ifl = LIST_NEXT(ifl, next);
+#ifdef CYGPKG_NET_BRIDGE_STP_CODE
+        if ((ifl->bif_flags & IFBIF_STP) &&
+            (ifl->bif_state == BSTP_IFSTATE_DISABLED ||
+            ifl->bif_state == BSTP_IFSTATE_BLOCKING)) {
+                m_freem(m);
+                return;
+        }
+#endif
+
 	if (SIMPLEQ_FIRST(&ifl->bif_brlout) &&
 	    bridge_filterrule(SIMPLEQ_FIRST(&ifl->bif_brlout), &eh) ==
 	    BRL_ACTION_BLOCK) {
@@ -1135,6 +1332,45 @@ bridge_input(ifp, eh, m)
 	if ((sc->sc_if.if_flags & IFF_RUNNING) == 0)
 		return (m);
 
+        LIST_FOREACH (ifl, &sc->sc_iflist, next) {
+                if (ifl->ifp == ifp)
+                        break;
+        }
+        if (ifl == LIST_END (&sc->sc_iflist))
+                return (m);
+
+#ifdef CYGPKG_NET_BRIDGE_STP_CODE
+        bridge_span(sc, eh, m);
+        /*
+         * Tap off 802.1D packets, they do not get forwarded 
+         */
+        if (m->m_flags & (M_BCAST | M_MCAST)) {
+                if (bcmp(eh->ether_dhost, bstp_etheraddr, ETHER_ADDR_LEN) == 0) {
+#ifdef __ECOS
+                        M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT);
+                        if (m == NULL)
+                                return (NULL);
+                        bcopy(eh, mtod(m, caddr_t), sizeof(struct ether_header));
+
+                        s = splimp ();
+                        if (IF_QFULL(&sc->sc_if.if_snd)) {
+                                m_freem (m);
+                                splx (s);
+                                return (NULL);
+                        }
+                        IF_ENQUEUE(&sc->sc_if.if_snd, m);
+                        splx (s);
+                        schednetisr (NETISR_BRIDGE);
+                        return (NULL);
+#else
+                        m = bstp_input(sc, ifp, eh, m);
+                        if (m == NULL)
+                                return (NULL);
+#endif
+                }
+        }
+#endif
+
 	if (m->m_flags & (M_BCAST | M_MCAST)) {
 		/*
 		 * make a copy of 'm' with 'eh' tacked on to the
@@ -1160,6 +1396,17 @@ bridge_input(ifp, eh, m)
 		return (m);
 	}
 
+        /*
+         * No need to queue frames for ifs in blocking, disabled or listening state
+         */
+#ifdef CYGPKG_NET_BRIDGE_STP_CODE
+        if ((ifl->bif_flags & IFBIF_STP) &&
+            ((ifl->bif_state == BSTP_IFSTATE_BLOCKING) ||
+             (ifl->bif_state == BSTP_IFSTATE_LISTENING) ||
+             (ifl->bif_state == BSTP_IFSTATE_DISABLED)))
+                 return (m);
+#endif
+
 	/*
 	 * Unicast, make sure it's not for us.
 	 */
@@ -1220,6 +1467,12 @@ bridge_broadcast(sc, ifp, eh, m)
 		if (p->ifp->if_index == ifp->if_index)
 			continue;
 
+#ifdef CYGPKG_NET_BRIDGE_STP_CODE
+                if ((p->bif_flags & IFBIF_STP) &&
+                    (p->bif_state != BSTP_IFSTATE_FORWARDING))
+                        continue;
+#endif
+
 		if ((p->bif_flags & IFBIF_DISCOVER) == 0 &&
 		    (m->m_flags & (M_BCAST | M_MCAST)) == 0)
 			continue;
@@ -1271,6 +1524,60 @@ bridge_broadcast(sc, ifp, eh, m)
 		m_freem(m);
 }
 
+#ifdef CYGPKG_NET_BRIDGE_STP_CODE
+void
+bridge_span(sc, eh, morig)
+        struct bridge_softc *sc;
+        struct ether_header *eh;
+        struct mbuf *morig;
+{
+        struct bridge_iflist *p;
+        struct ifnet *ifp;
+        struct mbuf *mc, *m;
+        int error;
+
+        if (LIST_EMPTY(&sc->sc_spanlist))
+                return;
+
+        m = m_copym2(morig, 0, M_COPYALL, M_NOWAIT);
+        if (m == NULL)
+                return;
+        if (eh != NULL) {
+                M_PREPEND(m, sizeof(struct ether_header), M_DONTWAIT);
+                if (m == NULL)
+                        return;
+                bcopy(eh, mtod(m, caddr_t), sizeof(struct ether_header));
+        }
+
+        LIST_FOREACH(p, &sc->sc_spanlist, next) {
+                ifp = p->ifp;
+
+                if ((ifp->if_flags & IFF_RUNNING) == 0)
+                        continue;
+
+#ifdef ALTQ
+                if (ALTQ_IS_ENABLED(&ifp->if_snd) == 0)
+#endif
+                        if (IF_QFULL(&ifp->if_snd)) {
+                                IF_DROP(&ifp->if_snd);
+                                sc->sc_if.if_oerrors++;
+                                continue;
+                        }
+
+                mc = m_copym(m, 0, M_COPYALL, M_DONTWAIT);
+                if (mc == NULL) {
+                        sc->sc_if.if_oerrors++;
+                        continue;
+                }
+
+                error = bridge_ifenqueue(sc, ifp, m);
+                if (error)
+                        continue;
+        }
+        m_freem(m);
+}
+#endif
+
 struct ifnet *
 bridge_rtupdate(sc, ea, ifp, setflags, flags)
 	struct bridge_softc *sc;
@@ -1641,7 +1948,7 @@ done:
  * Delete routes to a specific interface member.
  */
 void
-bridge_rtdelete(sc, ifp)
+bridge_rtdelete(sc, ifp, dynonly)
 	struct bridge_softc *sc;
 	struct ifnet *ifp;
 {
@@ -2018,3 +2325,28 @@ ifpromisc(ifp, pswitch)
 	return ((*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr));
 }
 
+int
+bridge_ifenqueue(sc, ifp, m)
+        struct bridge_softc *sc;
+        struct ifnet *ifp;
+        struct mbuf *m;
+{
+        int error, len;
+        short mflags;
+
+        len = m->m_pkthdr.len;
+        mflags = m->m_flags;
+        IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error);
+        if (error) {
+                sc->sc_if.if_oerrors++;
+                return (error);
+        }
+        sc->sc_if.if_opackets++;
+        sc->sc_if.if_obytes += len;
+        ifp->if_obytes += len;
+        if (mflags & M_MCAST)
+                ifp->if_omcasts++;
+        if ((ifp->if_flags & IFF_OACTIVE) == 0)
+                (*ifp->if_start)(ifp);
+                                                                                                           return (0);
+}