? doc/sgml/asleep.png ? doc/sgml/awake.png ? doc/sgml/filters.png ? doc/sgml/layout.png ? doc/sgml/menu_edit.png ? doc/sgml/menu_file.png ? doc/sgml/menu_help.png ? doc/sgml/menu_view.png ? doc/sgml/overview.png ? doc/sgml/preferences.png ? doc/sgml/screen_main.png ? doc/sgml/simple.png ? doc/sgml/synth-io-overview.png ? doc/sgml/tcpip.png ? doc/sgml/tutorials/ecos-tutorial.aux ? doc/sgml/tutorials/ecos-tutorial.log ? doc/sgml/tutorials/ecos-tutorial.out ? doc/sgml/tutorials/ecos-tutorial.pdf ? doc/sgml/tutorials/ecos-tutorial.tex Index: doc/ChangeLog =================================================================== RCS file: /cvs/ecos/ecos/doc/ChangeLog,v retrieving revision 1.20 diff -u -r1.20 ChangeLog --- doc/ChangeLog 22 Nov 2003 13:06:58 -0000 1.20 +++ doc/ChangeLog 27 Nov 2003 15:08:16 -0000 @@ -1,3 +1,7 @@ +2003-11-25 Manu Sharma + + * sgml/doclist: Add OpenBSD specific documentation. + 2003-11-22 Andrew Lunn * sgml/doclist: Added ipsec packages documentation Index: doc/sgml/doclist =================================================================== RCS file: /cvs/ecos/ecos/doc/sgml/doclist,v retrieving revision 1.11 diff -u -r1.11 doclist --- doc/sgml/doclist 22 Nov 2003 13:06:58 -0000 1.11 +++ doc/sgml/doclist 27 Nov 2003 15:08:16 -0000 @@ -16,6 +16,9 @@ net/common/current/doc/tcpip-manpages.sgml net/bsd_tcpip/current/doc/freebsd.sgml net/tcpip/current/doc/openbsd.sgml +net/tcpip/current/doc/openbsd-manpages-bridge.sgml +net/tcpip/current/doc/openbsd-manpages-netintro.sgml +net/tcpip/current/doc/openbsd-manpages-stp.sgml net/ns/dns/current/doc/dns.sgml net/common/current/doc/ipsec.sgml net/ipsec/libipsec/current/doc/libipsec-manpages.sgml Index: doc/sgml/makemakefile =================================================================== RCS file: /cvs/ecos/ecos/doc/sgml/makemakefile,v retrieving revision 1.15 diff -u -r1.15 makemakefile --- doc/sgml/makemakefile 22 Nov 2003 13:06:58 -0000 1.15 +++ doc/sgml/makemakefile 27 Nov 2003 15:08:17 -0000 @@ -213,6 +213,9 @@ "`basename $i`" != "snmp-manpages.sgml" -a \ "`basename $i`" != "libipsec.sgml" -a \ "`basename $i`" != "libipsec-manpages.sgml" -a \ + "`basename $i`" != "openbsd-manpages-bridge.sgml" -a \ + "`basename $i`" != "openbsd-manpages-netintro.sgml" -a \ + "`basename $i`" != "openbsd-manpages-stp.sgml" -a \ "`basename $i`" != "porting.sgml" ]; then echo "&$entityi;" >> ecos-ref.sgml fi Index: packages/net/common/current/ChangeLog =================================================================== RCS file: /cvs/ecos/ecos-opt/net/net/common/current/ChangeLog,v retrieving revision 1.52 diff -u -r1.52 ChangeLog --- packages/net/common/current/ChangeLog 24 Nov 2003 14:09:25 -0000 1.52 +++ packages/net/common/current/ChangeLog 27 Nov 2003 15:08:19 -0000 @@ -1,3 +1,8 @@ +2003-11-25 Manu Sharma + + * tests/bridge.c: Changes to enable Spanning Tree Protocol if the + corresponding CDL component is enabled. + 2003-11-24 Jani Monoses * cdl/net.cdl: Close quote for test list. Index: packages/net/common/current/tests/bridge.c =================================================================== RCS file: /cvs/ecos/ecos-opt/net/net/common/current/tests/bridge.c,v retrieving revision 1.3 diff -u -r1.3 bridge.c --- packages/net/common/current/tests/bridge.c 6 Oct 2003 19:07:50 -0000 1.3 +++ packages/net/common/current/tests/bridge.c 27 Nov 2003 15:08:21 -0000 @@ -67,6 +67,7 @@ #include #include #include + #ifdef CYGPKG_NET_BRIDGE_HANDLER #include #include @@ -955,11 +956,17 @@ interface_up("eth0"); eth0_up = 1; bridge_add(sock,brdg,"eth0"); +#ifdef CYGPKG_NET_BRIDGE_STP_CODE + bridge_ifsetflag (sock, brdg, "eth0", IFBIF_STP); +#endif #endif #ifdef CYGHWR_NET_DRIVER_ETH1 interface_up("eth1"); eth1_up = 1; bridge_add(sock,brdg,"eth1"); +#ifdef CYGPKG_NET_BRIDGE_STP_CODE + bridge_ifsetflag (sock, brdg, "eth1", IFBIF_STP); +#endif #endif bridge_status(sock,brdg); Index: packages/net/tcpip//current/ChangeLog =================================================================== RCS file: /cvs/ecos/ecos-opt/net/net/tcpip/current/ChangeLog,v retrieving revision 1.44 diff -u -r1.44 ChangeLog --- packages/net/tcpip//current/ChangeLog 22 Sep 2003 15:33:36 -0000 1.44 +++ packages/net/tcpip//current/ChangeLog 27 Nov 2003 15:08:26 -0000 @@ -1,3 +1,18 @@ +2003-11-25 Manu Sharma + * 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 * include/net/if.h: Define macro IF_IS_EMPTY needed by eth_drv.c Index: packages/net/tcpip//current/cdl/openbsd_net.cdl =================================================================== RCS file: /cvs/ecos/ecos-opt/net/net/tcpip/current/cdl/openbsd_net.cdl,v retrieving revision 1.2 diff -u -r1.2 openbsd_net.cdl --- packages/net/tcpip//current/cdl/openbsd_net.cdl 24 Feb 2003 14:31:59 -0000 1.2 +++ packages/net/tcpip//current/cdl/openbsd_net.cdl 27 Nov 2003 15:08:31 -0000 @@ -186,13 +186,22 @@ 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" flavor data 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." } } Index: packages/net/tcpip//current/doc/openbsd-manpages-bridge.sgml =================================================================== RCS file: packages/net/tcpip//current/doc/openbsd-manpages-bridge.sgml diff -N packages/net/tcpip//current/doc/openbsd-manpages-bridge.sgml --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ packages/net/tcpip//current/doc/openbsd-manpages-bridge.sgml 27 Nov 2003 15:08:31 -0000 @@ -0,0 +1,452 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Bridging + + +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 netintro. The following ioctl calls are + specific to bridge devices. They are defined in <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 + netintro, spanning-tree + +AUTHORS + The bridge kernel interface was written by Jason L. Wright + <jason@thought.net> as part of an undergraduate independent study at + the University of North Carolina at Greensboro. + + + + + Index: packages/net/tcpip//current/doc/openbsd-manpages-netintro.sgml =================================================================== RCS file: packages/net/tcpip//current/doc/openbsd-manpages-netintro.sgml diff -N packages/net/tcpip//current/doc/openbsd-manpages-netintro.sgml --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ packages/net/tcpip//current/doc/openbsd-manpages-netintro.sgml 27 Nov 2003 15:08:31 -0000 @@ -0,0 +1,310 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +OpenBSD networking facilities + + +NAME + networking - introduction to networking facilities + +SYNOPSIS + #include <sys/socket.h> + #include <net/route.h> + #include <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 + socket 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 socket. + 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 + bridge, spanning-tree + + + + + + Index: packages/net/tcpip//current/doc/openbsd-manpages-stp.sgml =================================================================== RCS file: packages/net/tcpip//current/doc/openbsd-manpages-stp.sgml diff -N packages/net/tcpip//current/doc/openbsd-manpages-stp.sgml --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ packages/net/tcpip//current/doc/openbsd-manpages-stp.sgml 27 Nov 2003 15:08:31 -0000 @@ -0,0 +1,137 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Spanning Tree Protocol + +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 bridge section. + The following ioctl calls are specific to STP functionality. They are + defined in <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 bridge. + +SEE ALSO + netintro, bridge + + + + + + Index: packages/net/tcpip//current/doc/openbsd.sgml =================================================================== RCS file: /cvs/ecos/ecos-opt/net/net/tcpip/current/doc/openbsd.sgml,v retrieving revision 1.2 diff -u -r1.2 openbsd.sgml --- packages/net/tcpip//current/doc/openbsd.sgml 15 Sep 2002 21:44:46 -0000 1.2 +++ packages/net/tcpip//current/doc/openbsd.sgml 27 Nov 2003 15:08:32 -0000 @@ -42,6 +42,8 @@ Networking Stack Features + +Introduction Since this networking package is based on BSD code, it is very complete and robust. The eCos implementation includes support for the following protocols: @@ -52,14 +54,18 @@ ICMP raw packet interface -These additional features are also present in the package, +Along with support for the above mentioned protocols, the OpenBSD +stack also supports ethernet bridging. + +The following additional features are also present in the package, but are not supported: Berkeley Packet Filter -Multi-cast and uni-cast support, including multi-casting +Multi-cast and uni-cast support, including multi-cast routing IPv6 + OpenBSD TCP/IP stack port @@ -113,6 +119,25 @@ support build options”. + +Inclusion of bridge code + +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. + +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. + APIs @@ -189,5 +214,8 @@ cyg_select_with_abort() call to cease waiting and continue execution. +&net-tcpip-openbsd-manpages-netintro-sgml +&net-tcpip-openbsd-manpages-bridge-sgml +&net-tcpip-openbsd-manpages-stp-sgml Index: packages/net/tcpip//current/include/net/if.h =================================================================== RCS file: /cvs/ecos/ecos-opt/net/net/tcpip/current/include/net/if.h,v retrieving revision 1.3 diff -u -r1.3 if.h --- packages/net/tcpip//current/include/net/if.h 22 Sep 2003 15:33:37 -0000 1.3 +++ packages/net/tcpip//current/include/net/if.h 27 Nov 2003 15:08:34 -0000 @@ -256,6 +256,19 @@ } #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 */ Index: packages/net/tcpip//current/include/net/if_bridge.h =================================================================== RCS file: /cvs/ecos/ecos-opt/net/net/tcpip/current/include/net/if_bridge.h,v retrieving revision 1.2 diff -u -r1.2 if_bridge.h --- packages/net/tcpip//current/include/net/if_bridge.h 20 May 2002 22:25:16 -0000 1.2 +++ packages/net/tcpip//current/include/net/if_bridge.h 27 Nov 2003 15:08:34 -0000 @@ -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 @@ * 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 */ -}; -#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 */ + 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 */ 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 */ Index: packages/net/tcpip//current/include/net/if_llc.h =================================================================== RCS file: /cvs/ecos/ecos-opt/net/net/tcpip/current/include/net/if_llc.h,v retrieving revision 1.2 diff -u -r1.2 if_llc.h --- packages/net/tcpip//current/include/net/if_llc.h 20 May 2002 22:25:16 -0000 1.2 +++ packages/net/tcpip//current/include/net/if_llc.h 27 Nov 2003 15:08:35 -0000 @@ -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_ Index: packages/net/tcpip//current/include/sys/sockio.h =================================================================== RCS file: /cvs/ecos/ecos-opt/net/net/tcpip/current/include/sys/sockio.h,v retrieving revision 1.4 diff -u -r1.4 sockio.h --- packages/net/tcpip//current/include/sys/sockio.h 20 May 2002 22:25:18 -0000 1.4 +++ packages/net/tcpip//current/include/sys/sockio.h 27 Nov 2003 15:08:36 -0000 @@ -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 /* 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 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 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 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 */ Index: packages/net/tcpip//current/src/sys/net/bridgestp.c =================================================================== RCS file: packages/net/tcpip//current/src/sys/net/bridgestp.c diff -N packages/net/tcpip//current/src/sys/net/bridgestp.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ packages/net/tcpip//current/src/sys/net/bridgestp.c 27 Nov 2003 15:08:40 -0000 @@ -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 +#include +#else +#include "bridge.h" +#endif + +#ifdef CYGPKG_NET_BRIDGE_STP_CODE +#if NBRIDGE + +#include +#ifndef __ECOS +#include +#endif +#include +#include +#include +#ifndef __ECOS +#include +#endif +#include + +#include +#include +#include +#include + +#ifdef INET +#include +#include +#include +#include +#include +#endif + +#if NBPFILTER > 0 +#include +#endif + +#include + +#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 : , 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 */ Index: packages/net/tcpip//current/src/sys/net/if_bridge.c =================================================================== RCS file: /cvs/ecos/ecos-opt/net/net/tcpip/current/src/sys/net/if_bridge.c,v retrieving revision 1.9 diff -u -r1.9 if_bridge.c --- packages/net/tcpip//current/src/sys/net/if_bridge.c 30 Jan 2003 15:38:02 -0000 1.9 +++ packages/net/tcpip//current/src/sys/net/if_bridge.c 27 Nov 2003 15:08:44 -0000 @@ -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 */ -}; - -/* - * 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 */ -}; +/* 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 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_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_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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ } 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 @@ 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 @@ 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 @@ { 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ * 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 @@ 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); +}