📄 portinfo.c
字号:
/************************************************************************ * 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"/* 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; printf ("\n%s:", title); for (iii = 0; iii < len; iii++) { if (! (iii % 24)) Print ("\n%6d:", iii); if (! (iii % 8)) Print (" "); Print ("%02lx", (unsigned long) buff[iii]); } Print ("\n");}#endifstatic RCVD_MSG_TrcvBpdu (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", "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 ("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", "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", "ConfirmedRootMsg"); }#endif return ConfirmedRootMsg; } #ifdef STP_DBG if (this->debug) { stp_trace ("%s", "OtherMsg"); }#endif return OtherMsg;}static BoolrecordProposed (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 BoolsetTcFlags (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 (TOLPLOGY_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 (TOLPLOGY_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; } } return True;}static BoolupdtBPDUVersion (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; } return True;}static BoolupdtRcvdInfoWhile (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/****/ } return True;}voidSTP_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); printf ("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); printf ("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++;#if 0 /* def 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++;#if 0 /* def 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; }#if 0 /* def 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 = -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; 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); }#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_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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -