📄 stp_trunk.c
字号:
* Parameters:
* tid - trunk group id
* pbmp - port bitmap(physical)
* Returns:
*
*/
int
stp_trunk_port_remove(stp_id_t tree_id, bcm_trunk_t tid, pbmp_t pbmp)
{
spantree_t *stp;
soc_port_t port;
int lport, r;
stp = stp_lookup_from_stp_id(tree_id);
if (stp == NULL) {
return -1;
}
if (!stp_trunk_initialized) {
trace(TRACE_TRUNK, TR_ERROR, "Trunk not initialized!\n");
return 1;
}
PBMP_ITER(pbmp, port) {
lport = stp_port_p2l(stp_my_cpuid, DEF_UNIT, port);
/*
* Remove port from trunk in the local module
*/
if ((r = stp_trunk_remove_one_port(stp, tid, lport)) < 0) {
return (r);
}
}
return (BCM_E_NONE);
}
/*
* Function:
* stp_trunk_psc_set
* Purpose:
* Set the RTAG for a trunk
* Parameters:
* tid - trunk id
* rtag - the new rtag value
* Returns:
*/
int
stp_trunk_psc_set(stp_id_t tree_id, bcm_trunk_t tid, int rtag)
{
/* int p, linkup; */
int unit;
if (!stp_trunk_initialized) {
trace(TRACE_TRUNK, TR_ERROR, "Trunk not initialized!\n");
return 1;
}
trunk_table[tid].rtag = rtag;
trace(TRACE_TRUNK, TR_VERBOSE,
"Trunk: rtag changes to %d for trunk %d\n", rtag, tid);
unit = get_gport_unit(tid);
bcm_trunk_psc_set(unit, tid, rtag);
return (0);
}
/*
* Function:
* stp_rcv_trunk_info
* Purpose:
* Handles trunk packets received from other modules of stack
* Parameters:
* value - trunk port add/del info
*/
void
stp_rcv_trunk_info(uint32 clientid, void *data, int length, int s_cpu)
{
spantree_t *stp;
stp_rdp_trunk_t *tpi;
stp_id_t tree_id;
int tid, lport, link;
tpi = (stp_rdp_trunk_t *)data;
if (!stp_trunk_initialized) {
trace(TRACE_TRUNK, TR_ERROR, "Trunk not initialized!\n");
return;
}
tree_id = soc_ntohs(tpi->tree_id);
tid = soc_ntohs(tpi->tid);
lport = soc_ntohl(tpi->lport);
link = soc_ntohl(tpi->link_up);
stp = stp_lookup_from_stp_id(tree_id);
if (stp == NULL) {
return;
}
if (soc_ntohl(tpi->add) == TRUE) {
/* Add port to trunk in the module */
stp_trunk_add_one_port(stp, tid, lport, link);
trace(TRACE_TRUNK, TR_VERBOSE,
"rcv_trunk_pkts: add port %d tid %d\n", lport, tid);
} else {
/* Remove port from trunk in the module */
stp_trunk_remove_one_port(stp, tid, lport);
trace(TRACE_TRUNK, TR_VERBOSE,
"rcv_trunk_pkts: remove port %d tid %d\n", lport, tid);
}
return;
}
/*------------------------------------------------------------------------------
* FUNCTION:stp_trunk_link_up
* DESCRIPTION:当端口链路UP的时候,如果这个端口是聚合组的第一个UP成员,就被选为ROOT端口。
* 否则就是聚合组的普通成员(MEMBER)。
* AUTHOR:ZHOUGUIS 2005-12-15
-------------------------------------------------------------------------------*/
int
stp_trunk_link_up(spantree_t *stp, int lport)
{
stp_port_t *stport;
int p, t;
stport = stp_port_lookup_from_id(stp, lport);
if (stport == NULL) {
return -1;
}
if (!stp_trunk_is_trunk_port(lport)) {
return -1;
}
for (t = 0; t < BCM_TRUNK_GROUP_MAX; t++) {
for (p = 0; p < BCM_TRUNK_MAX_PORTCNT; p++) {
if (trunk_table[t].port[p].num == lport) {
if (trunk_table[t].active_count) {
stp_trunk_member_add(stp, t, lport);
debugk(DK_STP,
"trunk_link_up: add %d to trunk %d\n",
lport, t);
} else {
stp_trunk_root_add(stp, t, lport);
trunk_table[t].port[p].flag |= TRUNK_PORT_ROOT;
debugk(DK_STP,
"trunk_link_up: add %d to tid %d as root\n",
lport, t);
}
trunk_table[t].port[p].flag |= TRUNK_PORT_ACTIVE;
return (0);
}
}
}
return (0);
}
/*------------------------------------------------------------------------------
* FUNCTION:stp_trunk_link_down
* DESCRIPTION:当端口链路DOWN的时候,如果这个端口是聚合组的一个成员,就把她的状态转为非ACTIVE。
* 如果是ROOT端口,那么需要从其它的活动成员中选择一个作为ROOT端口。
* AUTHOR:ZHOUGUIS 2005-12-15
-------------------------------------------------------------------------------*/
int
stp_trunk_link_down(spantree_t *stp, int lport)
{
int t, p, i,find =0;
if (!stp_trunk_is_trunk_port(lport)) {
return (0);
}
for (t = 0; t < BCM_TRUNK_GROUP_MAX; t++) {
for (p = 0; p < BCM_TRUNK_MAX_PORTCNT; p++) {
if (trunk_table[t].port[p].num == lport) { /* find it */
debugk(DK_STP,"find in trunk %d\n",t);
find = 1;
break;
}
}
if(find){ break;}
}
if(find)
{
if (trunk_table[t].port[p].flag & TRUNK_PORT_ACTIVE) {
trunk_table[t].port[p].flag &= ~TRUNK_PORT_ACTIVE;
if (trunk_table[t].port[p].flag & TRUNK_PORT_ROOT) {
for (i = 0; i < BCM_TRUNK_MAX_PORTCNT; i++) {
if (trunk_table[t].port[i].flag & TRUNK_PORT_ACTIVE) {
stp_trunk_root_add(stp, t, trunk_table[t].port[i].num);
trunk_table[t].port[i].flag |= TRUNK_PORT_ROOT;
debugk(DK_STP,
"trunk_link_down: change %d as root for trunk %d\n",
trunk_table[t].port[i].num, t);
trunk_table[t].active_count--;
break;
}
}
}
trunk_table[t].port[p].flag &= ~TRUNK_PORT_ROOT;
}
trunk_table[t].active_count--;
}
return (0);
}
/*------------------------------------------------------------------------------
* FUNCTION:stp_trunk_state_update
* DESCRIPTION:当聚合组根成员(ROOT)的状态改变的时候,它的成员(MEMBER)
* 的状态也要跟着改变,并且跟(ROOT)的状态一致。
* AUTHOR:ZHOUGUIS 2005-12-15
-------------------------------------------------------------------------------*/
void
stp_trunk_state_update(spantree_t *stp, stp_port_t *stport, int state)
{
stp_port_t *port;
/* 如果ROOT端口的状态发生改变的时候,它的成员端口的状态也要发生改变:跟它一致 */
if (stport->link_flags & STP_LF_TRUNKROOT) {
FOR_ALL_PORTS_IN_STP(stp, port) {
if (stport->lport != port->lport && port->tid == stport->tid &&
port->link_flags & STP_LF_TRUNKMEMBER) {
bcm_port_stp_set(port->unit, stp_port_l2p(port->lport), state);
}
}
}
}
/*------------------------------------------------------------------------------
* FUNCTION:stp_trunk_root_add
* DESCRIPTION:添加聚合组ROOT成员。
* AUTHOR:ZHOUGUIS 2005-12-15
-------------------------------------------------------------------------------*/
int
stp_trunk_root_add(spantree_t *stp, int tid, int lport)
{
stp_port_t *stport;
stp_port_t *root_port;
stp_port_bpdu_enable(stp, lport, TRUE);
debugk(DK_STP,"Add root lport= %d\n",lport);
root_port = stp_port_lookup_from_id(stp, lport);
if (root_port == NULL) {
return -1;
}
root_port->path_cost = STP_PATH_COST_AGGR;
enable_port(stp, root_port);
FOR_ALL_PORTS_IN_STP(stp, stport) {
if (stport->lport != lport && stport->tid == tid &&
stport->link_flags & STP_LF_TRUNKMEMBER) {
stp_port_bpdu_enable(stp, stport->lport, 0);
stport->link_flags &= ~STP_LF_TRUNKROOT;
/*其它端口状态的选择应该根据新端口状态一致*/
stp_port_state_set(stp, stport, root_port->state);
}
}
root_port->link_flags |= STP_LF_TRUNKMEMBER | STP_LF_TRUNKROOT;
root_port->tid = tid;
trunk_table[tid].active_count++;
return (0);
}
/*------------------------------------------------------------------------------
* FUNCTION:stp_trunk_root_get
* DESCRIPTION:获取聚合组根端口。
* AUTHOR:ZHOUGUIS 2005-12-15
-------------------------------------------------------------------------------*/
stp_port_t *
stp_trunk_root_get(spantree_t *stp, int tid)
{
stp_port_t *stport;
FOR_ALL_PORTS_IN_STP(stp, stport) {
if (stport->link_flags & STP_LF_TRUNKROOT) {
return (stport);
}
}
return (0);
}
/*------------------------------------------------------------------------------
* FUNCTION:stp_trunk_member_add
* DESCRIPTION:添加聚合组成员。
* AUTHOR:ZHOUGUIS 2005-12-15
-------------------------------------------------------------------------------*/
int
stp_trunk_member_add(spantree_t *stp, int tid, int lport)
{
stp_port_t *stport;
stp_port_t *root_port;
int state;
stport = stp_port_lookup_from_id(stp, lport);
if (stport == NULL) {
return -1;
}
debugk(DK_STP,"Add member lport= %d\n",lport);
stp_port_bpdu_enable(stp, lport, 0);
stport->link_flags |= STP_LF_TRUNKMEMBER;
stport->tid = tid;
if ((root_port = stp_trunk_root_get(stp, tid))) {
state = root_port->state;
} else {
state = STP_DISABLED;
}
stp_port_state_set(stp, stport, state);
trunk_table[tid].active_count++;
return (0);
}
/*
* Function:
* stp_trunk_member_remove
* Purpose:
* Remove this port from the trunk
* Parameters:
* tid - trunk group id
* lport - logical port number
* Returns:
*/
int
stp_trunk_member_remove(spantree_t *stp, int tid, int lport)
{
stp_port_t *stport;
stp_port_t *port;
stport = stp_port_lookup_from_id(stp, lport);
if (stport == NULL) {
return -1;
}
if (stport->link_flags & STP_LF_TRUNKROOT) {
FOR_ALL_PORTS_IN_STP(stp, port) {
if (lport != port->lport && port->tid == tid &&
port->link_flags & STP_LF_TRUNKMEMBER) {
if (port->state != STP_DISABLED) {
disable_port(stp, port);
}
stp_port_state_set(stp, port, STP_DISABLED);
}
}
}
stport->link_flags &= ~(STP_LF_TRUNKMEMBER | STP_LF_TRUNKROOT);
stport->tid = 0;
if (stport->state != STP_DISABLED) {
disable_port(stp, stport);
}
/*
* enable BPDUs from this port again
*/
stp_port_bpdu_enable(stp, lport, 1);
if (!(stport->link_flags & STP_LF_LINKDISABLED)) {
enable_port(stp, stport);
}
return (0);
}
/*------------------------------------------------------------------------------
* FUNCTION:stp_trunk_show
* DESCRIPTION:显示聚合组成员信息。
* AUTHOR:ZHOUGUIS 2005-12-15
-------------------------------------------------------------------------------*/
int
stp_trunk_show(void)
{
int t, p;
stp_print_trunk_table();
if (!stp_trunk_initialized) {
trace(TRACE_TRUNK, TR_ERROR, "Trunk not initialized!\n");
return 1;
}
printk("\tR - Root, A - Active");
for (t = 0; t < BCM_TRUNK_GROUP_MAX; t++) {
if (trunk_table[t].port_count > 0) {
printk("\n\nTrunk Group %d, psc %d, ports %d, active ports %d\n",
t, trunk_table[t].rtag, trunk_table[t].port_count,
trunk_table[t].active_count);
printk("Ports : ");
}
for (p = 0; p < trunk_table[t].port_count; p++) {
if (stp_stack_ready) {
printk(" M%dP%d(", stp_port_l2cpu(trunk_table[t].port[p].num),
stp_port_l2p(trunk_table[t].port[p].num));
} else {
printk(" %d(", trunk_table[t].port[p].num);
}
if (trunk_table[t].port[p].flag & TRUNK_PORT_ROOT) {
printk("R");
}
if (trunk_table[t].port[p].flag & TRUNK_PORT_ACTIVE) {
printk("A");
}
printk(")");
}
}
printk("\n");
return (0);
}
/*------------------------------------------------------------------------------
* FUNCTION:stp_trunk_deal_with_port
* DESCRIPTION:当创建生成树的时候如果VLAN成员里面有聚合成员,
* 应该把加到聚合组中。
* AUTHOR:ZHOUGUIS 2005-12-15
-------------------------------------------------------------------------------*/
void stp_trunk_deal_with_port(spantree_t *stp,int lport)
{
int trunk_id,link_up;
stp_port_t *stport;
/* 察看软件表的信息,判断这个端口是否为聚合组的一个成员 */
trunk_id = stp_trunk_get_trunk_id(lport);
if(trunk_id == -1){
return;
}
if (!stp_trunk_initialized) {
printL("Trunk not initialized!\n","");
return;
}
stport = stp_port_lookup_from_id(stp, lport);
if (stport == NULL) {
link_up = FALSE;
}
else{
link_up = TRUE;
}
stp_trunk_add_one_port(stp, trunk_id, lport, link_up);
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -