📄 stp_appl.c
字号:
stp_id_t tree_id;
bcm_stg_t stg;
tree_id = stp->external_id;
/*修改的代码 zhouguis modified 2005-12-1*/
stg = find_newstg_forvlan(tree_id);
for (unit = 0; unit < stp_all_units_onboard; unit++) {
/*
* Get the link status of all the ports that belong to this VLAN
*/
if(tree_id==1){
/* 缺省VLAN对应缺省STG */
bcm_stg_vlan_add(unit, 1, tree_id);
}
else{
bcm_stg_create_id(unit, stg);
bcm_stg_vlan_add(unit, stg, tree_id);
}
#if BOARD_TYPE==RHS8012GE_3T8F
bcm_stg_stp_set(unit, stg, 13, STP_FORWARDING);
#else
bcm_stg_stp_set(unit, stg, 12, STP_FORWARDING);
#endif
/* make high speed port to forwarding added by zhouguis 2005-12-7*/
bcm_vlan_port_get(unit, tree_id, &pbmp, NULL);
SOC_PBMP_AND(pbmp, PBMP_E_ALL(unit));
PBMP_ITER(pbmp, pport) {
lport = stp_port_p2l(stp_my_cpuid, unit, pport);
if (bcm_stk_port_is_stack(unit, pport)) {
stp_mark_stack_port(stp, lport);
if (stk_mode) {
stp_send_port_info(tree_id, lport, STP_PORT_INFO_STACK, 1, 0);
}
continue;
}
if (bcm_port_link_status_get(unit, pport, &link) < 0) {
trace(TRACE_STP, TR_ERROR, "bcm_port_link_status_get error\n");
continue;
}
if (link) {
stp_port_t *stport;
if (bcm_port_speed_get(unit, pport, &speed) < 0) {
trace(TRACE_STP, TR_ERROR, "bcm_port_speed_get error\n");
speed = 100;
}
if (stp_create_stp_port(&stport, stp, lport, "stp port") < 0) {
return;
}
stport->cpu = stp_my_cpuid;
stport->unit = unit;
stport->port = pport;
stport->port_type = stp_get_porttype(unit, pport);
stport->link_flags |= STP_LF_LOCAL;
/* for port id = pri + port id zhouguis adde 2005-12-22*/
gport = get_global_port(unit,pport);
stport->port_id |= gport;
stp_link_up(stp, stport, speed);
if (stk_mode) {
stp_send_port_info(tree_id, lport, STP_PORT_INFO_LINK,
speed, stport->port_type);
}
}
}
}
}
/*
* Function:
* stp_sys_init
* Purpose:
* System initialization before STP is run,
* set up COS for BPDU packets, register link scan callback,
* register with PMUX to receive BPDU packets.
* Note:
* This function tries to start PMUX if not already active.
* If STP runs in stack mode, MDP also tries to start PMUX,
* Because PMUX will remember whether in SL stack mode or not
* at the start, it is very important stp_sys_init() is called
* after the mdp_start() is called if intended to run
* STP in stack mode. Otherwise, the packet parsing will
* be totally screwed up because of the actual stack tag
* mismatch with what PMUX remembered when PMUX starts.
*/
int
stp_sys_init(void)
{
int unit;
int rv;
/* 清除vlan和stg对应表 zhouguis added this 2005-11-20 */
init_clear_all_mapping_table();
if(rhosStpLock == NULL){
rhosStpLock = semBCreate (SEM_Q_FIFO, SEM_FULL);
}
if(rhosStpLock == NULL){
return -1;
}
/* Set up packet receive queue */
stp_pakq_int(STP_QUEUE_SIZE);
rv = rhos_start_interface();/*added by kevin 2005.2.1*/
if(rv != OK)
{
trace(TRACE_STP, TR_ERROR, "bcm_pmux_start failed\n");
return -1;
}
for (unit = 0; unit < stp_all_units_onboard; unit++)
{
/* BPDU packets should use the best COS */
stp_bpdu_cos_set(unit);
/* register link scan callback function */
if (bcm_linkscan_register(unit, stp_link_scan_callback) != BCM_E_NONE)
{
trace(TRACE_STP, TR_ERROR, "Cannot register linkscan callback\n");
return (-1);
}
#if 0 /*removed by kevin 2005.2.1*/
/* Start packet reception via PMUX */
if (!bcm_pmux_active(unit, NULL, NULL, NULL))
{
rv = bcm_pmux_start(unit, ENET_MAX_SIZE, stp_sys_alloc, stp_sys_free);
if (rv != BCM_E_NONE) {
trace(TRACE_STP, TR_ERROR, "bcm_pmux_start failed\n");
return -1;
}
}
#endif
/*BCM_PMUX_PRIO_STP should higer than BCM_PMUX_PRIO_AMUX*/
if ((rv = bcm_pmux_info_register(unit, "STP", 0, BCM_PMUX_PRIO_STP,/*BCM_PMUX_PRIO_AMUX,*/
stp_sys_recv_pkts, NULL)) != BCM_E_NONE)
{
trace(TRACE_STP, TR_ERROR, "bcm_pmux_info_register failed\n");
return -1;
}
}
return 0;
}
/*
* Function:
* stp_sys_cleanup
* Purpose:
* Cleanup resources used by STP. Unregister port scan
* callback, stop STP config packet receive.
*/
void
stp_sys_cleanup(void)
{
int unit;
for (unit = 0; unit < stp_all_units_onboard; unit++) {
bcm_pmux_info_unregister(unit, BCM_PMUX_PRIO_STP, stp_sys_recv_pkts);
bcm_linkscan_unregister(unit, stp_link_scan_callback);
}
if (stp_stack_mode) {
mdp_unregister_callback(stp_do_start_mode);
rdp_rcv_unregister(BCM_RDP_ID_STP, stp_rcv_rdp_data);
}
stp_my_cpuid = stp_stk_num_cpu = 1;
stp_stack_port = 0;
stp_stack_mode = stp_stack_ready = FALSE;
stp_sys_initialized = 0;
}
/*
* return the number of prts for a chip type
*/
static int
stp_get_num_ports(int type)
{
switch (type) {
case SOC_CHIP_BCM5600:
case SOC_CHIP_BCM5605:
case SOC_CHIP_BCM5615:
return (26);
case SOC_CHIP_BCM5680:
return (8);
case SOC_CHIP_BCM5690:
return (13);
case SOC_CHIP_BCM5670:
return (8);
}
return (0);
}
/*
* Get all the stack module info we need
*/
static int
stp_save_stk_info(int stk_mode)
{
bcm_l2_addr_t l2addr;
int cpu, unit;
if (!stk_mode) { /* stand alone mode */
char *sys_addr;
sys_addr = sal_config_get(SAL_CONFIG_SWITCH_MAC);
parse_macaddr(sys_addr, stp_stk_modinfo[1].cpu_mcadd);
stp_my_cpuid = 1;
stp_stk_num_cpu = 1;
stp_stk_modinfo[1].num_chip = stp_all_units_onboard;
for (unit = 0; unit < stp_all_units_onboard; unit++) {
stp_stk_modinfo[1].chip[unit].soc_unit = unit;
stp_stk_modinfo[1].chip[unit].chip_type = SOC_CHIP_GROUP(unit);
}
} else { /* stacking mode */
mdp_num_cpu_get(&stp_stk_num_cpu);
mdp_cpuid_get(&stp_my_cpuid);
for (cpu = 1; cpu <= stp_stk_num_cpu; cpu++) {
mdp_cpu_info_get(cpu, &stp_stk_modinfo[cpu]);
}
}
/*
* Save the bridge ID, it is the CPU mac address(master's in stack mode)
*/
sal_memcpy(stp_bridge_mac, stp_stk_modinfo[1].cpu_mcadd, sizeof(mac_addr_t));
bcm_l2_addr_init(&l2addr, stp_bridge_mac, 1);
l2addr.flags |= BCM_L2_STATIC;
for (unit = 0; unit < stp_all_units_onboard; unit++) {
l2addr.port = CMIC_PORT(unit);
bcm_l2_addr_add(unit, &l2addr);
}
return 0;
}
/*
* zhouguis changed this 2005-11-28
*/
void stp_set_mac_address(spantree_t *stp)
{
char mac[6];
sysSwitchAddrGet(mac);
sal_memcpy(stp_bridge_mac, mac, 6);
sal_memcpy((stp->bridge_id + 2), mac, 6);
return;
}
/*
* Function:
* stp_do_start_mode
* Purpose:
* callback for stack up/down
* Parameters:
* stk_mode - TRUE if stack is up, FALSE if down.
* Returns:
* number of modules
*/
void
stp_do_start_mode(int stk_mode, void *cookie)
{
spantree_t *stp;
/* One time initialization, register link scan callback, PMUX */
if (!stp_sys_initialized) {
stp_sys_init();
stp_save_stk_info(stk_mode);
stp_sys_initialized = 1;
}
if (stk_mode) {
trace(TRACE_STP, TR_LOGIT,
"\nSTP in stack mode - # CPUs %d, my CPU ID %d\n",
stp_stk_num_cpu, stp_my_cpuid);
} else {
/* debugk(DK_STP,"\nSTP starts in stand alone mode\n");*/
}
if (cookie == NULL) { /* call back from MDP */
/* change from stacking mode to non-stacking mode, stop RDP */
if(stp_stack_ready && !stk_mode) {
rdp_rcv_unregister(BCM_RDP_ID_STP, stp_rcv_rdp_data);
rdp_cleanup();
}
stp_stack_ready = stk_mode;
/* In stack mode, make sure RDP is started on all modules */
if (stk_mode) {
rdp_init(stp_my_cpuid, stp_stk_num_cpu);
rdp_rcv_register(BCM_RDP_ID_STP, stp_rcv_rdp_data);
}
FOR_ALL_STP(stp) {
stp_deactivate_spantree(stp);
stp_delete_all_port(stp);
stp_set_spantree_mac_address(stp, stp_bridge_mac);
stp_set_mac_address(stp);
activate_spantree(stp);
stp_port_add(stp, stk_mode);
}
} else {
stp = (spantree_t *)cookie;
stp_set_spantree_mac_address(stp, stp_bridge_mac);
stp_set_mac_address(stp);
activate_spantree(stp);
stp_port_add(stp, stk_mode);
}
}
/*
* Function:
* stp_start
* Purpose:
* Start Spanning Tree (called from CLI command)
* Parameters:
* unit - Device unit number on which to run mdp
* tree_id - stp instance ID which is VLAN ID
* stack_mode - stack mode ?
* stk_port - stack port
*/
int
stp_start(stp_id_t tree_id, int stack_mode, int stk_unit, int stk_port)
{
spantree_t *stp;
uint8 *stp_name;
int mdp_state;
int unit;
if (!stp_sys_initialized) {
stp_all_units_onboard = soc_ndev_attached;
}
stp_name = sal_alloc(STP_NAME_SIZE, "stp");
sal_sprintf(stp_name, "STP group %d", tree_id);
/*
* all STP instances must agree on the stack mode
*/
if (stp_instance_q == NULL) { /* this is the first STP instance */
stp_stack_unit = stk_unit;
stp_stack_mode = stack_mode;
stp_stack_port = stk_port;
/* create STP instance */
if (stp_create_instance(&stp, tree_id, stp_name) < 0) {
sal_free(stp_name);
return -1;
}
stp->l2_age = 300;
stp_get_common_config_from_db(stp);
for (unit = 0; unit < stp_all_units_onboard; unit++) {
bcm_l2_age_timer_set(unit, stp->l2_age);
}
if (!stack_mode) {
mdp_state_get(&mdp_state);
if (mdp_state > 0) {
mdp_get_unit(&stp_stack_unit, &stp_stack_port);
stp_stack_mode = 1;
mdp_register_callback(stp_do_start_mode, NULL);
} else {
stp_do_start_mode(0, (void*)stp);
}
} else {
mdp_start(stk_unit, stp_stack_port, STK_SL, 1, stp_do_start_mode, NULL);
}
} else {
/* create STP instance */
if (stp_create_instance(&stp, tree_id, stp_name) < 0) {
sal_free(stp_name);
return -1;
}
stp->l2_age = 300;
stp_get_common_config_from_db(stp);
for (unit = 0; unit < stp_all_units_onboard; unit++) {
bcm_l2_age_timer_set(unit, stp->l2_age);
}
stp_do_start_mode(stp_stack_mode, (void*)stp);
}
return 0;
}
/*
* Function:
* stp_stop
* Purpose:
* Stop Spanning Tree
*/
void
stp_stop(stp_id_t tree_id)
{
spantree_t *stp;
int unit;
bcm_stg_t stg;
stp = stp_lookup_from_stp_id(tree_id);
if (stp == NULL) {
return;
}
sal_free(stp->namestring);
stp_delete_instance(stp);
stg = search_stg_through_vlan(tree_id);
for (unit = 0; unit < stp_all_units_onboard; unit++) {
bcm_stg_destroy(unit, stg);
}
stp_trunk_clean_tree_info(tree_id);
}
/*
* Function:
* stp_set_age_timer
* Purpose:
* Set the STP age timer
* Parameters:
* t - new timer value
* Returns:
* none
*/
void
stp_set_age_timer(stp_id_t tree_id, int t)
{
spantree_t *stp;
int unit;
stp = stp_lookup_from_stp_id(tree_id);
if (stp == NULL) {
return;
}
/* enable hardware aging of L2 table */
stp->l2_age = t;
for (unit = 0; unit < stp_all_units_onboard; unit++) {
bcm_l2_age_timer_set(unit, t);
}
if (stp_stack_ready) {
stp_send_timer_info(tree_id, t, STP_RDP_AGE_TIMER);
}
}
/*
* Function:
* stp_set_hello_interval
* Purpose:
* Set STP HELLO interval
* Parameters:
* t - New STP HELLO interval
* Returns:
* none
*/
void
stp_set_hello_interval(stp_id_t tree_id, uint16 t)
{
spantree_t *stp;
stp = stp_lookup_from_stp_id(tree_id);
if (stp == NULL) {
return;
}
set_hello_interval_api(stp, t);
if (stp_stack_ready) {
stp_send_timer_info(tree_id, t, STP_RDP_HELLO_TIME);
}
}
/*
* Function:
* stp_set_max_age
* Purpose:
* Set max age timer value
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -