📄 stp_api.c
字号:
/*
* Function:
* stp_show
* Purpose:
* Show STP parameters and states
* Parameters:
* none
* Returns:
* none
*/
void
stp_show(stp_id_t tree_id, int detail)
{
spantree_t *stp;
stp_port_t *stport;
char t[6];
uint16 priority, designated_port,temp_bridge_id,vlan_id;
stp = stp_lookup_from_stp_id(tree_id);
if (stp == NULL) {
return;
}
if (!stp_is_running(stp)) {
trace(TRACE_STP, TR_ERROR, "STP %d not running\n", tree_id);
return;
}
printk("This Bridge is executing IEEE compatible Spanning Tree Protocol\n\n");
printk("STP instance ID %d\n", tree_id);
temp_bridge_id = soc_ntohs_load(stp->bridge_id);
priority = (temp_bridge_id & 0xf000)>>12 ;
vlan_id = temp_bridge_id & 0x0fff;
sal_memcpy(t, (stp->bridge_id + 2), 6);
printk("Root bridge priority - %d.%d\n", priority,vlan_id);
printk("Bridge ID - %X:%X:%X:%X:%X:%X\n", t[0], t[1], t[2], t[3], t[4], t[5]);
if (stp->root_path_cost != 0) {
sal_memcpy(t, (stp->designated_root + 2), 6);
printk("Root Bridge - %X:%X:%X:%X:%X:%X\n",
t[0], t[1], t[2], t[3], t[4], t[5]);
printk("Root Port - %d\n", get_global_port(stp->root_port->unit,stp->root_port->port));
} else {
printk("\nRoot Bridge - self\n");
}
printk("HelloInterval = %d, MaxTime = %d, ForwardDelay = %d\n",
stp->bridge_hello_time, stp->bridge_max_age,
stp->bridge_forward_delay);
printk("TopologyChangeTime = %d, HoldTime = %d\n\n",
stp->topology_change_time, stp->hold_time);
printk("Bridge filter aging time is %d.\n\n", stp->l2_age);
if (stp->topology_change) {
printk("Topology change flag set, ");
} else {
printk("Topology change flag not set, ");
}
if (stp->topology_change_detected) {
printk("Topology change detected flag set\n\n");
} else {
printk("Topology change detected flag not set\n\n");
}
if (!detail) {
return;
}
FOR_ALL_PORTS_IN_STP(stp, stport) {
if (stport->state != STP_DISABLED) {
printk("Port %d (%s, operating speed = %s) is %s\n", get_global_port(stport->unit,stport->port),
stp_port_type_string(stport->port_type),
stp_port_speed_string(stport->path_cost),
stp_port_state_string(stport->state));
priority = stport->port_id >> 12;
printk(" Port path cost %d, Port priority %d\n",
stport->path_cost, priority);
temp_bridge_id = soc_ntohs_load(stport->designated_root);
priority = (temp_bridge_id & 0xf000)>>12 ;
vlan_id = temp_bridge_id & 0x0fff;
sal_memcpy(t, (stport->designated_root + 2), 6);
printk(" Designated root has priority %d.%d, ", priority,vlan_id);
printk("address %X:%X:%X:%X:%X:%X\n",
t[0], t[1], t[2], t[3], t[4], t[5]);
temp_bridge_id = soc_ntohs_load(stport->designated_bridge);
priority = (temp_bridge_id & 0xf000)>>12 ;
vlan_id = temp_bridge_id & 0x0fff;
sal_memcpy(t, (stport->designated_bridge + 2), 6);
printk(" Designated bridge has priority %d.%d, ", priority,vlan_id);
printk("address %X:%X:%X:%X:%X:%X\n",
t[0], t[1], t[2], t[3], t[4], t[5]);
designated_port = stport->designated_port & 0x00ff;
designated_port = get_global_port(designated_port&0x20,designated_port&0x1f);
printk(" Designated port is %d, path cost %d\n",
designated_port, stport->designated_cost);
printk(" BPDU send count = %d, BPDU receive count = %d\n",
stport->bpdu_out, stport->bpdu_in);
printk("\n");
} else {
if (stport->link_flags & STP_LF_TRUNKMEMBER) {
printk("Port %d is trunk port\n\n", stport->lport);
} else if (stport->link_flags & STP_LF_STACK) {
printk("Port %d is stack port\n\n", stport->lport);
}
}
}
}
/* zgs added this for port remove from vlan begin */
/*------------------------------------------------------------------------------
* FUNCTION:stp_sdd_new_stp_port
* DESCRIPTION:当把一个端口从一个VLAN中移到另外一个VLAN的时候。
* 则需要把从原来的STP移到新STP中。
* AUTHOR:ZHOUGUIS
-------------------------------------------------------------------------------*/
int
stp_sdd_new_stp_port(spantree_t *stp, stp_port_t *stport)
{
stport->next = stport;
stport->prev = stport;
stport->stp = stp;
stport->state = STP_DISABLED; /* Disable port until it is enabled */
/* 统一由链路UP的时候决定 */
/* stport->path_cost = STP_PATH_COST_1GB; */ /* default */
/* stport->port_type = STP_PORT_TYPE_GE; */
stport->link_flags = 0;
stport->bpdu_out = 0;
stport->bpdu_in = 0;
stp_port_list_insert(stp, stport);
stp->port_count++;
stport->link_flags |= STP_LF_LOCAL;
if(!(stport->link_flags & STP_LF_LINKDISABLED))
{
enable_port(stp, stport);
}
return 0;
}
/*------------------------------------------------------------------------------
* FUNCTION:stp_removed_port_todefault_stp
* DESCRIPTION:当从VLAN中删除一个端口的时候,如果VLAN有STP,这个端口是活动端口,
* 则把它添加到缺省STP中。
* AUTHOR:ZHOUGUIS
-------------------------------------------------------------------------------*/
void stp_removed_port_todefault_stp(int lport,vlan_id_t vid,int unit,vlan_id_t def_vid)
{
spantree_t *defstp,*curstp;
stp_port_t *sport = (stp_port_t *)NULL;
int find_flag=0;
/*找到生成树中的STP,并且删除连接*/
curstp=stp_lookup_from_stp_id(vid);
if(curstp == NULL){
return;
}
FOR_ALL_PORTS_IN_STP(curstp, sport) {
if ((sport->port == lport)&&(sport->unit == unit)) {
disable_port(curstp, sport);
dll_remove(sport);
curstp->port_count--;
find_flag = 1;
break;
}
}
if(find_flag){
defstp=stp_lookup_from_stp_id(def_vid);
if(defstp == NULL){
return;
}
stp_sdd_new_stp_port(defstp, sport);
}
return;
}
/*------------------------------------------------------------------------------
* FUNCTION:stp_delete_ifvlan_has_stp
* DESCRIPTION:当删除一个VLAN的时候,如果VLAN有STP,则停止它的STP.
*
* AUTHOR:ZHOUGUIS
-------------------------------------------------------------------------------*/
void stp_delete_ifvlan_has_stp(vlan_id_t vid)
{
spantree_t *stp;
/* 检查VLAN的生成树是否存在 */
stp=stp_lookup_from_stp_id(vid);
if(stp == NULL){
return;
}
stp_delete_section(vid);
stp_lock_link();
stp_stop(vid);
stp_unlock_link();
decrease_stg_number(vid);
return;
}
/*------------------------------------------------------------------------------
* FUNCTION:stp_check_stpofthe_vlanexist
* DESCRIPTION:检查一个VLAN是否拥有STP.
* RETURN:
* -1 :STP使能并且VLAN的STP已经存在;
* -2 :STP使能并且VLAN的STP不存在;
* 0 :STP没有使能;
* AUTHOR:ZHOUGUIS
-------------------------------------------------------------------------------*/
int stp_check_stpofthe_vlanexist(vlan_id_t vid)
{
spantree_t *stp;
if(stp_instance_q != NULL){
stp=stp_lookup_from_stp_id(vid);
if(stp == NULL){
return -2; /*stp enable&& vlan's stp not exist*/
}
else{
return -1; /* stp enable&& vlan's stp exist */
}
}
return 0;
}
/*------------------------------------------------------------------------------
* FUNCTION:vlan_ifhastp_addporto_stp
* DESCRIPTION:当添加一个端口到VLAN的时候,检查STP是否使能;
* 如果使能,这个端口又不处于DISABLE状态,那就
* 把这个端口从以前的STP中移到VLAN所在的STP中。
* RETURN:
NONE
* AUTHOR:ZHOUGUIS
-------------------------------------------------------------------------------*/
void vlan_ifhastp_addporto_stp(int unit,int lport,vlan_id_t vid,vlan_id_t def_vid)
{
spantree_t *defstp,*curstp;
stp_port_t *sport = (stp_port_t *)NULL;
int lcport;
lcport = stp_port_p2l(stp_my_cpuid, unit, lport);
/*找到生成树中的STP,并且删除连接*/
FOR_ALL_STP(curstp)
{
sport = stp_port_lookup_from_id(curstp, lcport);
if (sport == NULL) {
continue;
}
disable_port(curstp, sport);
dll_remove(sport);
curstp->port_count--;
break;
}
/*如果找到端口,就把它添加到生成树中去*/
if(sport != NULL)
{
defstp=stp_lookup_from_stp_id(vid);
if(defstp == NULL){
return;
}
stp_sdd_new_stp_port(defstp, sport);
}
return;
}
/* FUNCTION: stp_check_relation_for_trunk
* DESCRIPTION: 当创建TRUNK的时候,需要把TRUNK生成树中的信息删除。
* AUTHOR/DATE: zhouguis 2005-12-9
*/
void stp_check_relation_for_trunk(int gport)
{
spantree_t *curstp;
stp_port_t *sport = (stp_port_t *)NULL;
int unit,lport,lcport,link;
unit = get_gport_unit(gport);
lport = gport_to_lport(gport);
lcport = stp_port_p2l(stp_my_cpuid, unit, lport);
/*如果链路状态为DOWN,则返回*/
if (bcm_port_link_status_get(unit, lport, &link) < 0) {
/* debugk(DK_STP,"bcm_port_link_status_get error\n");*/
return;
}
if(link){
FOR_ALL_STP(curstp){
if(curstp == NULL) return;
sport = stp_port_lookup_from_id(curstp, lcport);
if (sport == NULL) {
continue;
}
disable_port(curstp, sport);
dll_remove(sport);
curstp->port_count--;
sal_free(sport);
break;
}
}
}
/* FUNCTION: stp_add_active_port_to_itstp
* DESCRIPTION: 当把TRUNK作为VLAN的时候服务的时候,需要把TRUNK口添加到VLAN的生成树中去。
* AUTHOR/DATE: zhouguis 2005-12-9
*/
void stp_add_active_port_to_itstp(int gport,vlan_id_t vid)
{
spantree_t *curstp;
stp_port_t *sport = (stp_port_t *)NULL;
int unit,lport,lcport,link,speed;
unit = get_gport_unit(gport);
lport = gport_to_lport(gport);
/*如果链路状态为UP,否则等到UP的时候再添加*/
if (bcm_port_link_status_get(unit, lport, &link) < 0) {
/* debugk(DK_STP,"bcm_port_link_status_get error\n");*/
return;
}
if(link){
/*如果生成树已经启动*/
curstp = stp_lookup_from_stp_id(vid);
if(curstp == NULL){
return;
}
lcport = stp_port_p2l(stp_my_cpuid, unit, lport);
sport = stp_port_lookup_from_id(curstp, lcport);
/*如果TRUNK口还没有在生成树中就创建一个端口,并把它添加到生成树中*/
if (sport == NULL) {
if (bcm_port_speed_get(unit, lport, &speed) < 0) {
/*trace(TRACE_STP, TR_ERROR, */
debugk(DK_STP,"bcm_port_speed_get error\n");
speed = 100;
}
if (stp_create_stp_port(&sport, curstp, lcport, "stp port") < 0) {
return;
}
sport->cpu = stp_my_cpuid;
sport->unit = unit;
sport->port = lport;
sport->port_type = stp_get_porttype(unit, lport);
sport->link_flags = 0 ;
sport->link_flags |= STP_LF_LOCAL;
/* for port id = pri + port id zhouguis adde 2005-12-22*/
sport->port_id |= gport;
stp_link_up(curstp, sport, speed);
}
}
}
/* FUNCTION: stp_deltrunk_inmoved_vlantree
* DESCRIPTION: 当TRUNK不为VLAN服务的时候,需要把TRUNK口从相应的生成树中删除。
* AUTHOR/DATE: zhouguis 2005-12-9
*/
void stp_deltrunk_inmoved_vlantree(int gport,vlan_id_t vid)
{
spantree_t *curstp;
stp_port_t *sport = (stp_port_t *)NULL;
int unit,lport,lcport,link;
unit = get_gport_unit(gport);
lport = gport_to_lport(gport);
/* 如果链路为DOWN,则在link_down事件处理中删除 */
if (bcm_port_link_status_get(unit, lport, &link) < 0) {
/* debugk(DK_STP,"bcm_port_link_status_get error\n");*/
return;
}
if(link){
FOR_ALL_STP(curstp){
if(curstp == NULL){
continue;
}
lcport = stp_port_p2l(stp_my_cpuid, unit, lport);
sport = stp_port_lookup_from_id(curstp, lcport);
/*如果TRUNK口已经在生成树中就删除*/
if (sport != NULL){
disable_port(curstp, sport);
dll_remove(sport);
curstp->port_count--;
sal_free(sport);
}
}
}
return;
}
/*------------------------------------------------------------------------------
* FUNCTION:stp_moveporto_defaultstp
* DESCRIPTION:如果使活动端口,就把它添加到缺省的STP中去。
* 否则删除这个端口。
* RETURN:
NONE
* AUTHOR:ZHOUGUIS
-------------------------------------------------------------------------------*/
void stp_moveporto_defaultstp(stp_port_t *stport)
{
spantree_t *stp,*curstp;
stp = stport->stp;
/* 检查端口状态 */
disable_port(stp, stport);
dll_remove(stport);
stp->port_count--;
curstp = stp_lookup_from_stp_id(1);
if(curstp == NULL){
return;
}
stp_sdd_new_stp_port(curstp, stport);
return;
}
/****************************************************************************
* FUNCTION NAME:port_is_edgeport
* DESCRIPTION:返回端口的属性信息。
* AUTHOR/DATE: ZHOUGUIS
****************************************************************************/
int port_is_edgeport(int gport)
{
if(check_gport_valid(gport)) {
return edgeport_array[gport-1].port_state;
}
else{
return 0;
}
}
/****************************************************************************
* FUNCTION NAME:stp_set_edgeport
* DESCRIPTION:设置边缘端口。
* AUTHOR/DATE: ZHOUGUIS
****************************************************************************/
void stp_set_edgeport(int gport)
{
int unit,lport;
if(check_gport_valid(gport)&&(!edgeport_array[gport-1].port_state))
{
edgeport_array[gport-1].port_state = 1;
unit = get_gport_unit(gport);
lport = gport_to_lport(gport);
check_config_port_to_forwarding(unit,gport,lport);
}
else
{
printL("Port has been setted to edge port state!\n","");
}
}
/****************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -