1*55fea89dSDan Cross /************************************************************************
2*55fea89dSDan Cross * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
3*55fea89dSDan Cross * Copyright (C) 2001-2003 Optical Access
4*55fea89dSDan Cross * Author: Alex Rozin
5*55fea89dSDan Cross *
6*55fea89dSDan Cross * This file is part of RSTP library.
7*55fea89dSDan Cross *
8*55fea89dSDan Cross * RSTP library is free software; you can redistribute it and/or modify it
9*55fea89dSDan Cross * under the terms of the GNU Lesser General Public License as published by the
10*55fea89dSDan Cross * Free Software Foundation; version 2.1
11*55fea89dSDan Cross *
12*55fea89dSDan Cross * RSTP library is distributed in the hope that it will be useful, but
13*55fea89dSDan Cross * WITHOUT ANY WARRANTY; without even the implied warranty of
14*55fea89dSDan Cross * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
15*55fea89dSDan Cross * General Public License for more details.
16*55fea89dSDan Cross *
17*55fea89dSDan Cross * You should have received a copy of the GNU Lesser General Public License
18*55fea89dSDan Cross * along with RSTP library; see the file COPYING. If not, write to the Free
19*55fea89dSDan Cross * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20*55fea89dSDan Cross * 02111-1307, USA.
214eaa4710SRishi Srivatsavai **********************************************************************/
224eaa4710SRishi Srivatsavai
234eaa4710SRishi Srivatsavai #include "base.h"
244eaa4710SRishi Srivatsavai #include "stpm.h"
254eaa4710SRishi Srivatsavai #include "stp_vectors.h"
264eaa4710SRishi Srivatsavai
274eaa4710SRishi Srivatsavai /* The Port Information State Machine : 17.21 */
284eaa4710SRishi Srivatsavai
294eaa4710SRishi Srivatsavai #define STATES { \
304eaa4710SRishi Srivatsavai CHOOSE(DISABLED), \
314eaa4710SRishi Srivatsavai CHOOSE(ENABLED), \
324eaa4710SRishi Srivatsavai CHOOSE(AGED), \
334eaa4710SRishi Srivatsavai CHOOSE(UPDATE), \
344eaa4710SRishi Srivatsavai CHOOSE(CURRENT), \
354eaa4710SRishi Srivatsavai CHOOSE(RECEIVE), \
364eaa4710SRishi Srivatsavai CHOOSE(SUPERIOR), \
374eaa4710SRishi Srivatsavai CHOOSE(REPEAT), \
384eaa4710SRishi Srivatsavai CHOOSE(AGREEMENT) \
394eaa4710SRishi Srivatsavai }
404eaa4710SRishi Srivatsavai
414eaa4710SRishi Srivatsavai #define GET_STATE_NAME STP_info_get_state_name
424eaa4710SRishi Srivatsavai #include "choose.h"
434eaa4710SRishi Srivatsavai
444eaa4710SRishi Srivatsavai #if 0 /* for debug */
454eaa4710SRishi Srivatsavai void
464eaa4710SRishi Srivatsavai _stp_dump (char* title, unsigned char* buff, int len)
474eaa4710SRishi Srivatsavai {
484eaa4710SRishi Srivatsavai register int iii;
494eaa4710SRishi Srivatsavai
504eaa4710SRishi Srivatsavai stp_trace ("\n%s:", title);
514eaa4710SRishi Srivatsavai for (iii = 0; iii < len; iii++) {
524eaa4710SRishi Srivatsavai if (! (iii % 24)) stp_trace ("\n%6d:", iii);
534eaa4710SRishi Srivatsavai if (! (iii % 8)) stp_trace (" ");
544eaa4710SRishi Srivatsavai stp_trace ("%02lx", (unsigned long) buff[iii]);
554eaa4710SRishi Srivatsavai }
564eaa4710SRishi Srivatsavai stp_trace ("\n");
574eaa4710SRishi Srivatsavai }
584eaa4710SRishi Srivatsavai #endif
594eaa4710SRishi Srivatsavai
604eaa4710SRishi Srivatsavai static RCVD_MSG_T
rcvBpdu(STATE_MACH_T * this)614eaa4710SRishi Srivatsavai rcvBpdu (STATE_MACH_T* this)
624eaa4710SRishi Srivatsavai {/* 17.19.8 */
634eaa4710SRishi Srivatsavai int bridcmp;
644eaa4710SRishi Srivatsavai register PORT_T* port = this->owner.port;
654eaa4710SRishi Srivatsavai
664eaa4710SRishi Srivatsavai if (port->msgBpduType == BPDU_TOPO_CHANGE_TYPE) {
674eaa4710SRishi Srivatsavai #ifdef STP_DBG
684eaa4710SRishi Srivatsavai if (this->debug) {
694eaa4710SRishi Srivatsavai stp_trace ("%s", "rcvBpdu: OtherMsg:BPDU_TOPO_CHANGE_TYPE");
704eaa4710SRishi Srivatsavai }
714eaa4710SRishi Srivatsavai #endif
724eaa4710SRishi Srivatsavai return OtherMsg;
734eaa4710SRishi Srivatsavai }
744eaa4710SRishi Srivatsavai
754eaa4710SRishi Srivatsavai port->msgPortRole = RSTP_PORT_ROLE_UNKN;
764eaa4710SRishi Srivatsavai
774eaa4710SRishi Srivatsavai if (BPDU_RSTP == port->msgBpduType) {
784eaa4710SRishi Srivatsavai port->msgPortRole = (port->msgFlags & PORT_ROLE_MASK) >> PORT_ROLE_OFFS;
794eaa4710SRishi Srivatsavai }
804eaa4710SRishi Srivatsavai
814eaa4710SRishi Srivatsavai if (RSTP_PORT_ROLE_DESGN == port->msgPortRole ||
824eaa4710SRishi Srivatsavai BPDU_CONFIG_TYPE == port->msgBpduType) {
834eaa4710SRishi Srivatsavai bridcmp = STP_VECT_compare_vector (&port->msgPrio, &port->portPrio);
844eaa4710SRishi Srivatsavai
854eaa4710SRishi Srivatsavai if (bridcmp < 0 ||
864eaa4710SRishi Srivatsavai (! STP_VECT_compare_bridge_id (&port->msgPrio.design_bridge,
874eaa4710SRishi Srivatsavai &port->portPrio.design_bridge) &&
884eaa4710SRishi Srivatsavai port->msgPrio.design_port == port->portPrio.design_port &&
894eaa4710SRishi Srivatsavai STP_compare_times (&port->msgTimes, &port->portTimes))) {
904eaa4710SRishi Srivatsavai #ifdef STP_DBG
914eaa4710SRishi Srivatsavai if (this->debug) {
924eaa4710SRishi Srivatsavai stp_trace ("rcvBpdu: SuperiorDesignateMsg:bridcmp=%d", (int) bridcmp);
934eaa4710SRishi Srivatsavai }
944eaa4710SRishi Srivatsavai #endif
954eaa4710SRishi Srivatsavai return SuperiorDesignateMsg;
964eaa4710SRishi Srivatsavai }
974eaa4710SRishi Srivatsavai }
984eaa4710SRishi Srivatsavai
994eaa4710SRishi Srivatsavai if (BPDU_CONFIG_TYPE == port->msgBpduType ||
1004eaa4710SRishi Srivatsavai RSTP_PORT_ROLE_DESGN == port->msgPortRole) {
1014eaa4710SRishi Srivatsavai if (! STP_VECT_compare_vector (&port->msgPrio,
1024eaa4710SRishi Srivatsavai &port->portPrio) &&
1034eaa4710SRishi Srivatsavai ! STP_compare_times (&port->msgTimes, &port->portTimes)) {
1044eaa4710SRishi Srivatsavai #ifdef STP_DBG
1054eaa4710SRishi Srivatsavai if (this->debug) {
1064eaa4710SRishi Srivatsavai stp_trace ("%s", "rcvBpdu: RepeatedDesignateMsg");
1074eaa4710SRishi Srivatsavai }
1084eaa4710SRishi Srivatsavai #endif
1094eaa4710SRishi Srivatsavai return RepeatedDesignateMsg;
1104eaa4710SRishi Srivatsavai }
1114eaa4710SRishi Srivatsavai }
1124eaa4710SRishi Srivatsavai
1134eaa4710SRishi Srivatsavai if (RSTP_PORT_ROLE_ROOT == port->msgBpduType &&
1144eaa4710SRishi Srivatsavai port->operPointToPointMac &&
1154eaa4710SRishi Srivatsavai ! STP_VECT_compare_bridge_id (&port->msgPrio.design_bridge,
1164eaa4710SRishi Srivatsavai &port->portPrio.design_bridge) &&
1174eaa4710SRishi Srivatsavai AGREEMENT_BIT & port->msgFlags) {
1184eaa4710SRishi Srivatsavai #ifdef STP_DBG
1194eaa4710SRishi Srivatsavai if (this->debug) {
1204eaa4710SRishi Srivatsavai stp_trace ("%s", "rcvBpdu: ConfirmedRootMsg");
1214eaa4710SRishi Srivatsavai }
1224eaa4710SRishi Srivatsavai #endif
1234eaa4710SRishi Srivatsavai return ConfirmedRootMsg;
1244eaa4710SRishi Srivatsavai }
1254eaa4710SRishi Srivatsavai
1264eaa4710SRishi Srivatsavai #ifdef STP_DBG
1274eaa4710SRishi Srivatsavai if (this->debug) {
1284eaa4710SRishi Srivatsavai if (RSTP_PORT_ROLE_ROOT == port->msgBpduType) {
1294eaa4710SRishi Srivatsavai if (!port->operPointToPointMac) {
1304eaa4710SRishi Srivatsavai stp_trace("rcvBpdu: OtherMsg: not point-to-point MAC");
1314eaa4710SRishi Srivatsavai } else if (STP_VECT_compare_bridge_id (&port->msgPrio.design_bridge,
1324eaa4710SRishi Srivatsavai &port->portPrio.design_bridge)) {
1334eaa4710SRishi Srivatsavai STP_VECT_br_id_print("rcvBpdu: OtherMsg: msgPrio", &port->msgPrio.design_bridge, True);
1344eaa4710SRishi Srivatsavai STP_VECT_br_id_print("rcvBpdu: portPrio", &port->portPrio.design_bridge, True);
1354eaa4710SRishi Srivatsavai } else {
1364eaa4710SRishi Srivatsavai stp_trace("rcvBpdu: OtherMsg: agreement bit not set");
1374eaa4710SRishi Srivatsavai }
1384eaa4710SRishi Srivatsavai } else {
1394eaa4710SRishi Srivatsavai stp_trace ("rcvBpdu: OtherMsg: type %d", port->msgBpduType);
1404eaa4710SRishi Srivatsavai }
1414eaa4710SRishi Srivatsavai }
1424eaa4710SRishi Srivatsavai #endif
1434eaa4710SRishi Srivatsavai return OtherMsg;
1444eaa4710SRishi Srivatsavai }
1454eaa4710SRishi Srivatsavai
1464eaa4710SRishi Srivatsavai /* ARGSUSED */
1474eaa4710SRishi Srivatsavai static Bool
recordProposed(STATE_MACH_T * this,char * reason)1484eaa4710SRishi Srivatsavai recordProposed (STATE_MACH_T* this, char* reason)
1494eaa4710SRishi Srivatsavai {/* 17.19.9 */
1504eaa4710SRishi Srivatsavai register PORT_T* port = this->owner.port;
1514eaa4710SRishi Srivatsavai
1524eaa4710SRishi Srivatsavai if (RSTP_PORT_ROLE_DESGN == port->msgPortRole &&
1534eaa4710SRishi Srivatsavai (PROPOSAL_BIT & port->msgFlags) &&
1544eaa4710SRishi Srivatsavai port->operPointToPointMac) {
1554eaa4710SRishi Srivatsavai return True;
1564eaa4710SRishi Srivatsavai }
1574eaa4710SRishi Srivatsavai return False;
1584eaa4710SRishi Srivatsavai }
1594eaa4710SRishi Srivatsavai
1604eaa4710SRishi Srivatsavai static void
setTcFlags(STATE_MACH_T * this)1614eaa4710SRishi Srivatsavai setTcFlags (STATE_MACH_T* this)
1624eaa4710SRishi Srivatsavai {/* 17.19.13 */
1634eaa4710SRishi Srivatsavai register PORT_T* port = this->owner.port;
1644eaa4710SRishi Srivatsavai
1654eaa4710SRishi Srivatsavai if (BPDU_TOPO_CHANGE_TYPE == port->msgBpduType) {
1664eaa4710SRishi Srivatsavai #ifdef STP_DBG
1674eaa4710SRishi Srivatsavai if (this->debug) {
1684eaa4710SRishi Srivatsavai stp_trace ("port %s rx rcvdTcn", port->port_name);
1694eaa4710SRishi Srivatsavai }
1704eaa4710SRishi Srivatsavai #endif
1714eaa4710SRishi Srivatsavai port->rcvdTcn = True;
1724eaa4710SRishi Srivatsavai } else {
1734eaa4710SRishi Srivatsavai if (TOPOLOGY_CHANGE_BIT & port->msgFlags) {
1744eaa4710SRishi Srivatsavai #ifdef STP_DBG
1754eaa4710SRishi Srivatsavai if (this->debug) {
1764eaa4710SRishi Srivatsavai stp_trace ("(%s-%s) rx rcvdTc 0X%lx",
1774eaa4710SRishi Srivatsavai port->owner->name, port->port_name,
1784eaa4710SRishi Srivatsavai (unsigned long) port->msgFlags);
1794eaa4710SRishi Srivatsavai }
1804eaa4710SRishi Srivatsavai #endif
1814eaa4710SRishi Srivatsavai port->rcvdTc = True;
1824eaa4710SRishi Srivatsavai }
1834eaa4710SRishi Srivatsavai if (TOPOLOGY_CHANGE_ACK_BIT & port->msgFlags) {
1844eaa4710SRishi Srivatsavai #ifdef STP_DBG
1854eaa4710SRishi Srivatsavai if (this->debug) {
1864eaa4710SRishi Srivatsavai stp_trace ("port %s rx rcvdTcAck 0X%lx",
1874eaa4710SRishi Srivatsavai port->port_name,
1884eaa4710SRishi Srivatsavai (unsigned long) port->msgFlags);
1894eaa4710SRishi Srivatsavai }
1904eaa4710SRishi Srivatsavai #endif
1914eaa4710SRishi Srivatsavai port->rcvdTcAck = True;
1924eaa4710SRishi Srivatsavai }
1934eaa4710SRishi Srivatsavai }
1944eaa4710SRishi Srivatsavai }
1954eaa4710SRishi Srivatsavai
1964eaa4710SRishi Srivatsavai static void
updtBPDUVersion(STATE_MACH_T * this)1974eaa4710SRishi Srivatsavai updtBPDUVersion (STATE_MACH_T* this)
1984eaa4710SRishi Srivatsavai {/* 17.19.18 */
1994eaa4710SRishi Srivatsavai register PORT_T* port = this->owner.port;
2004eaa4710SRishi Srivatsavai
2014eaa4710SRishi Srivatsavai if (BPDU_TOPO_CHANGE_TYPE == port->msgBpduType) {
2024eaa4710SRishi Srivatsavai port->rcvdSTP = True;
2034eaa4710SRishi Srivatsavai }
2044eaa4710SRishi Srivatsavai
2054eaa4710SRishi Srivatsavai if (port->msgBpduVersion < 2) {
2064eaa4710SRishi Srivatsavai port->rcvdSTP = True;
2074eaa4710SRishi Srivatsavai }
208*55fea89dSDan Cross
2094eaa4710SRishi Srivatsavai if (BPDU_RSTP == port->msgBpduType) {
2104eaa4710SRishi Srivatsavai /* port->port->owner->ForceVersion >= NORMAL_RSTP
2114eaa4710SRishi Srivatsavai we have checked in STP_info_rx_bpdu */
2124eaa4710SRishi Srivatsavai port->rcvdRSTP = True;
2134eaa4710SRishi Srivatsavai }
2144eaa4710SRishi Srivatsavai }
2154eaa4710SRishi Srivatsavai
2164eaa4710SRishi Srivatsavai static void
updtRcvdInfoWhile(STATE_MACH_T * this)2174eaa4710SRishi Srivatsavai updtRcvdInfoWhile (STATE_MACH_T* this)
2184eaa4710SRishi Srivatsavai {/* 17.19.19 */
2194eaa4710SRishi Srivatsavai register int eff_age, dm, dt;
2204eaa4710SRishi Srivatsavai register int hello3;
2214eaa4710SRishi Srivatsavai register PORT_T* port = this->owner.port;
222*55fea89dSDan Cross
2234eaa4710SRishi Srivatsavai eff_age = ( + port->portTimes.MaxAge) / 16;
2244eaa4710SRishi Srivatsavai if (eff_age < 1) eff_age = 1;
2254eaa4710SRishi Srivatsavai eff_age += port->portTimes.MessageAge;
2264eaa4710SRishi Srivatsavai
2274eaa4710SRishi Srivatsavai if (eff_age <= port->portTimes.MaxAge) {
2284eaa4710SRishi Srivatsavai hello3 = 3 * port->portTimes.HelloTime;
2294eaa4710SRishi Srivatsavai dm = port->portTimes.MaxAge - eff_age;
2304eaa4710SRishi Srivatsavai if (dm > hello3)
2314eaa4710SRishi Srivatsavai dt = hello3;
2324eaa4710SRishi Srivatsavai else
2334eaa4710SRishi Srivatsavai dt = dm;
2344eaa4710SRishi Srivatsavai port->rcvdInfoWhile = dt;
2354eaa4710SRishi Srivatsavai /****
2364eaa4710SRishi Srivatsavai stp_trace ("ma=%d eff_age=%d dm=%d dt=%d p=%s",
2374eaa4710SRishi Srivatsavai (int) port->portTimes.MessageAge,
2384eaa4710SRishi Srivatsavai (int) eff_age, (int) dm, (int) dt, port->port_name);
2394eaa4710SRishi Srivatsavai ****/
2404eaa4710SRishi Srivatsavai } else {
2414eaa4710SRishi Srivatsavai port->rcvdInfoWhile = 0;
2424eaa4710SRishi Srivatsavai /****/
2434eaa4710SRishi Srivatsavai #ifdef STP_DBG
2444eaa4710SRishi Srivatsavai /*if (this->debug) */
2454eaa4710SRishi Srivatsavai {
2464eaa4710SRishi Srivatsavai stp_trace ("port %s: MaxAge=%d MessageAge=%d HelloTime=%d rcvdInfoWhile=null !",
2474eaa4710SRishi Srivatsavai port->port_name,
2484eaa4710SRishi Srivatsavai (int) port->portTimes.MaxAge,
2494eaa4710SRishi Srivatsavai (int) port->portTimes.MessageAge,
2504eaa4710SRishi Srivatsavai (int) port->portTimes.HelloTime);
2514eaa4710SRishi Srivatsavai }
2524eaa4710SRishi Srivatsavai #endif
2534eaa4710SRishi Srivatsavai /****/
2544eaa4710SRishi Srivatsavai }
2554eaa4710SRishi Srivatsavai }
2564eaa4710SRishi Srivatsavai
2574eaa4710SRishi Srivatsavai
2584eaa4710SRishi Srivatsavai /* ARGSUSED */
2594eaa4710SRishi Srivatsavai void
STP_info_rx_bpdu(PORT_T * port,struct stp_bpdu_t * bpdu,size_t len)2604eaa4710SRishi Srivatsavai STP_info_rx_bpdu (PORT_T* port, struct stp_bpdu_t* bpdu, size_t len)
261*55fea89dSDan Cross {
2624eaa4710SRishi Srivatsavai #if 0
2634eaa4710SRishi Srivatsavai _stp_dump ("\nall BPDU", ((unsigned char*) bpdu) - 12, len + 12);
2644eaa4710SRishi Srivatsavai _stp_dump ("ETH_HEADER", (unsigned char*) &bpdu->eth, 5);
2654eaa4710SRishi Srivatsavai _stp_dump ("BPDU_HEADER", (unsigned char*) &bpdu->hdr, 4);
2664eaa4710SRishi Srivatsavai stp_trace ("protocol=%02x%02x version=%02x bpdu_type=%02x\n",
2674eaa4710SRishi Srivatsavai bpdu->hdr.protocol[0], bpdu->hdr.protocol[1],
2684eaa4710SRishi Srivatsavai bpdu->hdr.version, bpdu->hdr.bpdu_type);
2694eaa4710SRishi Srivatsavai
2704eaa4710SRishi Srivatsavai _stp_dump ("\nBPDU_BODY", (unsigned char*) &bpdu->body, sizeof (BPDU_BODY_T) + 2);
2714eaa4710SRishi Srivatsavai stp_trace ("flags=%02x\n", bpdu->body.flags);
2724eaa4710SRishi Srivatsavai _stp_dump ("root_id", bpdu->body.root_id, 8);
2734eaa4710SRishi Srivatsavai _stp_dump ("root_path_cost", bpdu->body.root_path_cost, 4);
2744eaa4710SRishi Srivatsavai _stp_dump ("bridge_id", bpdu->body.bridge_id, 8);
2754eaa4710SRishi Srivatsavai _stp_dump ("port_id", bpdu->body.port_id, 2);
2764eaa4710SRishi Srivatsavai _stp_dump ("message_age", bpdu->body.message_age, 2);
2774eaa4710SRishi Srivatsavai _stp_dump ("max_age", bpdu->body.max_age, 2);
2784eaa4710SRishi Srivatsavai _stp_dump ("hello_time", bpdu->body.hello_time, 2);
2794eaa4710SRishi Srivatsavai _stp_dump ("forward_delay", bpdu->body.forward_delay, 2);
2804eaa4710SRishi Srivatsavai _stp_dump ("ver_1_len", bpdu->ver_1_len, 2);
2814eaa4710SRishi Srivatsavai #endif
282*55fea89dSDan Cross
2834eaa4710SRishi Srivatsavai /* check bpdu type */
2844eaa4710SRishi Srivatsavai switch (bpdu->hdr.bpdu_type) {
2854eaa4710SRishi Srivatsavai case BPDU_CONFIG_TYPE:
2864eaa4710SRishi Srivatsavai port->rx_cfg_bpdu_cnt++;
2874eaa4710SRishi Srivatsavai #ifdef STP_DBG
288*55fea89dSDan Cross if (port->info->debug)
2894eaa4710SRishi Srivatsavai stp_trace ("CfgBpdu on port %s", port->port_name);
2904eaa4710SRishi Srivatsavai #endif
2914eaa4710SRishi Srivatsavai if (port->admin_non_stp) return;
2924eaa4710SRishi Srivatsavai port->rcvdBpdu = True;
2934eaa4710SRishi Srivatsavai break;
2944eaa4710SRishi Srivatsavai case BPDU_TOPO_CHANGE_TYPE:
2954eaa4710SRishi Srivatsavai port->rx_tcn_bpdu_cnt++;
2964eaa4710SRishi Srivatsavai #ifdef STP_DBG
2974eaa4710SRishi Srivatsavai if (port->info->debug)
2984eaa4710SRishi Srivatsavai stp_trace ("TcnBpdu on port %s", port->port_name);
2994eaa4710SRishi Srivatsavai #endif
3004eaa4710SRishi Srivatsavai if (port->admin_non_stp) return;
3014eaa4710SRishi Srivatsavai port->rcvdBpdu = True;
3024eaa4710SRishi Srivatsavai port->msgBpduVersion = bpdu->hdr.version;
3034eaa4710SRishi Srivatsavai port->msgBpduType = bpdu->hdr.bpdu_type;
3044eaa4710SRishi Srivatsavai return;
3054eaa4710SRishi Srivatsavai default:
3064eaa4710SRishi Srivatsavai stp_trace ("RX undef bpdu type=%d", (int) bpdu->hdr.bpdu_type);
3074eaa4710SRishi Srivatsavai return;
3084eaa4710SRishi Srivatsavai case BPDU_RSTP:
3094eaa4710SRishi Srivatsavai port->rx_rstp_bpdu_cnt++;
3104eaa4710SRishi Srivatsavai if (port->admin_non_stp) return;
3114eaa4710SRishi Srivatsavai if (port->owner->ForceVersion >= NORMAL_RSTP) {
3124eaa4710SRishi Srivatsavai port->rcvdBpdu = True;
313*55fea89dSDan Cross } else {
3144eaa4710SRishi Srivatsavai return;
3154eaa4710SRishi Srivatsavai }
3164eaa4710SRishi Srivatsavai #ifdef STP_DBG
3174eaa4710SRishi Srivatsavai if (port->info->debug)
3184eaa4710SRishi Srivatsavai stp_trace ("BPDU_RSTP on port %s", port->port_name);
3194eaa4710SRishi Srivatsavai #endif
3204eaa4710SRishi Srivatsavai break;
3214eaa4710SRishi Srivatsavai }
3224eaa4710SRishi Srivatsavai
3234eaa4710SRishi Srivatsavai port->msgBpduVersion = bpdu->hdr.version;
3244eaa4710SRishi Srivatsavai port->msgBpduType = bpdu->hdr.bpdu_type;
3254eaa4710SRishi Srivatsavai port->msgFlags = bpdu->body.flags;
3264eaa4710SRishi Srivatsavai
3274eaa4710SRishi Srivatsavai /* 17.18.11 */
3284eaa4710SRishi Srivatsavai STP_VECT_get_vector (&bpdu->body, &port->msgPrio);
3294eaa4710SRishi Srivatsavai port->msgPrio.bridge_port = port->port_id;
3304eaa4710SRishi Srivatsavai
3314eaa4710SRishi Srivatsavai /* 17.18.12 */
3324eaa4710SRishi Srivatsavai STP_get_times (&bpdu->body, &port->msgTimes);
3334eaa4710SRishi Srivatsavai
3344eaa4710SRishi Srivatsavai /* 17.18.25, 17.18.26 : see setTcFlags() */
3354eaa4710SRishi Srivatsavai }
3364eaa4710SRishi Srivatsavai
STP_info_enter_state(STATE_MACH_T * this)3374eaa4710SRishi Srivatsavai void STP_info_enter_state (STATE_MACH_T* this)
3384eaa4710SRishi Srivatsavai {
3394eaa4710SRishi Srivatsavai register PORT_T* port = this->owner.port;
3404eaa4710SRishi Srivatsavai
3414eaa4710SRishi Srivatsavai switch (this->State) {
3424eaa4710SRishi Srivatsavai case BEGIN:
3434eaa4710SRishi Srivatsavai port->rcvdMsg = OtherMsg;
3444eaa4710SRishi Srivatsavai port->msgBpduType = (unsigned char)-1;
3454eaa4710SRishi Srivatsavai port->msgPortRole = RSTP_PORT_ROLE_UNKN;
3464eaa4710SRishi Srivatsavai port->msgFlags = 0;
3474eaa4710SRishi Srivatsavai
3484eaa4710SRishi Srivatsavai /* clear port statistics */
3494eaa4710SRishi Srivatsavai port->rx_cfg_bpdu_cnt =
3504eaa4710SRishi Srivatsavai port->rx_rstp_bpdu_cnt =
3514eaa4710SRishi Srivatsavai port->rx_tcn_bpdu_cnt = 0;
3524eaa4710SRishi Srivatsavai /* FALLTHRU */
3534eaa4710SRishi Srivatsavai case DISABLED:
3544eaa4710SRishi Srivatsavai port->rcvdBpdu = port->rcvdRSTP = port->rcvdSTP = False;
3554eaa4710SRishi Srivatsavai port->updtInfo = port->proposing = False; /* In DISABLED */
3564eaa4710SRishi Srivatsavai port->agreed = port->proposed = False;
3574eaa4710SRishi Srivatsavai port->rcvdInfoWhile = 0;
3584eaa4710SRishi Srivatsavai port->infoIs = Disabled;
3594eaa4710SRishi Srivatsavai port->reselect = True;
3604eaa4710SRishi Srivatsavai port->selected = False;
3614eaa4710SRishi Srivatsavai break;
3624eaa4710SRishi Srivatsavai case ENABLED: /* IEEE 802.1y, 17.21, Z.14 */
3634eaa4710SRishi Srivatsavai STP_VECT_copy (&port->portPrio, &port->designPrio);
3644eaa4710SRishi Srivatsavai STP_copy_times (&port->portTimes, &port->designTimes);
3654eaa4710SRishi Srivatsavai break;
3664eaa4710SRishi Srivatsavai case AGED:
3674eaa4710SRishi Srivatsavai port->infoIs = Aged;
3684eaa4710SRishi Srivatsavai port->reselect = True;
3694eaa4710SRishi Srivatsavai port->selected = False;
3704eaa4710SRishi Srivatsavai break;
3714eaa4710SRishi Srivatsavai case UPDATE:
3724eaa4710SRishi Srivatsavai STP_VECT_copy (&port->portPrio, &port->designPrio);
3734eaa4710SRishi Srivatsavai STP_copy_times (&port->portTimes, &port->designTimes);
3744eaa4710SRishi Srivatsavai port->updtInfo = False;
3754eaa4710SRishi Srivatsavai port->agreed = port->synced = False; /* In UPDATE */
3764eaa4710SRishi Srivatsavai port->proposed = port->proposing = False; /* in UPDATE */
3774eaa4710SRishi Srivatsavai port->infoIs = Mine;
3784eaa4710SRishi Srivatsavai port->newInfo = True;
3794eaa4710SRishi Srivatsavai #ifdef STP_DBG
3804eaa4710SRishi Srivatsavai if (this->debug) {
3814eaa4710SRishi Srivatsavai STP_VECT_br_id_print ("updated: portPrio.design_bridge",
3824eaa4710SRishi Srivatsavai &port->portPrio.design_bridge, True);
3834eaa4710SRishi Srivatsavai STP_VECT_br_id_print ("updated: portPrio.root_bridge",
3844eaa4710SRishi Srivatsavai &port->portPrio.root_bridge, True);
3854eaa4710SRishi Srivatsavai }
3864eaa4710SRishi Srivatsavai #endif
3874eaa4710SRishi Srivatsavai break;
3884eaa4710SRishi Srivatsavai case CURRENT:
3894eaa4710SRishi Srivatsavai break;
3904eaa4710SRishi Srivatsavai case RECEIVE:
3914eaa4710SRishi Srivatsavai port->rcvdMsg = rcvBpdu (this);
3924eaa4710SRishi Srivatsavai updtBPDUVersion (this);
3934eaa4710SRishi Srivatsavai setTcFlags (this);
3944eaa4710SRishi Srivatsavai port->rcvdBpdu = False;
3954eaa4710SRishi Srivatsavai break;
3964eaa4710SRishi Srivatsavai case SUPERIOR:
3974eaa4710SRishi Srivatsavai STP_VECT_copy (&port->portPrio, &port->msgPrio);
3984eaa4710SRishi Srivatsavai STP_copy_times (&port->portTimes, &port->msgTimes);
3994eaa4710SRishi Srivatsavai updtRcvdInfoWhile (this);
4004eaa4710SRishi Srivatsavai #if 1 /* due 802.1y, Z.7 */
4014eaa4710SRishi Srivatsavai port->agreed = False; /* deleted due 802.y in SUPERIOR */
4024eaa4710SRishi Srivatsavai port->synced = False; /* due 802.y deleted in SUPERIOR */
4034eaa4710SRishi Srivatsavai #endif
4044eaa4710SRishi Srivatsavai port->proposing = False; /* in SUPERIOR */
4054eaa4710SRishi Srivatsavai port->proposed = recordProposed (this, "SUPERIOR");
4064eaa4710SRishi Srivatsavai port->infoIs = Received;
4074eaa4710SRishi Srivatsavai port->reselect = True;
4084eaa4710SRishi Srivatsavai port->selected = False;
4094eaa4710SRishi Srivatsavai #ifdef STP_DBG
4104eaa4710SRishi Srivatsavai if (this->debug) {
4114eaa4710SRishi Srivatsavai STP_VECT_br_id_print ("stored: portPrio.design_bridge",
4124eaa4710SRishi Srivatsavai &port->portPrio.design_bridge, True);
4134eaa4710SRishi Srivatsavai STP_VECT_br_id_print ("stored: portPrio.root_bridge",
4144eaa4710SRishi Srivatsavai &port->portPrio.root_bridge, True);
4154eaa4710SRishi Srivatsavai stp_trace ("proposed=%d on port %s",
4164eaa4710SRishi Srivatsavai (int) port->proposed, port->port_name);
4174eaa4710SRishi Srivatsavai }
4184eaa4710SRishi Srivatsavai #endif
4194eaa4710SRishi Srivatsavai break;
4204eaa4710SRishi Srivatsavai case REPEAT:
4214eaa4710SRishi Srivatsavai port->proposed = recordProposed (this, "REPEAT");
4224eaa4710SRishi Srivatsavai updtRcvdInfoWhile (this);
4234eaa4710SRishi Srivatsavai break;
4244eaa4710SRishi Srivatsavai case AGREEMENT:
4254eaa4710SRishi Srivatsavai #ifdef STP_DBG
4264eaa4710SRishi Srivatsavai if (port->roletrns->debug) {
4274eaa4710SRishi Srivatsavai stp_trace ("(%s-%s) rx AGREEMENT flag !",
4284eaa4710SRishi Srivatsavai port->owner->name, port->port_name);
4294eaa4710SRishi Srivatsavai }
4304eaa4710SRishi Srivatsavai #endif
431*55fea89dSDan Cross
4324eaa4710SRishi Srivatsavai port->agreed = True;
4334eaa4710SRishi Srivatsavai port->proposing = False; /* In AGREEMENT */
4344eaa4710SRishi Srivatsavai break;
4354eaa4710SRishi Srivatsavai }
4364eaa4710SRishi Srivatsavai
4374eaa4710SRishi Srivatsavai }
4384eaa4710SRishi Srivatsavai
STP_info_check_conditions(STATE_MACH_T * this)4394eaa4710SRishi Srivatsavai Bool STP_info_check_conditions (STATE_MACH_T* this)
4404eaa4710SRishi Srivatsavai {
4414eaa4710SRishi Srivatsavai register PORT_T* port = this->owner.port;
4424eaa4710SRishi Srivatsavai
4434eaa4710SRishi Srivatsavai if ((! port->portEnabled && port->infoIs != Disabled) || BEGIN == this->State) {
4444eaa4710SRishi Srivatsavai return STP_hop_2_state (this, DISABLED);
4454eaa4710SRishi Srivatsavai }
4464eaa4710SRishi Srivatsavai
4474eaa4710SRishi Srivatsavai switch (this->State) {
4484eaa4710SRishi Srivatsavai case DISABLED:
4494eaa4710SRishi Srivatsavai if (port->updtInfo) {
4504eaa4710SRishi Srivatsavai return STP_hop_2_state (this, DISABLED);
4514eaa4710SRishi Srivatsavai }
4524eaa4710SRishi Srivatsavai if (port->portEnabled && port->selected) {
4534eaa4710SRishi Srivatsavai return STP_hop_2_state (this, ENABLED);
4544eaa4710SRishi Srivatsavai }
4554eaa4710SRishi Srivatsavai if (port->rcvdBpdu) {
4564eaa4710SRishi Srivatsavai return STP_hop_2_state (this, DISABLED);
4574eaa4710SRishi Srivatsavai }
458*55fea89dSDan Cross break;
4594eaa4710SRishi Srivatsavai case ENABLED: /* IEEE 802.1y, 17.21, Z.14 */
4604eaa4710SRishi Srivatsavai return STP_hop_2_state (this, AGED);
4614eaa4710SRishi Srivatsavai case AGED:
4624eaa4710SRishi Srivatsavai if (port->selected && port->updtInfo) {
4634eaa4710SRishi Srivatsavai return STP_hop_2_state (this, UPDATE);
4644eaa4710SRishi Srivatsavai }
4654eaa4710SRishi Srivatsavai break;
4664eaa4710SRishi Srivatsavai case UPDATE:
4674eaa4710SRishi Srivatsavai return STP_hop_2_state (this, CURRENT);
4684eaa4710SRishi Srivatsavai case CURRENT:
4694eaa4710SRishi Srivatsavai if (port->selected && port->updtInfo) {
4704eaa4710SRishi Srivatsavai return STP_hop_2_state (this, UPDATE);
4714eaa4710SRishi Srivatsavai }
4724eaa4710SRishi Srivatsavai
4734eaa4710SRishi Srivatsavai if (Received == port->infoIs &&
4744eaa4710SRishi Srivatsavai ! port->rcvdInfoWhile &&
4754eaa4710SRishi Srivatsavai ! port->updtInfo &&
4764eaa4710SRishi Srivatsavai ! port->rcvdBpdu) {
4774eaa4710SRishi Srivatsavai return STP_hop_2_state (this, AGED);
4784eaa4710SRishi Srivatsavai }
4794eaa4710SRishi Srivatsavai if (port->rcvdBpdu && !port->updtInfo) {
4804eaa4710SRishi Srivatsavai return STP_hop_2_state (this, RECEIVE);
4814eaa4710SRishi Srivatsavai }
4824eaa4710SRishi Srivatsavai break;
4834eaa4710SRishi Srivatsavai case RECEIVE:
4844eaa4710SRishi Srivatsavai switch (port->rcvdMsg) {
4854eaa4710SRishi Srivatsavai case SuperiorDesignateMsg:
4864eaa4710SRishi Srivatsavai return STP_hop_2_state (this, SUPERIOR);
4874eaa4710SRishi Srivatsavai case RepeatedDesignateMsg:
4884eaa4710SRishi Srivatsavai return STP_hop_2_state (this, REPEAT);
4894eaa4710SRishi Srivatsavai case ConfirmedRootMsg:
4904eaa4710SRishi Srivatsavai return STP_hop_2_state (this, AGREEMENT);
4914eaa4710SRishi Srivatsavai default:
4924eaa4710SRishi Srivatsavai return STP_hop_2_state (this, CURRENT);
4934eaa4710SRishi Srivatsavai }
4944eaa4710SRishi Srivatsavai case SUPERIOR:
4954eaa4710SRishi Srivatsavai return STP_hop_2_state (this, CURRENT);
4964eaa4710SRishi Srivatsavai case REPEAT:
4974eaa4710SRishi Srivatsavai return STP_hop_2_state (this, CURRENT);
4984eaa4710SRishi Srivatsavai case AGREEMENT:
4994eaa4710SRishi Srivatsavai return STP_hop_2_state (this, CURRENT);
5004eaa4710SRishi Srivatsavai }
5014eaa4710SRishi Srivatsavai
5024eaa4710SRishi Srivatsavai return False;
5034eaa4710SRishi Srivatsavai }
504