📄 stp_in.c
字号:
}
semTake(sem_rstp,WAIT_FOREVER);
entry->port_id = port->port_id;
/*printf("port role %d\r\n",port->role);*/
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)
{
memset (&entry->designated_root, 0, sizeof (UID_BRIDGE_ID_T));
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;
/* printf("wl_debug,entry->operEdge = %d\r\n",port->operEdge);*/
entry->oper_stp_neigb = 0;
}
else
{
entry->oper_point2point = port->operPointToPointMac ? 1 : 0;
/*printf("wl_debug,port->operEdge = %d\r\n",port->operEdge);*/
entry->oper_edge = port->operEdge ? 1 : 0;
/*printf("wl_debug,entry->operEdge = %d\r\n",entry->operEdge);*/
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;
semGive(sem_rstp);
return 0;
}
/****************************************************************************************
函数名称: STP_IN_stpm0_get_state
功能描述: 获取桥的配置信息,写入entry
输入参数: port
输出参数: uid_cfg
返回值: 0 -成功返回
不为0 -遇错返回
备注:
作者: wl
日期: 2003-03-14
*****************************************************************************************/
int STP_IN_stpm_get_state (IN struct net_bridge *this, OUT UID_STP_STATE_T * entry)
{
semTake(sem_rstp,WAIT_FOREVER);
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;
semGive(sem_rstp);
return 0;
}
#if 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)
strncpy (name, stpm->name, buffsize);
else
memset (name, 0, buffsize);
iret = 0;
break;
}
}
RSTP_CRITICAL_PATH_END;
return iret;
}
#endif
int STP_IN_enable_port (struct net_bridge_port *port, Bool enable)/* call it, when link Up/Down */
{
register struct net_bridge *br ;
br = port->br;
semTake(sem_rstp,WAIT_FOREVER);
tev = enable ? RSTP_PORT_EN_T : RSTP_PORT_DIS_T;
/*INCR100 (nev);*/
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");
added by wl */
}
if (STP_ENABLED != br->admin_state)
{
semGive(sem_rstp);
return -1;
}
_stp_in_enable_port_on_stpm (br, port, enable);
/* STP_stpm_update (stpm); */
semGive(sem_rstp);
return 0;
}
#if 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;
tev = RSTP_PORT_SPEED_T;
INCR100 (nev);
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;
}
semGive(sem_rstp);
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;
tev = RSTP_PORT_DPLEX_T;
INCR100 (nev);
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;
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
#endif
int STP_IN_rx_bpdu (unsigned char *pkt/*,int vlan_id, BPDU_T * bpdu, size_t len*/)
{
int iret;
unsigned char *buf; /*LLC pkt */
short portno;
struct net_bridge_port *port;
BPDU_T *bpdu;
semTake(sem_rstp,WAIT_FOREVER);
portno = *(short *)pkt;
port = br_get_port_byno(portno);/*get the port's structure whose port number equal to portno*/
if(!port)
{
free(pkt);
return;
}
buf = pkt + 14 ;/*DA,SA...*/
bpdu = (BPDU_T*)buf;
if (STP_DISABLED == port->br->admin_state)
{ /* the stpm had not yet been enabled :( */
semGive(sem_rstp);
return STP_Had_Not_Yet_Been_Enabled_On_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 */
}
#if 0
if (!port->portEnabled)
{ /* port link change indication will come later :( */
_stp_in_enable_port_on_stpm (this, port->port_index, True);
}
#endif /*added by wl*/
#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);*/
STP_info_rx_bpdu(port,bpdu/*,len*/);
STP_stpm_update (port->br);
semGive(sem_rstp);
free(pkt);
return iret;
}
/****************************************************************************************
函数名称: STP_IN_one_second
功能描述: 每秒钟进入此函数一次,主要是改变状态机
输入参数:
输出参数: 所有的状态机
返回值: dbg_cn-进入的次数
备注:
作者: wl
日期: 2003-03-14
*****************************************************************************************/
int STP_IN_one_second (void)
{
/*register struct net_bridge *stpm = bridge_list;*/
register struct net_bridge *stpm = br_get_byname("default");/*modified by wl 2007-8-3*/
register int dbg_cnt = 0;
semTake(sem_rstp,WAIT_FOREVER);
/*tev = RSTP_PORT_TIME_T;*/
/*延时函数?*/
/* INCR100 (nev);*/
while (stpm)
{
if (STP_ENABLED == stpm->admin_state)
{
STP_stpm_one_second (stpm);
dbg_cnt++;
}
stpm = stpm->next;
}
semGive(sem_rstp);
return dbg_cnt;
}
/************************************************************************************
* 函数名称: STP_IN_stpm_set_cfg
* 功能描述:
* 输入参数:
* 输出参数:
* 返回值:
* 备注:
* 作者:
* 日期:
*
************************************************************************************/
int STP_IN_stpm_set_cfg (IN UID_STP_CFG_T * uid_cfg,struct vty*vty)
{
int rc = 0, prev_prio, err_code;
Bool created_here, enabled_here;
register struct net_bridge *this;
UID_STP_CFG_T old;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -