📄 stp_api.c
字号:
/***********************************************************************
* Copyright (C) 2005,UNE Corporation.
*
* File Name: stp_api.c
* File Mark: Multiple Spanning Tree (PVST) API functions
* Description:
* Others:
* Note:
* 1. Although the spanning tree software supports multiple
* spanning tree, on early StrataSwitch based systems
* (BCM5600, BCM5680) which do not have spanning tree group
* table, only one instance of STP can be ran. Later
* generations of chip (Starta II, XGS) supports up to
* 256 instances of spanning tree.
* 2. Multiple instances of Spanning Tree all share one thread.
* which are started when the first instance of STP is started,
* and teared down when the last instance of STP exits.
* 3. Only supports IEEE 802.1D spanning tree, doesn't support
* IBM or DEC spanning tree.
* Version: V1.0
* Author:
* Date:
* History 1:
* Date:
* Version:
* Author:
* Modification:
* History 2: …
**********************************************************************/
#include <vxWorks.h>
#include <sysLib.h>
#include <stdio.h>
#include <stdLib.h>
#include <fioLib.h>
#include <sal/kern/libc.h>
#include <sal/user/sal.h>
#include <sal/user/io.h>
#include <sys/types.h>
#include <soc/mem.h>
#include <soc/drv.h>
#include <soc/types.h>
#include <soc/util.h>
#include <soc/debug.h>
#include <bcm/error.h>
#include <bcm/pmux.h>
#include <bcm/port.h>
#include <bcm/stg.h>
#include <bcm/packet.h>
#include <bcm/l2.h>
#include <bcm/mirror.h>
#include <bcm/stack.h>
#include <diag/system.h>
#include <stacking/trace.h>
#include <stacking/stk_transport.h>
#include <stacking/stk_platform.h>
#include <stacking/simplex.h>
#include <stacking/chassis.h>
#include <stacking/rdp.h>
#include <stp/stp.h>
#include <stp/stp_api.h>
#include <stp/stp_appl.h>
#include <stp/stp_trunk.h>
#include "txtdb/h/dbfileCnfg.h"
extern STATUS sysSwitchAddrGet(char macaddr[6]);
extern int trunk_number_get();
extern int bcm_port_link_status_get(int unit, bcm_port_t port, int *up);
extern int bcm_vlan_port_get(int unit, bcm_vlan_t vid, pbmp_t *pbmp, pbmp_t *ubmp);
extern int search_stg_through_vlan(bcm_vlan_t vid);
extern void decrease_stg_number(vlan_id_t vid);
extern int strcasecmp(const char* s1, const char* s2);
/*
* BPDU packet destination address
*/
static
mac_addr_t stp_bridge_group_addr = {0x1, 0x80, 0xc2, 0x00, 0x00, 0x00};
edgeport_table_t edgeport_array[24] =
{
{"edgevalue1" , 0 },
{"edgevalue2" , 0 },
{"edgevalue3" , 0 },
{"edgevalue4" , 0 },
{"edgevalue5" , 0 },
{"edgevalue6" , 0 },
{"edgevalue7" , 0 },
{"edgevalue8" , 0 },
{"edgevalue9" , 0 },
{"edgevalue10" , 0 },
{"edgevalue11" , 0 },
{"edgevalue12" , 0 },
{"edgevalue13" , 0 },
{"edgevalue14" , 0 },
{"edgevalue15" , 0 },
{"edgevalue16" , 0 },
{"edgevalue17" , 0 },
{"edgevalue18" , 0 },
{"edgevalue19" , 0 },
{"edgevalue20" , 0 },
{"edgevalue21" , 0 },
{"edgevalue22" , 0 },
{"edgevalue23" , 0 },
{"edgevalue24" , 0 }
};
/*
* find a spanning tree, given an external STP ID
*/
spantree_t *
stp_lookup_from_stp_id(stp_id_t stree_id)
{
spantree_t *stp;
FOR_ALL_STP(stp) {
if (stp->external_id == stree_id) {
return (stp);
}
}
return (NULL);
}
/*
* Insert a spanning tree instance into the instance queue
*/
static void
stp_insert_instance(spantree_t *stp)
{
stp->next = stp_instance_q;
stp_instance_q = stp;
}
/*
* Remove a spanning tree instance from the instance queue
*/
static void
stp_detach_instance(spantree_t *stp)
{
spantree_t *entry;
if (stp == stp_instance_q) {
stp_instance_q = stp->next;
return;
}
FOR_ALL_STP(entry) {
if (entry->next == stp) {
break;
}
}
entry->next = stp->next;
}
/*
* create a spanning tree instance
*/
int
stp_create_instance(spantree_t **stp_out, stp_id_t tree_id, uint8 *namestring)
{
spantree_t *stp;
/* make sure STP ID does not exist yet */
if ((stp = stp_lookup_from_stp_id(tree_id)) != NULL ) {
printk("stp_create_instance: tree_id exists\n");
*stp_out = stp;
return (-1);
}
/* Allocate spanning tree data structure */
stp = (spantree_t *)sal_alloc(sizeof(spantree_t), "stp");
if (stp == NULL) {
return (-1);
}
/* Allocate buffer for transfering BPDU messages */
stp->bpdu_send_buff = sal_dma_alloc(ENET_MAX_SIZE, "stp");
if (stp->bpdu_send_buff == NULL) {
sal_free(stp);
*stp_out = NULL;
return (-1);
}
*stp_out = stp;
stp->external_id = tree_id;
stp->running = FALSE;
stp->namestring = namestring;
sal_memcpy(stp->bpdu_mac, stp_bridge_group_addr, 6);
/* empty port list */
stp->port_list.next = &stp->port_list;
stp->port_list.prev = &stp->port_list;
stp->port_count = 0;
/* Bridge ID */
sal_memset(stp->bridge_id, 0, ID_BYTES);
/* added by zhouguis 2005-11-29 */
stp_set_mac_address(stp);
/* Set span tree parameters to default value */
stp_config_params_set(stp, NULL);
/* Start stp thread if not already started */
if (start_stp_process() < 0) {
sal_free(stp);
return (-1);
}
/* now we have a valid STP instance, insert into STP list */
stp_insert_instance(stp);
return (0);
}
/*
* delete a spanning tree instance
*/
int
stp_delete_instance(spantree_t *stp)
{
/*
* if the stp is currently active, suspend it first
*/
if (stp_is_running(stp)) {
stp_deactivate_spantree(stp);
}
/* STP is stopped, free up all the port structures */
/* added by zgs 只有是缺省STP条件或者停止所有生成树的条件下才删除。*/
if((stp->external_id == 1) ||(stp_get_stop_method()))
{
while (stp->port_list.next != &stp->port_list) {
stp_delete_stp_port(stp->port_list.next);
}
}
else /* 否则把端口添加到缺省STP中去。*/
{
while (stp->port_list.next != &stp->port_list) {
stp_moveporto_defaultstp(stp->port_list.next);
}
}
/* remove from STP instances list */
stp_detach_instance(stp);
/* free the packet buffer */
if (stp->bpdu_send_buff) {
sal_dma_free(stp->bpdu_send_buff);
}
sal_free(stp);
/* kill the thread if there is no STP instances */
if (stp_instance_q == NULL) {
stp_process_teardown();
}
/*zhouguis moved this to no stp command*/
return 0;
}
/*
* Set the MAC address for a spanning tree when creating
* a new STP instance structure.
* Note: Use set_bridge_id_api() to set bridge ID after STP is running.
*/
int
stp_set_spantree_mac_address(spantree_t *stp, uint8 *bridge_mac)
{
uint16 temp_vid;
soc_htons_store(stp->bridge_id, STP_DEF_BRIDGE_PRIORITY);
/* zgs added vlan id to bridge priority 2005-11-29 */
temp_vid = stp->external_id;
stp->bridge_id[1] = temp_vid & 0x00ff;
stp->bridge_id[0] = (stp->bridge_id[0] |((temp_vid >> 8) & 0x000f) );
sal_memcpy((stp->bridge_id + 2), bridge_mac, 6);
return (0);
}
/*
* return the MAC address of a spanning tree
*/
int
stp_get_spantree_mac_address(spantree_t *stp, uint8 *mac_address)
{
if (mac_address == NULL) {
return (-1);
} else {
sal_memcpy(mac_address, (stp->bridge_id + 2), 6);
}
return (0);
}
/*
* return a boolean indication as to whether a spanning tree is running
*/
int
stp_is_running(spantree_t *stp)
{
return (stp->running);
}
/*
function name:stp_get_count
function description:get number of stp
input:none
output:count---number of stp
return:
number of stp
*/
int
stp_get_count(int *count)
{
spantree_t *stp;
*count=0;
FOR_ALL_STP(stp) {
(*count)++;
}
return *count;
}
/*
function name:stp_get_stp_id_by_number
function description:get external stp id through internal id
input:counte----stp internal id
output:none
return:
stp external id
*/
uint32
stp_get_stp_id_by_number(int count)
{
spantree_t *stp;
int internal_count=0;
FOR_ALL_STP(stp) {
if (internal_count==(count)) {
return (stp->external_id);
}
else
{
internal_count++;
}
}
return 0;
}
/*
* given an external ID(a.k.a logical port number), find a spanning tree port
*/
stp_port_t *
stp_port_lookup_from_id(spantree_t *stp, int lport)
{
stp_port_t *port;
FOR_ALL_PORTS_IN_STP(stp, port) {
if (port->lport == lport) {
return (port);
}
}
/* not found */
return ((stp_port_t *)NULL);
}
/*
* dll_insert - insert new "entry" into a doubly-linked list after "pred".
* Note: an empty list is formed by having the initial element
* have both the next and prev point to itself. Think of this
* as a circular list rather than a simple double-linked list where
* the terminal elements point to NULL.
*/
STATIC void
dll_insert(stp_port_t *entry, stp_port_t *pred)
{
pred->next->prev = entry;
entry->next = pred->next;
entry->prev = pred;
pred->next = entry;
}
/*
* dll_remove - remove an "entry" from a doubly-linked list.
* Note: the removed element has its next & prev set to point to itself.
*/
STATIC void
dll_remove(stp_port_t *entry)
{
entry->prev->next = entry->next;
entry->next->prev = entry->prev;
entry->next = entry->prev = entry;
}
/*
* Add port into spanning tree port list
*/
static void
stp_port_list_insert(spantree_t *stp, stp_port_t *port)
{
stp_port_t *port_ndx;
if (stp->port_list.next == &stp->port_list) { /* list is empty */
dll_insert(port, &stp->port_list);
} else {
/*
* insert port in increasing port number, so we get nice view
* from show command. This is not required by STP protocol
*/
FOR_ALL_PORTS_IN_STP(stp, port_ndx) {
if (port_ndx->lport > port->lport) {
break;
}
}
/* link into the doubly-linked list */
dll_insert(port, port_ndx->prev);
}
}
/*
* Create a spanning tree port data structure
*/
int
stp_create_stp_port(stp_port_t **stport_out, spantree_t *stp,
int lport, uint8 *namestring)
{
stp_port_t *stport;
char mac[6];
/* make sure theres no collision on port id */
if ((stport = stp_port_lookup_from_id(stp, lport)) != NULL) {
printk("stp_create_stp_port: port exists\n");
*stport_out = stport;
return (-1);
}
/* create a spanning tree port data structure */
stport = (stp_port_t *)sal_alloc(sizeof(*stport), "stp port");
if (stport == NULL) {
*stport_out = NULL;
return (-1);
}
sal_memset(stport, 0, sizeof(stp_port_t));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -