📄 topoch.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.
**********************************************************************/
/* 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 INIT 2
#define INACTIVE 3
#define TCACTIVE 4
#define DETECTED 5
#define NOTIFIED_TC 6
#define PROPAGATING 7
#define ACKNOWLEDGED 8
#define NOTIFIED_TCN 9
#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
在许多的硬件中,STP_OUT_flush_it是a)非常难的
b) 不能为每个端口删除学习信息。
代替的方法是这样的:我们不需要关心operEdge
Flag,但是为TopologyChage把所有的学习表都清理
一次,除了接收端口。我将讨论。看看下面的
文字STRONGLY_SPEC_802_1W
*/
#else
/************************************************************************************
函数名称:
输入参数:
输出参数:
功能描述:
返回值 :
备注 : 17.19.6.
作者 :
日期 :
************************************************************************************/
static Bool flush (STATE_MACH_T * this, char *reason) /* 17.19.6 */
{
register struct net_bridge_port *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
/************************************************************************************
函数名称:
输入参数:
输出参数:
功能描述: 将所有端口的tcProp设置为TRUE,除了引起此函数的端口
返回值 :
备注 : 17.19.14.
作者 :
日期 :
************************************************************************************/
static void setTcPropBridge (STATE_MACH_T * this, char *reason) /* 17.19.14 */
{
register struct net_bridge_port *port = this->owner.port;
register struct net_bridge_port *tmp;
for (tmp = port->br->port_list; tmp; tmp = tmp->next)
{
if (!is_port_uplink_port(port->port_no))
continue;
if (tmp->port_id != port->port_id)
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
}
/************************************************************************************
函数名称:
输入参数:
输出参数:
功能描述: 设置TcWhile
返回值 :
备注 : 17.19.7.
作者 :
日期 :
************************************************************************************/
static unsigned int newTcWhile (STATE_MACH_T * this) /* 17.19.7 */
{
register struct net_bridge_port *port = this->owner.port;
if (port->sendRSTP && port->operPointToPointMac)
{
return 2 * port->br->rootTimes.HelloTime;
}
return port->br->rootTimes.MaxAge;
}
/************************************************************************************
函数名称:
输入参数:
输出参数:
功能描述:
返回值 :
备注 : 17.19.25.
作者 :
日期 :
************************************************************************************/
void STP_topoch_enter_state (STATE_MACH_T * this)
{
register struct net_bridge_port *port = this->owner.port;
switch (this->State)
{
case BEGIN:
case INIT:
#ifdef STRONGLY_SPEC_802_1W
/*移除端口上学到的fdb信息*/
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);/*重新设置tcWhile*/
#ifdef STP_DBG
if (this->debug)
stp_trace ("DETECTED: tcWhile=%d on port %s", port->tcWhile,
port->port_name);
#endif
/*
设置桥中其它端口的Tcprop,
通知它们如果是活动拓扑中
的一部分,就传播TC信息
*/
setTcPropBridge (this, "DETECTED");
port->tc = False;/*已经侦测到变化,清除tc*/
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;
case NOTIFIED_TC:
port->rcvdTcn = port->rcvdTc = False;/*引起状态转移的变量要恢复*/
if (port->role == DesignatedPort)
{
port->tcAck = True;/*拓扑变化应答*/
}
/*
* 设置桥中其它端口的Tcprop,
* 通知它们如果是活动拓扑中
* 的一部分,就传播TC信息
*/
setTcPropBridge (this, "NOTIFIED_TC");
break;
case PROPAGATING:
port->tcWhile = newTcWhile (this);/*tcWhile重置*/
#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; /*拓扑变化已经被应答了,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;
};
}
/************************************************************************************
函数名称:
输入参数:
输出参数:
功能描述:
返回值 :
备注 : 17.19.25.
作者 :
日期 :
************************************************************************************/
Bool STP_topoch_check_conditions (STATE_MACH_T * this)
{
register struct net_bridge_port *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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -