summaryrefslogtreecommitdiff
path: root/usr/src/lib/librstp
diff options
context:
space:
mode:
authorRishi Srivatsavai <Rishi.Srivatsavai@Sun.COM>2009-09-10 15:11:49 -0400
committerRishi Srivatsavai <Rishi.Srivatsavai@Sun.COM>2009-09-10 15:11:49 -0400
commit4eaa471005973e11a6110b69fe990530b3b95a38 (patch)
tree3aca4c2ad771c935bfa146d4a6abbe51ee464a57 /usr/src/lib/librstp
parentd5688513c1985c22c27675da44b5b691f123818e (diff)
downloadillumos-joyent-4eaa471005973e11a6110b69fe990530b3b95a38.tar.gz
PSARC 2007/596 RBridges: Routing Bridges
PSARC 2008/055 Solaris Bridging PSARC 2009/344 Bridging Updates 6223953 Solaris should provide layer 2 bridging 6770623 bogus error messages generated by dladm should be cleaned up
Diffstat (limited to 'usr/src/lib/librstp')
-rw-r--r--usr/src/lib/librstp/Makefile60
-rw-r--r--usr/src/lib/librstp/Makefile.com53
-rw-r--r--usr/src/lib/librstp/THIRDPARTYLICENSE.descrip1
-rw-r--r--usr/src/lib/librstp/common/COPYING504
-rw-r--r--usr/src/lib/librstp/common/ChangeLog62
-rw-r--r--usr/src/lib/librstp/common/README37
-rw-r--r--usr/src/lib/librstp/common/README.CVS.HOWTO22
-rw-r--r--usr/src/lib/librstp/common/README.authors3
-rw-r--r--usr/src/lib/librstp/common/README.files58
-rw-r--r--usr/src/lib/librstp/common/README.news19
-rw-r--r--usr/src/lib/librstp/common/TODO22
-rw-r--r--usr/src/lib/librstp/common/base.h198
-rw-r--r--usr/src/lib/librstp/common/choose.h42
-rw-r--r--usr/src/lib/librstp/common/edge.c115
-rw-r--r--usr/src/lib/librstp/common/edge.h38
-rw-r--r--usr/src/lib/librstp/common/llib-lrstp30
-rw-r--r--usr/src/lib/librstp/common/mapfile-vers71
-rw-r--r--usr/src/lib/librstp/common/migrate.c119
-rw-r--r--usr/src/lib/librstp/common/migrate.h37
-rw-r--r--usr/src/lib/librstp/common/p2p.c90
-rw-r--r--usr/src/lib/librstp/common/p2p.h37
-rw-r--r--usr/src/lib/librstp/common/pcost.c132
-rw-r--r--usr/src/lib/librstp/common/pcost.h37
-rw-r--r--usr/src/lib/librstp/common/port.c253
-rw-r--r--usr/src/lib/librstp/common/port.h185
-rw-r--r--usr/src/lib/librstp/common/portinfo.c509
-rw-r--r--usr/src/lib/librstp/common/portinfo.h40
-rw-r--r--usr/src/lib/librstp/common/rolesel.c400
-rw-r--r--usr/src/lib/librstp/common/rolesel.h41
-rw-r--r--usr/src/lib/librstp/common/roletrns.c431
-rw-r--r--usr/src/lib/librstp/common/roletrns.h37
-rw-r--r--usr/src/lib/librstp/common/statmch.c123
-rw-r--r--usr/src/lib/librstp/common/statmch.h89
-rw-r--r--usr/src/lib/librstp/common/stp_bpdu.h90
-rw-r--r--usr/src/lib/librstp/common/stp_in.c1026
-rw-r--r--usr/src/lib/librstp/common/stp_in.h227
-rw-r--r--usr/src/lib/librstp/common/stp_to.h48
-rw-r--r--usr/src/lib/librstp/common/stp_vectors.h90
-rw-r--r--usr/src/lib/librstp/common/stpm.c360
-rw-r--r--usr/src/lib/librstp/common/stpm.h126
-rw-r--r--usr/src/lib/librstp/common/stpmgmt.c161
-rw-r--r--usr/src/lib/librstp/common/sttrans.c140
-rw-r--r--usr/src/lib/librstp/common/sttrans.h38
-rw-r--r--usr/src/lib/librstp/common/times.c80
-rw-r--r--usr/src/lib/librstp/common/times.h50
-rw-r--r--usr/src/lib/librstp/common/topoch.c227
-rw-r--r--usr/src/lib/librstp/common/topoch.h37
-rw-r--r--usr/src/lib/librstp/common/transmit.c368
-rw-r--r--usr/src/lib/librstp/common/transmit.h38
-rw-r--r--usr/src/lib/librstp/common/uid_stp.h202
-rw-r--r--usr/src/lib/librstp/common/vector.c183
-rw-r--r--usr/src/lib/librstp/common/vector.h79
-rw-r--r--usr/src/lib/librstp/i386/Makefile29
-rw-r--r--usr/src/lib/librstp/sparc/Makefile29
54 files changed, 7523 insertions, 0 deletions
diff --git a/usr/src/lib/librstp/Makefile b/usr/src/lib/librstp/Makefile
new file mode 100644
index 0000000000..b94d9944a3
--- /dev/null
+++ b/usr/src/lib/librstp/Makefile
@@ -0,0 +1,60 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+include $(SRC)/lib/Makefile.lib
+
+HDRS = stp_bpdu.h stp_in.h stp_vectors.h uid_stp.h
+HDRDIR = common
+SUBDIRS = $(MACH)
+
+all := TARGET = all
+clean := TARGET = clean
+clobber := TARGET = clobber
+install := TARGET = install
+lint := TARGET = lint
+
+.KEEP_STATE:
+
+all clean clobber install lint: $(SUBDIRS)
+
+install: THIRDPARTYLICENSE
+
+THIRDPARTYLICENSE: common/COPYING
+ $(RM) $@
+ $(CP) $? $@
+
+CLOBBERFILES += THIRDPARTYLICENSE
+
+install_h: $(ROOTHDRS)
+
+check:
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
+
+include $(SRC)/Makefile.msg.targ
+include $(SRC)/lib/Makefile.targ
diff --git a/usr/src/lib/librstp/Makefile.com b/usr/src/lib/librstp/Makefile.com
new file mode 100644
index 0000000000..de23f29906
--- /dev/null
+++ b/usr/src/lib/librstp/Makefile.com
@@ -0,0 +1,53 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+LIBRARY = librstp.a
+VERS = .1
+OBJECTS = edge.o migrate.o p2p.o pcost.o port.o portinfo.o rolesel.o \
+ roletrns.o statmch.o stp_in.o stpm.o stpmgmt.o sttrans.o \
+ times.o topoch.o transmit.o vector.o
+
+include ../../Makefile.lib
+
+LIBS = $(DYNLIB) $(LINTLIB)
+
+SRCDIR = ../common
+SRCS = $(OBJECTS:%.o=$(SRCDIR)/%.c)
+
+$(LINTLIB):= SRCS = $(SRCDIR)/$(LINTSRC)
+
+LDLIBS += -lc
+
+CFLAGS += $(CCVERBOSE)
+CPPFLAGS += -I$(SRCDIR) -D__SUN__ -D__STP_INTERNAL__
+
+.KEEP_STATE:
+
+all: $(LIBS)
+
+lint: lintcheck
+
+include ../../Makefile.targ
diff --git a/usr/src/lib/librstp/THIRDPARTYLICENSE.descrip b/usr/src/lib/librstp/THIRDPARTYLICENSE.descrip
new file mode 100644
index 0000000000..578adad180
--- /dev/null
+++ b/usr/src/lib/librstp/THIRDPARTYLICENSE.descrip
@@ -0,0 +1 @@
+SPANNING TREE SOFTWARE
diff --git a/usr/src/lib/librstp/common/COPYING b/usr/src/lib/librstp/common/COPYING
new file mode 100644
index 0000000000..223ede7de3
--- /dev/null
+++ b/usr/src/lib/librstp/common/COPYING
@@ -0,0 +1,504 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/usr/src/lib/librstp/common/ChangeLog b/usr/src/lib/librstp/common/ChangeLog
new file mode 100644
index 0000000000..ef8fa2342f
--- /dev/null
+++ b/usr/src/lib/librstp/common/ChangeLog
@@ -0,0 +1,62 @@
+ChangeLog
+=========
+james.d.carlson@sun.com
+ - Removed bits and pieces not needed for use as a stand-alone library.
+ - Fixed two unreachable statements (statmch.c and stpm.c).
+ - Wrote Makefile for use with ON.
+ - Changed rstplib into a real library; expecting the caller to provide
+ symbol definitions is just wrong.
+
+##
+- $Log: ChangeLog,v $
+- Revision 1.7 2002/01/20 07:34:36 ralex
+- - 'clilib' has been changed for 'readline' version 4.2 (thanks to
+- Michael Rozhavsky <mike@nbase.co.il>)
+- - 'The bug in clilib has been fixed
+-
+- Revision 1.6 2002/01/09 06:58:08 ralex
+- The first version is to outcome
+-
+- Revision 1.5 2001/11/29 09:54:31 ralex
+- - The bug in "Port Role Transitions state machine" has been
+- fixed (hop to the DESIGNATED_LISTEN)
+- - Defaults for 'bridge' and 'ports' configuration have
+- been moved; order of the initialization has been changed
+-
+- Revision 1.4 2001/11/26 08:02:12 ralex
+- All management entities from 14.8.1 & 14.8.2 are now supported
+-
+- Revision 1.3 2001/11/21 14:32:27 ralex
+- The file ChangeLog has been 'synchrinyzed'
+-
+- Revision 1.2 2001/11/21 14:22:12 ralex
+- - In the librstp.a : drastic change in Port Role Selection
+- state machine as a result of posting
+- of Mick Seaman and implementation of 802.1y Z1
+- - In libcli.c : readline completion works; for it
+- the structure CMD_DSCR_T has been redisgned
+- and the languages (both in 'mngr' and in 'bridge')
+- have been changed
+-
+- Revision 1.1 2001/11/14 14:10:44 ralex
+- - All per Port variables have been moved from the State
+- Machines into the Port instance (it made the state
+- machines much more clear)
+-
+- - In libcli.a instead of stupid fgets() function we use
+- now readline (thanks to Michel Roshavsky)
+-
+- - 'mcheck' support
+-
+- - 'nonStp' support (I know, that it is out the standard,
+- but it seems to be useful (see a discussion on
+- http://www1.ietf.org/mail-archive/working-groups/bridge/current/msg00038.html)
+- and our customers demand it
+-
+- - The function rolesel.c has been drastically fixed, IMHO
+- closer to the standard
+-
+- - Nicer output
+
+##
+
diff --git a/usr/src/lib/librstp/common/README b/usr/src/lib/librstp/common/README
new file mode 100644
index 0000000000..abcdb9e114
--- /dev/null
+++ b/usr/src/lib/librstp/common/README
@@ -0,0 +1,37 @@
+
+
+The Rapid Spanning Tree Library project contains a full implementation
+of 802.1s as an library with API. There is two processes, using this
+library: 'bridge' & 'mngr'. First simulates RSTP bridge behavior, second
+is dedicated to link/unlink 'bridges' into virtual RSTP domain (VRSTPD).
+Both 'bridge' & 'mngr' has its own simple CLI like language of commands;
+these commands allow to manage the VRSTPD. There are tools to trace
+state machine transitions and get traps about drastic changes.
+
+Purpose: studying, debugging, development.
+
+The library may be used in real bridges/routers while bounding to a real
+system depending environment.
+
+To run:
+1. In one shell run 'mngr'
+./mngr
+You will get prompt of 'mngr'; type '?' and get full help of
+'mngr' commands.
+
+2. In another shell run bridge instance.
+./bridge
+You will get prompt of 'bridge'; type '?' and get full help
+of bridge management commands.
+
+3. You may (and should) run a number of bridge instances, each in its
+separate shell (this way you will be able manage them).
+
+For example, if there were two bridge instances, you may see examples
+of the dialog in files mngr.txt, B5055.txt and B5056.txt.
+
+Note: prompt both of 'mngr' and of 'bridge' instance contains time stamp,
+while all these process run onto the same computer, these time stamps
+are synchronized.
+
+
diff --git a/usr/src/lib/librstp/common/README.CVS.HOWTO b/usr/src/lib/librstp/common/README.CVS.HOWTO
new file mode 100644
index 0000000000..987724d00e
--- /dev/null
+++ b/usr/src/lib/librstp/common/README.CVS.HOWTO
@@ -0,0 +1,22 @@
+Anonymous CVS Access
+
+This project's SourceForge CVS repository can be checked out through
+anonymous (pserver) CVS with the following instruction set. The module
+you wish to check out must be specified as the modulename. When prompted
+for a password for anonymous, simply press the Enter key.
+
+cvs -d:pserver:anonymous@cvs.rstplib.sourceforge.net:/cvsroot/rstplib login
+
+cvs -z3 -d:pserver:anonymous@cvs.rstplib.sourceforge.net:/cvsroot/rstplib co modulename
+
+Updates from within the module's directory do not need the -d parameter.
+
+Developer CVS Access via SSH
+
+Only project developers can access the CVS tree via this method. SSH1 must
+be installed on your client machine. Substitute modulename and developername
+with the proper values. Enter your site password when prompted.
+
+export CVS_RSH=ssh
+
+cvs -z3 -d:ext:developername@cvs.rstplib.sourceforge.net:/cvsroot/rstplib co modulename
diff --git a/usr/src/lib/librstp/common/README.authors b/usr/src/lib/librstp/common/README.authors
new file mode 100644
index 0000000000..71dc74ec09
--- /dev/null
+++ b/usr/src/lib/librstp/common/README.authors
@@ -0,0 +1,3 @@
+Alex Rozin <alexr@nbase.co.il>
+Michael Rozhavsky <mike@nbase.co.il>
+
diff --git a/usr/src/lib/librstp/common/README.files b/usr/src/lib/librstp/common/README.files
new file mode 100644
index 0000000000..f08ea7d503
--- /dev/null
+++ b/usr/src/lib/librstp/common/README.files
@@ -0,0 +1,58 @@
+This guide describes the list of the files of the project.
+==========================================================
+
+There are two target binaries: mngr & bridge
+o The first is a simplest tools to connect/disconnect
+ bridges and check their current connection. These its
+ functions are managed from command line simple language
+ and use the library libcli.a (see below). Beside it mngr
+ serves to transport BPDU messages between bridges; for
+ this purpose mngr uses the library libuid.a
+ The source code of the mngr: file mngr.c
+
+o The second is a simulation of virtual RSTP bridge. It
+ accepts two types of messages: UID_CNTRL & UID_BPDU (see
+ file uid.h). This program is linked with the same two
+ libraries libcli.a & libuid.a; beside it uses a system
+ independent librstp.a: implementation of Rapid Spanning
+ Tree (802.1w) - see below.
+ The source code of the bridge: files bridge.c,stp_cli.c,
+ stp_to.c
+ * bridge.c - simulates the main bridge behavior
+ * stp_cli.c - consists from command line functions
+ * stp_to.c - API, that librstp.a uses for its purposes.
+ The management communication between bridge and librstp.a
+ uses structures and definitions from the header uid_stp.h
+
+o libcli.a - library for command line features. It has only
+ one file cli.c, the API is described in the header cli.h.
+
+o libuid.a - the 'transport' library: the source code you
+ may find in the file uid_sock.c and in the two headers:
+ uid.h & uid_sock.h
+
+o (so far, so good) librstp.a - it is a heart of the project
+ Actually, it implements 802.1w state machines. Files
+ stpm.c - the RSTP instance (some reflection of Port0)
+ port.c - the RSTP port instance
+ portinfo.c - Port Information State Machine, 17.21
+ rolesel.c - Port Role Selection State Machine, 17.22
+ roletrns.c - Port Role Transition State Machine, 17.23
+ sttrans.c - Port State Transition State Machine, 17.24
+ topoch.c - Topology Change State Machine, 17.25
+ migrate.c - Port Protocol Migration State Machine, 17.26
+ transmit.c - Port Transmit State Machine 17.27
+ pcost.c - Path Cost Resolution State Machine
+ edge.c - operEdge Port Resolution State Machine
+ p2p.c - operPointToPoit Resolution State Machine
+ statmch.c - generic state machine implementation
+ vector.c - Priority Vectors manipulations
+ times.c - Times manipulations
+ stp_in.c - API for calls from outside.
+ sttrans.c - API for calls from outside (dedicated for creation
+ deleting, starting & stopping the RSTP instance) less
+ relevant to the project.
+
+
+
+
diff --git a/usr/src/lib/librstp/common/README.news b/usr/src/lib/librstp/common/README.news
new file mode 100644
index 0000000000..5ac0d573e9
--- /dev/null
+++ b/usr/src/lib/librstp/common/README.news
@@ -0,0 +1,19 @@
+- All per Port variables have been moved from the State
+ Machines into the Port instance (it made the state
+ machines much more clear)
+
+- In libcli.a instead of stupid fgets() function we use
+ now readline (thanks to Michel Roshavsky)
+
+- 'mcheck' support
+
+- 'nonStp' support (I know, that it is out the standard,
+ but it seems to be useful (see a discussion on
+http://www1.ietf.org/mail-archive/working-groups/bridge/current/msg00038.html)
+ and our customers demand it
+
+- The function rolesel.c has been drastically fixed, IMHO
+ closer to the standard
+
+- Nicer output
+
diff --git a/usr/src/lib/librstp/common/TODO b/usr/src/lib/librstp/common/TODO
new file mode 100644
index 0000000000..7037509731
--- /dev/null
+++ b/usr/src/lib/librstp/common/TODO
@@ -0,0 +1,22 @@
+This guide describes our plans.
+==============================
+
+Volunteers are welcomed !
+==========================
+
+1. To support a full set of management features
+ from 14.8 (like timeSince_Topo_Change, 14.8.1.1.3.b)
+
+2. To send traps about topology changes (as call to stp_to.c)
+
+3. To rewrite edge.c for more exact correspondence with the
+ standard (now portEnabled variable is realized in 'dirty' way),
+ simulate MAC Operational and MAC Enabled.
+
+4. To support SNMP management via AgentX
+
+5. To move the project in he direction toward 802.1s (MSTP)
+
+
+
+
diff --git a/usr/src/lib/librstp/common/base.h b/usr/src/lib/librstp/common/base.h
new file mode 100644
index 0000000000..f00324349e
--- /dev/null
+++ b/usr/src/lib/librstp/common/base.h
@@ -0,0 +1,198 @@
+/************************************************************************
+ * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
+ * Copyright (C) 2001-2003 Optical Access
+ * Author: Alex Rozin
+ *
+ * This file is part of RSTP library.
+ *
+ * RSTP library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; version 2.1
+ *
+ * RSTP library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with RSTP library; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ **********************************************************************/
+
+/* Mutual RSTP definitions */
+
+#ifndef _STP_BASE_H__
+#define _STP_BASE_H__
+
+#include <stdlib.h>
+#include <string.h>
+
+#define STP_DBG 1
+
+#if defined(__LINUX__) || defined(__SUN__)
+# include <stddef.h>
+# include <stdio.h>
+# include <netinet/in.h>
+# include "uid_stp.h"
+#else
+# include <psos.h>
+# include "comdef.h"
+# include "comdef.x"
+# include "Bitmap/bitmap.h"
+# include "Bitmap/bitmap.x"
+# include "Ui/uid_stp.h"
+#endif
+
+#ifndef INOUT
+# define IN /* consider as comments near 'input' parameters */
+# define OUT /* consider as comments near 'output' parameters */
+# define INOUT /* consider as comments near 'input/output' parameters */
+#endif
+
+#ifndef Zero
+# define Zero 0
+# define One 1
+#endif
+
+#ifndef Bool
+# define Bool int
+# define False 0
+# define True 1
+#endif
+
+#include "stp_bpdu.h"
+#include "vector.h"
+#include "times.h"
+
+#define RSTP_ERRORS { \
+ CHOOSE(STP_OK), \
+ CHOOSE(STP_Cannot_Find_Vlan), \
+ CHOOSE(STP_Implicit_Instance_Create_Failed), \
+ CHOOSE(STP_Small_Bridge_Priority), \
+ CHOOSE(STP_Large_Bridge_Priority), \
+ CHOOSE(STP_Small_Hello_Time), \
+ CHOOSE(STP_Large_Hello_Time), \
+ CHOOSE(STP_Small_Max_Age), \
+ CHOOSE(STP_Large_Max_Age), \
+ CHOOSE(STP_Small_Forward_Delay), \
+ CHOOSE(STP_Large_Forward_Delay), \
+ CHOOSE(STP_Forward_Delay_And_Max_Age_Are_Inconsistent),\
+ CHOOSE(STP_Hello_Time_And_Max_Age_Are_Inconsistent), \
+ CHOOSE(STP_Vlan_Had_Not_Yet_Been_Created), \
+ CHOOSE(STP_Port_Is_Absent_In_The_Vlan), \
+ CHOOSE(STP_Big_len8023_Format), \
+ CHOOSE(STP_Small_len8023_Format), \
+ CHOOSE(STP_len8023_Format_Gt_Len), \
+ CHOOSE(STP_Not_Proper_802_3_Packet), \
+ CHOOSE(STP_Invalid_Protocol), \
+ CHOOSE(STP_Invalid_Version), \
+ CHOOSE(STP_Had_Not_Yet_Been_Enabled_On_The_Vlan), \
+ CHOOSE(STP_Cannot_Create_Instance_For_Vlan), \
+ CHOOSE(STP_Cannot_Create_Instance_For_Port), \
+ CHOOSE(STP_Invalid_Bridge_Priority), \
+ CHOOSE(STP_There_Are_No_Ports), \
+ CHOOSE(STP_Cannot_Compute_Bridge_Prio), \
+ CHOOSE(STP_Another_Error), \
+ CHOOSE(STP_Nothing_To_Do), \
+ CHOOSE(STP_No_Such_State_Machine), \
+ CHOOSE(STP_LAST_DUMMY) \
+}
+
+#define CHOOSE(a) a
+typedef enum RSTP_ERRORS RSTP_ERRORS_T;
+#undef CHOOSE
+
+#if !defined(__LINUX__) && !defined(__SUN__)
+extern char* strdup (const char *s);
+
+extern USHORT Ntohs (USHORT n);
+extern ULONG Htonl (ULONG h);
+extern USHORT Htons (USHORT h);
+extern ULONG Ntohl (ULONG n);
+
+#define htonl Htonl
+#define htons Htons
+#define ntohl Ntohl
+#define ntohs Ntohs
+
+#endif
+
+#if defined(__LINUX__) || defined(__SUN__)
+#ifdef STP_DBG
+#define STP_FATAL(TXT, MSG, EXCOD) \
+ {stp_trace ("FATAL:%s failed: %s:%d", TXT, MSG, EXCOD); \
+ exit (EXCOD);}
+#else
+#define STP_FATAL(TXT, MSG, EXCOD) \
+ abort();
+#endif
+#else
+#define STP_FATAL(TXT, MSG, EXCOD) \
+ printf("FATAL: %s code %s:%d\n", TXT, MSG, EXCOD)
+#endif
+
+#define STP_MALLOC(PTR, TYPE, MSG) \
+ { \
+ PTR = (TYPE*) calloc (1, sizeof (TYPE)); \
+ if (! PTR) { \
+ STP_FATAL("malloc", MSG, -6); \
+ } \
+ }
+
+#define STP_FREE(PTR, MSG) \
+ { \
+ if (! PTR) { \
+ STP_FATAL("free", MSG, -66); \
+ } \
+ free (PTR); \
+ PTR = NULL; \
+ }
+
+#define STP_STRDUP(PTR, SRC, MSG) \
+ { \
+ PTR = strdup (SRC); \
+ if (! PTR) { \
+ STP_FATAL("strdup", MSG, -7); \
+ } \
+ }
+
+#define STP_NEW_IN_LIST(WHAT, TYPE, LIST, MSG) \
+ { \
+ STP_MALLOC(WHAT, TYPE, MSG); \
+ WHAT->next = LIST; \
+ LIST = WHAT; \
+ }
+
+/* for debug trace messages */
+
+#ifdef STP_DBG
+#if defined(__LINUX__)
+extern char* sprint_time_stump (void);
+#define stp_trace(F, B...) printf("%s:" F "\n", sprint_time_stump(), ##B)
+#elif defined(__SUN__)
+#define stp_trace (*stp_vectors->trace)
+#else
+extern ULONG stp_trace (const char* fmt, ...);
+#endif
+#else /* !STP_DBG */
+#define stp_trace(F, B...) ((void)0)
+#endif /* STP_DBG */
+
+
+/* Inner usage definitions & functions */
+
+#if defined(__LINUX__) || defined(__SUN__)
+# define RSTP_INIT_CRITICAL_PATH_PROTECTIO
+# define RSTP_CRITICAL_PATH_START
+# define RSTP_CRITICAL_PATH_END
+#else
+# define RSTP_INIT_CRITICAL_PATH_PROTECTIO STP_OUT_psos_init_semaphore ()
+# define RSTP_CRITICAL_PATH_START STP_OUT_psos_close_semaphore ()
+# define RSTP_CRITICAL_PATH_END STP_OUT_psos_open_semaphore ()
+ extern void STP_OUT_psos_init_semaphore (void);
+ extern void STP_OUT_psos_close_semaphore (void);
+ extern void STP_OUT_psos_open_semaphore (void);
+#endif
+
+#endif /* _STP_BASE_H__ */
diff --git a/usr/src/lib/librstp/common/choose.h b/usr/src/lib/librstp/common/choose.h
new file mode 100644
index 0000000000..7f614faed1
--- /dev/null
+++ b/usr/src/lib/librstp/common/choose.h
@@ -0,0 +1,42 @@
+/************************************************************************
+ * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
+ * Copyright (C) 2001-2003 Optical Access
+ * Author: Alex Rozin
+ *
+ * This file is part of RSTP library.
+ *
+ * RSTP library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; version 2.1
+ *
+ * RSTP library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with RSTP library; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ **********************************************************************/
+
+#ifndef _STP_CHOOSE_H__
+#define _STP_CHOOSE_H__
+
+/* State machines states & debug tools. Sorry, if these are no readable enogth :( */
+
+#define CHOOSE(a) a
+typedef enum STATES THE_STATE_T;
+#undef CHOOSE
+
+char * GET_STATE_NAME (int state)
+{
+#define CHOOSE(a) #a
+static char *state_names[] = STATES;
+#undef CHOOSE
+
+ if (BEGIN == state) return "Begin";
+ return state_names[state];
+}
+
+#endif /* _STP_CHOOSE_H__ */
diff --git a/usr/src/lib/librstp/common/edge.c b/usr/src/lib/librstp/common/edge.c
new file mode 100644
index 0000000000..8b3c3029e6
--- /dev/null
+++ b/usr/src/lib/librstp/common/edge.c
@@ -0,0 +1,115 @@
+/************************************************************************
+ * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
+ * Copyright (C) 2001-2003 Optical Access
+ * Author: Alex Rozin
+ *
+ * This file is part of RSTP library.
+ *
+ * RSTP library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; version 2.1
+ *
+ * RSTP library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with RSTP library; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ **********************************************************************/
+
+/* Note: this state mashine distinkts from described in P802.1t Clause 18. */
+/* I am ready to discuss it */
+
+#include "base.h"
+#include "stpm.h"
+#include "stp_vectors.h"
+
+#define STATES { \
+ CHOOSE(DISABLED), \
+ CHOOSE(DETECTED), \
+ CHOOSE(DELAYED), \
+ CHOOSE(RESOLVED) \
+}
+
+#define GET_STATE_NAME STP_edge_get_state_name
+#include "choose.h"
+
+#define DEFAULT_LINK_DELAY 3
+
+void
+STP_edge_enter_state (STATE_MACH_T *s)
+{
+ register PORT_T *port = s->owner.port;
+
+ switch (s->State) {
+ case BEGIN:
+ break;
+ case DISABLED:
+ port->operEdge = port->adminEdge;
+ port->wasInitBpdu = False;
+ port->lnkWhile = 0;
+ port->portEnabled = False;
+ break;
+ case DETECTED:
+ port->portEnabled = True;
+ port->lnkWhile = port->LinkDelay;
+ port->operEdge = False;
+ break;
+ case DELAYED:
+ break;
+ case RESOLVED:
+ if (! port->wasInitBpdu) {
+ port->operEdge = port->adminEdge;
+ }
+ break;
+ }
+}
+
+Bool
+STP_edge_check_conditions (STATE_MACH_T *s)
+{
+ register PORT_T *port = s->owner.port;
+
+ /* If we're disabled, then stay that way. */
+ if (!port->adminEnable) {
+ if (s->State == DISABLED)
+ return False;
+ else
+ return STP_hop_2_state (s, DISABLED);
+ }
+
+ switch (s->State) {
+ case BEGIN:
+ return STP_hop_2_state (s, DISABLED);
+ case DISABLED:
+ if (port->adminEnable) {
+ return STP_hop_2_state (s, DETECTED);
+ }
+ break;
+ case DETECTED:
+ return STP_hop_2_state (s, DELAYED);
+ case DELAYED:
+ if (port->wasInitBpdu) {
+#ifdef STP_DBG
+ if (s->debug)
+ stp_trace ("port %s 'edge' resolved by BPDU", port->port_name);
+#endif
+ return STP_hop_2_state (s, RESOLVED);
+ }
+
+ if (! port->lnkWhile) {
+#ifdef STP_DBG
+ if (s->debug)
+ stp_trace ("port %s 'edge' resolved by timer", port->port_name);
+#endif
+ return STP_hop_2_state (s, RESOLVED);
+ }
+ break;
+ case RESOLVED:
+ break;
+ }
+ return False;
+}
diff --git a/usr/src/lib/librstp/common/edge.h b/usr/src/lib/librstp/common/edge.h
new file mode 100644
index 0000000000..e41264d1e0
--- /dev/null
+++ b/usr/src/lib/librstp/common/edge.h
@@ -0,0 +1,38 @@
+/************************************************************************
+ * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
+ * Copyright (C) 2001-2003 Optical Access
+ * Author: Alex Rozin
+ *
+ * This file is part of RSTP library.
+ *
+ * RSTP library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; version 2.1
+ *
+ * RSTP library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with RSTP library; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ **********************************************************************/
+
+/* Note: this state mashine distinkts from described in P802.1t Clause 18. */
+/* I am ready to discuss it */
+
+#ifndef _STP_EDGE_H__
+#define _STP_EDGE_H__
+
+void
+STP_edge_enter_state (STATE_MACH_T* s);
+
+Bool
+STP_edge_check_conditions (STATE_MACH_T* s);
+
+char*
+STP_edge_get_state_name (int state);
+
+#endif /* _STP_EDGE_H__ */
diff --git a/usr/src/lib/librstp/common/llib-lrstp b/usr/src/lib/librstp/common/llib-lrstp
new file mode 100644
index 0000000000..e80ecd4156
--- /dev/null
+++ b/usr/src/lib/librstp/common/llib-lrstp
@@ -0,0 +1,30 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/* LINTLIBRARY */
+/* PROTOLIB1 */
+
+#include <stp_in.h>
+#include <stp_vectors.h>
diff --git a/usr/src/lib/librstp/common/mapfile-vers b/usr/src/lib/librstp/common/mapfile-vers
new file mode 100644
index 0000000000..f3b7876a5a
--- /dev/null
+++ b/usr/src/lib/librstp/common/mapfile-vers
@@ -0,0 +1,71 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# MAPFILE HEADER START
+#
+# WARNING: STOP NOW. DO NOT MODIFY THIS FILE.
+# Object versioning must comply with the rules detailed in
+#
+# usr/src/lib/README.mapfiles
+#
+# You should not be making modifications here until you've read the most current
+# copy of that file. If you need help, contact a gatekeeper for guidance.
+#
+# MAPFILE HEADER END
+#
+
+SUNWprivate_1.1 {
+ global:
+ STP_IN_init;
+ STP_IN_stpm_create;
+ STP_IN_stpm_delete;
+ STP_IN_stop_all;
+ STP_IN_delete_all;
+ STP_IN_get_is_stpm_enabled;
+ STP_IN_stpm_get_vlan_id_by_name;
+ STP_IN_stpm_get_name_by_vlan_id;
+ STP_IN_get_error_explanation;
+ STP_IN_stpm_get_cfg;
+ STP_IN_stpm_get_state;
+ STP_IN_port_get_cfg;
+ STP_IN_port_set_cfg;
+ STP_IN_port_get_state;
+ STP_IN_stpm_set_cfg;
+ STP_IN_one_second;
+ STP_IN_enable_port;
+ STP_IN_changed_port_speed;
+ STP_IN_changed_port_duplex;
+ STP_IN_check_bpdu_header;
+ STP_IN_rx_bpdu;
+ STP_IN_dbg_set_port_trace;
+ STP_IN_port_add;
+ STP_IN_port_remove;
+ STP_IN_get_bridge_id;
+ STP_IN_state2str;
+ local:
+ *;
+};
diff --git a/usr/src/lib/librstp/common/migrate.c b/usr/src/lib/librstp/common/migrate.c
new file mode 100644
index 0000000000..08540d3a24
--- /dev/null
+++ b/usr/src/lib/librstp/common/migrate.c
@@ -0,0 +1,119 @@
+/************************************************************************
+ * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
+ * Copyright (C) 2001-2003 Optical Access
+ * Author: Alex Rozin
+ *
+ * This file is part of RSTP library.
+ *
+ * RSTP library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; version 2.1
+ *
+ * RSTP library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with RSTP library; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ **********************************************************************/
+
+/* Port Protocol Migration state machine : 17.26 */
+
+#include "base.h"
+#include "stpm.h"
+
+#define STATES { \
+ CHOOSE(INIT), \
+ CHOOSE(SEND_RSTP), \
+ CHOOSE(SENDING_RSTP), \
+ CHOOSE(SEND_STP), \
+ CHOOSE(SENDING_STP) \
+}
+
+#define GET_STATE_NAME STP_migrate_get_state_name
+#include "choose.h"
+
+#define MigrateTime 3 /* 17,16.4 */
+
+void
+STP_migrate_enter_state (STATE_MACH_T* this)
+{
+ register PORT_T* port = this->owner.port;
+
+ switch (this->State) {
+ case BEGIN:
+ case INIT:
+ port->initPm = True;
+ port->mcheck = False;
+ break;
+ case SEND_RSTP:
+ port->mdelayWhile = MigrateTime;
+ port->mcheck = port->initPm = False;
+ port->sendRSTP = True;
+ break;
+ case SENDING_RSTP:
+ port->rcvdRSTP = port->rcvdSTP = False;
+ break;
+ case SEND_STP:
+ port->mdelayWhile = MigrateTime;
+ port->sendRSTP = False;
+ port->initPm = False;
+ break;
+ case SENDING_STP:
+ port->rcvdRSTP = port->rcvdSTP = False;
+ break;
+ }
+}
+
+Bool
+STP_migrate_check_conditions (STATE_MACH_T* this)
+{
+ register PORT_T* port = this->owner.port;
+
+ if ((!port->portEnabled && !port->initPm) || BEGIN == this->State)
+ return STP_hop_2_state (this, INIT);
+
+ switch (this->State) {
+ case INIT:
+ if (port->portEnabled) {
+ return STP_hop_2_state (this, (port->owner->ForceVersion >= 2) ?
+ SEND_RSTP : SEND_STP);
+ }
+ break;
+ case SEND_RSTP:
+ return STP_hop_2_state (this, SENDING_RSTP);
+ case SENDING_RSTP:
+ if (port->mcheck)
+ return STP_hop_2_state (this, SEND_RSTP);
+ if (port->mdelayWhile &&
+ (port->rcvdSTP || port->rcvdRSTP)) {
+ return STP_hop_2_state (this, SENDING_RSTP);
+ }
+
+ if (!port->mdelayWhile && port->rcvdSTP) {
+ return STP_hop_2_state (this, SEND_STP);
+ }
+
+ if (port->owner->ForceVersion < 2) {
+ return STP_hop_2_state (this, SEND_STP);
+ }
+
+ break;
+ case SEND_STP:
+ return STP_hop_2_state (this, SENDING_STP);
+ case SENDING_STP:
+ if (port->mcheck)
+ return STP_hop_2_state (this, SEND_RSTP);
+ if (port->mdelayWhile &&
+ (port->rcvdSTP || port->rcvdRSTP))
+ return STP_hop_2_state (this, SENDING_STP);
+ if (!port->mdelayWhile && port->rcvdRSTP)
+ return STP_hop_2_state (this, SEND_RSTP);
+ break;
+ }
+ return False;
+}
+
diff --git a/usr/src/lib/librstp/common/migrate.h b/usr/src/lib/librstp/common/migrate.h
new file mode 100644
index 0000000000..0c38606a4e
--- /dev/null
+++ b/usr/src/lib/librstp/common/migrate.h
@@ -0,0 +1,37 @@
+/************************************************************************
+ * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
+ * Copyright (C) 2001-2003 Optical Access
+ * Author: Alex Rozin
+ *
+ * This file is part of RSTP library.
+ *
+ * RSTP library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; version 2.1
+ *
+ * RSTP library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with RSTP library; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ **********************************************************************/
+
+/* Port Protocol Migration state machine : 17.26 */
+
+#ifndef _STP_MIGRATE_H__
+#define _STP_MIGRATE_H__
+
+void
+STP_migrate_enter_state (STATE_MACH_T* s);
+
+Bool
+STP_migrate_check_conditions (STATE_MACH_T* s);
+
+char*
+STP_migrate_get_state_name (int state);
+
+#endif /* _STP_MIGRATE_H__ */
diff --git a/usr/src/lib/librstp/common/p2p.c b/usr/src/lib/librstp/common/p2p.c
new file mode 100644
index 0000000000..7cb7b381eb
--- /dev/null
+++ b/usr/src/lib/librstp/common/p2p.c
@@ -0,0 +1,90 @@
+/************************************************************************
+ * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
+ * Copyright (C) 2001-2003 Optical Access
+ * Author: Alex Rozin
+ *
+ * This file is part of RSTP library.
+ *
+ * RSTP library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; version 2.1
+ *
+ * RSTP library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with RSTP library; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ **********************************************************************/
+
+/* Point To Point MAC mode selection machine : 6.4.3, 6.5.1 */
+
+#include "base.h"
+#include "stpm.h"
+#include "stp_to.h" /* for STP_OUT_get_duplex */
+
+#define STATES { \
+ CHOOSE(INIT), \
+ CHOOSE(RECOMPUTE), \
+ CHOOSE(STABLE) \
+}
+
+#define GET_STATE_NAME STP_p2p_get_state_name
+#include "choose.h"
+
+static Bool
+computeP2P (PORT_T *port)
+{
+ switch (port->adminPointToPointMac) {
+ case P2P_FORCE_TRUE:
+ return True;
+ case P2P_FORCE_FALSE:
+ return False;
+ default:
+ case P2P_AUTO:
+ return STP_OUT_get_duplex (port->port_index);
+ }
+}
+
+void
+STP_p2p_enter_state (STATE_MACH_T* s)
+{
+ register PORT_T* port = s->owner.port;
+
+ switch (s->State) {
+ case BEGIN:
+ case INIT:
+ port->p2p_recompute = True;
+ break;
+ case RECOMPUTE:
+ port->operPointToPointMac = computeP2P (port);
+ port->p2p_recompute = False;
+ break;
+ case STABLE:
+ break;
+ }
+}
+
+Bool
+STP_p2p_check_conditions (STATE_MACH_T* s)
+{
+ register PORT_T* port = s->owner.port;
+
+ switch (s->State) {
+ case BEGIN:
+ case INIT:
+ return STP_hop_2_state (s, STABLE);
+ case RECOMPUTE:
+ return STP_hop_2_state (s, STABLE);
+ case STABLE:
+ if (port->p2p_recompute) {
+ return STP_hop_2_state (s, RECOMPUTE);
+ }
+ break;
+ }
+ return False;
+}
+
diff --git a/usr/src/lib/librstp/common/p2p.h b/usr/src/lib/librstp/common/p2p.h
new file mode 100644
index 0000000000..ea892ab4a6
--- /dev/null
+++ b/usr/src/lib/librstp/common/p2p.h
@@ -0,0 +1,37 @@
+/************************************************************************
+ * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
+ * Copyright (C) 2001-2003 Optical Access
+ * Author: Alex Rozin
+ *
+ * This file is part of RSTP library.
+ *
+ * RSTP library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; version 2.1
+ *
+ * RSTP library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with RSTP library; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ **********************************************************************/
+
+/* Point To Point MAC mode selection machine : 6.4.3, 6.5.1 */
+
+#ifndef _STP_P2P_H__
+#define _STP_P2P_H__
+
+void
+STP_p2p_enter_state (STATE_MACH_T* s);
+
+Bool
+STP_p2p_check_conditions (STATE_MACH_T* s);
+
+char*
+STP_p2p_get_state_name (int state);
+
+#endif /* _STP_P2P_H__ */
diff --git a/usr/src/lib/librstp/common/pcost.c b/usr/src/lib/librstp/common/pcost.c
new file mode 100644
index 0000000000..72dd144043
--- /dev/null
+++ b/usr/src/lib/librstp/common/pcost.c
@@ -0,0 +1,132 @@
+/************************************************************************
+ * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
+ * Copyright (C) 2001-2003 Optical Access
+ * Author: Alex Rozin
+ *
+ * This file is part of RSTP library.
+ *
+ * RSTP library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; version 2.1
+ *
+ * RSTP library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with RSTP library; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ **********************************************************************/
+
+/* Path Cost monitoring state machine */
+
+#include "base.h"
+#include "stpm.h"
+#include "stp_to.h" /* for STP_OUT_get_port_oper_speed */
+
+#define STATES { \
+ CHOOSE(AUTO), \
+ CHOOSE(FORSE), \
+ CHOOSE(STABLE) \
+}
+
+#define GET_STATE_NAME STP_pcost_get_state_name
+#include "choose.h"
+
+static long
+computeAutoPCost (STATE_MACH_T *this)
+{
+ long lret;
+ register PORT_T* port = this->owner.port;
+
+ if (port->usedSpeed < 10L) { /* < 10Mb/s */
+ lret = 20000000;
+ } else if (port->usedSpeed <= 10L) { /* 10 Mb/s */
+ lret = 2000000;
+ } else if (port->usedSpeed <= 100L) { /* 100 Mb/s */
+ lret = 200000;
+ } else if (port->usedSpeed <= 1000L) { /* 1 Gb/s */
+ lret = 20000;
+ } else if (port->usedSpeed <= 10000L) { /* 10 Gb/s */
+ lret = 2000;
+ } else if (port->usedSpeed <= 100000L) { /* 100 Gb/s */
+ lret = 200;
+ } else if (port->usedSpeed <= 1000000L) { /* 1 GTb/s */
+ lret = 20;
+ } else if (port->usedSpeed <= 10000000L) { /* 10 Tb/s */
+ lret = 2;
+ } else /* ??? */ { /* > Tb/s */
+ lret = 1;
+ }
+#ifdef STP_DBG
+ if (port->pcost->debug) {
+ stp_trace ("usedSpeed=%lu lret=%ld", port->usedSpeed, lret);
+ }
+#endif
+
+ return lret;
+}
+
+/* ARGSUSED */
+static void
+updPortPathCost (STATE_MACH_T *this)
+{
+}
+
+void
+STP_pcost_enter_state (STATE_MACH_T *this)
+{
+ register PORT_T* port = this->owner.port;
+
+ switch (this->State) {
+ case BEGIN:
+ break;
+ case AUTO:
+ port->operSpeed = STP_OUT_get_port_oper_speed (port->port_index);
+#ifdef STP_DBG
+ if (port->pcost->debug) {
+ stp_trace ("AUTO:operSpeed=%lu", port->operSpeed);
+ }
+#endif
+ port->usedSpeed = port->operSpeed;
+ port->operPCost = computeAutoPCost (this);
+ break;
+ case FORSE:
+ port->operPCost = port->adminPCost;
+ port->usedSpeed = (unsigned long)-1;
+ break;
+ case STABLE:
+ updPortPathCost (this);
+ break;
+ }
+}
+
+Bool
+STP_pcost_check_conditions (STATE_MACH_T* this)
+{
+ register PORT_T* port = this->owner.port;
+
+ switch (this->State) {
+ case BEGIN:
+ return STP_hop_2_state (this, AUTO);
+ case AUTO:
+ return STP_hop_2_state (this, STABLE);
+ case FORSE:
+ return STP_hop_2_state (this, STABLE);
+ case STABLE:
+ if (ADMIN_PORT_PATH_COST_AUTO == port->adminPCost &&
+ port->operSpeed != port->usedSpeed) {
+ return STP_hop_2_state (this, AUTO);
+ }
+
+ if (ADMIN_PORT_PATH_COST_AUTO != port->adminPCost &&
+ port->operPCost != port->adminPCost) {
+ return STP_hop_2_state (this, FORSE);
+ }
+ break;
+ }
+ return False;
+}
+
diff --git a/usr/src/lib/librstp/common/pcost.h b/usr/src/lib/librstp/common/pcost.h
new file mode 100644
index 0000000000..cb19ade3bc
--- /dev/null
+++ b/usr/src/lib/librstp/common/pcost.h
@@ -0,0 +1,37 @@
+/************************************************************************
+ * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
+ * Copyright (C) 2001-2003 Optical Access
+ * Author: Alex Rozin
+ *
+ * This file is part of RSTP library.
+ *
+ * RSTP library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; version 2.1
+ *
+ * RSTP library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with RSTP library; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ **********************************************************************/
+
+/* Path Cost monitoring state machine */
+
+#ifndef _STP_PCOST_H__
+#define _STP_PCOST_H__
+
+void
+STP_pcost_enter_state (STATE_MACH_T* s);
+
+Bool
+STP_pcost_check_conditions (STATE_MACH_T* s);
+
+char*
+STP_pcost_get_state_name (int state);
+
+#endif /* _STP_PCOST_H__ */
diff --git a/usr/src/lib/librstp/common/port.c b/usr/src/lib/librstp/common/port.c
new file mode 100644
index 0000000000..30ba26a72e
--- /dev/null
+++ b/usr/src/lib/librstp/common/port.c
@@ -0,0 +1,253 @@
+/************************************************************************
+ * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
+ * Copyright (C) 2001-2003 Optical Access
+ * Author: Alex Rozin
+ *
+ * This file is part of RSTP library.
+ *
+ * RSTP library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; version 2.1
+ *
+ * RSTP library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with RSTP library; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ **********************************************************************/
+
+/* STP PORT instance : 17.18, 17.15 */
+
+#include "base.h"
+#include "stpm.h"
+#include "stp_in.h"
+
+/* #include "rolesel.h" */
+#include "portinfo.h"
+#include "roletrns.h"
+#include "sttrans.h"
+#include "topoch.h"
+#include "migrate.h"
+#include "transmit.h"
+#include "p2p.h"
+#include "pcost.h"
+#include "edge.h"
+
+#include "stp_to.h" /* for STP_OUT_get_port_name & STP_OUT_get_port_link_status */
+
+int port_trace_flags;
+
+PORT_T *
+STP_port_create (STPM_T* stpm, int port_index)
+{
+ PORT_T* this;
+ UID_STP_PORT_CFG_T port_cfg;
+ register int iii;
+ unsigned short port_prio;
+
+ /* check, if the port has just been added */
+ for (this = stpm->ports; this; this = this->next) {
+ if (this->port_index == port_index) {
+ return NULL;
+ }
+ }
+
+ STP_NEW_IN_LIST(this, PORT_T, stpm->ports, "port create");
+
+ this->owner = stpm;
+ this->machines = NULL;
+ this->port_index = port_index;
+ this->port_name = strdup (STP_OUT_get_port_name (port_index));
+ this->uptime = 0;
+
+ STP_OUT_get_init_port_cfg (stpm->vlan_id, port_index, &port_cfg);
+ port_prio = port_cfg.port_priority;
+ this->admin_non_stp = port_cfg.admin_non_stp;
+ this->adminEdge = port_cfg.admin_edge;
+ this->adminPCost = port_cfg.admin_port_path_cost;
+ this->adminPointToPointMac = port_cfg.admin_point2point;
+
+ this->LinkDelay = DEF_LINK_DELAY;
+ this->port_id = (port_prio << 8) + port_index;
+
+ iii = 0;
+ this->timers[iii++] = &this->fdWhile;
+ this->timers[iii++] = &this->helloWhen;
+ this->timers[iii++] = &this->mdelayWhile;
+ this->timers[iii++] = &this->rbWhile;
+ this->timers[iii++] = &this->rcvdInfoWhile;
+ this->timers[iii++] = &this->rrWhile;
+ this->timers[iii++] = &this->tcWhile;
+ this->timers[iii++] = &this->txCount;
+ this->timers[iii++] = &this->lnkWhile;
+
+ /* create and bind port state machines */
+ STP_STATE_MACH_IN_LIST(topoch);
+
+ STP_STATE_MACH_IN_LIST(migrate);
+
+ STP_STATE_MACH_IN_LIST(p2p);
+
+ STP_STATE_MACH_IN_LIST(edge);
+
+ STP_STATE_MACH_IN_LIST(pcost)
+
+ STP_STATE_MACH_IN_LIST(info);
+
+ STP_STATE_MACH_IN_LIST(roletrns);
+
+ STP_STATE_MACH_IN_LIST(sttrans);
+
+ STP_STATE_MACH_IN_LIST(transmit);
+
+#ifdef STP_DBG
+
+#if 0
+ this->roletrns->ignoreHop2State = 14; /* DESIGNATED_PORT; */
+ this->info->ignoreHop2State = 3; /* CURRENT */
+ this->transmit->ignoreHop2State = 3; /* IDLE */
+ this->edge->ignoreHop2State = 0; /* DISABLED; */
+#endif
+
+#if 0
+ this->info->debug = 1;
+ this->pcost->debug = 1;
+ this->p2p->debug = 1;
+ this->edge->debug = 1;
+ this->migrate->debug = 1;
+ this->sttrans->debug = 1;
+ this->topoch->debug = 1;
+ this->roletrns->debug = 1;
+#endif
+ this->sttrans->debug = 1;
+
+#endif
+ return this;
+}
+
+void
+STP_port_init (PORT_T* this, STPM_T* stpm, Bool check_link)
+{
+ if (check_link) {
+ this->adminEnable = STP_OUT_get_port_link_status (this->port_index);
+ STP_VECT_create (&this->designPrio,
+ &stpm->BrId,
+ 0,
+ &stpm->BrId,
+ this->port_id,
+ this->port_id);
+ STP_copy_times (&this->designTimes, &stpm->rootTimes);
+ }
+
+ /* reset timers */
+ this->fdWhile =
+ this->helloWhen =
+ this->mdelayWhile =
+ this->rbWhile =
+ this->rcvdInfoWhile =
+ this->rrWhile =
+ this->tcWhile =
+ this->txCount = 0;
+
+ this->msgPortRole = RSTP_PORT_ROLE_UNKN;
+ this->selectedRole = DisabledPort;
+ this->sendRSTP = True;
+ this->operSpeed = STP_OUT_get_port_oper_speed (this->port_index);
+ this->p2p_recompute = True;
+}
+
+void
+STP_port_delete (PORT_T* this)
+{
+ STPM_T* stpm;
+ register PORT_T* prev;
+ register PORT_T* tmp;
+ register STATE_MACH_T* stater;
+ register void* pv;
+
+ stpm = this->owner;
+
+ free (this->port_name);
+ for (stater = this->machines; stater; ) {
+ pv = (void*) stater->next;
+ STP_state_mach_delete (stater);
+ stater = (STATE_MACH_T*) pv;
+ }
+
+ prev = NULL;
+ for (tmp = stpm->ports; tmp; tmp = tmp->next) {
+ if (tmp->port_index == this->port_index) {
+ if (prev) {
+ prev->next = this->next;
+ } else {
+ stpm->ports = this->next;
+ }
+ STP_FREE(this, "stp instance");
+ break;
+ }
+ prev = tmp;
+ }
+}
+
+int
+STP_port_rx_bpdu (PORT_T* this, BPDU_T* bpdu, size_t len)
+{
+ STP_info_rx_bpdu (this, bpdu, len);
+
+ return 0;
+}
+
+#ifdef STP_DBG
+int STP_port_trace_state_machine (PORT_T* this, char* mach_name, int enadis)
+{
+ STATE_MACH_T *stater;
+ int nmatch = 0;
+
+ for (stater = this->machines; stater; stater = stater->next) {
+ if (! strcmp (mach_name, "all") || ! strcmp (mach_name, stater->name)) {
+ if (stater->debug != enadis)
+ {
+ stp_trace ("port %s on %s trace %-8s (was %s) now %s",
+ this->port_name, this->owner->name,
+ stater->name,
+ stater->debug ? " enabled" :"disabled",
+ enadis ? " enabled" :"disabled");
+ }
+ stater->debug = enadis;
+ nmatch++;
+ }
+ }
+
+ if (nmatch == 0) {
+ stp_trace("port %s no such state machine as '%s'", this->port_name,
+ mach_name);
+ return STP_No_Such_State_Machine;
+ }
+
+ return 0;
+}
+
+void STP_port_trace_flags (char* title, PORT_T* this)
+{
+ unsigned long flag = 0L;
+
+ if (!port_trace_flags) return;
+
+ if (this->reRoot) flag |= 0x000001L;
+ if (this->sync) flag |= 0x000002L;
+ if (this->synced) flag |= 0x000004L;
+
+ if (this->proposed) flag |= 0x000010L;
+ if (this->proposing) flag |= 0x000020L;
+ if (this->agreed) flag |= 0x000040L;
+ if (this->updtInfo) flag |= 0x000080L;
+
+ if (this->operEdge) flag |= 0x000100L;
+ stp_trace (" %-12s: flags=0x%04lx fdWhile=%d port=%s", title, flag, this->fdWhile, this->port_name);
+}
+
+#endif
diff --git a/usr/src/lib/librstp/common/port.h b/usr/src/lib/librstp/common/port.h
new file mode 100644
index 0000000000..03556eade1
--- /dev/null
+++ b/usr/src/lib/librstp/common/port.h
@@ -0,0 +1,185 @@
+/************************************************************************
+ * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
+ * Copyright (C) 2001-2003 Optical Access
+ * Author: Alex Rozin
+ *
+ * This file is part of RSTP library.
+ *
+ * RSTP library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; version 2.1
+ *
+ * RSTP library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with RSTP library; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ **********************************************************************/
+
+/* STP PORT instance : 17.18, 17.15 */
+
+#ifndef _STP_PORT_H__
+#define _STP_PORT_H__
+
+#include "statmch.h"
+
+#define TIMERS_NUMBER 9
+typedef unsigned int PORT_TIMER_T;
+
+typedef enum {
+ Mine,
+ Aged,
+ Received,
+ Disabled
+} INFO_IS_T;
+
+typedef enum {
+ SuperiorDesignateMsg,
+ RepeatedDesignateMsg,
+ ConfirmedRootMsg,
+ OtherMsg
+} RCVD_MSG_T;
+
+typedef enum {
+ DisabledPort = 0,
+ AlternatePort,
+ BackupPort,
+ RootPort,
+ DesignatedPort,
+ NonStpPort
+} PORT_ROLE_T;
+
+typedef struct port_t {
+ struct port_t* next;
+
+ /* per Port state machines */
+ STATE_MACH_T* info; /* 17.21 */
+ STATE_MACH_T* roletrns; /* 17.23 */
+ STATE_MACH_T* sttrans; /* 17.24 */
+ STATE_MACH_T* topoch; /* 17.25 */
+ STATE_MACH_T* migrate; /* 17.26 */
+ STATE_MACH_T* transmit; /* 17.26 */
+ STATE_MACH_T* p2p; /* 6.4.3, 6.5.1 */
+ STATE_MACH_T* edge; /* */
+ STATE_MACH_T* pcost; /* */
+
+ STATE_MACH_T* machines; /* list of machines */
+
+ struct stpm_t* owner; /* Bridge, that this port belongs to */
+
+ /* per port Timers */
+ PORT_TIMER_T fdWhile; /* 17.15.1 */
+ PORT_TIMER_T helloWhen; /* 17.15.2 */
+ PORT_TIMER_T mdelayWhile; /* 17.15.3 */
+ PORT_TIMER_T rbWhile; /* 17.15.4 */
+ PORT_TIMER_T rcvdInfoWhile;/* 17.15.5 */
+ PORT_TIMER_T rrWhile; /* 17.15.6 */
+ PORT_TIMER_T tcWhile; /* 17.15.7 */
+ PORT_TIMER_T txCount; /* 17.18.40 */
+ PORT_TIMER_T lnkWhile;
+
+ PORT_TIMER_T* timers[TIMERS_NUMBER]; /*list of timers */
+
+ Bool agreed; /* 17.18.1 */
+ PRIO_VECTOR_T designPrio; /* 17.18.2 */
+ TIMEVALUES_T designTimes; /* 17.18.3 */
+ Bool forward; /* 17.18.4 */
+ Bool forwarding; /* 17.18.5 */
+ INFO_IS_T infoIs; /* 17.18.6 */
+ Bool initPm; /* 17.18.7 */
+ Bool learn; /* 17.18.8 */
+ Bool learning; /* 17.18.9 */
+ Bool mcheck; /* 17.18.10 */
+ PRIO_VECTOR_T msgPrio; /* 17.18.11 */
+ TIMEVALUES_T msgTimes; /* 17.18.12 */
+ Bool newInfo; /* 17.18.13 */
+ Bool operEdge; /* 17.18.14 */
+ Bool adminEdge; /* 17.18.14 */
+ Bool portEnabled; /* 17.18.15 */
+ PORT_ID port_id; /* 17.18.16 */
+ PRIO_VECTOR_T portPrio; /* 17.18.17 */
+ TIMEVALUES_T portTimes; /* 17.18.18 */
+ Bool proposed; /* 17.18.19 */
+ Bool proposing; /* 17.18.20 */
+ Bool rcvdBpdu; /* 17.18.21 */
+ RCVD_MSG_T rcvdMsg; /* 17.18.22 */
+ Bool rcvdRSTP; /* 17/18.23 */
+ Bool rcvdSTP; /* 17.18.24 */
+ Bool rcvdTc; /* 17.18.25 */
+ Bool rcvdTcAck; /* 17.18.26 */
+ Bool rcvdTcn; /* 17.18.27 */
+ Bool reRoot; /* 17.18.28 */
+ Bool reselect; /* 17.18.29 */
+ PORT_ROLE_T role; /* 17.18.30 */
+ Bool selected; /* 17.18.31 */
+ PORT_ROLE_T selectedRole; /* 17.18.32 */
+ Bool sendRSTP; /* 17.18.33 */
+ Bool sync; /* 17.18.34 */
+ Bool synced; /* 17.18.35 */
+ Bool tc; /* 17.18.36 */
+ Bool tcAck; /* 17.18.37 */
+ Bool tcProp; /* 17.18.38 */
+
+ Bool updtInfo; /* 17.18.41 */
+
+ /* message information */
+ unsigned char msgBpduVersion;
+ unsigned char msgBpduType;
+ unsigned char msgPortRole;
+ unsigned char msgFlags;
+
+ unsigned long adminPCost; /* may be ADMIN_PORT_PATH_COST_AUTO */
+ unsigned long operPCost;
+ unsigned long operSpeed;
+ unsigned long usedSpeed;
+ int LinkDelay; /* TBD: LinkDelay may be managed ? */
+ Bool adminEnable; /* 'has LINK' */
+ Bool wasInitBpdu;
+ Bool admin_non_stp;
+
+ Bool p2p_recompute;
+ Bool operPointToPointMac;
+ ADMIN_P2P_T adminPointToPointMac;
+
+ /* statistics */
+ unsigned long rx_cfg_bpdu_cnt;
+ unsigned long rx_rstp_bpdu_cnt;
+ unsigned long rx_tcn_bpdu_cnt;
+
+ unsigned long uptime; /* 14.8.2.1.3.a */
+
+ int port_index;
+ char* port_name;
+
+#ifdef STP_DBG
+ unsigned int skip_rx;
+ unsigned int skip_tx;
+#endif
+} PORT_T;
+
+PORT_T*
+STP_port_create (struct stpm_t* stpm, int port_index);
+
+void
+STP_port_delete (PORT_T* this);
+
+int
+STP_port_rx_bpdu (PORT_T* this, BPDU_T* bpdu, size_t len);
+
+void
+STP_port_init (PORT_T* this, struct stpm_t* stpm, Bool check_link);
+
+#ifdef STP_DBG
+int
+STP_port_trace_state_machine (PORT_T* this, char* mach_name, int enadis);
+
+void
+STP_port_trace_flags (char* title, PORT_T* this);
+#endif
+
+#endif /* _STP_PORT_H__ */
+
diff --git a/usr/src/lib/librstp/common/portinfo.c b/usr/src/lib/librstp/common/portinfo.c
new file mode 100644
index 0000000000..67af0b3320
--- /dev/null
+++ b/usr/src/lib/librstp/common/portinfo.c
@@ -0,0 +1,509 @@
+/************************************************************************
+ * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
+ * Copyright (C) 2001-2003 Optical Access
+ * Author: Alex Rozin
+ *
+ * This file is part of RSTP library.
+ *
+ * RSTP library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; version 2.1
+ *
+ * RSTP library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with RSTP library; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ **********************************************************************/
+
+#include "base.h"
+#include "stpm.h"
+#include "stp_vectors.h"
+
+/* The Port Information State Machine : 17.21 */
+
+#define STATES { \
+ CHOOSE(DISABLED), \
+ CHOOSE(ENABLED), \
+ CHOOSE(AGED), \
+ CHOOSE(UPDATE), \
+ CHOOSE(CURRENT), \
+ CHOOSE(RECEIVE), \
+ CHOOSE(SUPERIOR), \
+ CHOOSE(REPEAT), \
+ CHOOSE(AGREEMENT) \
+}
+
+#define GET_STATE_NAME STP_info_get_state_name
+#include "choose.h"
+
+#if 0 /* for debug */
+void
+_stp_dump (char* title, unsigned char* buff, int len)
+{
+ register int iii;
+
+ stp_trace ("\n%s:", title);
+ for (iii = 0; iii < len; iii++) {
+ if (! (iii % 24)) stp_trace ("\n%6d:", iii);
+ if (! (iii % 8)) stp_trace (" ");
+ stp_trace ("%02lx", (unsigned long) buff[iii]);
+ }
+ stp_trace ("\n");
+}
+#endif
+
+static RCVD_MSG_T
+rcvBpdu (STATE_MACH_T* this)
+{/* 17.19.8 */
+ int bridcmp;
+ register PORT_T* port = this->owner.port;
+
+ if (port->msgBpduType == BPDU_TOPO_CHANGE_TYPE) {
+#ifdef STP_DBG
+ if (this->debug) {
+ stp_trace ("%s", "rcvBpdu: OtherMsg:BPDU_TOPO_CHANGE_TYPE");
+ }
+#endif
+ return OtherMsg;
+ }
+
+ port->msgPortRole = RSTP_PORT_ROLE_UNKN;
+
+ if (BPDU_RSTP == port->msgBpduType) {
+ port->msgPortRole = (port->msgFlags & PORT_ROLE_MASK) >> PORT_ROLE_OFFS;
+ }
+
+ if (RSTP_PORT_ROLE_DESGN == port->msgPortRole ||
+ BPDU_CONFIG_TYPE == port->msgBpduType) {
+ bridcmp = STP_VECT_compare_vector (&port->msgPrio, &port->portPrio);
+
+ if (bridcmp < 0 ||
+ (! STP_VECT_compare_bridge_id (&port->msgPrio.design_bridge,
+ &port->portPrio.design_bridge) &&
+ port->msgPrio.design_port == port->portPrio.design_port &&
+ STP_compare_times (&port->msgTimes, &port->portTimes))) {
+#ifdef STP_DBG
+ if (this->debug) {
+ stp_trace ("rcvBpdu: SuperiorDesignateMsg:bridcmp=%d", (int) bridcmp);
+ }
+#endif
+ return SuperiorDesignateMsg;
+ }
+ }
+
+ if (BPDU_CONFIG_TYPE == port->msgBpduType ||
+ RSTP_PORT_ROLE_DESGN == port->msgPortRole) {
+ if (! STP_VECT_compare_vector (&port->msgPrio,
+ &port->portPrio) &&
+ ! STP_compare_times (&port->msgTimes, &port->portTimes)) {
+#ifdef STP_DBG
+ if (this->debug) {
+ stp_trace ("%s", "rcvBpdu: RepeatedDesignateMsg");
+ }
+#endif
+ return RepeatedDesignateMsg;
+ }
+ }
+
+ if (RSTP_PORT_ROLE_ROOT == port->msgBpduType &&
+ port->operPointToPointMac &&
+ ! STP_VECT_compare_bridge_id (&port->msgPrio.design_bridge,
+ &port->portPrio.design_bridge) &&
+ AGREEMENT_BIT & port->msgFlags) {
+#ifdef STP_DBG
+ if (this->debug) {
+ stp_trace ("%s", "rcvBpdu: ConfirmedRootMsg");
+ }
+#endif
+ return ConfirmedRootMsg;
+ }
+
+#ifdef STP_DBG
+ if (this->debug) {
+ if (RSTP_PORT_ROLE_ROOT == port->msgBpduType) {
+ if (!port->operPointToPointMac) {
+ stp_trace("rcvBpdu: OtherMsg: not point-to-point MAC");
+ } else if (STP_VECT_compare_bridge_id (&port->msgPrio.design_bridge,
+ &port->portPrio.design_bridge)) {
+ STP_VECT_br_id_print("rcvBpdu: OtherMsg: msgPrio", &port->msgPrio.design_bridge, True);
+ STP_VECT_br_id_print("rcvBpdu: portPrio", &port->portPrio.design_bridge, True);
+ } else {
+ stp_trace("rcvBpdu: OtherMsg: agreement bit not set");
+ }
+ } else {
+ stp_trace ("rcvBpdu: OtherMsg: type %d", port->msgBpduType);
+ }
+ }
+#endif
+ return OtherMsg;
+}
+
+/* ARGSUSED */
+static Bool
+recordProposed (STATE_MACH_T* this, char* reason)
+{/* 17.19.9 */
+ register PORT_T* port = this->owner.port;
+
+ if (RSTP_PORT_ROLE_DESGN == port->msgPortRole &&
+ (PROPOSAL_BIT & port->msgFlags) &&
+ port->operPointToPointMac) {
+ return True;
+ }
+ return False;
+}
+
+static void
+setTcFlags (STATE_MACH_T* this)
+{/* 17.19.13 */
+ register PORT_T* port = this->owner.port;
+
+ if (BPDU_TOPO_CHANGE_TYPE == port->msgBpduType) {
+#ifdef STP_DBG
+ if (this->debug) {
+ stp_trace ("port %s rx rcvdTcn", port->port_name);
+ }
+#endif
+ port->rcvdTcn = True;
+ } else {
+ if (TOPOLOGY_CHANGE_BIT & port->msgFlags) {
+#ifdef STP_DBG
+ if (this->debug) {
+ stp_trace ("(%s-%s) rx rcvdTc 0X%lx",
+ port->owner->name, port->port_name,
+ (unsigned long) port->msgFlags);
+ }
+#endif
+ port->rcvdTc = True;
+ }
+ if (TOPOLOGY_CHANGE_ACK_BIT & port->msgFlags) {
+#ifdef STP_DBG
+ if (this->debug) {
+ stp_trace ("port %s rx rcvdTcAck 0X%lx",
+ port->port_name,
+ (unsigned long) port->msgFlags);
+ }
+#endif
+ port->rcvdTcAck = True;
+ }
+ }
+}
+
+static void
+updtBPDUVersion (STATE_MACH_T* this)
+{/* 17.19.18 */
+ register PORT_T* port = this->owner.port;
+
+ if (BPDU_TOPO_CHANGE_TYPE == port->msgBpduType) {
+ port->rcvdSTP = True;
+ }
+
+ if (port->msgBpduVersion < 2) {
+ port->rcvdSTP = True;
+ }
+
+ if (BPDU_RSTP == port->msgBpduType) {
+ /* port->port->owner->ForceVersion >= NORMAL_RSTP
+ we have checked in STP_info_rx_bpdu */
+ port->rcvdRSTP = True;
+ }
+}
+
+static void
+updtRcvdInfoWhile (STATE_MACH_T* this)
+{/* 17.19.19 */
+ register int eff_age, dm, dt;
+ register int hello3;
+ register PORT_T* port = this->owner.port;
+
+ eff_age = ( + port->portTimes.MaxAge) / 16;
+ if (eff_age < 1) eff_age = 1;
+ eff_age += port->portTimes.MessageAge;
+
+ if (eff_age <= port->portTimes.MaxAge) {
+ hello3 = 3 * port->portTimes.HelloTime;
+ dm = port->portTimes.MaxAge - eff_age;
+ if (dm > hello3)
+ dt = hello3;
+ else
+ dt = dm;
+ port->rcvdInfoWhile = dt;
+/****
+ stp_trace ("ma=%d eff_age=%d dm=%d dt=%d p=%s",
+ (int) port->portTimes.MessageAge,
+ (int) eff_age, (int) dm, (int) dt, port->port_name);
+****/
+ } else {
+ port->rcvdInfoWhile = 0;
+/****/
+#ifdef STP_DBG
+ /*if (this->debug) */
+ {
+ stp_trace ("port %s: MaxAge=%d MessageAge=%d HelloTime=%d rcvdInfoWhile=null !",
+ port->port_name,
+ (int) port->portTimes.MaxAge,
+ (int) port->portTimes.MessageAge,
+ (int) port->portTimes.HelloTime);
+ }
+#endif
+/****/
+ }
+}
+
+
+/* ARGSUSED */
+void
+STP_info_rx_bpdu (PORT_T* port, struct stp_bpdu_t* bpdu, size_t len)
+{
+#if 0
+ _stp_dump ("\nall BPDU", ((unsigned char*) bpdu) - 12, len + 12);
+ _stp_dump ("ETH_HEADER", (unsigned char*) &bpdu->eth, 5);
+ _stp_dump ("BPDU_HEADER", (unsigned char*) &bpdu->hdr, 4);
+ stp_trace ("protocol=%02x%02x version=%02x bpdu_type=%02x\n",
+ bpdu->hdr.protocol[0], bpdu->hdr.protocol[1],
+ bpdu->hdr.version, bpdu->hdr.bpdu_type);
+
+ _stp_dump ("\nBPDU_BODY", (unsigned char*) &bpdu->body, sizeof (BPDU_BODY_T) + 2);
+ stp_trace ("flags=%02x\n", bpdu->body.flags);
+ _stp_dump ("root_id", bpdu->body.root_id, 8);
+ _stp_dump ("root_path_cost", bpdu->body.root_path_cost, 4);
+ _stp_dump ("bridge_id", bpdu->body.bridge_id, 8);
+ _stp_dump ("port_id", bpdu->body.port_id, 2);
+ _stp_dump ("message_age", bpdu->body.message_age, 2);
+ _stp_dump ("max_age", bpdu->body.max_age, 2);
+ _stp_dump ("hello_time", bpdu->body.hello_time, 2);
+ _stp_dump ("forward_delay", bpdu->body.forward_delay, 2);
+ _stp_dump ("ver_1_len", bpdu->ver_1_len, 2);
+#endif
+
+ /* check bpdu type */
+ switch (bpdu->hdr.bpdu_type) {
+ case BPDU_CONFIG_TYPE:
+ port->rx_cfg_bpdu_cnt++;
+#ifdef STP_DBG
+ if (port->info->debug)
+ stp_trace ("CfgBpdu on port %s", port->port_name);
+#endif
+ if (port->admin_non_stp) return;
+ port->rcvdBpdu = True;
+ break;
+ case BPDU_TOPO_CHANGE_TYPE:
+ port->rx_tcn_bpdu_cnt++;
+#ifdef STP_DBG
+ if (port->info->debug)
+ stp_trace ("TcnBpdu on port %s", port->port_name);
+#endif
+ if (port->admin_non_stp) return;
+ port->rcvdBpdu = True;
+ port->msgBpduVersion = bpdu->hdr.version;
+ port->msgBpduType = bpdu->hdr.bpdu_type;
+ return;
+ default:
+ stp_trace ("RX undef bpdu type=%d", (int) bpdu->hdr.bpdu_type);
+ return;
+ case BPDU_RSTP:
+ port->rx_rstp_bpdu_cnt++;
+ if (port->admin_non_stp) return;
+ if (port->owner->ForceVersion >= NORMAL_RSTP) {
+ port->rcvdBpdu = True;
+ } else {
+ return;
+ }
+#ifdef STP_DBG
+ if (port->info->debug)
+ stp_trace ("BPDU_RSTP on port %s", port->port_name);
+#endif
+ break;
+ }
+
+ port->msgBpduVersion = bpdu->hdr.version;
+ port->msgBpduType = bpdu->hdr.bpdu_type;
+ port->msgFlags = bpdu->body.flags;
+
+ /* 17.18.11 */
+ STP_VECT_get_vector (&bpdu->body, &port->msgPrio);
+ port->msgPrio.bridge_port = port->port_id;
+
+ /* 17.18.12 */
+ STP_get_times (&bpdu->body, &port->msgTimes);
+
+ /* 17.18.25, 17.18.26 : see setTcFlags() */
+}
+
+void STP_info_enter_state (STATE_MACH_T* this)
+{
+ register PORT_T* port = this->owner.port;
+
+ switch (this->State) {
+ case BEGIN:
+ port->rcvdMsg = OtherMsg;
+ port->msgBpduType = (unsigned char)-1;
+ port->msgPortRole = RSTP_PORT_ROLE_UNKN;
+ port->msgFlags = 0;
+
+ /* clear port statistics */
+ port->rx_cfg_bpdu_cnt =
+ port->rx_rstp_bpdu_cnt =
+ port->rx_tcn_bpdu_cnt = 0;
+ /* FALLTHRU */
+ case DISABLED:
+ port->rcvdBpdu = port->rcvdRSTP = port->rcvdSTP = False;
+ port->updtInfo = port->proposing = False; /* In DISABLED */
+ port->agreed = port->proposed = False;
+ port->rcvdInfoWhile = 0;
+ port->infoIs = Disabled;
+ port->reselect = True;
+ port->selected = False;
+ break;
+ case ENABLED: /* IEEE 802.1y, 17.21, Z.14 */
+ STP_VECT_copy (&port->portPrio, &port->designPrio);
+ STP_copy_times (&port->portTimes, &port->designTimes);
+ break;
+ case AGED:
+ port->infoIs = Aged;
+ port->reselect = True;
+ port->selected = False;
+ break;
+ case UPDATE:
+ STP_VECT_copy (&port->portPrio, &port->designPrio);
+ STP_copy_times (&port->portTimes, &port->designTimes);
+ port->updtInfo = False;
+ port->agreed = port->synced = False; /* In UPDATE */
+ port->proposed = port->proposing = False; /* in UPDATE */
+ port->infoIs = Mine;
+ port->newInfo = True;
+#ifdef STP_DBG
+ if (this->debug) {
+ STP_VECT_br_id_print ("updated: portPrio.design_bridge",
+ &port->portPrio.design_bridge, True);
+ STP_VECT_br_id_print ("updated: portPrio.root_bridge",
+ &port->portPrio.root_bridge, True);
+ }
+#endif
+ break;
+ case CURRENT:
+ break;
+ case RECEIVE:
+ port->rcvdMsg = rcvBpdu (this);
+ updtBPDUVersion (this);
+ setTcFlags (this);
+ port->rcvdBpdu = False;
+ break;
+ case SUPERIOR:
+ STP_VECT_copy (&port->portPrio, &port->msgPrio);
+ STP_copy_times (&port->portTimes, &port->msgTimes);
+ updtRcvdInfoWhile (this);
+#if 1 /* due 802.1y, Z.7 */
+ port->agreed = False; /* deleted due 802.y in SUPERIOR */
+ port->synced = False; /* due 802.y deleted in SUPERIOR */
+#endif
+ port->proposing = False; /* in SUPERIOR */
+ port->proposed = recordProposed (this, "SUPERIOR");
+ port->infoIs = Received;
+ port->reselect = True;
+ port->selected = False;
+#ifdef STP_DBG
+ if (this->debug) {
+ STP_VECT_br_id_print ("stored: portPrio.design_bridge",
+ &port->portPrio.design_bridge, True);
+ STP_VECT_br_id_print ("stored: portPrio.root_bridge",
+ &port->portPrio.root_bridge, True);
+ stp_trace ("proposed=%d on port %s",
+ (int) port->proposed, port->port_name);
+ }
+#endif
+ break;
+ case REPEAT:
+ port->proposed = recordProposed (this, "REPEAT");
+ updtRcvdInfoWhile (this);
+ break;
+ case AGREEMENT:
+#ifdef STP_DBG
+ if (port->roletrns->debug) {
+ stp_trace ("(%s-%s) rx AGREEMENT flag !",
+ port->owner->name, port->port_name);
+ }
+#endif
+
+ port->agreed = True;
+ port->proposing = False; /* In AGREEMENT */
+ break;
+ }
+
+}
+
+Bool STP_info_check_conditions (STATE_MACH_T* this)
+{
+ register PORT_T* port = this->owner.port;
+
+ if ((! port->portEnabled && port->infoIs != Disabled) || BEGIN == this->State) {
+ return STP_hop_2_state (this, DISABLED);
+ }
+
+ switch (this->State) {
+ case DISABLED:
+ if (port->updtInfo) {
+ return STP_hop_2_state (this, DISABLED);
+ }
+ if (port->portEnabled && port->selected) {
+ return STP_hop_2_state (this, ENABLED);
+ }
+ if (port->rcvdBpdu) {
+ return STP_hop_2_state (this, DISABLED);
+ }
+ break;
+ case ENABLED: /* IEEE 802.1y, 17.21, Z.14 */
+ return STP_hop_2_state (this, AGED);
+ break;
+ case AGED:
+ if (port->selected && port->updtInfo) {
+ return STP_hop_2_state (this, UPDATE);
+ }
+ break;
+ case UPDATE:
+ return STP_hop_2_state (this, CURRENT);
+ break;
+ case CURRENT:
+ if (port->selected && port->updtInfo) {
+ return STP_hop_2_state (this, UPDATE);
+ }
+
+ if (Received == port->infoIs &&
+ ! port->rcvdInfoWhile &&
+ ! port->updtInfo &&
+ ! port->rcvdBpdu) {
+ return STP_hop_2_state (this, AGED);
+ }
+ if (port->rcvdBpdu && !port->updtInfo) {
+ return STP_hop_2_state (this, RECEIVE);
+ }
+ break;
+ case RECEIVE:
+ switch (port->rcvdMsg) {
+ case SuperiorDesignateMsg:
+ return STP_hop_2_state (this, SUPERIOR);
+ case RepeatedDesignateMsg:
+ return STP_hop_2_state (this, REPEAT);
+ case ConfirmedRootMsg:
+ return STP_hop_2_state (this, AGREEMENT);
+ default:
+ return STP_hop_2_state (this, CURRENT);
+ }
+ break;
+ case SUPERIOR:
+ return STP_hop_2_state (this, CURRENT);
+ break;
+ case REPEAT:
+ return STP_hop_2_state (this, CURRENT);
+ break;
+ case AGREEMENT:
+ return STP_hop_2_state (this, CURRENT);
+ break;
+ }
+
+ return False;
+}
diff --git a/usr/src/lib/librstp/common/portinfo.h b/usr/src/lib/librstp/common/portinfo.h
new file mode 100644
index 0000000000..ef1dceb4ac
--- /dev/null
+++ b/usr/src/lib/librstp/common/portinfo.h
@@ -0,0 +1,40 @@
+/************************************************************************
+ * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
+ * Copyright (C) 2001-2003 Optical Access
+ * Author: Alex Rozin
+ *
+ * This file is part of RSTP library.
+ *
+ * RSTP library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; version 2.1
+ *
+ * RSTP library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with RSTP library; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ **********************************************************************/
+
+/* The Port Information State Machine : 17.21 */
+
+#ifndef _STP_INFOR_H__
+#define _STP_INFOR_H__
+
+void
+STP_info_enter_state (STATE_MACH_T* s);
+
+Bool
+STP_info_check_conditions (STATE_MACH_T* s);
+
+void
+STP_info_rx_bpdu (PORT_T* this, struct stp_bpdu_t* bpdu, size_t len);
+
+char*
+STP_info_get_state_name (int state);
+
+#endif /* _STP_INFOR_H__ */
diff --git a/usr/src/lib/librstp/common/rolesel.c b/usr/src/lib/librstp/common/rolesel.c
new file mode 100644
index 0000000000..871622d354
--- /dev/null
+++ b/usr/src/lib/librstp/common/rolesel.c
@@ -0,0 +1,400 @@
+/************************************************************************
+ * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
+ * Copyright (C) 2001-2003 Optical Access
+ * Author: Alex Rozin
+ *
+ * This file is part of RSTP library.
+ *
+ * RSTP library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; version 2.1
+ *
+ * RSTP library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with RSTP library; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ **********************************************************************/
+
+/* Port Role Selection state machine : 17.22 */
+
+#include "base.h"
+#include "stpm.h"
+#include "stp_vectors.h"
+
+#define STATES { \
+ CHOOSE(INIT_BRIDGE), \
+ CHOOSE(ROLE_SELECTION) \
+}
+
+#define GET_STATE_NAME STP_rolesel_get_state_name
+#include "choose.h"
+
+#if 0
+void stp_dbg_break_point (PORT_T * port, STPM_T* stpm)
+{
+}
+#endif
+
+static Bool
+_is_backup_port (PORT_T* port, STPM_T* this)
+{
+ if (!STP_VECT_compare_bridge_id
+ (&port->portPrio.design_bridge, &this->BrId)) {
+#if 0 /* def STP_DBG */
+ if (port->info->debug) {
+ STP_VECT_br_id_print ("portPrio.design_bridge",
+ &port->portPrio.design_bridge, True);
+ STP_VECT_br_id_print (" this->BrId",
+ &this->BrId, True);
+ }
+ stp_dbg_break_point (port, this);
+#endif
+ return True;
+ } else {
+ return False;
+ }
+}
+
+/* ARGSUSED */
+static void
+setRoleSelected (char* reason, STPM_T* stpm, PORT_T* port,
+ PORT_ROLE_T newRole)
+{
+#ifdef STP_DBG
+ char* new_role_name;
+#endif
+
+ port->selectedRole = newRole;
+
+ if (newRole == port->role)
+ return;
+
+ switch (newRole) {
+ case DisabledPort:
+#ifdef STP_DBG
+ new_role_name = "Disabled";
+#endif
+ break;
+ case AlternatePort:
+#ifdef STP_DBG
+ new_role_name = "Alternate";
+#endif
+ break;
+ case BackupPort:
+#ifdef STP_DBG
+ new_role_name = "Backup";
+#endif
+ break;
+ case RootPort:
+#ifdef STP_DBG
+ new_role_name = "Root";
+#endif
+ break;
+ case DesignatedPort:
+#ifdef STP_DBG
+ new_role_name = "Designated";
+#endif
+ break;
+ case NonStpPort:
+#ifdef STP_DBG
+ new_role_name = "NonStp";
+#endif
+ port->role = newRole;
+ break;
+ default:
+#ifdef STP_DBG
+ stp_trace ("%s-%s:port %s => Unknown (%d ?)",
+ reason, stpm->name, port->port_name, (int) newRole);
+#else
+ abort();
+#endif
+ return;
+ }
+
+#ifdef STP_DBG
+ if (port->roletrns->debug)
+ stp_trace ("%s(%s-%s) => %s",
+ reason, stpm->name, port->port_name, new_role_name);
+#endif
+}
+
+static void
+updtRoleDisableBridge (STPM_T* this)
+{ /* 17.10.20 */
+ register PORT_T *port;
+
+ for (port = this->ports; port; port = port->next) {
+ port->selectedRole = DisabledPort;
+ }
+}
+
+static void
+clearReselectBridge (STPM_T* this)
+{ /* 17.19.1 */
+ register PORT_T *port;
+
+ for (port = this->ports; port; port = port->next) {
+ port->reselect = False;
+ }
+}
+
+static void
+updtRootPrio (STATE_MACH_T* this)
+{
+ PRIO_VECTOR_T rootPathPrio; /* 17.4.2.2 */
+ register PORT_T *port;
+ register STPM_T *stpm;
+ register unsigned int dm;
+
+ stpm = this->owner.stpm;
+
+ for (port = stpm->ports; port; port = port->next) {
+ if (port->admin_non_stp) {
+ continue;
+ }
+
+ if (Disabled == port->infoIs)
+ continue;
+ if (Aged == port->infoIs)
+ continue;
+ if (Mine == port->infoIs) {
+#if 0 /* def STP_DBG */
+ stp_dbg_break_point (port); /* for debugger break point */
+#endif
+ continue;
+ }
+
+ STP_VECT_copy (&rootPathPrio, &port->portPrio);
+ rootPathPrio.root_path_cost += port->operPCost;
+
+ if (STP_VECT_compare_vector (&rootPathPrio, &stpm->rootPrio) < 0) {
+ STP_VECT_copy (&stpm->rootPrio, &rootPathPrio);
+ STP_copy_times (&stpm->rootTimes, &port->portTimes);
+ dm = (8 + stpm->rootTimes.MaxAge) / 16;
+ if (!dm)
+ dm = 1;
+ stpm->rootTimes.MessageAge += dm;
+#ifdef STP_DBG
+ if (port->roletrns->debug)
+ stp_trace ("updtRootPrio: dm=%d rootTimes.MessageAge=%d on port %s",
+ (int) dm, (int) stpm->rootTimes.MessageAge,
+ port->port_name);
+#endif
+ }
+ }
+}
+
+static void
+updtRolesBridge (STATE_MACH_T* this)
+{ /* 17.19.21 */
+ register PORT_T* port;
+ register STPM_T* stpm;
+#ifdef STP_DBG
+ PORT_ID old_root_port; /* for tracing of root port changing */
+#endif
+
+ stpm = this->owner.stpm;
+#ifdef STP_DBG
+ old_root_port = stpm->rootPortId;
+#endif
+
+ STP_VECT_create (&stpm->rootPrio, &stpm->BrId, 0, &stpm->BrId, 0, 0);
+ STP_copy_times (&stpm->rootTimes, &stpm->BrTimes);
+ stpm->rootPortId = 0;
+
+ updtRootPrio (this);
+
+ for (port = stpm->ports; port; port = port->next) {
+ if (port->admin_non_stp) {
+ continue;
+ }
+ STP_VECT_create (&port->designPrio,
+ &stpm->rootPrio.root_bridge,
+ stpm->rootPrio.root_path_cost,
+ &stpm->BrId, port->port_id, port->port_id);
+ STP_copy_times (&port->designTimes, &stpm->rootTimes);
+
+#if 0
+#ifdef STP_DBG
+ if (port->roletrns->debug) {
+ STP_VECT_br_id_print ("ch:designPrio.design_bridge",
+ &port->designPrio.design_bridge, True);
+ }
+#endif
+#endif
+ }
+
+ stpm->rootPortId = stpm->rootPrio.bridge_port;
+
+#ifdef STP_DBG
+ if (old_root_port != stpm->rootPortId) {
+ if (! stpm->rootPortId) {
+ stp_trace ("bridge %s became root", stpm->name);
+ } else {
+ stp_trace ("bridge %s new root port: %s",
+ stpm->name,
+ STP_stpm_get_port_name_by_id (stpm, stpm->rootPortId));
+ }
+ }
+#endif
+
+ for (port = stpm->ports; port; port = port->next) {
+ if (port->admin_non_stp) {
+ setRoleSelected ("Non", stpm, port, NonStpPort);
+ port->forward = port->learn = True;
+ continue;
+ }
+
+ switch (port->infoIs) {
+ case Disabled:
+ setRoleSelected ("Dis", stpm, port, DisabledPort);
+ break;
+ case Aged:
+ setRoleSelected ("Age", stpm, port, DesignatedPort);
+ port->updtInfo = True;
+ break;
+ case Mine:
+ setRoleSelected ("Mine", stpm, port, DesignatedPort);
+ if (0 != STP_VECT_compare_vector (&port->portPrio,
+ &port->designPrio) ||
+ 0 != STP_compare_times (&port->portTimes,
+ &port->designTimes)) {
+ port->updtInfo = True;
+ }
+ break;
+ case Received:
+ if (stpm->rootPortId == port->port_id) {
+ setRoleSelected ("Rec", stpm, port, RootPort);
+ } else if (STP_VECT_compare_vector (&port->designPrio, &port->portPrio) < 0) {
+ /* Note: this important piece has been inserted after
+ * discussion with Mick Sieman and reading 802.1y Z1 */
+ setRoleSelected ("Rec", stpm, port, DesignatedPort);
+ port->updtInfo = True;
+ break;
+ } else {
+ if (_is_backup_port (port, stpm)) {
+ setRoleSelected ("rec", stpm, port, BackupPort);
+ } else {
+ setRoleSelected ("rec", stpm, port, AlternatePort);
+ }
+ }
+ port->updtInfo = False;
+ break;
+ default:
+ stp_trace ("undef infoIs=%d", (int) port->infoIs);
+ break;
+ }
+ }
+
+}
+
+
+static Bool
+setSelectedBridge (STPM_T* this)
+{
+ register PORT_T* port;
+
+ for (port = this->ports; port; port = port->next) {
+ if (port->reselect) {
+#ifdef STP_DBG
+ stp_trace ("setSelectedBridge: TRUE=reselect on port %s", port->port_name);
+#endif
+ return False;
+ }
+ }
+
+ for (port = this->ports; port; port = port->next) {
+ port->selected = True;
+ }
+
+ return True;
+}
+
+void
+STP_rolesel_enter_state (STATE_MACH_T* this)
+{
+ STPM_T* stpm;
+
+ stpm = this->owner.stpm;
+
+ switch (this->State) {
+ case BEGIN:
+ case INIT_BRIDGE:
+ updtRoleDisableBridge (stpm);
+ break;
+ case ROLE_SELECTION:
+ clearReselectBridge (stpm);
+ updtRolesBridge (this);
+ (void) setSelectedBridge (stpm);
+ break;
+ }
+}
+
+Bool
+STP_rolesel_check_conditions (STATE_MACH_T* s)
+{
+ STPM_T* stpm;
+ register PORT_T* port;
+
+ /*
+ * This doesn't look right. Why should we hop state twice in a single check
+ * condition call? It means we can never perform the enter-state action for
+ * INIT_BRIDGE.
+ */
+#ifdef carlsonj_removed
+ if (BEGIN == s->State) {
+ (void) STP_hop_2_state (s, INIT_BRIDGE);
+ }
+#endif
+
+ switch (s->State) {
+ case BEGIN:
+ return STP_hop_2_state (s, INIT_BRIDGE);
+ case INIT_BRIDGE:
+ return STP_hop_2_state (s, ROLE_SELECTION);
+ case ROLE_SELECTION:
+ stpm = s->owner.stpm;
+ for (port = stpm->ports; port; port = port->next) {
+ if (port->reselect) {
+ /* stp_trace ("reselect on port %s", port->port_name); */
+ return STP_hop_2_state (s, ROLE_SELECTION);
+ }
+ }
+ break;
+ }
+
+ return False;
+}
+
+void
+STP_rolesel_update_stpm (STPM_T* this)
+{
+ register PORT_T* port;
+ PRIO_VECTOR_T rootPathPrio; /* 17.4.2.2 */
+
+ stp_trace ("%s", "??? STP_rolesel_update_stpm ???");
+ STP_VECT_create (&rootPathPrio, &this->BrId, 0, &this->BrId, 0, 0);
+
+ if (!this->rootPortId ||
+ STP_VECT_compare_vector (&rootPathPrio, &this->rootPrio) < 0) {
+ STP_VECT_copy (&this->rootPrio, &rootPathPrio);
+ }
+
+ for (port = this->ports; port; port = port->next) {
+ STP_VECT_create (&port->designPrio,
+ &this->rootPrio.root_bridge,
+ this->rootPrio.root_path_cost,
+ &this->BrId, port->port_id, port->port_id);
+ if (Received != port->infoIs || this->rootPortId == port->port_id) {
+ STP_VECT_copy (&port->portPrio, &port->designPrio);
+ }
+ port->reselect = True;
+ port->selected = False;
+ }
+}
+
diff --git a/usr/src/lib/librstp/common/rolesel.h b/usr/src/lib/librstp/common/rolesel.h
new file mode 100644
index 0000000000..38dad55c30
--- /dev/null
+++ b/usr/src/lib/librstp/common/rolesel.h
@@ -0,0 +1,41 @@
+/************************************************************************
+ * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
+ * Copyright (C) 2001-2003 Optical Access
+ * Author: Alex Rozin
+ *
+ * This file is part of RSTP library.
+ *
+ * RSTP library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; version 2.1
+ *
+ * RSTP library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with RSTP library; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ **********************************************************************/
+
+/* Port Role Selection state machine : 17.22 */
+
+#ifndef _STP_ROLES_SELECT_H
+#define _STP_ROLES_SELECT_H
+
+void
+STP_rolesel_enter_state (STATE_MACH_T* s);
+
+Bool
+STP_rolesel_check_conditions (STATE_MACH_T* s);
+
+void
+STP_rolesel_update_stpm (struct stpm_t* this);
+
+char*
+STP_rolesel_get_state_name (int state);
+
+#endif /* _STP_ROLES_SELECT_H */
+
diff --git a/usr/src/lib/librstp/common/roletrns.c b/usr/src/lib/librstp/common/roletrns.c
new file mode 100644
index 0000000000..d6684d3958
--- /dev/null
+++ b/usr/src/lib/librstp/common/roletrns.c
@@ -0,0 +1,431 @@
+/************************************************************************
+ * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
+ * Copyright (C) 2001-2003 Optical Access
+ * Author: Alex Rozin
+ *
+ * This file is part of RSTP library.
+ *
+ * RSTP library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; version 2.1
+ *
+ * RSTP library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with RSTP library; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ **********************************************************************/
+
+/* Port Role Transitions state machine : 17.24 */
+
+#include "base.h"
+
+#include "stpm.h"
+
+#define STATES { \
+ CHOOSE(INIT_PORT), \
+ CHOOSE(BLOCK_PORT), \
+ CHOOSE(BLOCKED_PORT), \
+ CHOOSE(BACKUP_PORT), \
+ CHOOSE(ROOT_PROPOSED), \
+ CHOOSE(ROOT_AGREED), \
+ CHOOSE(REROOT), \
+ CHOOSE(ROOT_PORT), \
+ CHOOSE(REROOTED), \
+ CHOOSE(ROOT_LEARN), \
+ CHOOSE(ROOT_FORWARD), \
+ CHOOSE(DESIGNATED_PROPOSE), \
+ CHOOSE(DESIGNATED_SYNCED), \
+ CHOOSE(DESIGNATED_RETIRED), \
+ CHOOSE(DESIGNATED_PORT), \
+ CHOOSE(DESIGNATED_LISTEN), \
+ CHOOSE(DESIGNATED_LEARN), \
+ CHOOSE(DESIGNATED_FORWARD) \
+}
+
+#define GET_STATE_NAME STP_roletrns_get_state_name
+#include "choose.h"
+
+static void
+setSyncBridge (STATE_MACH_T *this)
+{
+ register PORT_T* port;
+
+ for (port = this->owner.port->owner->ports; port; port = port->next) {
+ port->sync = True; /* in ROOT_PROPOSED (setSyncBridge) */
+ }
+}
+
+static void
+setReRootBridge (STATE_MACH_T *this)
+{
+ register PORT_T* port;
+
+ for (port = this->owner.port->owner->ports; port; port = port->next) {
+ port->reRoot = True; /* In setReRootBridge */
+ }
+}
+
+static Bool
+compute_all_synced (PORT_T* this)
+{
+ register PORT_T* port;
+
+ for (port = this->owner->ports; port; port = port->next) {
+ if (port->port_index == this->port_index) continue;
+ if (! port->synced) {
+ return False;
+ }
+ }
+
+ return True;
+}
+
+static Bool
+compute_re_rooted (PORT_T* this)
+{
+ register PORT_T* port;
+
+ for (port = this->owner->ports; port; port = port->next) {
+ if (port->port_index == this->port_index) continue;
+ if (port->rrWhile) {
+ return False;
+ }
+ }
+ return True;
+}
+
+void
+STP_roletrns_enter_state (STATE_MACH_T* this)
+{
+ register PORT_T* port = this->owner.port;
+ register STPM_T* stpm;
+
+ stpm = port->owner;
+
+ switch (this->State) {
+ case BEGIN:
+ case INIT_PORT:
+#if 0 /* due 802.1y Z.4 */
+ port->role = DisabledPort;
+#else
+ port->role = port->selectedRole = DisabledPort;
+ port->reselect = True;
+#endif
+ port->synced = False; /* in INIT */
+ port->sync = True; /* in INIT */
+ port->reRoot = True; /* in INIT_PORT */
+ port->rrWhile = stpm->rootTimes.ForwardDelay;
+ port->fdWhile = stpm->rootTimes.ForwardDelay;
+ port->rbWhile = 0;
+#ifdef STP_DBG
+ if (this->debug)
+ STP_port_trace_flags ("after init", port);
+#endif
+ break;
+ case BLOCK_PORT:
+ port->role = port->selectedRole;
+ port->learn =
+ port->forward = False;
+ break;
+ case BLOCKED_PORT:
+ port->fdWhile = stpm->rootTimes.ForwardDelay;
+ port->synced = True; /* In BLOCKED_PORT */
+ port->rrWhile = 0;
+ port->sync = port->reRoot = False; /* BLOCKED_PORT */
+ break;
+ case BACKUP_PORT:
+ port->rbWhile = 2 * stpm->rootTimes.HelloTime;
+ break;
+
+ /* 17.23.2 */
+ case ROOT_PROPOSED:
+ setSyncBridge (this);
+ port->proposed = False;
+#ifdef STP_DBG
+ if (this->debug)
+ STP_port_trace_flags ("ROOT_PROPOSED", port);
+#endif
+ break;
+ case ROOT_AGREED:
+ port->proposed = port->sync = False; /* in ROOT_AGREED */
+ port->synced = True; /* In ROOT_AGREED */
+ port->newInfo = True;
+#ifdef STP_DBG
+ if (this->debug)
+ STP_port_trace_flags ("ROOT_AGREED", port);
+#endif
+ break;
+ case REROOT:
+ setReRootBridge (this);
+#ifdef STP_DBG
+ if (this->debug)
+ STP_port_trace_flags ("REROOT", port);
+#endif
+ break;
+ case ROOT_PORT:
+ port->role = RootPort;
+ port->rrWhile = stpm->rootTimes.ForwardDelay;
+#ifdef STP_DBG
+ if (this->debug)
+ STP_port_trace_flags ("ROOT_PORT", port);
+#endif
+ break;
+ case REROOTED:
+ port->reRoot = False; /* In REROOTED */
+#ifdef STP_DBG
+ if (this->debug)
+ STP_port_trace_flags ("REROOTED", port);
+#endif
+ break;
+ case ROOT_LEARN:
+ port->fdWhile = stpm->rootTimes.ForwardDelay;
+ port->learn = True;
+#ifdef STP_DBG
+ if (this->debug)
+ STP_port_trace_flags ("ROOT_LEARN", port);
+#endif
+ break;
+ case ROOT_FORWARD:
+ port->fdWhile = 0;
+ port->forward = True;
+#ifdef STP_DBG
+ if (this->debug)
+ STP_port_trace_flags ("ROOT_FORWARD", port);
+#endif
+ break;
+
+ /* 17.23.3 */
+ case DESIGNATED_PROPOSE:
+ port->proposing = True; /* in DESIGNATED_PROPOSE */
+ port->newInfo = True;
+#ifdef STP_DBG
+ if (this->debug)
+ STP_port_trace_flags ("DESIGNATED_PROPOSE", port);
+#endif
+ break;
+ case DESIGNATED_SYNCED:
+ port->rrWhile = 0;
+ port->synced = True; /* DESIGNATED_SYNCED */
+ port->sync = False; /* DESIGNATED_SYNCED */
+#ifdef STP_DBG
+ if (this->debug)
+ STP_port_trace_flags ("DESIGNATED_SYNCED", port);
+#endif
+ break;
+ case DESIGNATED_RETIRED:
+ port->reRoot = False; /* DESIGNATED_RETIRED */
+#ifdef STP_DBG
+ if (this->debug)
+ STP_port_trace_flags ("DESIGNATED_RETIRED", port);
+#endif
+ break;
+ case DESIGNATED_PORT:
+ port->role = DesignatedPort;
+#ifdef STP_DBG
+ if (this->debug)
+ STP_port_trace_flags ("DESIGNATED_PORT", port);
+#endif
+ break;
+ case DESIGNATED_LISTEN:
+ port->learn = port->forward = False;
+ port->fdWhile = stpm->rootTimes.ForwardDelay;
+#ifdef STP_DBG
+ if (this->debug)
+ STP_port_trace_flags ("DESIGNATED_LISTEN", port);
+#endif
+ break;
+ case DESIGNATED_LEARN:
+ port->learn = True;
+ port->fdWhile = stpm->rootTimes.ForwardDelay;
+#ifdef STP_DBG
+ if (this->debug)
+ STP_port_trace_flags ("DESIGNATED_LEARN", port);
+#endif
+ break;
+ case DESIGNATED_FORWARD:
+ port->forward = True;
+ port->fdWhile = 0;
+#ifdef STP_DBG
+ if (this->debug)
+ STP_port_trace_flags ("DESIGNATED_FORWARD", port);
+#endif
+ break;
+ };
+}
+
+Bool
+STP_roletrns_check_conditions (STATE_MACH_T* this)
+{
+ register PORT_T *port = this->owner.port;
+ register STPM_T *stpm;
+ Bool allSynced;
+ Bool allReRooted;
+
+ stpm = port->owner;
+
+ if (BEGIN == this->State) {
+ return STP_hop_2_state (this, INIT_PORT);
+ }
+
+ if (port->role != port->selectedRole &&
+ port->selected &&
+ ! port->updtInfo) {
+ switch (port->selectedRole) {
+ case DisabledPort:
+ case AlternatePort:
+ case BackupPort:
+#if 0 /* def STP_DBG */
+ if (this->debug) {
+ stp_trace ("hop to BLOCK_PORT role=%d selectedRole=%d",
+ (int) port->role, (int) port->selectedRole);
+ }
+#endif
+ return STP_hop_2_state (this, BLOCK_PORT);
+ case RootPort:
+ return STP_hop_2_state (this, ROOT_PORT);
+ case DesignatedPort:
+ return STP_hop_2_state (this, DESIGNATED_PORT);
+ default:
+ return False;
+ }
+ }
+
+ switch (this->State) {
+ /* 17.23.1 */
+ case INIT_PORT:
+ return STP_hop_2_state (this, BLOCK_PORT);
+ case BLOCK_PORT:
+ if (!port->selected || port->updtInfo) break;
+ if (!port->learning && !port->forwarding) {
+ return STP_hop_2_state (this, BLOCKED_PORT);
+ }
+ break;
+ case BLOCKED_PORT:
+ if (!port->selected || port->updtInfo) break;
+ if (port->fdWhile != stpm->rootTimes.ForwardDelay ||
+ port->sync ||
+ port->reRoot ||
+ !port->synced) {
+ return STP_hop_2_state (this, BLOCKED_PORT);
+ }
+ if (port->rbWhile != 2 * stpm->rootTimes.HelloTime &&
+ port->role == BackupPort) {
+ return STP_hop_2_state (this, BACKUP_PORT);
+ }
+ break;
+ case BACKUP_PORT:
+ return STP_hop_2_state (this, BLOCKED_PORT);
+
+ /* 17.23.2 */
+ case ROOT_PROPOSED:
+ return STP_hop_2_state (this, ROOT_PORT);
+ case ROOT_AGREED:
+ return STP_hop_2_state (this, ROOT_PORT);
+ case REROOT:
+ return STP_hop_2_state (this, ROOT_PORT);
+ case ROOT_PORT:
+ if (!port->selected || port->updtInfo) break;
+ if (!port->forward && !port->reRoot) {
+ return STP_hop_2_state (this, REROOT);
+ }
+ allSynced = compute_all_synced (port);
+ if ((port->proposed && allSynced) ||
+ (!port->synced && allSynced)) {
+ return STP_hop_2_state (this, ROOT_AGREED);
+ }
+ if (port->proposed && !port->synced) {
+ return STP_hop_2_state (this, ROOT_PROPOSED);
+ }
+
+ allReRooted = compute_re_rooted (port);
+ if ((!port->fdWhile ||
+ ((allReRooted && !port->rbWhile) && stpm->ForceVersion >=2)) &&
+ port->learn && !port->forward) {
+ return STP_hop_2_state (this, ROOT_FORWARD);
+ }
+ if ((!port->fdWhile ||
+ ((allReRooted && !port->rbWhile) && stpm->ForceVersion >=2)) &&
+ !port->learn) {
+ return STP_hop_2_state (this, ROOT_LEARN);
+ }
+
+ if (port->reRoot && port->forward) {
+ return STP_hop_2_state (this, REROOTED);
+ }
+ if (port->rrWhile != stpm->rootTimes.ForwardDelay) {
+ return STP_hop_2_state (this, ROOT_PORT);
+ }
+ break;
+ case REROOTED:
+ return STP_hop_2_state (this, ROOT_PORT);
+ case ROOT_LEARN:
+ return STP_hop_2_state (this, ROOT_PORT);
+ case ROOT_FORWARD:
+ return STP_hop_2_state (this, ROOT_PORT);
+
+ /* 17.23.3 */
+ case DESIGNATED_PROPOSE:
+ return STP_hop_2_state (this, DESIGNATED_PORT);
+ case DESIGNATED_SYNCED:
+ return STP_hop_2_state (this, DESIGNATED_PORT);
+ case DESIGNATED_RETIRED:
+ return STP_hop_2_state (this, DESIGNATED_PORT);
+ case DESIGNATED_PORT:
+ if (!port->selected || port->updtInfo) break;
+
+ if (!port->forward && !port->agreed && !port->proposing && !port->operEdge) {
+ return STP_hop_2_state (this, DESIGNATED_PROPOSE);
+ }
+
+ if (!port->rrWhile && port->reRoot) {
+ return STP_hop_2_state (this, DESIGNATED_RETIRED);
+ }
+
+ if (!port->learning && !port->forwarding && !port->synced) {
+ return STP_hop_2_state (this, DESIGNATED_SYNCED);
+ }
+
+ if (port->agreed && !port->synced) {
+ return STP_hop_2_state (this, DESIGNATED_SYNCED);
+ }
+ if (port->operEdge && !port->synced) {
+ return STP_hop_2_state (this, DESIGNATED_SYNCED);
+ }
+ if (port->sync && port->synced) {
+ return STP_hop_2_state (this, DESIGNATED_SYNCED);
+ }
+
+ if ((!port->fdWhile || port->agreed || port->operEdge) &&
+ (!port->rrWhile || !port->reRoot) &&
+ !port->sync &&
+ (port->learn && !port->forward)) {
+ return STP_hop_2_state (this, DESIGNATED_FORWARD);
+ }
+ if ((!port->fdWhile || port->agreed || port->operEdge) &&
+ (!port->rrWhile || !port->reRoot) &&
+ !port->sync && !port->learn) {
+ return STP_hop_2_state (this, DESIGNATED_LEARN);
+ }
+ if (((port->sync && !port->synced) ||
+ (port->reRoot && port->rrWhile)) &&
+ !port->operEdge && (port->learn || port->forward)) {
+ return STP_hop_2_state (this, DESIGNATED_LISTEN);
+ }
+ break;
+ case DESIGNATED_LISTEN:
+ return STP_hop_2_state (this, DESIGNATED_PORT);
+ case DESIGNATED_LEARN:
+ return STP_hop_2_state (this, DESIGNATED_PORT);
+ case DESIGNATED_FORWARD:
+ return STP_hop_2_state (this, DESIGNATED_PORT);
+ };
+
+ return False;
+}
+
+
diff --git a/usr/src/lib/librstp/common/roletrns.h b/usr/src/lib/librstp/common/roletrns.h
new file mode 100644
index 0000000000..6ba116dfa8
--- /dev/null
+++ b/usr/src/lib/librstp/common/roletrns.h
@@ -0,0 +1,37 @@
+/************************************************************************
+ * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
+ * Copyright (C) 2001-2003 Optical Access
+ * Author: Alex Rozin
+ *
+ * This file is part of RSTP library.
+ *
+ * RSTP library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; version 2.1
+ *
+ * RSTP library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with RSTP library; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ **********************************************************************/
+
+/* Port Role Transitions state machine : 17.24 */
+
+#ifndef _STP_ROLES_TRANSIT_H__
+#define _STP_ROLES_TRANSIT_H__
+
+void
+STP_roletrns_enter_state (STATE_MACH_T* s);
+
+Bool
+STP_roletrns_check_conditions (STATE_MACH_T* s);
+
+char* STP_roletrns_get_state_name (int state);
+
+#endif /* _STP_ROLES_TRANSIT_H__ */
+
diff --git a/usr/src/lib/librstp/common/statmch.c b/usr/src/lib/librstp/common/statmch.c
new file mode 100644
index 0000000000..7f4c1f3a27
--- /dev/null
+++ b/usr/src/lib/librstp/common/statmch.c
@@ -0,0 +1,123 @@
+/************************************************************************
+ * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
+ * Copyright (C) 2001-2003 Optical Access
+ * Author: Alex Rozin
+ *
+ * This file is part of RSTP library.
+ *
+ * RSTP library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; version 2.1
+ *
+ * RSTP library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with RSTP library; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ **********************************************************************/
+
+/* Generic (abstract) state machine : 17.13, 17.14 */
+
+#include "base.h"
+#include "statmch.h"
+#include "stp_vectors.h"
+
+#if STP_DBG
+# include "stpm.h"
+#endif
+
+STATE_MACH_T *
+STP_state_mach_create (void (*concreteEnterState) (STATE_MACH_T*),
+ Bool (*concreteCheckCondition) (STATE_MACH_T*),
+ char *(*concreteGetStatName) (int),
+ void *owner, char *name)
+{
+ STATE_MACH_T *this;
+
+ STP_MALLOC(this, STATE_MACH_T, "state machine");
+
+ this->State = BEGIN;
+ this->name = (char*) strdup (name);
+ this->changeState = False;
+#if STP_DBG
+ this->debug = False;
+ this->ignoreHop2State = BEGIN;
+#endif
+ this->concreteEnterState = concreteEnterState;
+ this->concreteCheckCondition = concreteCheckCondition;
+ this->concreteGetStatName = concreteGetStatName;
+ this->owner.owner = owner;
+
+ return this;
+}
+
+void
+STP_state_mach_delete (STATE_MACH_T *this)
+{
+ free (this->name);
+ STP_FREE(this, "state machine");
+}
+
+Bool
+STP_check_condition (STATE_MACH_T* this)
+{
+ Bool bret;
+
+ bret = (*(this->concreteCheckCondition)) (this);
+ if (bret) {
+ this->changeState = True;
+ }
+
+ return bret;
+}
+
+Bool
+STP_change_state (STATE_MACH_T* this)
+{
+ register int number_of_loops;
+
+ for (number_of_loops = 0; ; number_of_loops++) {
+ if (! this->changeState) break;
+ (*(this->concreteEnterState)) (this);
+ this->changeState = False;
+ (void) STP_check_condition (this);
+ }
+
+ return number_of_loops;
+}
+
+Bool
+STP_hop_2_state (STATE_MACH_T* this, unsigned int new_state)
+{
+#ifdef STP_DBG
+ switch (this->debug) {
+ case 0: break;
+ case 1:
+ if (new_state == this->State || new_state == this->ignoreHop2State) break;
+ stp_trace ("%-8s(%s-%s): %s=>%s",
+ this->name,
+ *this->owner.port->owner->name ? this->owner.port->owner->name : "Glbl",
+ this->owner.port->port_name,
+ (*(this->concreteGetStatName)) (this->State),
+ (*(this->concreteGetStatName)) (new_state));
+ break;
+ case 2:
+ if (new_state == this->State) break;
+ stp_trace ("%s(%s): %s=>%s",
+ this->name,
+ *this->owner.stpm->name ? this->owner.stpm->name : "Glbl",
+ (*(this->concreteGetStatName)) (this->State),
+ (*(this->concreteGetStatName)) (new_state));
+ break;
+ }
+#endif
+
+ this->State = new_state;
+ this->changeState = True;
+ return True;
+}
+
diff --git a/usr/src/lib/librstp/common/statmch.h b/usr/src/lib/librstp/common/statmch.h
new file mode 100644
index 0000000000..e083fdbce7
--- /dev/null
+++ b/usr/src/lib/librstp/common/statmch.h
@@ -0,0 +1,89 @@
+/************************************************************************
+ * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
+ * Copyright (C) 2001-2003 Optical Access
+ * Author: Alex Rozin
+ *
+ * This file is part of RSTP library.
+ *
+ * RSTP library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; version 2.1
+ *
+ * RSTP library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with RSTP library; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ **********************************************************************/
+
+/* Generic (abstract state machine) state machine : 17.13, 17.14 */
+
+#ifndef _STP_STATER_H__
+#define _STP_STATER_H__
+
+#define BEGIN 9999 /* distinct from any valid state */
+
+#define STP_DBG 1
+
+typedef struct state_mach_t {
+ struct state_mach_t* next;
+
+ char* name; /* for debugging */
+#ifdef STP_DBG
+ char debug; /* 0- no dbg, 1 - port, 2 - stpm */
+ unsigned int ignoreHop2State;
+#endif
+
+ Bool changeState;
+ unsigned int State;
+
+ void (* concreteEnterState) (struct state_mach_t * );
+ Bool (* concreteCheckCondition) (struct state_mach_t * );
+ char* (* concreteGetStatName) (int);
+ union {
+ struct stpm_t* stpm;
+ struct port_t* port;
+ void * owner;
+ } owner;
+
+} STATE_MACH_T;
+
+#define STP_STATE_MACH_IN_LIST(WHAT) \
+ { \
+ STATE_MACH_T* abstr; \
+ \
+ abstr = STP_state_mach_create (STP_##WHAT##_enter_state, \
+ STP_##WHAT##_check_conditions, \
+ STP_##WHAT##_get_state_name, \
+ this, \
+ #WHAT); \
+ abstr->next = this->machines; \
+ this->machines = abstr; \
+ this->WHAT = abstr; \
+ }
+
+
+STATE_MACH_T *
+STP_state_mach_create (void (* concreteEnterState) (STATE_MACH_T*),
+ Bool (* concreteCheckCondition) (STATE_MACH_T*),
+ char * (* concreteGetStatName) (int),
+ void* owner, char* name);
+
+void
+STP_state_mach_delete (STATE_MACH_T* this);
+
+Bool
+STP_check_condition (STATE_MACH_T* this);
+
+Bool
+STP_change_state (STATE_MACH_T* this);
+
+Bool
+STP_hop_2_state (STATE_MACH_T* this, unsigned int new_state);
+
+#endif /* _STP_STATER_H__ */
+
diff --git a/usr/src/lib/librstp/common/stp_bpdu.h b/usr/src/lib/librstp/common/stp_bpdu.h
new file mode 100644
index 0000000000..02773d5e88
--- /dev/null
+++ b/usr/src/lib/librstp/common/stp_bpdu.h
@@ -0,0 +1,90 @@
+/************************************************************************
+ * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
+ * Copyright (C) 2001-2003 Optical Access
+ * Author: Alex Rozin
+ *
+ * This file is part of RSTP library.
+ *
+ * RSTP library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; version 2.1
+ *
+ * RSTP library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with RSTP library; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ **********************************************************************/
+
+/* BPDU formats: 9.1 - 9.3, 17.28 */
+
+#ifndef _STP_BPDU_H__
+#define _STP_BPDU_H__
+
+#define MIN_BPDU 7
+#define BPDU_L_SAP 0x42
+#define LLC_UI 0x03
+#define BPDU_PROTOCOL_ID 0x0000
+#define BPDU_VERSION_ID 0x00
+#define BPDU_VERSION_RAPID_ID 0x02
+
+#define BPDU_TOPO_CHANGE_TYPE 0x80
+#define BPDU_CONFIG_TYPE 0x00
+#define BPDU_RSTP 0x02
+
+#define TOPOLOGY_CHANGE_BIT 0x01
+#define PROPOSAL_BIT 0x02
+#define PORT_ROLE_OFFS 2 /* 0x04 & 0x08 */
+#define PORT_ROLE_MASK (0x03 << PORT_ROLE_OFFS)
+#define LEARN_BIT 0x10
+#define FORWARD_BIT 0x20
+#define AGREEMENT_BIT 0x40
+#define TOPOLOGY_CHANGE_ACK_BIT 0x80
+
+#define RSTP_PORT_ROLE_UNKN 0x00
+#define RSTP_PORT_ROLE_ALTBACK 0x01
+#define RSTP_PORT_ROLE_ROOT 0x02
+#define RSTP_PORT_ROLE_DESGN 0x03
+
+typedef struct mac_header_t {
+ unsigned char dst_mac[6];
+ unsigned char src_mac[6];
+} MAC_HEADER_T;
+
+typedef struct eth_header_t {
+ unsigned char len8023[2];
+ unsigned char dsap;
+ unsigned char ssap;
+ unsigned char llc;
+} ETH_HEADER_T;
+
+typedef struct bpdu_header_t {
+ unsigned char protocol[2];
+ unsigned char version;
+ unsigned char bpdu_type;
+} BPDU_HEADER_T;
+
+typedef struct bpdu_body_t {
+ unsigned char flags;
+ unsigned char root_id[8];
+ unsigned char root_path_cost[4];
+ unsigned char bridge_id[8];
+ unsigned char port_id[2];
+ unsigned char message_age[2];
+ unsigned char max_age[2];
+ unsigned char hello_time[2];
+ unsigned char forward_delay[2];
+} BPDU_BODY_T;
+
+typedef struct stp_bpdu_t {
+ ETH_HEADER_T eth;
+ BPDU_HEADER_T hdr;
+ BPDU_BODY_T body;
+ unsigned char ver_1_len[2];
+} BPDU_T;
+
+#endif /* _STP_BPDU_H__ */
diff --git a/usr/src/lib/librstp/common/stp_in.c b/usr/src/lib/librstp/common/stp_in.c
new file mode 100644
index 0000000000..f8bd6954f0
--- /dev/null
+++ b/usr/src/lib/librstp/common/stp_in.c
@@ -0,0 +1,1026 @@
+/************************************************************************
+ * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
+ * Copyright (C) 2001-2003 Optical Access
+ * Author: Alex Rozin
+ *
+ * This file is part of RSTP library.
+ *
+ * RSTP library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; version 2.1
+ *
+ * RSTP library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with RSTP library; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ **********************************************************************/
+
+/* This file contains API from an operation system to the RSTP library */
+
+#include "base.h"
+#include "stpm.h"
+#include "stp_in.h"
+#include "stp_to.h"
+
+#define _stp_in_stpm_enable stp_in_stpm_enable
+
+STP_VECTORS_T *stp_vectors;
+
+void *
+stp_in_stpm_create (int vlan_id, char* name, int* err_code)
+{
+ register STPM_T* this;
+
+ /* stp_trace ("stp_in_stpm_create(%s)", name); */
+ this = stpapi_stpm_find (vlan_id);
+ if (this) { /* it had just been created :( */
+ *err_code = STP_Nothing_To_Do;
+ return this;
+ }
+
+ this = STP_stpm_create (vlan_id, name);
+ if (! this) { /* can't create stpm :( */
+ *err_code = STP_Cannot_Create_Instance_For_Vlan;
+ return NULL;
+ }
+
+ *err_code = STP_OK;
+ return this;
+}
+
+int
+_stp_in_stpm_enable (int vlan_id, char* name,
+ UID_STP_MODE_T admin_state)
+{
+ register STPM_T* this;
+ Bool created_here = False;
+ int rc, err_code;
+
+ /* stp_trace ("_stp_in_stpm_enable(%s)", name); */
+ this = stpapi_stpm_find (vlan_id);
+
+ if (STP_DISABLED != admin_state) {
+ if (! vlan_id) { /* STP_IN_stop_all (); */
+ register STPM_T* stpm;
+
+ for (stpm = STP_stpm_get_the_list (); stpm; stpm = stpm->next) {
+ if (STP_DISABLED != stpm->admin_state) {
+ STP_OUT_set_hardware_mode (stpm->vlan_id, STP_DISABLED);
+ (void) STP_stpm_enable (stpm, STP_DISABLED);
+ }
+ }
+ }
+ }
+
+ if (! this) { /* it had not yet been created */
+ if (STP_ENABLED == admin_state) {/* try to create it */
+ stp_trace ("implicit create to vlan '%s'", name);
+ this = stp_in_stpm_create (vlan_id, name, &err_code);
+ if (! this) {
+ stp_trace ("implicit create to vlan '%s' failed", name);
+ return STP_Implicit_Instance_Create_Failed;
+ }
+ created_here = True;
+ } else {/* try to disable nothing ? */
+ return 0;
+ }
+ }
+
+ if (this->admin_state == admin_state) { /* nothing to do :) */
+ return 0;
+ }
+
+ rc = STP_stpm_enable (this, admin_state);
+ if (! rc) {
+ STP_OUT_set_hardware_mode (vlan_id, admin_state);
+ }
+
+ if (rc && created_here) {
+ STP_stpm_delete (this);
+ }
+
+ return rc;
+}
+
+
+STPM_T *
+stpapi_stpm_find (int vlan_id)
+{
+ register STPM_T* this;
+
+ for (this = STP_stpm_get_the_list (); this; this = this->next)
+ if (vlan_id == this->vlan_id)
+ return this;
+
+ return NULL;
+}
+
+static PORT_T *
+_stpapi_port_find (STPM_T* this, int port_index)
+{
+ register PORT_T* port;
+
+ for (port = this->ports; port; port = port->next)
+ if (port_index == port->port_index) {
+ return port;
+ }
+
+ return NULL;
+}
+
+
+static void
+_conv_br_id_2_uid (IN BRIDGE_ID* f, OUT UID_BRIDGE_ID_T* t)
+{
+ (void) memcpy (t, f, sizeof (UID_BRIDGE_ID_T));
+}
+
+static int
+_check_stpm_config (IN UID_STP_CFG_T* uid_cfg)
+{
+ if (uid_cfg->bridge_priority < MIN_BR_PRIO) {
+ stp_trace ("%d bridge_priority small", (int) uid_cfg->bridge_priority);
+ return STP_Small_Bridge_Priority;
+ }
+
+ if (uid_cfg->bridge_priority > MAX_BR_PRIO) {
+ stp_trace ("%d bridge_priority large", (int) uid_cfg->bridge_priority);
+ return STP_Large_Bridge_Priority;
+ }
+
+ if (uid_cfg->hello_time < MIN_BR_HELLOT) {
+ stp_trace ("%d hello_time small", (int) uid_cfg->hello_time);
+ return STP_Small_Hello_Time;
+ }
+
+ if (uid_cfg->hello_time > MAX_BR_HELLOT) {
+ stp_trace ("%d hello_time large", (int) uid_cfg->hello_time);
+ return STP_Large_Hello_Time;
+ }
+
+ if (uid_cfg->max_age < MIN_BR_MAXAGE) {
+ stp_trace ("%d max_age small", (int) uid_cfg->max_age);
+ return STP_Small_Max_Age;
+ }
+
+ if (uid_cfg->max_age > MAX_BR_MAXAGE) {
+ stp_trace ("%d max_age large", (int) uid_cfg->max_age);
+ return STP_Large_Max_Age;
+ }
+
+ if (uid_cfg->forward_delay < MIN_BR_FWDELAY) {
+ stp_trace ("%d forward_delay small", (int) uid_cfg->forward_delay);
+ return STP_Small_Forward_Delay;
+ }
+
+ if (uid_cfg->forward_delay > MAX_BR_FWDELAY) {
+ stp_trace ("%d forward_delay large", (int) uid_cfg->forward_delay);
+ return STP_Large_Forward_Delay;
+ }
+
+ if (2 * (uid_cfg->forward_delay - 1) < uid_cfg->max_age) {
+ return STP_Forward_Delay_And_Max_Age_Are_Inconsistent;
+ }
+
+ if (uid_cfg->max_age < 2 * (uid_cfg->hello_time + 1)) {
+ return STP_Hello_Time_And_Max_Age_Are_Inconsistent;
+ }
+
+ return 0;
+}
+
+static void
+_stp_in_enable_port_on_stpm (STPM_T* stpm, int port_index, Bool enable)
+{
+ register PORT_T* port;
+
+ port = _stpapi_port_find (stpm, port_index);
+ if (! port) return;
+ if (port->portEnabled == enable) {/* nothing to do :) */
+ return;
+ }
+
+ port->uptime = 0;
+ if (enable) { /* clear port statistics */
+ port->rx_cfg_bpdu_cnt =
+ port->rx_rstp_bpdu_cnt =
+ port->rx_tcn_bpdu_cnt = 0;
+ }
+
+#ifdef STP_DBG
+ if (port->edge->debug) {
+ stp_trace ("Port %s became '%s' adminEdge=%c",
+ port->port_name, enable ? "enable" : "disable",
+ port->adminEdge ? 'Y' : 'N');
+ }
+#endif
+
+ port->adminEnable = enable;
+ STP_port_init (port, stpm, False);
+
+ port->reselect = True;
+ port->selected = False;
+}
+
+void
+STP_IN_init (STP_VECTORS_T *vectors)
+{
+ RSTP_INIT_CRITICAL_PATH_PROTECTIO;
+ stp_vectors = vectors;
+}
+
+int
+STP_IN_stpm_get_cfg (IN int vlan_id, OUT UID_STP_CFG_T* uid_cfg)
+{
+ register STPM_T* this;
+
+ uid_cfg->field_mask = 0;
+
+ RSTP_CRITICAL_PATH_START;
+ this = stpapi_stpm_find (vlan_id);
+
+ if (!this) { /* it had not yet been created :( */
+ RSTP_CRITICAL_PATH_END;
+ return STP_Vlan_Had_Not_Yet_Been_Created;
+ }
+
+ if (this->admin_state != STP_DISABLED) {
+ uid_cfg->field_mask |= BR_CFG_STATE;
+ }
+ uid_cfg->stp_enabled = this->admin_state;
+
+ if (this->ForceVersion != 2) {
+ uid_cfg->field_mask |= BR_CFG_FORCE_VER;
+ }
+ uid_cfg->force_version = this->ForceVersion;
+
+ if (this->BrId.prio != DEF_BR_PRIO) {
+ uid_cfg->field_mask |= BR_CFG_PRIO;
+ }
+ uid_cfg->bridge_priority = this->BrId.prio;
+
+ if (this->BrTimes.MaxAge != DEF_BR_MAXAGE) {
+ uid_cfg->field_mask |= BR_CFG_AGE;
+ }
+ uid_cfg->max_age = this->BrTimes.MaxAge;
+
+ if (this->BrTimes.HelloTime != DEF_BR_HELLOT) {
+ uid_cfg->field_mask |= BR_CFG_HELLO;
+ }
+ uid_cfg->hello_time = this->BrTimes.HelloTime;
+
+ if (this->BrTimes.ForwardDelay != DEF_BR_FWDELAY) {
+ uid_cfg->field_mask |= BR_CFG_DELAY;
+ }
+ uid_cfg->forward_delay = this->BrTimes.ForwardDelay;
+
+ uid_cfg->hold_time = TxHoldCount;
+
+ RSTP_CRITICAL_PATH_END;
+ return 0;
+}
+
+int
+STP_IN_port_get_cfg (int vlan_id, int port_index, UID_STP_PORT_CFG_T* uid_cfg)
+{
+ register STPM_T* this;
+ register PORT_T* port;
+
+ RSTP_CRITICAL_PATH_START;
+ this = stpapi_stpm_find (vlan_id);
+
+ if (!this) { /* it had not yet been created :( */
+ RSTP_CRITICAL_PATH_END;
+ return STP_Vlan_Had_Not_Yet_Been_Created;
+ }
+
+ port = _stpapi_port_find (this, port_index);
+ if (! port) {/* port is absent in the stpm :( */
+ RSTP_CRITICAL_PATH_END;
+ return STP_Port_Is_Absent_In_The_Vlan;
+ }
+
+ uid_cfg->field_mask = 0;
+
+ uid_cfg->port_priority = port->port_id >> 8;
+ if (uid_cfg->port_priority != DEF_PORT_PRIO)
+ uid_cfg->field_mask |= PT_CFG_PRIO;
+
+ uid_cfg->admin_port_path_cost = port->adminPCost;
+ if (uid_cfg->admin_port_path_cost != ADMIN_PORT_PATH_COST_AUTO)
+ uid_cfg->field_mask |= PT_CFG_COST;
+
+ uid_cfg->admin_point2point = port->adminPointToPointMac;
+ if (uid_cfg->admin_point2point != DEF_P2P)
+ uid_cfg->field_mask |= PT_CFG_P2P;
+
+ uid_cfg->admin_edge = port->adminEdge;
+ if (uid_cfg->admin_edge != DEF_ADMIN_EDGE)
+ uid_cfg->field_mask |= PT_CFG_EDGE;
+
+ uid_cfg->admin_non_stp = port->admin_non_stp;
+ if (uid_cfg->admin_non_stp != DEF_ADMIN_NON_STP)
+ uid_cfg->field_mask |= PT_CFG_NON_STP;
+
+ if (port->mcheck)
+ uid_cfg->field_mask |= PT_CFG_MCHECK;
+
+ RSTP_CRITICAL_PATH_END;
+ return 0;
+}
+
+int
+STP_IN_port_get_state (IN int vlan_id, INOUT UID_STP_PORT_STATE_T* entry)
+{
+ register STPM_T* this;
+ register PORT_T* port;
+
+ RSTP_CRITICAL_PATH_START;
+ this = stpapi_stpm_find (vlan_id);
+
+ if (!this) { /* it had not yet been created :( */
+ RSTP_CRITICAL_PATH_END;
+ return STP_Vlan_Had_Not_Yet_Been_Created;
+ }
+
+ port = _stpapi_port_find (this, entry->port_no);
+ if (! port) {/* port is absent in the stpm :( */
+ RSTP_CRITICAL_PATH_END;
+ return STP_Port_Is_Absent_In_The_Vlan;
+ }
+
+ entry->port_id = port->port_id;
+ if (DisabledPort == port->role) {
+ entry->state = UID_PORT_DISABLED;
+ } else if (! port->forward && ! port->learn) {
+ entry->state = UID_PORT_DISCARDING;
+ } else if (! port->forward && port->learn) {
+ entry->state = UID_PORT_LEARNING;
+ } else {
+ entry->state = UID_PORT_FORWARDING;
+ }
+
+ entry->uptime = port->uptime;
+ entry->path_cost = port->operPCost;
+ _conv_br_id_2_uid (&port->portPrio.root_bridge, &entry->designated_root);
+ entry->designated_cost = port->portPrio.root_path_cost;
+ _conv_br_id_2_uid (&port->portPrio.design_bridge, &entry->designated_bridge);
+ entry->designated_port = port->portPrio.design_port;
+
+ switch (port->role) {
+ case DisabledPort: entry->role = ' '; break;
+ case AlternatePort: entry->role = 'A'; break;
+ case BackupPort: entry->role = 'B'; break;
+ case RootPort: entry->role = 'R'; break;
+ case DesignatedPort: entry->role = 'D'; break;
+ case NonStpPort: entry->role = '-'; break;
+ default: entry->role = '?'; break;
+ }
+
+ if (DisabledPort == port->role || NonStpPort == port->role) {
+ (void) memset (&entry->designated_root, 0, sizeof (UID_BRIDGE_ID_T));
+ (void) memset (&entry->designated_bridge, 0, sizeof (UID_BRIDGE_ID_T));
+ entry->designated_cost = 0;
+ entry->designated_port = port->port_id;
+ }
+
+ if (DisabledPort == port->role) {
+ entry->oper_point2point = (P2P_FORCE_FALSE == port->adminPointToPointMac) ? 0 : 1;
+ entry->oper_edge = port->adminEdge;
+ entry->oper_stp_neigb = 0;
+ } else {
+ entry->oper_point2point = port->operPointToPointMac ? 1 : 0;
+ entry->oper_edge = port->operEdge ? 1 : 0;
+ entry->oper_stp_neigb = port->sendRSTP ? 0 : 1;
+ }
+ entry->oper_port_path_cost = port->operPCost;
+
+ entry->rx_cfg_bpdu_cnt = port->rx_cfg_bpdu_cnt;
+ entry->rx_rstp_bpdu_cnt = port->rx_rstp_bpdu_cnt;
+ entry->rx_tcn_bpdu_cnt = port->rx_tcn_bpdu_cnt;
+
+ entry->fdWhile = port->fdWhile; /* 17.15.1 */
+ entry->helloWhen = port->helloWhen; /* 17.15.2 */
+ entry->mdelayWhile = port->mdelayWhile; /* 17.15.3 */
+ entry->rbWhile = port->rbWhile; /* 17.15.4 */
+ entry->rcvdInfoWhile = port->rcvdInfoWhile;/* 17.15.5 */
+ entry->rrWhile = port->rrWhile; /* 17.15.6 */
+ entry->tcWhile = port->tcWhile; /* 17.15.7 */
+ entry->txCount = port->txCount; /* 17.18.40 */
+ entry->lnkWhile = port->lnkWhile;
+
+ entry->rcvdInfoWhile = port->rcvdInfoWhile;
+ entry->top_change_ack = port->tcAck;
+ entry->tc = port->tc;
+
+ RSTP_CRITICAL_PATH_END;
+ return 0;
+}
+
+int
+STP_IN_stpm_get_state (IN int vlan_id, OUT UID_STP_STATE_T* entry)
+{
+ register STPM_T* this;
+
+ RSTP_CRITICAL_PATH_START;
+ this = stpapi_stpm_find (vlan_id);
+
+ if (!this) { /* it had not yet been created :( */
+ RSTP_CRITICAL_PATH_END;
+ return STP_Vlan_Had_Not_Yet_Been_Created;
+ }
+
+ (void) strncpy (entry->vlan_name, this->name, NAME_LEN);
+ entry->vlan_id = this->vlan_id;
+ _conv_br_id_2_uid (&this->rootPrio.root_bridge, &entry->designated_root);
+ entry->root_path_cost = this->rootPrio.root_path_cost;
+ entry->root_port = this->rootPortId;
+ entry->max_age = this->rootTimes.MaxAge;
+ entry->forward_delay = this->rootTimes.ForwardDelay;
+ entry->hello_time = this->rootTimes.HelloTime;
+
+ _conv_br_id_2_uid (&this->BrId, &entry->bridge_id);
+
+ entry->stp_enabled = this->admin_state;
+
+ entry->timeSince_Topo_Change = this->timeSince_Topo_Change;
+ entry->Topo_Change_Count = this->Topo_Change_Count;
+ entry->Topo_Change = this->Topo_Change;
+
+ RSTP_CRITICAL_PATH_END;
+ return 0;
+}
+
+int
+STP_IN_stpm_get_name_by_vlan_id (int vlan_id, char* name, size_t buffsize)
+{
+ register STPM_T* stpm;
+ int iret = -1;
+
+ RSTP_CRITICAL_PATH_START;
+ for (stpm = STP_stpm_get_the_list (); stpm; stpm = stpm->next) {
+ if (vlan_id == stpm->vlan_id) {
+ if (stpm->name)
+ (void) strncpy (name, stpm->name, buffsize);
+ else
+ (void) memset (name, 0, buffsize);
+ iret = 0;
+ break;
+ }
+ }
+ RSTP_CRITICAL_PATH_END;
+ return iret;
+}
+
+int /* call it, when link Up/Down */
+STP_IN_enable_port (int port_index, Bool enable)
+{
+ register STPM_T* stpm;
+
+ RSTP_CRITICAL_PATH_START;
+ if (! enable) {
+#ifdef STP_DBG
+ stp_trace("%s (p%02d, all, %s, '%s')",
+ "clearFDB", (int) port_index, "this port", "disable port");
+#endif
+ STP_OUT_flush_lt (port_index, 0, LT_FLASH_ONLY_THE_PORT, "disable port");
+ }
+
+ for (stpm = STP_stpm_get_the_list (); stpm; stpm = stpm->next) {
+ if (STP_ENABLED != stpm->admin_state) continue;
+
+ _stp_in_enable_port_on_stpm (stpm, port_index, enable);
+ /* STP_stpm_update (stpm);*/
+ }
+
+ RSTP_CRITICAL_PATH_END;
+ return 0;
+}
+
+int /* call it, when port speed has been changed, speed in Kb/s */
+STP_IN_changed_port_speed (int port_index, long speed)
+{
+ register STPM_T* stpm;
+ register PORT_T* port;
+
+ RSTP_CRITICAL_PATH_START;
+ for (stpm = STP_stpm_get_the_list (); stpm; stpm = stpm->next) {
+ if (STP_ENABLED != stpm->admin_state) continue;
+
+ port = _stpapi_port_find (stpm, port_index);
+ if (! port) continue;
+ port->operSpeed = speed;
+#ifdef STP_DBG
+ if (port->pcost->debug) {
+ stp_trace ("changed operSpeed=%lu", port->operSpeed);
+ }
+#endif
+
+ port->reselect = True;
+ port->selected = False;
+ }
+ RSTP_CRITICAL_PATH_END;
+ return 0;
+}
+
+int /* call it, when port duplex mode has been changed */
+STP_IN_changed_port_duplex (int port_index)
+{
+ register STPM_T* stpm;
+ register PORT_T* port;
+
+ RSTP_CRITICAL_PATH_START;
+ for (stpm = STP_stpm_get_the_list (); stpm; stpm = stpm->next) {
+ if (STP_ENABLED != stpm->admin_state) continue;
+
+ port = _stpapi_port_find (stpm, port_index);
+ if (! port) continue;
+#ifdef STP_DBG
+ if (port->p2p->debug) {
+ stp_trace ("STP_IN_changed_port_duplex(%s)", port->port_name);
+ }
+#endif
+ port->p2p_recompute = True;
+ port->reselect = True;
+ port->selected = False;
+ }
+ RSTP_CRITICAL_PATH_END;
+ return 0;
+}
+
+int
+STP_IN_check_bpdu_header (BPDU_T* bpdu, size_t len)
+{
+ unsigned short len8023;
+
+ /* LINTED: alignment */
+ len8023 = ntohs (*(unsigned short*) bpdu->eth.len8023);
+ if (len8023 > 1500) {/* big len8023 format :( */
+ return STP_Big_len8023_Format;
+ }
+
+ if (len8023 < MIN_BPDU) { /* small len8023 format :( */
+ return STP_Small_len8023_Format;
+ }
+
+ if (len8023 + 14 > len) { /* len8023 format gt len :( */
+ return STP_len8023_Format_Gt_Len;
+ }
+
+ if (bpdu->eth.dsap != BPDU_L_SAP ||
+ bpdu->eth.ssap != BPDU_L_SAP ||
+ bpdu->eth.llc != LLC_UI) {
+ /* this is not a proper 802.3 pkt! :( */
+ return STP_Not_Proper_802_3_Packet;
+ }
+
+ if (bpdu->hdr.protocol[0] || bpdu->hdr.protocol[1]) {
+ return STP_Invalid_Protocol;
+ }
+
+#if 0
+ if (bpdu->hdr.version != BPDU_VERSION_ID) {
+ return STP_Invalid_Version;
+ }
+#endif
+ /* see also 9.3.4: think & TBD :( */
+ return 0;
+}
+
+#ifdef STP_DBG
+int dbg_rstp_deny = 0;
+#endif
+
+
+int
+STP_IN_rx_bpdu (int vlan_id, int port_index, BPDU_T* bpdu, size_t len)
+{
+ register PORT_T* port;
+ register STPM_T* this;
+ int iret;
+
+#ifdef STP_DBG
+ if (1 == dbg_rstp_deny) {
+ return 0;
+ }
+#endif
+
+ RSTP_CRITICAL_PATH_START;
+ this = stpapi_stpm_find (vlan_id);
+ if (! this) { /* the stpm had not yet been created :( */
+ RSTP_CRITICAL_PATH_END;
+ return STP_Vlan_Had_Not_Yet_Been_Created;
+ }
+
+ if (STP_DISABLED == this->admin_state) {/* the stpm had not yet been enabled :( */
+ RSTP_CRITICAL_PATH_END;
+ return STP_Had_Not_Yet_Been_Enabled_On_The_Vlan;
+ }
+
+ port = _stpapi_port_find (this, port_index);
+ if (! port) {/* port is absent in the stpm :( */
+#ifdef STP_DBG
+ stp_trace ("RX bpdu vlan_id=%d port=%d port is absent in the stpm :(", (int) vlan_id, (int) port_index);
+#endif
+ RSTP_CRITICAL_PATH_END;
+ return STP_Port_Is_Absent_In_The_Vlan;
+ }
+
+#ifdef STP_DBG
+ if (port->skip_rx > 0) {
+ if (1 == port->skip_rx)
+ stp_trace ("port %s stop rx skipping",
+ port->port_name);
+ else
+ stp_trace ("port %s skip rx %d",
+ port->port_name, port->skip_rx);
+ port->skip_rx--;
+ RSTP_CRITICAL_PATH_END;
+ return STP_Nothing_To_Do;
+ }
+#endif
+
+ if (port->operEdge && ! port->lnkWhile && port->portEnabled) {
+#ifdef STP_DBG
+ if (port->topoch->debug) {
+ stp_trace ("port %s tc=TRUE by operEdge", port->port_name);
+ }
+#endif
+ port->tc = True; /* IEEE 802.1y, 17.30 */
+ }
+
+/* port link change indication will come later :( */
+ if (! port->portEnabled &&
+ STP_OUT_get_port_link_status (port->port_index)) {
+ _stp_in_enable_port_on_stpm (this, port->port_index, True);
+ }
+
+#ifdef STP_DBG
+ if (port->edge->debug && port->operEdge) {
+ stp_trace ("port %s not operEdge !", port->port_name);
+ }
+#endif
+
+ port->operEdge = False;
+ port->wasInitBpdu = True;
+
+ iret = STP_port_rx_bpdu (port, bpdu, len);
+ (void) STP_stpm_update (this);
+ RSTP_CRITICAL_PATH_END;
+
+ return iret;
+}
+
+int
+STP_IN_one_second (void)
+{
+ register STPM_T* stpm;
+ register int dbg_cnt = 0;
+
+ RSTP_CRITICAL_PATH_START;
+ for (stpm = STP_stpm_get_the_list (); stpm; stpm = stpm->next) {
+ if (STP_ENABLED == stpm->admin_state) {
+ /* stp_trace ("STP_IN_one_second vlan_id=%d", (int) stpm->vlan_id); */
+ STP_stpm_one_second (stpm);
+ dbg_cnt++;
+ }
+ }
+
+ RSTP_CRITICAL_PATH_END;
+
+ return dbg_cnt;
+}
+
+int
+STP_IN_stpm_set_cfg (IN int vlan_id,
+ IN UID_STP_CFG_T* uid_cfg)
+{
+ int rc = 0, prev_prio, err_code;
+ Bool created_here, enabled_here;
+ register STPM_T* this;
+ UID_STP_CFG_T old;
+
+ /* stp_trace ("STP_IN_stpm_set_cfg"); */
+ if (0 != STP_IN_stpm_get_cfg (vlan_id, &old)) {
+ STP_OUT_get_init_stpm_cfg (vlan_id, &old);
+ }
+
+ RSTP_CRITICAL_PATH_START;
+ if (BR_CFG_PRIO & uid_cfg->field_mask) {
+ old.bridge_priority = uid_cfg->bridge_priority;
+ }
+
+ if (BR_CFG_AGE & uid_cfg->field_mask) {
+ old.max_age = uid_cfg->max_age;
+ }
+
+ if (BR_CFG_HELLO & uid_cfg->field_mask) {
+ old.hello_time = uid_cfg->hello_time;
+ }
+
+ if (BR_CFG_DELAY & uid_cfg->field_mask) {
+ old.forward_delay = uid_cfg->forward_delay;
+ }
+
+ if (BR_CFG_FORCE_VER & uid_cfg->field_mask) {
+ old.force_version = uid_cfg->force_version;
+ }
+
+ rc = _check_stpm_config (&old);
+ if (0 != rc) {
+ stp_trace ("_check_stpm_config failed %d", (int) rc);
+ RSTP_CRITICAL_PATH_END;
+ return rc;
+ }
+
+ if ((BR_CFG_STATE & uid_cfg->field_mask) &&
+ (STP_DISABLED == uid_cfg->stp_enabled)) {
+ rc = _stp_in_stpm_enable (vlan_id, uid_cfg->vlan_name, STP_DISABLED);
+ if (0 != rc) {
+ stp_trace ("can't disable rc=%d", (int) rc);
+ RSTP_CRITICAL_PATH_END;
+ return rc;
+ }
+ uid_cfg->field_mask &= ~BR_CFG_STATE;
+ if (! uid_cfg->field_mask) {
+ RSTP_CRITICAL_PATH_END;
+ return 0;
+ }
+ }
+
+ /* get current state */
+ this = stpapi_stpm_find (vlan_id);
+ created_here = False;
+ enabled_here = False;
+ if (! this) { /* it had not yet been created */
+ this = stp_in_stpm_create (vlan_id, uid_cfg->vlan_name, &err_code);
+ if (! this) {
+ RSTP_CRITICAL_PATH_END;
+ return err_code;
+ }
+ }
+
+ prev_prio = this->BrId.prio;
+ this->BrId.prio = old.bridge_priority;
+ if (STP_ENABLED == this->admin_state) {
+ if (0 != STP_stpm_check_bridge_priority (this)) {
+ this->BrId.prio = prev_prio;
+ stp_trace ("%s", "STP_stpm_check_bridge_priority failed");
+ RSTP_CRITICAL_PATH_END;
+ return STP_Invalid_Bridge_Priority;
+ }
+ }
+
+ this->BrTimes.MaxAge = old.max_age;
+ this->BrTimes.HelloTime = old.hello_time;
+ this->BrTimes.ForwardDelay = old.forward_delay;
+ this->ForceVersion = (PROTOCOL_VERSION_T) old.force_version;
+
+ if ((BR_CFG_STATE & uid_cfg->field_mask) &&
+ STP_DISABLED != uid_cfg->stp_enabled &&
+ STP_DISABLED == this->admin_state) {
+ rc = _stp_in_stpm_enable (vlan_id, uid_cfg->vlan_name, uid_cfg->stp_enabled);
+ if (0 != rc) {
+ stp_trace ("%s", "cannot enable");
+ if (created_here) {
+ STP_stpm_delete (this);
+ }
+ RSTP_CRITICAL_PATH_END;
+ return rc;
+ }
+ enabled_here = True;
+ }
+
+ if (! enabled_here && STP_DISABLED != this->admin_state) {
+ STP_stpm_update_after_bridge_management (this);
+ }
+ RSTP_CRITICAL_PATH_END;
+ return 0;
+}
+
+int
+STP_IN_port_set_cfg (IN int vlan_id, IN int port_index,
+ IN UID_STP_PORT_CFG_T* uid_cfg)
+{
+ register STPM_T* this;
+ register PORT_T* port;
+
+ RSTP_CRITICAL_PATH_START;
+ this = stpapi_stpm_find (vlan_id);
+ if (! this) { /* it had not yet been created :( */
+ RSTP_CRITICAL_PATH_END;
+ stp_trace ("RSTP instance with tag %d hasn't been created\n", vlan_id);
+ return STP_Vlan_Had_Not_Yet_Been_Created;
+ }
+
+ port = _stpapi_port_find (this, port_index);
+ if (! port) {/* port is absent in the stpm :( */
+ return STP_Port_Is_Absent_In_The_Vlan;
+ }
+
+ if (PT_CFG_MCHECK & uid_cfg->field_mask) {
+ if (this->ForceVersion >= NORMAL_RSTP)
+ port->mcheck = True;
+ }
+
+ if (PT_CFG_COST & uid_cfg->field_mask) {
+ port->adminPCost = uid_cfg->admin_port_path_cost;
+ }
+
+ if (PT_CFG_PRIO & uid_cfg->field_mask) {
+ port->port_id = (uid_cfg->port_priority << 8) + port_index;
+ }
+
+ if (PT_CFG_P2P & uid_cfg->field_mask) {
+ port->adminPointToPointMac = uid_cfg->admin_point2point;
+ port->p2p_recompute = True;
+ }
+
+ if (PT_CFG_EDGE & uid_cfg->field_mask) {
+ port->adminEdge = uid_cfg->admin_edge;
+ port->operEdge = port->adminEdge;
+#ifdef STP_DBG
+ if (port->edge->debug) {
+ stp_trace ("port %s is operEdge=%c in STP_IN_port_set_cfg",
+ port->port_name,
+ port->operEdge ? 'Y' : 'n');
+ }
+#endif
+ }
+
+ if (PT_CFG_NON_STP & uid_cfg->field_mask) {
+#ifdef STP_DBG
+ if (port->roletrns->debug && port->admin_non_stp != uid_cfg->admin_non_stp) {
+ stp_trace ("port %s is adminNonStp=%c in STP_IN_port_set_cfg",
+ port->port_name,
+ uid_cfg->admin_non_stp ? 'Y' : 'n');
+ }
+#endif
+ port->admin_non_stp = uid_cfg->admin_non_stp;
+ }
+
+#ifdef STP_DBG
+ if (PT_CFG_DBG_SKIP_RX & uid_cfg->field_mask) {
+ port->skip_rx = uid_cfg->skip_rx;
+ }
+
+ if (PT_CFG_DBG_SKIP_TX & uid_cfg->field_mask) {
+ port->skip_tx = uid_cfg->skip_tx;
+ }
+
+#endif
+
+ port->reselect = True;
+ port->selected = False;
+
+ (void) STP_stpm_update (this);
+
+ RSTP_CRITICAL_PATH_END;
+
+ return 0;
+}
+
+#ifdef STP_DBG
+int
+
+STP_IN_dbg_set_port_trace (char* mach_name, int enadis,
+ int vlan_id, int port_no)
+{
+ register STPM_T* this;
+ register PORT_T* port;
+ int rc;
+
+ RSTP_CRITICAL_PATH_START;
+ this = stpapi_stpm_find (vlan_id);
+ if (! this) { /* it had not yet been created :( */
+ RSTP_CRITICAL_PATH_END;
+ stp_trace ("RSTP instance with tag %d hasn't been created\n", vlan_id);
+ return STP_Vlan_Had_Not_Yet_Been_Created;
+ }
+
+ port = _stpapi_port_find (this, port_no);
+ if (! port) {/* port is absent in the stpm :( */
+ return STP_Port_Is_Absent_In_The_Vlan;
+ }
+ rc = STP_port_trace_state_machine (port, mach_name, enadis);
+
+ RSTP_CRITICAL_PATH_END;
+
+ return rc;
+}
+
+#endif
+
+const char*
+STP_IN_get_error_explanation (int rstp_err_no)
+{
+#define CHOOSE(a) #a
+static char* rstp_error_names[] = RSTP_ERRORS;
+#undef CHOOSE
+ if (rstp_err_no < STP_OK) {
+ return "Too small error code :(";
+ }
+ if (rstp_err_no >= STP_LAST_DUMMY) {
+ return "Too big error code :(";
+ }
+
+ return rstp_error_names[rstp_err_no];
+}
+
+int
+STP_IN_port_add(int vlan_id, int port_index)
+{
+ STPM_T *this;
+ PORT_T *port;
+ int rc = STP_OK;
+
+ RSTP_CRITICAL_PATH_START;
+ this = stpapi_stpm_find (vlan_id);
+
+ if (!this) { /* it had not yet been created :( */
+ RSTP_CRITICAL_PATH_END;
+ return STP_Vlan_Had_Not_Yet_Been_Created;
+ }
+
+ port = this->ports;
+
+ if (! STP_port_create (this, port_index)) {
+ /* can't add port :( */
+ stp_trace ("can't create port %d", port_index);
+ RSTP_CRITICAL_PATH_END;
+ return STP_Cannot_Create_Instance_For_Port;
+ }
+
+ if (!port)
+ rc = STP_stpm_start (this);
+
+ RSTP_CRITICAL_PATH_END;
+
+ return rc;
+}
+
+int
+STP_IN_port_remove(int vlan_id, int port_index)
+{
+ STPM_T *this;
+ PORT_T *port;
+
+ RSTP_CRITICAL_PATH_START;
+ this = stpapi_stpm_find (vlan_id);
+
+ if (!this) { /* it had not yet been created :( */
+ RSTP_CRITICAL_PATH_END;
+ return STP_Vlan_Had_Not_Yet_Been_Created;
+ }
+
+ port = _stpapi_port_find (this, port_index);
+ if (! port) {/* port is absent in the stpm :( */
+ RSTP_CRITICAL_PATH_END;
+ return STP_Port_Is_Absent_In_The_Vlan;
+ }
+
+ STP_port_delete (port);
+
+ if (!this->ports)
+ STP_stpm_stop (this);
+ RSTP_CRITICAL_PATH_END;
+
+ return STP_OK;
+}
+
+void
+STP_IN_get_bridge_id(int vlan_id, unsigned short *priority, unsigned char *mac)
+{
+ STPM_T *this;
+
+ RSTP_CRITICAL_PATH_START;
+ this = stpapi_stpm_find (vlan_id);
+ *priority = this->BrId.prio;
+ (void) memcpy(mac, this->BrId.addr, 6);
+ RSTP_CRITICAL_PATH_END;
+}
+
+const char *
+STP_IN_state2str(RSTP_PORT_STATE state)
+{
+ switch (state) {
+ case UID_PORT_DISABLED:
+ return ("disabled");
+ case UID_PORT_DISCARDING:
+ return ("discarding");
+ case UID_PORT_LEARNING:
+ return ("learning");
+ case UID_PORT_FORWARDING:
+ return ("forwarding");
+ case UID_PORT_NON_STP:
+ return ("non-stp");
+ case UID_PORT_BADSDU: /* synthetic state used by daemon */
+ return ("bad-mtu");
+ }
+ return ("unknown");
+}
diff --git a/usr/src/lib/librstp/common/stp_in.h b/usr/src/lib/librstp/common/stp_in.h
new file mode 100644
index 0000000000..cf98175092
--- /dev/null
+++ b/usr/src/lib/librstp/common/stp_in.h
@@ -0,0 +1,227 @@
+/************************************************************************
+ * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
+ * Copyright (C) 2001-2003 Optical Access
+ * Author: Alex Rozin
+ *
+ * This file is part of RSTP library.
+ *
+ * RSTP library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; version 2.1
+ *
+ * RSTP library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with RSTP library; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ **********************************************************************/
+
+ /* This file contains prototypes for API from an operation
+ system to the RSTP */
+
+#ifndef _STP_API_H__
+#define _STP_API_H__
+
+#include <sys/types.h>
+
+#define STP_DBG 1
+
+/************************
+ * Common base constants
+ ************************/
+
+#ifndef INOUT
+# define IN /* consider as comments near 'input' parameters */
+# define OUT /* consider as comments near 'output' parameters */
+# define INOUT /* consider as comments near 'input/output' parameters */
+#endif
+
+#ifndef Zero
+# define Zero 0
+# define One 1
+#endif
+
+#ifndef Bool
+# define Bool int
+# define False 0
+# define True 1
+#endif
+
+/********************************************
+ * constants: default values and linitations
+ *********************************************/
+
+/* bridge configuration */
+
+#define DEF_BR_PRIO 32768
+#define MIN_BR_PRIO 0
+#define MAX_BR_PRIO 61440
+
+#define DEF_BR_HELLOT 2
+#define MIN_BR_HELLOT 1
+#define MAX_BR_HELLOT 10
+
+#define DEF_BR_MAXAGE 20
+#define MIN_BR_MAXAGE 6
+#define MAX_BR_MAXAGE 40
+
+#define DEF_BR_FWDELAY 15
+#define MIN_BR_FWDELAY 4
+#define MAX_BR_FWDELAY 30
+
+#define IEEE_TIMER_SCALE 256
+
+/* Note that this works with unscaled values */
+#define CHECK_BRIDGE_CONFIG(cfg) \
+ (2 * (cfg.forward_delay - 1) >= cfg.max_age && \
+ cfg.max_age >= 2 * (cfg.hello_time + 1))
+
+/*
+ * These macros provide limits and tests for displaying comprehensible errors.
+ */
+#define NO_MAXAGE(cfg) ((cfg.forward_delay - 1) < (cfg.hello_time + 1))
+#define MIN_FWDELAY_NOM(cfg) \
+ (cfg.hello_time < MIN_BR_FWDELAY - 2 ? MIN_BR_FWDELAY : \
+ cfg.hello_time + 2)
+#define MAX_HELLOTIME_NOM(cfg) \
+ (cfg.forward_delay > MAX_BR_HELLOT + 2 ? MAX_BR_HELLOT : \
+ cfg.forward_delay - 2)
+
+#define SMALL_MAXAGE(cfg) (cfg.max_age < 2 * (cfg.hello_time + 1))
+#define MIN_MAXAGE(cfg) \
+ (cfg.hello_time < (MIN_BR_MAXAGE / 2 - 1) ? MIN_BR_MAXAGE : \
+ (2 * (cfg.hello_time + 1)))
+#define MAX_HELLOTIME(cfg) \
+ (cfg.max_age > 2 * (MAX_BR_HELLOT + 1) ? MAX_BR_HELLOT : \
+ (cfg.max_age / 2 - 1))
+
+#define MIN_FWDELAY(cfg) (cfg.max_age / 2 + 1)
+#define MAX_MAXAGE(cfg) \
+ (cfg.forward_delay > (MAX_BR_MAXAGE / 2 + 1) ? MAX_BR_MAXAGE : \
+ (2 * (cfg.forward_delay - 1)))
+
+#define CAPPED_MAXAGE(cfg) (cfg.forward_delay < (MAX_BR_MAXAGE / 2 + 1))
+#define FLOORED_MAXAGE(cfg) (cfg.hello_time > (MIN_BR_MAXAGE / 2 - 1))
+
+#define DEF_FORCE_VERS 2 /* NORMAL_RSTP */
+
+/* port configuration */
+
+#define DEF_PORT_PRIO 128
+#define MIN_PORT_PRIO 0
+#define MAX_PORT_PRIO 240 /* in steps of 16 */
+
+#define DEF_ADMIN_NON_STP False
+#define DEF_ADMIN_EDGE True
+#define DEF_LINK_DELAY 3 /* see edge.c */
+#define DEF_P2P P2P_AUTO
+
+#include <uid_stp.h>
+#include <stp_bpdu.h>
+
+#ifndef __STPM_T__
+#define __STPM_T__
+struct stpm_t;
+typedef struct stpm_t STPM_T;
+#endif
+#ifndef __STP_VECTORS_T__
+#define __STP_VECTORS_T__
+struct stp_vectors;
+typedef struct stp_vectors STP_VECTORS_T;
+#endif
+
+/* Section 1: Create/Delete/Start/Stop the RSTP instance */
+
+void /* init the engine */
+STP_IN_init (STP_VECTORS_T *vectors);
+
+int
+STP_IN_stpm_create (int vlan_id, char* name);
+
+int
+STP_IN_stpm_delete (int vlan_id);
+
+int
+STP_IN_port_add (int vlan_id, int port_index);
+
+int
+STP_IN_port_remove (int vlan_id, int port_index);
+
+int
+STP_IN_stop_all (void);
+
+int
+STP_IN_delete_all (void);
+
+/* Section 2. "Get" management */
+
+Bool
+STP_IN_get_is_stpm_enabled (int vlan_id);
+
+int
+STP_IN_stpm_get_vlan_id_by_name (char* name, int* vlan_id);
+
+int
+STP_IN_stpm_get_name_by_vlan_id (int vlan_id, char* name, size_t buffsize);
+
+const char*
+STP_IN_get_error_explanation (int rstp_err_no);
+
+int
+STP_IN_stpm_get_cfg (int vlan_id, UID_STP_CFG_T* uid_cfg);
+
+int
+STP_IN_stpm_get_state (int vlan_id, UID_STP_STATE_T* entry);
+
+int
+STP_IN_port_get_cfg (int vlan_id, int port_index, UID_STP_PORT_CFG_T* uid_cfg);
+
+int
+STP_IN_port_get_state (int vlan_id, UID_STP_PORT_STATE_T* entry);
+
+const char *
+STP_IN_state2str(RSTP_PORT_STATE);
+
+/* Section 3. "Set" management */
+
+int
+STP_IN_stpm_set_cfg (int vlan_id,
+ UID_STP_CFG_T* uid_cfg);
+
+int
+STP_IN_port_set_cfg (int vlan_id, int port_index,
+ UID_STP_PORT_CFG_T* uid_cfg);
+
+#ifdef STP_DBG
+int STP_IN_dbg_set_port_trace (char *mach_name, int enadis,
+ int vlan_id, int port_index);
+#endif
+
+/* Section 4. RSTP functionality events */
+
+int
+STP_IN_one_second (void);
+
+int /* for Link UP/DOWN */
+STP_IN_enable_port (int port_index, Bool enable);
+
+int /* call it, when port speed has been changed, speed in Kb/s */
+STP_IN_changed_port_speed (int port_index, long speed);
+
+int /* call it, when current port duplex mode has been changed */
+STP_IN_changed_port_duplex (int port_index);
+
+int
+STP_IN_check_bpdu_header (BPDU_T* bpdu, size_t len);
+
+int
+STP_IN_rx_bpdu (int vlan_id, int port_index, BPDU_T* bpdu, size_t len);
+
+void
+STP_IN_get_bridge_id(int vlan_id, unsigned short *priority, unsigned char *mac);
+
+#endif /* _STP_API_H__ */
diff --git a/usr/src/lib/librstp/common/stp_to.h b/usr/src/lib/librstp/common/stp_to.h
new file mode 100644
index 0000000000..e002044039
--- /dev/null
+++ b/usr/src/lib/librstp/common/stp_to.h
@@ -0,0 +1,48 @@
+/************************************************************************
+ * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
+ * Copyright (C) 2001-2003 Optical Access
+ * Author: Alex Rozin
+ *
+ * This file is part of RSTP library.
+ *
+ * RSTP library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; version 2.1
+ *
+ * RSTP library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with RSTP library; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ **********************************************************************/
+
+/* This file contains prototypes for system dependent API
+ from the RSTP to an operation system */
+
+#ifndef _STP_OUT_H__
+#define _STP_OUT_H__
+
+#include "stp_vectors.h"
+#define STP_OUT_flush_lt (*stp_vectors->flush_lt)
+#define STP_OUT_get_port_mac (*stp_vectors->get_port_mac)
+#define STP_OUT_get_port_oper_speed (*stp_vectors->get_port_oper_speed)
+#define STP_OUT_get_port_link_status (*stp_vectors->get_port_link_status)
+#define STP_OUT_get_duplex (*stp_vectors->get_duplex)
+#ifdef STRONGLY_SPEC_802_1W
+#define STP_OUT_set_learning (*stp_vectors->set_learning)
+#define STP_OUT_set_forwarding (*stp_vectors->set_forwarding)
+#else
+#define STP_OUT_set_port_state (*stp_vectors->set_port_state)
+#endif
+#define STP_OUT_set_hardware_mode (*stp_vectors->set_hardware_mode)
+#define STP_OUT_tx_bpdu (*stp_vectors->tx_bpdu)
+#define STP_OUT_get_port_name (*stp_vectors->get_port_name)
+#define STP_OUT_get_init_stpm_cfg (*stp_vectors->get_init_stpm_cfg)
+#define STP_OUT_get_init_port_cfg (*stp_vectors->get_init_port_cfg)
+
+#endif /* _STP_OUT_H__ */
+
diff --git a/usr/src/lib/librstp/common/stp_vectors.h b/usr/src/lib/librstp/common/stp_vectors.h
new file mode 100644
index 0000000000..e18e244b17
--- /dev/null
+++ b/usr/src/lib/librstp/common/stp_vectors.h
@@ -0,0 +1,90 @@
+/************************************************************************
+ * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
+ * Copyright (C) 2001-2003 Optical Access
+ * Author: Alex Rozin
+ *
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ *
+ * This file is part of RSTP library.
+ *
+ * RSTP library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; version 2.1
+ *
+ * RSTP library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with RSTP library; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ **********************************************************************/
+
+#ifndef __STP_VECTORS_H__
+#define __STP_VECTORS_H__
+
+/* This file defines callback vectors to be supplied by library user */
+
+/* In the best case: clean all Learning entries with
+ the vlan_id and the port (if 'exclude'=0) or for all ports,
+ exclude the port (if ''exclude'=1). If 'port'=0, delete all
+ entries with the vlan_id, don't care to 'exclude' */
+typedef enum {
+ LT_FLASH_ALL_PORTS_EXCLUDE_THIS,
+ LT_FLASH_ONLY_THE_PORT
+} LT_FLASH_TYPE_T;
+
+struct stp_vectors {
+ int (*flush_lt)(IN int port_index, IN int vlan_id,
+ IN LT_FLASH_TYPE_T type, IN char* reason);
+
+ /* for bridge id calculation */
+ void (*get_port_mac) (IN int port_index, OUT unsigned char* mac);
+
+ unsigned long (*get_port_oper_speed) (IN unsigned int portNo);
+
+ /* 1- Up, 0- Down */
+ int (*get_port_link_status) (IN int port_index);
+
+ /* 1- Full, 0- Half */
+ int (*get_duplex) (IN int port_index);
+
+#ifdef STRONGLY_SPEC_802_1W
+ int (*set_learning) (IN int port_index, IN int vlan_id, IN int enable);
+ int (*set_forwarding) (IN int port_index, IN int vlan_id,
+ IN int enable);
+#else
+/*
+ * In many kinds of hardware the state of ports may
+ * be changed with another method
+ */
+ int (*set_port_state) (IN int port_index, IN int vlan_id,
+ IN RSTP_PORT_STATE state);
+#endif
+
+ int (*set_hardware_mode) (int vlan_id, UID_STP_MODE_T mode);
+ int (*tx_bpdu) (IN int port_index, IN int vlan_id,
+ IN unsigned char* bpdu,
+ IN size_t bpdu_len);
+ const char *(*get_port_name) (IN int port_index);
+ int (*get_init_stpm_cfg) (IN int vlan_id,
+ INOUT UID_STP_CFG_T* cfg);
+ int (*get_init_port_cfg) (IN int vlan_id,
+ IN int port_index,
+ INOUT UID_STP_PORT_CFG_T* cfg);
+ void (*trace)(const char *fmt, ...);
+};
+
+#ifndef __STP_VECTORS_T__
+#define __STP_VECTORS_T__
+typedef struct stp_vectors STP_VECTORS_T;
+#endif
+
+#ifdef __STP_INTERNAL__
+extern STP_VECTORS_T *stp_vectors;
+#endif
+
+#endif /* __STP_VECTORS_H__ */
diff --git a/usr/src/lib/librstp/common/stpm.c b/usr/src/lib/librstp/common/stpm.c
new file mode 100644
index 0000000000..af1e4aa70e
--- /dev/null
+++ b/usr/src/lib/librstp/common/stpm.c
@@ -0,0 +1,360 @@
+/************************************************************************
+ * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
+ * Copyright (C) 2001-2003 Optical Access
+ * Author: Alex Rozin
+ *
+ * This file is part of RSTP library.
+ *
+ * RSTP library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; version 2.1
+ *
+ * RSTP library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with RSTP library; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ **********************************************************************/
+
+ /* STP machine instance : bridge per VLAN: 17.17 */
+
+#include "base.h"
+#include "stpm.h"
+#include "stp_to.h" /* for STP_OUT_flush_lt */
+
+static STPM_T *bridges = NULL;
+
+static int
+_stp_stpm_init_machine (STATE_MACH_T* this)
+{
+ this->State = BEGIN;
+ (*(this->concreteEnterState)) (this);
+ return 0;
+}
+
+static int
+_stp_stpm_iterate_machines (STPM_T* this,
+ int (*iter_callb) (STATE_MACH_T*),
+ Bool exit_on_non_zero_ret)
+{
+ register STATE_MACH_T* stater;
+ register PORT_T* port;
+ int iret, mret = 0;
+
+ /* state machines per bridge */
+ for (stater = this->machines; stater; stater = stater->next) {
+ iret = (*iter_callb) (stater);
+ if (exit_on_non_zero_ret && iret)
+ return iret;
+ else
+ mret += iret;
+ }
+
+ /* state machines per port */
+ for (port = this->ports; port; port = port->next) {
+ for (stater = port->machines; stater; stater = stater->next) {
+ iret = (*iter_callb) (stater);
+ if (exit_on_non_zero_ret && iret)
+ return iret;
+ else
+ mret += iret;
+ }
+ }
+
+ return mret;
+}
+
+void
+_stp_stpm_init_data (STPM_T* this)
+{
+ STP_VECT_create (&this->rootPrio,
+ &this->BrId,
+ 0,
+ &this->BrId,
+ 0, 0);
+
+ this->BrTimes.MessageAge = 0;
+
+ STP_copy_times (&this->rootTimes, &this->BrTimes);
+}
+
+static unsigned char
+_check_topoch (STPM_T* this)
+{
+ register PORT_T* port;
+
+ for (port = this->ports; port; port = port->next) {
+ if (port->tcWhile) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+void
+STP_stpm_one_second (STPM_T* param)
+{
+ STPM_T* this = (STPM_T*) param;
+ register PORT_T* port;
+ register int iii;
+
+ if (STP_ENABLED != this->admin_state) return;
+
+ for (port = this->ports; port; port = port->next) {
+ for (iii = 0; iii < TIMERS_NUMBER; iii++) {
+ if (*(port->timers[iii]) > 0) {
+ (*port->timers[iii])--;
+ }
+ }
+ port->uptime++;
+ }
+
+ (void) STP_stpm_update (this);
+ this->Topo_Change = _check_topoch (this);
+ if (this->Topo_Change) {
+ this->Topo_Change_Count++;
+ this->timeSince_Topo_Change = 0;
+ } else {
+ this->Topo_Change_Count = 0;
+ this->timeSince_Topo_Change++;
+ }
+}
+
+STPM_T*
+STP_stpm_create (int vlan_id, char* name)
+{
+ STPM_T* this;
+
+ STP_NEW_IN_LIST(this, STPM_T, bridges, "stp instance");
+
+ this->admin_state = STP_DISABLED;
+
+ this->vlan_id = vlan_id;
+ if (name) {
+ STP_STRDUP(this->name, name, "stp bridge name");
+ }
+
+ this->machines = NULL;
+ this->ports = NULL;
+
+ STP_STATE_MACH_IN_LIST(rolesel);
+
+#ifdef STP_DBG
+ /* this->rolesel->debug = 2; */
+#endif
+
+ return this;
+}
+
+int
+STP_stpm_enable (STPM_T* this, UID_STP_MODE_T admin_state)
+{
+ int rc = 0;
+
+ if (admin_state == this->admin_state) {
+ /* nothing to do :) */
+ return 0;
+ }
+
+ if (STP_ENABLED == admin_state) {
+ if (this->ports)
+ rc = STP_stpm_start (this);
+ this->admin_state = admin_state;
+ } else {
+ this->admin_state = admin_state;
+ STP_stpm_stop (this);
+ }
+
+ return rc;
+}
+
+void
+STP_stpm_delete (STPM_T* this)
+{
+ register STPM_T* tmp;
+ register STPM_T* prev;
+ register STATE_MACH_T* stater;
+ register PORT_T* port;
+ register void* pv;
+
+ (void) STP_stpm_enable (this, STP_DISABLED);
+
+ for (stater = this->machines; stater; ) {
+ pv = (void*) stater->next;
+ STP_state_mach_delete (stater);
+ this->machines = stater = (STATE_MACH_T*) pv;
+ }
+
+ for (port = this->ports; port; ) {
+ pv = (void*) port->next;
+ STP_port_delete (port);
+ this->ports = port = (PORT_T*) pv;
+ }
+
+ prev = NULL;
+ for (tmp = bridges; tmp; tmp = tmp->next) {
+ if (tmp->vlan_id == this->vlan_id) {
+ if (prev) {
+ prev->next = this->next;
+ } else {
+ bridges = this->next;
+ }
+
+ if (this->name)
+ STP_FREE(this->name, "stp bridge name");
+ STP_FREE(this, "stp instance");
+ break;
+ }
+ prev = tmp;
+ }
+}
+
+int
+STP_stpm_start (STPM_T* this)
+{
+ register PORT_T* port;
+
+ if (! this->ports) { /* there are not any ports :( */
+ return STP_There_Are_No_Ports;
+ }
+
+ if (! STP_compute_bridge_id (this)) {/* can't compute bridge id ? :( */
+ return STP_Cannot_Compute_Bridge_Prio;
+ }
+
+ /* check, that the stpm has unique bridge Id */
+ if (0 != STP_stpm_check_bridge_priority (this)) {
+ /* there is an enabled bridge with same ID :( */
+ return STP_Invalid_Bridge_Priority;
+ }
+
+ _stp_stpm_init_data (this);
+
+ for (port = this->ports; port; port = port->next) {
+ STP_port_init (port, this, True);
+ }
+
+#ifndef STRONGLY_SPEC_802_1W
+ /* A. see comment near STRONGLY_SPEC_802_1W in topoch.c */
+ /* B. port=0 here means: delete for all ports */
+#ifdef STP_DBG
+ stp_trace("%s (all, start stpm)",
+ "clearFDB");
+#endif
+
+ STP_OUT_flush_lt (0, this->vlan_id, LT_FLASH_ONLY_THE_PORT, "start stpm");
+#endif
+
+ (void) _stp_stpm_iterate_machines (this, _stp_stpm_init_machine, False);
+ (void) STP_stpm_update (this);
+
+ return 0;
+}
+
+/* ARGSUSED */
+void
+STP_stpm_stop (STPM_T* this)
+{
+}
+
+int
+STP_stpm_update (STPM_T* this) /* returns number of loops */
+{
+ register Bool need_state_change;
+ register int number_of_loops = 0;
+
+ need_state_change = False;
+
+ for (;;) {/* loop until not need changes */
+ need_state_change = _stp_stpm_iterate_machines (this,
+ STP_check_condition,
+ True);
+ if (! need_state_change) break;
+
+ number_of_loops++;
+ /* here we know, that at least one stater must be
+ updated (it has changed state) */
+ number_of_loops += _stp_stpm_iterate_machines (this,
+ STP_change_state,
+ False);
+
+ }
+
+ return number_of_loops;
+}
+
+BRIDGE_ID *
+STP_compute_bridge_id (STPM_T* this)
+{
+ register PORT_T* port;
+ register PORT_T* min_num_port = NULL;
+ int port_index = 0;
+
+ for (port = this->ports; port; port = port->next) {
+ if (! port_index || port->port_index < port_index) {
+ min_num_port = port;
+ port_index = port->port_index;
+ }
+ }
+
+ if (! min_num_port) return NULL; /* IMHO, it may not be */
+
+ STP_OUT_get_port_mac (min_num_port->port_index, this->BrId.addr);
+
+ return &this->BrId;
+}
+
+STPM_T*
+STP_stpm_get_the_list (void)
+{
+ return bridges;
+}
+
+void
+STP_stpm_update_after_bridge_management (STPM_T* this)
+{
+ register PORT_T* port;
+
+ for (port = this->ports; port; port = port->next) {
+ port->reselect = True;
+ port->selected = False;
+ }
+}
+
+int
+STP_stpm_check_bridge_priority (STPM_T* this)
+{
+ register STPM_T* oth;
+
+ for (oth = bridges; oth; oth = oth->next) {
+ if (STP_ENABLED == oth->admin_state && oth != this &&
+ ! STP_VECT_compare_bridge_id (&this->BrId, &oth->BrId)) {
+ return STP_Invalid_Bridge_Priority;
+ }
+ }
+
+ return 0;
+}
+
+const char*
+STP_stpm_get_port_name_by_id (STPM_T* this, PORT_ID port_id)
+{
+ register PORT_T* port;
+
+ for (port = this->ports; port; port = port->next) {
+ if (port_id == port->port_id) {
+ return port->port_name;
+ }
+ }
+
+ return "Undef?";
+}
+
+
+
+
+
diff --git a/usr/src/lib/librstp/common/stpm.h b/usr/src/lib/librstp/common/stpm.h
new file mode 100644
index 0000000000..62db3928fc
--- /dev/null
+++ b/usr/src/lib/librstp/common/stpm.h
@@ -0,0 +1,126 @@
+/************************************************************************
+ * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
+ * Copyright (C) 2001-2003 Optical Access
+ * Author: Alex Rozin
+ *
+ * This file is part of RSTP library.
+ *
+ * RSTP library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; version 2.1
+ *
+ * RSTP library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with RSTP library; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ **********************************************************************/
+
+/* STP machine instance : bridge per VLAN: 17.17 */
+/* The Clause 17.13 points: "NOTE:The operation of the Bridge as a whole can
+ * be represented by the interaction between Bridge Ports specified,
+ * and by parameters of the Bridge stored in ‘Port 0’. This removes the
+ * need for any ‘per Bridge’ specification elements, and helps ensure
+ * the minimum dependencies between Bridge Ports. This in turn supports
+ * the development of implementations that scale well with increasing
+ * numbers of Bridge Ports. This shift of focus to ‘per Port operation’
+ * for the RSTP is supported by underlying technical changes from the
+ * Spanning Tree Algorithm and Protocol (Clause 8):"
+ * Newetheless, it seems to me, the behaviour of of the bridge, its variables
+ * and functions are so distinct from Port, that I decided to design Bridge
+ * instance. I called this object 'stpm' from STP machine. I'd like to see
+ * another procedural model, more corresponding to this note on Clause 17.13 */
+
+#ifndef _STP_MACHINE_H__
+#define _STP_MACHINE_H__
+
+#include "port.h"
+#include "rolesel.h"
+
+#define TxHoldCount 3 /* 17.16.6, 17.28.2(Table 17-5) */
+
+typedef enum {/* 17.12, 17.16.1 */
+ FORCE_STP_COMPAT = 0,
+ NORMAL_RSTP = 2
+} PROTOCOL_VERSION_T;
+
+struct stpm_t {
+ struct stpm_t* next;
+
+ struct port_t* ports;
+
+ /* The only "per bridge" state machine */
+ STATE_MACH_T* rolesel; /* the Port Role Selection State machione: 17.22 */
+ STATE_MACH_T* machines;
+
+ /* variables */
+ PROTOCOL_VERSION_T ForceVersion; /* 17.12, 17.16.1 */
+ BRIDGE_ID BrId; /* 17.17.2 */
+ TIMEVALUES_T BrTimes; /* 17.17.4 */
+ PORT_ID rootPortId; /* 17.17.5 */
+ PRIO_VECTOR_T rootPrio; /* 17.17.6 */
+ TIMEVALUES_T rootTimes; /* 17.17.7 */
+
+ int vlan_id; /* let's say: tag */
+ char* name; /* name of the VLAN, maily for debugging */
+ UID_STP_MODE_T admin_state; /* STP_DISABLED or STP_ENABLED; type see in UiD */
+
+ unsigned long timeSince_Topo_Change; /* 14.8.1.1.3.b */
+ unsigned long Topo_Change_Count; /* 14.8.1.1.3.c */
+ unsigned char Topo_Change; /* 14.8.1.1.3.d */
+};
+
+#ifndef __STPM_T__
+#define __STPM_T__
+typedef struct stpm_t STPM_T;
+#endif
+
+/* Functions prototypes */
+
+void
+STP_stpm_one_second (STPM_T* param);
+
+STPM_T*
+STP_stpm_create (int vlan_id, char* name);
+
+int
+STP_stpm_enable (STPM_T* this, UID_STP_MODE_T admin_state);
+
+void
+STP_stpm_delete (STPM_T* this);
+
+int
+STP_stpm_start (STPM_T* this);
+
+void
+STP_stpm_stop (STPM_T* this);
+
+int
+STP_stpm_update (STPM_T* this);
+
+BRIDGE_ID *
+STP_compute_bridge_id (STPM_T* this);
+
+STPM_T *
+STP_stpm_get_the_list (void);
+
+void
+STP_stpm_update_after_bridge_management (STPM_T* this);
+
+int
+STP_stpm_check_bridge_priority (STPM_T* this);
+
+const char*
+STP_stpm_get_port_name_by_id (STPM_T* this, PORT_ID port_id);
+
+STPM_T* stpapi_stpm_find (int vlan_id);
+
+int stp_in_stpm_enable (int vlan_id, char* name,
+ UID_STP_MODE_T admin_state);
+void* stp_in_stpm_create (int vlan_id, char *name, int *err_code);
+
+#endif /* _STP_MACHINE_H__ */
diff --git a/usr/src/lib/librstp/common/stpmgmt.c b/usr/src/lib/librstp/common/stpmgmt.c
new file mode 100644
index 0000000000..83f214be3c
--- /dev/null
+++ b/usr/src/lib/librstp/common/stpmgmt.c
@@ -0,0 +1,161 @@
+/************************************************************************
+ * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
+ * Copyright (C) 2001-2003 Optical Access
+ * Author: Alex Rozin
+ *
+ * This file is part of RSTP library.
+ *
+ * RSTP library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; version 2.1
+ *
+ * RSTP library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with RSTP library; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ **********************************************************************/
+
+/* This file contains API from an operation system to the RSTP library */
+
+#include "base.h"
+#include "stpm.h"
+#include "stp_in.h" /* for bridge defaults */
+#include "stp_to.h"
+
+
+int
+STP_IN_stpm_create (int vlan_id, char* name)
+{
+ register STPM_T* this;
+ int err_code;
+ UID_STP_CFG_T init_cfg;
+
+ stp_trace ("STP_IN_stpm_create(%s)", name);
+
+ init_cfg.field_mask = BR_CFG_ALL;
+ STP_OUT_get_init_stpm_cfg (vlan_id, &init_cfg);
+ init_cfg.field_mask = 0;
+
+ RSTP_CRITICAL_PATH_START;
+ this = stp_in_stpm_create (vlan_id, name, &err_code);
+ if (this) {
+ this->BrId.prio = init_cfg.bridge_priority;
+ this->BrTimes.MaxAge = init_cfg.max_age;
+ this->BrTimes.HelloTime = init_cfg.hello_time;
+ this->BrTimes.ForwardDelay = init_cfg.forward_delay;
+ this->ForceVersion = (PROTOCOL_VERSION_T) init_cfg.force_version;
+ }
+
+ RSTP_CRITICAL_PATH_END;
+ return err_code;
+}
+
+int
+STP_IN_stpm_delete (int vlan_id)
+{
+ register STPM_T* this;
+ int iret = 0;
+
+ RSTP_CRITICAL_PATH_START;
+ this = stpapi_stpm_find (vlan_id);
+
+ if (! this) { /* it had not yet been created :( */
+ iret = STP_Vlan_Had_Not_Yet_Been_Created;
+ } else {
+
+ if (STP_ENABLED == this->admin_state) {
+ if (0 != STP_stpm_enable (this, STP_DISABLED)) {/* can't disable :( */
+ iret = STP_Another_Error;
+ } else
+ STP_OUT_set_hardware_mode (vlan_id, STP_DISABLED);
+ }
+
+ if (0 == iret) {
+ STP_stpm_delete (this);
+ }
+ }
+ RSTP_CRITICAL_PATH_END;
+ return iret;
+}
+
+int
+STP_IN_stpm_get_vlan_id_by_name (char* name, int* vlan_id)
+{
+ register STPM_T* stpm;
+ int iret = STP_Cannot_Find_Vlan;
+
+ RSTP_CRITICAL_PATH_START;
+ for (stpm = STP_stpm_get_the_list (); stpm; stpm = stpm->next) {
+ if (stpm->name && ! strcmp (stpm->name, name)) {
+ *vlan_id = stpm->vlan_id;
+ iret = 0;
+ break;
+ }
+ }
+ RSTP_CRITICAL_PATH_END;
+
+ return iret;
+}
+
+
+Bool
+STP_IN_get_is_stpm_enabled (int vlan_id)
+{
+ STPM_T* this;
+ Bool iret = False;
+
+ RSTP_CRITICAL_PATH_START;
+ this = stpapi_stpm_find (vlan_id);
+
+ if (this) {
+ if (this->admin_state == STP_ENABLED) {
+ iret = True;
+ }
+#ifdef notdef
+ } else {
+ ; /* it had not yet been created :( */
+#endif
+ }
+
+ RSTP_CRITICAL_PATH_END;
+ return iret;
+}
+
+int
+STP_IN_stop_all (void)
+{
+ register STPM_T* stpm;
+
+ RSTP_CRITICAL_PATH_START;
+
+ for (stpm = STP_stpm_get_the_list (); stpm; stpm = stpm->next) {
+ if (STP_DISABLED != stpm->admin_state) {
+ STP_OUT_set_hardware_mode (stpm->vlan_id, STP_DISABLED);
+ (void) STP_stpm_enable (stpm, STP_DISABLED);
+ }
+ }
+
+ RSTP_CRITICAL_PATH_END;
+ return 0;
+}
+
+int
+STP_IN_delete_all (void)
+{
+ register STPM_T* stpm;
+
+ RSTP_CRITICAL_PATH_START;
+ for (stpm = STP_stpm_get_the_list (); stpm; stpm = stpm->next) {
+ (void) STP_stpm_enable (stpm, STP_DISABLED);
+ STP_stpm_delete (stpm);
+ }
+
+ RSTP_CRITICAL_PATH_END;
+ return 0;
+}
+
diff --git a/usr/src/lib/librstp/common/sttrans.c b/usr/src/lib/librstp/common/sttrans.c
new file mode 100644
index 0000000000..e1754b2b8e
--- /dev/null
+++ b/usr/src/lib/librstp/common/sttrans.c
@@ -0,0 +1,140 @@
+/************************************************************************
+ * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
+ * Copyright (C) 2001-2003 Optical Access
+ * Author: Alex Rozin
+ *
+ * This file is part of RSTP library.
+ *
+ * RSTP library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; version 2.1
+ *
+ * RSTP library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with RSTP library; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ **********************************************************************/
+
+/* Port State Transition state machine : 17.24 */
+
+#include "base.h"
+#include "stpm.h"
+#include "stp_to.h"
+
+#define STATES { \
+ CHOOSE(DISCARDING), \
+ CHOOSE(LEARNING), \
+ CHOOSE(FORWARDING) \
+}
+
+#define GET_STATE_NAME STP_sttrans_get_state_name
+#include "choose.h"
+
+
+#ifdef STRONGLY_SPEC_802_1W
+static Bool
+disableLearning (STATE_MACH_T *this)
+{
+ register PORT_T *port = this->owner.port;
+
+ return STP_OUT_set_learning (port->port_index, port->owner->vlan_id, False);
+}
+
+static Bool
+enableLearning (STATE_MACH_T *this)
+{
+ register PORT_T *port = this->owner.port;
+
+ return STP_OUT_set_learning (port->port_index, port->owner->vlan_id, True);
+}
+
+static Bool
+disableForwarding (STATE_MACH_T *this)
+{
+ register PORT_T *port = this->owner.port;
+
+ return STP_OUT_set_forwarding (port->port_index, port->owner->vlan_id, False);
+}
+
+static Bool
+enableForwarding (STATE_MACH_T *this)
+{
+ register PORT_T *port = this->owner.port;
+
+ return STP_OUT_set_forwarding (port->port_index, port->owner->vlan_id, True);
+}
+#endif
+
+void
+STP_sttrans_enter_state (STATE_MACH_T *this)
+{
+ register PORT_T *port = this->owner.port;
+
+ switch (this->State) {
+ case BEGIN:
+ case DISCARDING:
+ port->learning = False;
+ port->forwarding = False;
+#ifdef STRONGLY_SPEC_802_1W
+ disableLearning (this);
+ disableForwarding (this);
+#else
+ STP_OUT_set_port_state (port->port_index, port->owner->vlan_id, UID_PORT_DISCARDING);
+#endif
+ break;
+ case LEARNING:
+ port->learning = True;
+#ifdef STRONGLY_SPEC_802_1W
+ enableLearning (this);
+#else
+ STP_OUT_set_port_state (port->port_index, port->owner->vlan_id, UID_PORT_LEARNING);
+#endif
+ break;
+ case FORWARDING:
+ port->tc = !port->operEdge;
+ port->forwarding = True;
+#ifdef STRONGLY_SPEC_802_1W
+ enableForwarding (this);
+#else
+ STP_OUT_set_port_state (port->port_index, port->owner->vlan_id, UID_PORT_FORWARDING);
+#endif
+ break;
+ }
+
+}
+
+Bool
+STP_sttrans_check_conditions (STATE_MACH_T *this)
+{
+ register PORT_T *port = this->owner.port;
+
+ switch (this->State) {
+ case BEGIN:
+ return STP_hop_2_state (this, DISCARDING);
+ case DISCARDING:
+ if (port->learn) {
+ return STP_hop_2_state (this, LEARNING);
+ }
+ break;
+ case LEARNING:
+ if (port->forward) {
+ return STP_hop_2_state (this, FORWARDING);
+ }
+ if (!port->learn) {
+ return STP_hop_2_state (this, DISCARDING);
+ }
+ break;
+ case FORWARDING:
+ if (!port->forward) {
+ return STP_hop_2_state (this, DISCARDING);
+ }
+ break;
+ }
+
+ return False;
+}
diff --git a/usr/src/lib/librstp/common/sttrans.h b/usr/src/lib/librstp/common/sttrans.h
new file mode 100644
index 0000000000..da0b81ed84
--- /dev/null
+++ b/usr/src/lib/librstp/common/sttrans.h
@@ -0,0 +1,38 @@
+/************************************************************************
+ * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
+ * Copyright (C) 2001-2003 Optical Access
+ * Author: Alex Rozin
+ *
+ * This file is part of RSTP library.
+ *
+ * RSTP library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; version 2.1
+ *
+ * RSTP library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with RSTP library; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ **********************************************************************/
+
+/* Port State Transition state machine : 17.24 */
+
+#ifndef _STP_STATE_TRANSIT_H__
+#define _STP_STATE_TRANSIT_H__
+
+void
+STP_sttrans_enter_state (STATE_MACH_T* s);
+
+Bool
+STP_sttrans_check_conditions (STATE_MACH_T* s);
+
+char*
+STP_sttrans_get_state_name (int state);
+
+#endif /* _STP_STATE_TRANSIT_H__ */
+
diff --git a/usr/src/lib/librstp/common/times.c b/usr/src/lib/librstp/common/times.c
new file mode 100644
index 0000000000..b9eae3ceee
--- /dev/null
+++ b/usr/src/lib/librstp/common/times.c
@@ -0,0 +1,80 @@
+/************************************************************************
+ * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
+ * Copyright (C) 2001-2003 Optical Access
+ * Author: Alex Rozin
+ *
+ * This file is part of RSTP library.
+ *
+ * RSTP library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; version 2.1
+ *
+ * RSTP library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with RSTP library; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ **********************************************************************/
+
+/* "Times" API : bridgeTime, rootTimes, portTimes, designatedTimes, msgTimes */
+
+#include "base.h"
+
+int
+STP_compare_times (IN TIMEVALUES_T *t1, IN TIMEVALUES_T *t2)
+{
+ if (t1->MessageAge < t2->MessageAge) return -1;
+ if (t1->MessageAge > t2->MessageAge) return 1;
+
+ if (t1->MaxAge < t2->MaxAge) return -2;
+ if (t1->MaxAge > t2->MaxAge) return 2;
+
+ if (t1->ForwardDelay < t2->ForwardDelay) return -3;
+ if (t1->ForwardDelay > t2->ForwardDelay) return 3;
+
+ if (t1->HelloTime < t2->HelloTime) return -4;
+ if (t1->HelloTime > t2->HelloTime) return 4;
+
+ return 0;
+}
+
+void
+STP_get_times (IN BPDU_BODY_T *b, OUT TIMEVALUES_T *v)
+{
+ /* LINTED: alignment */
+ v->MessageAge = ntohs (*((unsigned short*) b->message_age)) >> 8;
+ /* LINTED: alignment */
+ v->MaxAge = ntohs (*((unsigned short*) b->max_age)) >> 8;
+ /* LINTED: alignment */
+ v->ForwardDelay = ntohs (*((unsigned short*) b->forward_delay)) >> 8;
+ /* LINTED: alignment */
+ v->HelloTime = ntohs (*((unsigned short*) b->hello_time)) >> 8;
+}
+
+void
+STP_set_times (IN TIMEVALUES_T *v, OUT BPDU_BODY_T *b)
+{
+ unsigned short mt;
+ #define STP_SET_TIME(f, t) \
+ mt = htons (f << 8); \
+ (void) memcpy (t, &mt, 2);
+
+ STP_SET_TIME(v->MessageAge, b->message_age);
+ STP_SET_TIME(v->MaxAge, b->max_age);
+ STP_SET_TIME(v->ForwardDelay, b->forward_delay);
+ STP_SET_TIME(v->HelloTime, b->hello_time);
+}
+
+void
+STP_copy_times (OUT TIMEVALUES_T *t, IN TIMEVALUES_T *f)
+{
+ t->MessageAge = f->MessageAge;
+ t->MaxAge = f->MaxAge;
+ t->ForwardDelay = f->ForwardDelay;
+ t->HelloTime = f->HelloTime;
+}
+
diff --git a/usr/src/lib/librstp/common/times.h b/usr/src/lib/librstp/common/times.h
new file mode 100644
index 0000000000..4bdc1e28df
--- /dev/null
+++ b/usr/src/lib/librstp/common/times.h
@@ -0,0 +1,50 @@
+/************************************************************************
+ * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
+ * Copyright (C) 2001-2003 Optical Access
+ * Author: Alex Rozin
+ *
+ * This file is part of RSTP library.
+ *
+ * RSTP library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; version 2.1
+ *
+ * RSTP library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with RSTP library; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ **********************************************************************/
+
+/* "Times" API : bridgeTime, rootTimes, portTimes, designatedTimes, msgTimes */
+
+#ifndef _RSTP_TIMES_H__
+#define _RSTP_TIMES_H__
+
+typedef struct timevalues_t {
+ unsigned short MessageAge;
+ unsigned short MaxAge;
+ unsigned short ForwardDelay;
+ unsigned short HelloTime;
+} TIMEVALUES_T;
+
+int
+STP_compare_times (IN TIMEVALUES_T* t1, IN TIMEVALUES_T* t2);
+
+void
+STP_get_times (IN BPDU_BODY_T* b, OUT TIMEVALUES_T* v);
+
+void
+STP_set_times (IN TIMEVALUES_T* v, OUT BPDU_BODY_T* b);
+
+void
+STP_copy_times (OUT TIMEVALUES_T* t, IN TIMEVALUES_T* f);
+
+#endif /* _RSTP_TIMES_H__ */
+
+
+
diff --git a/usr/src/lib/librstp/common/topoch.c b/usr/src/lib/librstp/common/topoch.c
new file mode 100644
index 0000000000..1926bcfe44
--- /dev/null
+++ b/usr/src/lib/librstp/common/topoch.c
@@ -0,0 +1,227 @@
+/************************************************************************
+ * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
+ * Copyright (C) 2001-2003 Optical Access
+ * Author: Alex Rozin
+ *
+ * This file is part of RSTP library.
+ *
+ * RSTP library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; version 2.1
+ *
+ * RSTP library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with RSTP library; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ **********************************************************************/
+
+/* Topolgy Change state machine : 17.25 */
+
+#include "base.h"
+#include "stpm.h"
+#include "stp_to.h" /* for STP_OUT_flush_lt */
+
+#define STATES { \
+ CHOOSE(INIT), \
+ CHOOSE(INACTIVE), \
+ CHOOSE(TCACTIVE), \
+ CHOOSE(DETECTED), \
+ CHOOSE(NOTIFIED_TC), \
+ CHOOSE(PROPAGATING), \
+ CHOOSE(ACKNOWLEDGED), \
+ CHOOSE(NOTIFIED_TCN) \
+}
+
+#define GET_STATE_NAME STP_topoch_get_state_name
+#include "choose.h"
+
+#ifndef STRONGLY_SPEC_802_1W
+/*
+ * In many kinds of hardware the function
+ * STP_OUT_flush_lt is a) is very hard and b) cannot
+ * delete learning emtries per port. The alternate
+ * method may be used: we don't care operEdge flag here,
+ * but clean learning table once for TopologyChange
+ * for all ports, except the received port. I am ready to discuss :(
+ * See below word STRONGLY_SPEC_802_1W
+ */
+#else
+static Bool
+flush (STATE_MACH_T *this, char* reason) /* 17.19.9 */
+{
+ register PORT_T* port = this->owner.port;
+ Bool bret;
+
+ if (port->operEdge) return True;
+ if (this->debug) {
+ stp_trace("%s (%s, %s, %s, '%s')",
+ "flush", port->port_name, port->owner->name,
+ LT_FLASH_ONLY_THE_PORT == type ? "this port" : "other ports",
+ reason);
+ }
+
+ bret = STP_OUT_flush_lt (port->port_index, port->owner->vlan_id,
+ LT_FLASH_ONLY_THE_PORT, reason);
+}
+#endif
+
+static void
+setTcPropBridge (STATE_MACH_T* this, char* reason) /* 17.19.14 */
+{
+ register PORT_T* port = this->owner.port;
+ register PORT_T* tmp;
+
+ for (tmp = port->owner->ports; tmp; tmp = tmp->next) {
+ if (tmp->port_index != port->port_index)
+ tmp->tcProp = True;
+ }
+
+#ifndef STRONGLY_SPEC_802_1W
+#ifdef STP_DBG
+ if (this->debug) {
+ stp_trace("%s (%s, %s, %s, '%s')",
+ "clearFDB", port->port_name, port->owner->name,
+ "other ports", reason);
+ }
+#endif
+
+ STP_OUT_flush_lt (port->port_index, port->owner->vlan_id,
+ LT_FLASH_ALL_PORTS_EXCLUDE_THIS, reason);
+#endif
+}
+
+static unsigned int
+newTcWhile (STATE_MACH_T* this) /* 17.19.7 */
+{
+ register PORT_T* port = this->owner.port;
+
+ if (port->sendRSTP && port->operPointToPointMac) {
+ return 2 * port->owner->rootTimes.HelloTime;
+ }
+ return port->owner->rootTimes.MaxAge;
+}
+
+void
+STP_topoch_enter_state (STATE_MACH_T* this)
+{
+ register PORT_T* port = this->owner.port;
+
+ switch (this->State) {
+ case BEGIN:
+ case INIT:
+#ifdef STRONGLY_SPEC_802_1W
+ flush (this, "topoch INIT");
+#endif
+ port->tcWhile = 0;
+ port->tc =
+ port->tcProp =
+ port->tcAck = False;
+ break;
+ case INACTIVE:
+ port->rcvdTc =
+ port->rcvdTcn =
+ port->rcvdTcAck = port->tc = port->tcProp = False;
+ break;
+ case TCACTIVE:
+ break;
+ case DETECTED:
+ port->tcWhile = newTcWhile (this);
+#ifdef STP_DBG
+ if (this->debug)
+ stp_trace("DETECTED: tcWhile=%d on port %s",
+ port->tcWhile, port->port_name);
+#endif
+ setTcPropBridge (this, "DETECTED");
+ port->tc = False;
+ break;
+ case NOTIFIED_TC:
+ port->rcvdTcn = port->rcvdTc = False;
+ if (port->role == DesignatedPort) {
+ port->tcAck = True;
+ }
+ setTcPropBridge (this, "NOTIFIED_TC");
+ break;
+ case PROPAGATING:
+ port->tcWhile = newTcWhile (this);
+#ifdef STP_DBG
+ if (this->debug)
+ stp_trace("PROPAGATING: tcWhile=%d on port %s",
+ port->tcWhile, port->port_name);
+#endif
+#ifdef STRONGLY_SPEC_802_1W
+ flush (this, "topoch PROPAGATING");
+#endif
+ port->tcProp = False;
+ break;
+ case ACKNOWLEDGED:
+ port->tcWhile = 0;
+#ifdef STP_DBG
+ if (this->debug)
+ stp_trace("ACKNOWLEDGED: tcWhile=%d on port %s",
+ port->tcWhile, port->port_name);
+#endif
+ port->rcvdTcAck = False;
+ break;
+ case NOTIFIED_TCN:
+ port->tcWhile = newTcWhile (this);
+#ifdef STP_DBG
+ if (this->debug)
+ stp_trace("NOTIFIED_TCN: tcWhile=%d on port %s",
+ port->tcWhile, port->port_name);
+#endif
+ break;
+ };
+}
+
+Bool
+STP_topoch_check_conditions (STATE_MACH_T* this)
+{
+ register PORT_T* port = this->owner.port;
+
+ if (BEGIN == this->State) {
+ return STP_hop_2_state (this, INIT);
+ }
+
+ switch (this->State) {
+ case INIT:
+ return STP_hop_2_state (this, INACTIVE);
+ case INACTIVE:
+ if (port->role == RootPort || port->role == DesignatedPort)
+ return STP_hop_2_state (this, TCACTIVE);
+ if (port->rcvdTc || port->rcvdTcn || port->rcvdTcAck ||
+ port->tc || port->tcProp)
+ return STP_hop_2_state (this, INACTIVE);
+ break;
+ case TCACTIVE:
+ if (port->role != RootPort && (port->role != DesignatedPort))
+ return STP_hop_2_state (this, INIT);
+ if (port->tc)
+ return STP_hop_2_state (this, DETECTED);
+ if (port->rcvdTcn)
+ return STP_hop_2_state (this, NOTIFIED_TCN);
+ if (port->rcvdTc)
+ return STP_hop_2_state (this, NOTIFIED_TC);
+ if (port->tcProp && !port->operEdge)
+ return STP_hop_2_state (this, PROPAGATING);
+ if (port->rcvdTcAck)
+ return STP_hop_2_state (this, ACKNOWLEDGED);
+ break;
+ case DETECTED:
+ return STP_hop_2_state (this, TCACTIVE);
+ case NOTIFIED_TC:
+ return STP_hop_2_state (this, TCACTIVE);
+ case PROPAGATING:
+ return STP_hop_2_state (this, TCACTIVE);
+ case ACKNOWLEDGED:
+ return STP_hop_2_state (this, TCACTIVE);
+ case NOTIFIED_TCN:
+ return STP_hop_2_state (this, NOTIFIED_TC);
+ };
+ return False;
+}
+
diff --git a/usr/src/lib/librstp/common/topoch.h b/usr/src/lib/librstp/common/topoch.h
new file mode 100644
index 0000000000..8b7324c425
--- /dev/null
+++ b/usr/src/lib/librstp/common/topoch.h
@@ -0,0 +1,37 @@
+/************************************************************************
+ * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
+ * Copyright (C) 2001-2003 Optical Access
+ * Author: Alex Rozin
+ *
+ * This file is part of RSTP library.
+ *
+ * RSTP library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; version 2.1
+ *
+ * RSTP library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with RSTP library; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ **********************************************************************/
+
+/* Topolgy Change state machine : 17.25 */
+
+#ifndef _STP_TOPO_CHANGE_H__
+#define _STP_TOPO_CHANGE_H__
+
+void
+STP_topoch_enter_state (STATE_MACH_T* s);
+
+Bool
+STP_topoch_check_conditions (STATE_MACH_T* s);
+
+char* STP_topoch_get_state_name (int state);
+
+#endif /* _STP_TOPO_CHANGE_H__ */
+
diff --git a/usr/src/lib/librstp/common/transmit.c b/usr/src/lib/librstp/common/transmit.c
new file mode 100644
index 0000000000..cead2143e8
--- /dev/null
+++ b/usr/src/lib/librstp/common/transmit.c
@@ -0,0 +1,368 @@
+/************************************************************************
+ * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
+ * Copyright (C) 2001-2003 Optical Access
+ * Author: Alex Rozin
+ *
+ * This file is part of RSTP library.
+ *
+ * RSTP library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; version 2.1
+ *
+ * RSTP library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with RSTP library; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ **********************************************************************/
+
+/* Port Transmit state machine : 17.27 */
+
+#include "base.h"
+#include "stpm.h"
+#include "stp_to.h" /* for STP_OUT_get_port_mac & STP_OUT_tx_bpdu */
+
+#define BPDU_LEN8023_OFF 12
+
+#define STATES { \
+ CHOOSE(TRANSMIT_INIT), \
+ CHOOSE(TRANSMIT_PERIODIC), \
+ CHOOSE(IDLE), \
+ CHOOSE(TRANSMIT_CONFIG), \
+ CHOOSE(TRANSMIT_TCN), \
+ CHOOSE(TRANSMIT_RSTP) \
+}
+
+#define GET_STATE_NAME STP_transmit_get_state_name
+#include "choose.h"
+
+#define MIN_FRAME_LENGTH 64
+
+
+typedef struct tx_tcn_bpdu_t {
+ MAC_HEADER_T mac;
+ ETH_HEADER_T eth;
+ BPDU_HEADER_T hdr;
+} TCN_BPDU_T;
+
+typedef struct tx_stp_bpdu_t {
+ MAC_HEADER_T mac;
+ ETH_HEADER_T eth;
+ BPDU_HEADER_T hdr;
+ BPDU_BODY_T body;
+} CONFIG_BPDU_T;
+
+typedef struct tx_rstp_bpdu_t {
+ MAC_HEADER_T mac;
+ ETH_HEADER_T eth;
+ BPDU_HEADER_T hdr;
+ BPDU_BODY_T body;
+ unsigned char ver_1_length[2];
+} RSTP_BPDU_T;
+
+
+static RSTP_BPDU_T bpdu_packet = {
+ {/* MAC_HEADER_T */
+ {0x01, 0x80, 0xc2, 0x00, 0x00, 0x00}, /* dst_mac */
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* src_mac */
+ },
+ { /* ETH_HEADER_T */
+ {0x00, 0x00}, /* len8023 */
+ BPDU_L_SAP, BPDU_L_SAP, LLC_UI /* dsap, ssap, llc */
+ },
+ {/* BPDU_HEADER_T */
+ {0x00, 0x00}, /* protocol */
+ BPDU_VERSION_ID, 0x00 /* version, bpdu_type */
+ },
+ {
+ 0x00, /* flags; */
+ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* root_id[8]; */
+ {0x00,0x00,0x00,0x00}, /* root_path_cost[4]; */
+ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* bridge_id[8]; */
+ {0x00,0x00}, /* port_id[2]; */
+ {0x00,0x00}, /* message_age[2]; */
+ {0x00,0x00}, /* max_age[2]; */
+ {0x00,0x00}, /* hello_time[2]; */
+ {0x00,0x00}, /* forward_delay[2]; */
+ },
+ {0x00,0x00}, /* ver_1_length[2]; */
+};
+
+static size_t
+build_bpdu_header (int port_index,
+ unsigned char bpdu_type,
+ unsigned short pkt_len)
+{
+ unsigned short len8023;
+
+ STP_OUT_get_port_mac (port_index, bpdu_packet.mac.src_mac);
+
+ bpdu_packet.hdr.bpdu_type = bpdu_type;
+ bpdu_packet.hdr.version = (BPDU_RSTP == bpdu_type) ?
+ BPDU_VERSION_RAPID_ID :
+ BPDU_VERSION_ID;
+
+ /* NOTE: I suppose, that sizeof(unsigned short)=2 ! */
+ len8023 = htons ((unsigned short) (pkt_len + 3));
+ (void) memcpy (&bpdu_packet.eth.len8023, &len8023, 2);
+
+ if (pkt_len < MIN_FRAME_LENGTH) pkt_len = MIN_FRAME_LENGTH;
+ return pkt_len;
+}
+
+static int
+txTcn (STATE_MACH_T* this)
+{ /* 17.19.17 (page 68) & 9.3.2 (page 25) */
+ register size_t pkt_len;
+ register int port_index, vlan_id;
+
+#ifdef STP_DBG
+ if (this->owner.port->skip_tx > 0) {
+ if (1 == this->owner.port->skip_tx)
+ stp_trace ("port %s stop tx skipping",
+ this->owner.port->port_name);
+ this->owner.port->skip_tx--;
+ return STP_Nothing_To_Do;
+ }
+#endif
+
+ if (this->owner.port->admin_non_stp) return 1;
+ port_index = this->owner.port->port_index;
+ vlan_id = this->owner.port->owner->vlan_id;
+
+ pkt_len = build_bpdu_header (port_index,
+ BPDU_TOPO_CHANGE_TYPE,
+ sizeof (BPDU_HEADER_T));
+
+#ifdef STP_DBG
+ if (this->debug)
+ stp_trace ("port %s txTcn", this->owner.port->port_name);
+#endif
+ return STP_OUT_tx_bpdu (port_index, vlan_id,
+ (unsigned char *) &bpdu_packet,
+ pkt_len);
+}
+
+static void
+build_config_bpdu (PORT_T* port, Bool set_topo_ack_flag)
+{
+ bpdu_packet.body.flags = 0;
+ if (port->tcWhile) {
+#ifdef STP_DBG
+ if (port->topoch->debug)
+ stp_trace ("tcWhile=%d =>tx TOPOLOGY_CHANGE_BIT to port %s",
+ (int) port->tcWhile, port->port_name);
+#endif
+ bpdu_packet.body.flags |= TOPOLOGY_CHANGE_BIT;
+ }
+
+ if (set_topo_ack_flag && port->tcAck) {
+ bpdu_packet.body.flags |= TOPOLOGY_CHANGE_ACK_BIT;
+ }
+
+ STP_VECT_set_vector (&port->portPrio, &bpdu_packet.body);
+ STP_set_times (&port->portTimes, &bpdu_packet.body);
+}
+
+static int
+txConfig (STATE_MACH_T* this)
+{/* 17.19.15 (page 67) & 9.3.1 (page 23) */
+ register size_t pkt_len;
+ register PORT_T* port = NULL;
+ register int port_index, vlan_id;
+
+#ifdef STP_DBG
+ if (this->owner.port->skip_tx > 0) {
+ if (1 == this->owner.port->skip_tx)
+ stp_trace ("port %s stop tx skipping",
+ this->owner.port->port_name);
+ this->owner.port->skip_tx--;
+ return STP_Nothing_To_Do;
+ }
+#endif
+
+ port = this->owner.port;
+ if (port->admin_non_stp) return 1;
+ port_index = port->port_index;
+ vlan_id = port->owner->vlan_id;
+
+ pkt_len = build_bpdu_header (port->port_index,
+ BPDU_CONFIG_TYPE,
+ sizeof (BPDU_HEADER_T) + sizeof (BPDU_BODY_T));
+ build_config_bpdu (port, True);
+
+#ifdef STP_DBG
+ if (this->debug)
+ stp_trace ("port %s txConfig flags=0X%lx",
+ port->port_name,
+ (unsigned long) bpdu_packet.body.flags);
+#endif
+ return STP_OUT_tx_bpdu (port_index, vlan_id,
+ (unsigned char *) &bpdu_packet,
+ pkt_len);
+}
+
+static int
+txRstp (STATE_MACH_T* this)
+{/* 17.19.16 (page 68) & 9.3.3 (page 25) */
+ register size_t pkt_len;
+ register PORT_T* port = NULL;
+ register int port_index, vlan_id;
+ unsigned char role;
+
+#ifdef STP_DBG
+ if (this->owner.port->skip_tx > 0) {
+ if (1 == this->owner.port->skip_tx)
+ stp_trace ("port %s stop tx skipping",
+ this->owner.port->port_name);
+ else
+ stp_trace ("port %s skip tx %d",
+ this->owner.port->port_name, this->owner.port->skip_tx);
+
+ this->owner.port->skip_tx--;
+ return STP_Nothing_To_Do;
+ }
+#endif
+
+ port = this->owner.port;
+ if (port->admin_non_stp) return 1;
+ port_index = port->port_index;
+ vlan_id = port->owner->vlan_id;
+
+ pkt_len = build_bpdu_header (port->port_index,
+ BPDU_RSTP,
+ sizeof (BPDU_HEADER_T) + sizeof (BPDU_BODY_T) + 2);
+ build_config_bpdu (port, False);
+
+ switch (port->selectedRole) {
+ default:
+ case DisabledPort:
+ role = RSTP_PORT_ROLE_UNKN;
+ break;
+ case AlternatePort:
+ role = RSTP_PORT_ROLE_ALTBACK;
+ break;
+ case BackupPort:
+ role = RSTP_PORT_ROLE_ALTBACK;
+ break;
+ case RootPort:
+ role = RSTP_PORT_ROLE_ROOT;
+ break;
+ case DesignatedPort:
+ role = RSTP_PORT_ROLE_DESGN;
+ break;
+ }
+
+ bpdu_packet.body.flags |= (role << PORT_ROLE_OFFS);
+
+ if (port->synced) {
+#if 0 /* def STP_DBG */
+ if (port->roletrns->debug)
+ stp_trace ("tx AGREEMENT_BIT to port %s", port->port_name);
+#endif
+ bpdu_packet.body.flags |= AGREEMENT_BIT;
+ }
+
+ if (port->proposing) {
+#if 0 /* def STP_DBG */
+ if (port->roletrns->debug)
+ stp_trace ("tx PROPOSAL_BIT to port %s", port->port_name);
+#endif
+ bpdu_packet.body.flags |= PROPOSAL_BIT;
+ }
+
+#ifdef STP_DBG
+ if (this->debug)
+ stp_trace ("port %s txRstp flags=0X%lx",
+ port->port_name,
+ (unsigned long) bpdu_packet.body.flags);
+#endif
+
+ return STP_OUT_tx_bpdu (port_index, vlan_id,
+ (unsigned char *) &bpdu_packet,
+ pkt_len);
+}
+
+void
+STP_transmit_enter_state (STATE_MACH_T* this)
+{
+ register PORT_T* port = this->owner.port;
+
+ switch (this->State) {
+ case BEGIN:
+ case TRANSMIT_INIT:
+ port->newInfo = False;
+ port->helloWhen = 0;
+ port->txCount = 0;
+ break;
+ case TRANSMIT_PERIODIC:
+ port->newInfo = port->newInfo ||
+ ((port->role == DesignatedPort) ||
+ ((port->role == RootPort) && port->tcWhile));
+ port->helloWhen = port->owner->rootTimes.HelloTime;
+ break;
+ case IDLE:
+ break;
+ case TRANSMIT_CONFIG:
+ port->newInfo = False;
+ (void) txConfig (this);
+ port->txCount++;
+ port->tcAck = False;
+ break;
+ case TRANSMIT_TCN:
+ port->newInfo = False;
+ (void) txTcn (this);
+ port->txCount++;
+ break;
+ case TRANSMIT_RSTP:
+ port->newInfo = False;
+ (void) txRstp (this);
+ port->txCount++;
+ port->tcAck = False;
+ break;
+ };
+}
+
+Bool
+STP_transmit_check_conditions (STATE_MACH_T* this)
+{
+ register PORT_T* port = this->owner.port;
+
+ switch (this->State) {
+ case BEGIN:
+ return STP_hop_2_state (this, TRANSMIT_INIT);
+ case TRANSMIT_INIT:
+ return STP_hop_2_state (this, IDLE);
+ case TRANSMIT_PERIODIC:
+ return STP_hop_2_state (this, IDLE);
+ case IDLE:
+ if (!port->helloWhen) return STP_hop_2_state (this, TRANSMIT_PERIODIC);
+ if (!port->sendRSTP && port->newInfo &&
+ (port->txCount < TxHoldCount) &&
+ (port->role == DesignatedPort) &&
+ port->helloWhen)
+ return STP_hop_2_state (this, TRANSMIT_CONFIG);
+ if (!port->sendRSTP && port->newInfo &&
+ (port->txCount < TxHoldCount) &&
+ (port->role == RootPort) &&
+ port->helloWhen)
+ return STP_hop_2_state (this, TRANSMIT_TCN);
+ if (port->sendRSTP && port->newInfo &&
+ (port->txCount < TxHoldCount) &&
+ ((port->role == RootPort) ||
+ (port->role == DesignatedPort)))
+ return STP_hop_2_state (this, TRANSMIT_RSTP);
+ break;
+ case TRANSMIT_CONFIG:
+ return STP_hop_2_state (this, IDLE);
+ case TRANSMIT_TCN:
+ return STP_hop_2_state (this, IDLE);
+ case TRANSMIT_RSTP:
+ return STP_hop_2_state (this, IDLE);
+ };
+ return False;
+}
diff --git a/usr/src/lib/librstp/common/transmit.h b/usr/src/lib/librstp/common/transmit.h
new file mode 100644
index 0000000000..620013ce5a
--- /dev/null
+++ b/usr/src/lib/librstp/common/transmit.h
@@ -0,0 +1,38 @@
+/************************************************************************
+ * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
+ * Copyright (C) 2001-2003 Optical Access
+ * Author: Alex Rozin
+ *
+ * This file is part of RSTP library.
+ *
+ * RSTP library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; version 2.1
+ *
+ * RSTP library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with RSTP library; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ **********************************************************************/
+
+/* Port Transmit state machine : 17.27 */
+
+#ifndef _STP_TRANSMIT_H__
+#define _STP_TRANSMIT_H__
+
+void
+STP_transmit_enter_state (STATE_MACH_T* s);
+
+Bool
+STP_transmit_check_conditions (STATE_MACH_T* s);
+
+char*
+STP_transmit_get_state_name (int state);
+
+#endif /* _STP_TRANSMIT_H__ */
+
diff --git a/usr/src/lib/librstp/common/uid_stp.h b/usr/src/lib/librstp/common/uid_stp.h
new file mode 100644
index 0000000000..a960081f59
--- /dev/null
+++ b/usr/src/lib/librstp/common/uid_stp.h
@@ -0,0 +1,202 @@
+/************************************************************************
+ * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
+ * Copyright (C) 2001-2003 Optical Access
+ * Author: Alex Rozin
+ *
+ * This file is part of RSTP library.
+ *
+ * RSTP library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; version 2.1
+ *
+ * RSTP library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with RSTP library; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ **********************************************************************/
+
+/* External management communication API definitions */
+
+#ifndef _UID_STP_H__
+#define _UID_STP_H__
+
+#define STP_DBG 1
+
+#define NAME_LEN 20
+
+typedef enum {
+ STP_DISABLED,
+ STP_ENABLED
+} UID_STP_MODE_T;
+
+typedef struct {
+ unsigned short prio;
+ unsigned char addr[6];
+} UID_BRIDGE_ID_T;
+
+typedef struct {
+ char vlan_name[NAME_LEN]; /* name of the VLAN, key of the bridge */
+ char action; /* 1-create, 0- delete */
+} UID_STP_BR_CTRL_T;
+
+#define BR_CFG_STATE (1L << 0)
+#define BR_CFG_PRIO (1L << 1)
+#define BR_CFG_AGE (1L << 2)
+#define BR_CFG_HELLO (1L << 3)
+#define BR_CFG_DELAY (1L << 4)
+#define BR_CFG_FORCE_VER (1L << 5)
+#define BR_CFG_AGE_MODE (1L << 6)
+#define BR_CFG_AGE_TIME (1L << 7)
+#define BR_CFG_HOLD_TIME (1L << 8)
+#define BR_CFG_ALL BR_CFG_STATE | \
+ BR_CFG_PRIO | \
+ BR_CFG_AGE | \
+ BR_CFG_HELLO | \
+ BR_CFG_DELAY | \
+ BR_CFG_FORCE_VER | \
+ BR_CFG_AGE_MODE | \
+ BR_CFG_AGE_TIME | \
+ BR_CFG_HOLD_TIME
+
+typedef struct {
+ /* service data */
+ unsigned long field_mask; /* which fields to change */
+ UID_STP_MODE_T stp_enabled;
+ char vlan_name[NAME_LEN]; /* name of the VLAN, key of the bridge */
+
+ /* protocol data */
+ int bridge_priority;
+ int max_age;
+ int hello_time;
+ int forward_delay;
+ int force_version;
+ int hold_time;
+} UID_STP_CFG_T;
+
+typedef struct {
+ /* service data */
+ char vlan_name[NAME_LEN]; /* name of the VLAN, key of the bridge */
+ unsigned long vlan_id;
+ UID_STP_MODE_T stp_enabled;
+
+ /* protocol data */
+ UID_BRIDGE_ID_T designated_root;
+ unsigned long root_path_cost;
+
+ unsigned long timeSince_Topo_Change; /* 14.8.1.1.3.b: TBD */
+ unsigned long Topo_Change_Count; /* 14.8.1.1.3.c: TBD */
+ unsigned char Topo_Change; /* 14.8.1.1.3.d: TBD */
+
+ unsigned short root_port;
+ int max_age;
+ int hello_time;
+ int forward_delay;
+ UID_BRIDGE_ID_T bridge_id;
+} UID_STP_STATE_T;
+
+typedef enum {
+ UID_PORT_DISABLED = 0,
+ UID_PORT_DISCARDING,
+ UID_PORT_LEARNING,
+ UID_PORT_FORWARDING,
+ UID_PORT_NON_STP,
+ UID_PORT_BADSDU
+} RSTP_PORT_STATE;
+
+typedef unsigned short UID_PORT_ID;
+
+typedef enum {
+ P2P_FORCE_TRUE,
+ P2P_FORCE_FALSE,
+ P2P_AUTO
+} ADMIN_P2P_T;
+
+#define PT_CFG_STATE (1L << 0)
+#define PT_CFG_COST (1L << 1)
+#define PT_CFG_PRIO (1L << 2)
+#define PT_CFG_P2P (1L << 3)
+#define PT_CFG_EDGE (1L << 4)
+#define PT_CFG_MCHECK (1L << 5)
+#define PT_CFG_NON_STP (1L << 6)
+#ifdef STP_DBG
+#define PT_CFG_DBG_SKIP_RX (1L << 16)
+#define PT_CFG_DBG_SKIP_TX (1L << 17)
+#endif
+
+#define PT_CFG_ALL PT_CFG_STATE | \
+ PT_CFG_COST | \
+ PT_CFG_PRIO | \
+ PT_CFG_P2P | \
+ PT_CFG_EDGE | \
+ PT_CFG_MCHECK | \
+ PT_CFG_NON_STP
+
+#define ADMIN_PORT_PATH_COST_AUTO 0
+
+typedef struct {
+ /* service data */
+ unsigned long field_mask; /* which fields to change */
+ char vlan_name[NAME_LEN]; /* name of the VLAN, key of the bridge */
+
+ /* protocol data */
+ int port_priority;
+ unsigned long admin_port_path_cost; /* ADMIN_PORT_PATH_COST_AUTO - auto sence */
+ ADMIN_P2P_T admin_point2point;
+ unsigned char admin_edge;
+ unsigned char admin_non_stp; /* 1- doesn't participate in STP, 1 - regular */
+#ifdef STP_DBG
+ unsigned int skip_rx;
+ unsigned int skip_tx;
+#endif
+
+} UID_STP_PORT_CFG_T;
+
+typedef struct {
+ /* service data */
+ char vlan_name[NAME_LEN]; /* name of the VLAN, key of the bridge */
+ unsigned int port_no; /* key of the entry */
+
+ /* protocol data */
+ UID_PORT_ID port_id;
+ RSTP_PORT_STATE state;
+ unsigned long path_cost;
+
+ UID_BRIDGE_ID_T designated_root;
+ unsigned long designated_cost;
+ UID_BRIDGE_ID_T designated_bridge;
+ UID_PORT_ID designated_port;
+
+#if 0
+ int infoIs;
+ unsigned short handshake_flags;
+#endif
+
+ unsigned long rx_cfg_bpdu_cnt;
+ unsigned long rx_rstp_bpdu_cnt;
+ unsigned long rx_tcn_bpdu_cnt;
+ int fdWhile; /* 17.15.1 */
+ int helloWhen; /* 17.15.2 */
+ int mdelayWhile; /* 17.15.3 */
+ int rbWhile; /* 17.15.4 */
+ int rcvdInfoWhile;/* 17.15.5 */
+ int rrWhile; /* 17.15.6 */
+ int tcWhile; /* 17.15.7 */
+ int txCount; /* 17.18.40 */
+ int lnkWhile;
+
+ unsigned long uptime; /* 14.8.2.1.3.a */
+ unsigned long oper_port_path_cost;
+ unsigned char role;
+ unsigned char oper_point2point;
+ unsigned char oper_edge;
+ unsigned char oper_stp_neigb;
+ unsigned char top_change_ack;
+ unsigned char tc;
+} UID_STP_PORT_STATE_T;
+
+#endif
diff --git a/usr/src/lib/librstp/common/vector.c b/usr/src/lib/librstp/common/vector.c
new file mode 100644
index 0000000000..a268b92319
--- /dev/null
+++ b/usr/src/lib/librstp/common/vector.c
@@ -0,0 +1,183 @@
+/************************************************************************
+ * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
+ * Copyright (C) 2001-2003 Optical Access
+ * Author: Alex Rozin
+ *
+ * This file is part of RSTP library.
+ *
+ * RSTP library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; version 2.1
+ *
+ * RSTP library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with RSTP library; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ **********************************************************************/
+
+/* STP priority vectors API : 17.4.2 */
+
+#include "base.h"
+#include "stp_bpdu.h"
+#include "vector.h"
+#include "stp_vectors.h"
+
+int
+STP_VECT_compare_bridge_id (BRIDGE_ID* b1, BRIDGE_ID* b2)
+{
+ if (b1->prio < b2->prio)
+ return -1;
+
+ if (b1->prio > b2->prio)
+ return 1;
+ return memcmp (b1->addr, b2->addr, 6);
+}
+
+void
+STP_VECT_copy (OUT PRIO_VECTOR_T* t, IN PRIO_VECTOR_T* f)
+{
+ (void) memcpy (t, f, sizeof (PRIO_VECTOR_T));
+}
+
+void
+STP_VECT_create (OUT PRIO_VECTOR_T* t,
+ IN BRIDGE_ID* root_br,
+ IN unsigned long root_path_cost,
+ IN BRIDGE_ID* design_bridge,
+ IN PORT_ID design_port,
+ IN PORT_ID bridge_port)
+{
+ (void) memcpy (&t->root_bridge, root_br, sizeof (BRIDGE_ID));
+ t->root_path_cost = root_path_cost;
+ (void) memcpy (&t->design_bridge, design_bridge, sizeof (BRIDGE_ID));
+ t->design_port = design_port;
+ t->bridge_port = bridge_port;
+}
+
+int
+STP_VECT_compare_vector (PRIO_VECTOR_T* v1, PRIO_VECTOR_T* v2)
+{
+ int bridcmp;
+
+ bridcmp = STP_VECT_compare_bridge_id (&v1->root_bridge, &v2->root_bridge);
+ if (bridcmp < 0) return bridcmp;
+
+ if (! bridcmp) {
+ bridcmp = v1->root_path_cost - v2->root_path_cost;
+ if (bridcmp < 0) return bridcmp;
+ if (! bridcmp) {
+ bridcmp = STP_VECT_compare_bridge_id (&v1->design_bridge, &v2->design_bridge);
+ if (bridcmp < 0) return bridcmp;
+ if (! bridcmp) {
+ bridcmp = v1->design_port - v2->design_port;
+ if (bridcmp < 0) return bridcmp;
+ if (! bridcmp)
+ return v1->bridge_port - v2->bridge_port;
+ }
+ }
+ }
+
+ return bridcmp;
+}
+
+static unsigned short
+stp_vect_get_short (IN unsigned char* f)
+{
+ /* LINTED: alignment */
+ return ntohs (*(unsigned short *)f);
+}
+
+static void
+stp_vect_set_short (IN unsigned short f, OUT unsigned char* t)
+{
+ /* LINTED: alignment */
+ *(unsigned short *)t = htons (f);
+}
+
+static void
+stp_vect_get_bridge_id (IN unsigned char* c_br, OUT BRIDGE_ID* bridge_id)
+{
+ bridge_id->prio = stp_vect_get_short (c_br);
+ (void) memcpy (bridge_id->addr, c_br + 2, 6);
+}
+
+static void
+stp_vect_set_bridge_id (IN BRIDGE_ID* bridge_id, OUT unsigned char* c_br)
+{
+ stp_vect_set_short (bridge_id->prio, c_br);
+ (void) memcpy (c_br + 2, bridge_id->addr, 6);
+}
+
+void
+STP_VECT_get_vector (IN BPDU_BODY_T* b, OUT PRIO_VECTOR_T* v)
+{
+ stp_vect_get_bridge_id (b->root_id, &v->root_bridge);
+
+ /* LINTED: alignment */
+ v->root_path_cost = ntohl (*((long*) b->root_path_cost));
+
+ stp_vect_get_bridge_id (b->bridge_id, &v->design_bridge);
+
+ v->design_port = stp_vect_get_short (b->port_id);
+}
+
+void
+STP_VECT_set_vector (IN PRIO_VECTOR_T* v, OUT BPDU_BODY_T* b)
+{
+ unsigned long root_path_cost;
+
+ stp_vect_set_bridge_id (&v->root_bridge, b->root_id);
+
+ root_path_cost = htonl (v->root_path_cost);
+ (void) memcpy (b->root_path_cost, &root_path_cost, 4);
+
+ stp_vect_set_bridge_id (&v->design_bridge, b->bridge_id);
+
+ stp_vect_set_short (v->design_port, b->port_id);
+}
+
+#ifdef STP_DBG
+
+/*ARGSUSED*/
+void
+STP_VECT_br_id_print (IN char *title, IN BRIDGE_ID* br_id, IN Bool cr)
+{
+ stp_trace ("%s=%04lX-%02x%02x%02x%02x%02x%02x",
+ title,
+ (unsigned long) br_id->prio,
+ (unsigned char) br_id->addr[0],
+ (unsigned char) br_id->addr[1],
+ (unsigned char) br_id->addr[2],
+ (unsigned char) br_id->addr[3],
+ (unsigned char) br_id->addr[4],
+ (unsigned char) br_id->addr[5]);
+#ifndef __SUN__
+ stp_trace (cr ? "\n" : " ");
+#endif
+}
+
+void
+STP_VECT_print (IN char *title, IN PRIO_VECTOR_T *v)
+{
+ stp_trace ("%s:", title);
+ STP_VECT_br_id_print ("rootBr", &v->root_bridge, False);
+
+/****
+ stp_trace (" rpc=%ld ", (long) v->root_path_cost);
+****/
+
+ STP_VECT_br_id_print ("designBr", &v->design_bridge, False);
+
+/****/
+ stp_trace (" dp=%lx bp=%lx ",
+ (unsigned long) v->design_port,
+ (unsigned long) v->bridge_port);
+/***********/
+ stp_trace ("\n");
+}
+#endif
diff --git a/usr/src/lib/librstp/common/vector.h b/usr/src/lib/librstp/common/vector.h
new file mode 100644
index 0000000000..917d4a64c7
--- /dev/null
+++ b/usr/src/lib/librstp/common/vector.h
@@ -0,0 +1,79 @@
+/************************************************************************
+ * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
+ * Copyright (C) 2001-2003 Optical Access
+ * Author: Alex Rozin
+ *
+ * This file is part of RSTP library.
+ *
+ * RSTP library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; version 2.1
+ *
+ * RSTP library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with RSTP library; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ **********************************************************************/
+
+/* STP priority vectors API : 17.4.2 */
+
+#ifndef _PRIO_VECTOR_H__
+#define _PRIO_VECTOR_H__
+
+#define STP_DBG 1
+
+typedef struct bridge_id
+{
+ unsigned short prio;
+ unsigned char addr[6];
+} BRIDGE_ID;
+
+typedef unsigned short PORT_ID;
+
+typedef struct prio_vector_t {
+ BRIDGE_ID root_bridge;
+ unsigned long root_path_cost;
+ BRIDGE_ID design_bridge;
+ PORT_ID design_port;
+ PORT_ID bridge_port;
+} PRIO_VECTOR_T;
+
+void
+STP_VECT_create (OUT PRIO_VECTOR_T* t,
+ IN BRIDGE_ID* root_br,
+ IN unsigned long root_path_cost,
+ IN BRIDGE_ID* design_bridge,
+ IN PORT_ID design_port,
+ IN PORT_ID bridge_port);
+void
+STP_VECT_copy (OUT PRIO_VECTOR_T* t, IN PRIO_VECTOR_T* f);
+
+int
+STP_VECT_compare_bridge_id (IN BRIDGE_ID* b1, IN BRIDGE_ID* b2);
+
+int
+STP_VECT_compare_vector (IN PRIO_VECTOR_T* v1, IN PRIO_VECTOR_T* v2);
+
+void
+STP_VECT_get_vector (IN BPDU_BODY_T* b, OUT PRIO_VECTOR_T* v);
+
+void
+STP_VECT_set_vector (IN PRIO_VECTOR_T* v, OUT BPDU_BODY_T* b);
+
+#ifdef STP_DBG
+void
+STP_VECT_print (IN char* title, IN PRIO_VECTOR_T* v);
+
+void
+STP_VECT_br_id_print (IN char *title, IN BRIDGE_ID* br_id, IN Bool cr);
+
+#endif
+
+#endif /* _PRIO_VECTOR_H__ */
+
+
diff --git a/usr/src/lib/librstp/i386/Makefile b/usr/src/lib/librstp/i386/Makefile
new file mode 100644
index 0000000000..946d8867f9
--- /dev/null
+++ b/usr/src/lib/librstp/i386/Makefile
@@ -0,0 +1,29 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# lib/librstp/i386/Makefile
+
+include ../Makefile.com
+
+install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
diff --git a/usr/src/lib/librstp/sparc/Makefile b/usr/src/lib/librstp/sparc/Makefile
new file mode 100644
index 0000000000..07093c0afe
--- /dev/null
+++ b/usr/src/lib/librstp/sparc/Makefile
@@ -0,0 +1,29 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# lib/librstp/sparc/Makefile
+
+include ../Makefile.com
+
+install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)