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