📄 stp_appl.c
字号:
/***********************************************************************
* Copyright (C) 2005,UNE Corporation.
*
* File Name: stp_appl.c
* File Mark: A sample Spanning Tree application built on the
Broadcom multiple spanning tree API (PVST)
(see stp_process.c and stp_api.c). This demostrates
STP working on Broadcom SDKs in either standalone mode
or simplex stacking mode.
* Description:
* Others:
* Note:
* This sample STP code supports standalone mode.
* In stacking mode, only simplex stacking is supported now.
* Version: V1.0
* Author:
* Date:
* History 1:
* Date:
* Version:
* Author:
* Modification:
* History 2: …
**********************************************************************/
#include <sal/user/sal.h>
#include <sal/user/io.h>
#include <sal/user/config.h>
#include <sys/types.h>
#include <soc/mem.h>
#include <soc/drv.h>
#include <soc/arl.h>
#include <soc/debug.h>
#include <diag/system.h>
#include <diag/rhosvlantable.h>
#include <bcm/init.h>
#include <bcm/l2.h>
#include <bcm/link.h>
#include <bcm/error.h>
#include <bcm/pmux.h>
#include <bcm/stg.h>
#include <bcm/vlan.h>
#include <bcm/port.h>
#include <bcm/cosq.h>
#include <bcm/stack.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"
#include "taskLib.h"
#define STP_NAME_SIZE 20
/*
* Received BPDU packet
*/
typedef struct stp_pkt_s {
uint8 *mac_start; /* pointer to MAC header */
uint8 *ieee_start; /* pointer to network layer header */
int size; /* Length of raw packet data */
int unit; /* ingress unit */
int port; /* input port */
} stp_pkt_t;
typedef struct stp_pkt_queue_s {
stp_pkt_t *pakq; /* the packet queue */
int total; /* total queue size */
int count; /* number of packet in queue */
int head;
int tail;
int drop; /* dropped packets */
sal_thread_t pkt_thread;
sal_sem_t pkt_sem;
int thread_exit;
} stp_pkt_queue_t;
#define STP_QUEUE_SIZE 128
/* Global Variables */
uint16 stp_my_cpuid = 1;
uint16 stp_stk_num_cpu = 1;
int stp_stack_unit = 0;
int stp_stack_port = 0;
int stp_stack_ready = FALSE;
/* zhouguis added this for vlan mapping to stg */
typedef struct vlan_stg_mapping_t
{
bcm_vlan_t vlan;
bcm_stg_t stg;
}vlan_stg_mapping_s;
vlan_stg_mapping_s vlan_stg_mapping_table[256];
SEM_ID rhosStpLock = NULL; /*sem for l2_igmp*/
#define STP_LOCK() semTake(rhosStpLock,WAIT_FOREVER) /* igmp lock */
#define STP_UNLOCK() semGive(rhosStpLock)
/* Local variables */
static mac_addr_t stp_bridge_mac;
static int stp_stack_mode = 0;
static cpu_mod_info_t stp_stk_modinfo[STACK_MAX_CPUS];
static stp_pkt_queue_t stpQ;
static int stp_sys_initialized = 0;
static int stp_all_units_onboard = 0;
/*
* Function Declarations
*/
static void stp_do_start_mode(int, void *cookie);
static void stp_packet_thread(void *param);
static int stp_get_num_ports(int type);
static void init_clear_all_mapping_table(void);
static bcm_stg_t find_newstg_forvlan(vlan_id_t vid);
int search_stg_through_vlan(bcm_vlan_t vid);
extern STATUS sysSwitchAddrGet(char macaddr[6]);
extern BOOL rhos_trunk_isexist(int port);
#define STP_LP_PORT_SHIFTS 0
#define STP_LP_UNIT_SHIFTS 5
#define STP_LP_CPU_SHIFTS 8
#define STP_LP_TOTAL_BITS 12
/*
* Note: Logical port is 12 bits, used in the lower 12 bits
* of port ID field of BPDU, the upper 4 bits of Port ID
* field is the port priority. - Broadcom specific
* IEEE 802.1D actually dictates that the upper 8 bits to
* be the port priority, lower 8 bits to be port number.
* But this means max of 255 ports
*
* +------+-------+-------+
* |cpu(4)|unit(3)|port(5)|
* +------+-------+-------+
*
* Another way to do port numbering is continously count
* all ports from CPU 1, UNIT 0, 1 ... CPU 2, UNIT 0, 1 ...
* CPU3, UNIT 0, 1, ..., but this is obvious not as efficient as above
*/
/*
* translate between physical port number to logical port
*/
int
stp_port_p2l(int cpu, int unit, int pport)
{
return ((cpu << STP_LP_CPU_SHIFTS) | (unit << STP_LP_UNIT_SHIFTS) | pport);
#if 0
int lport = 1;
int c, u;
for (c = 1; c < cpu; c++) {
for (u = 0; u < stp_stk_modinfo[c].num_chip; u++) {
lport += stp_get_num_ports(stp_stk_modinfo[c].chip[u].chip_type);
}
}
for (u = 0; u < unit; u++) {
lport += stp_get_num_ports(stp_stk_modinfo[cpu].chip[u].chip_type);
}
lport += pport;
return lport;
#endif
}
/*
* translate between logical port number to physical port
*/
int
stp_port_l2p(int lport)
{
return (lport & 0x1f);
#if 0
int pport, c, u;
int no_ps;
pport = lport-1;
for (c = 1; c <= stp_stk_num_cpu; c++) {
for (u = 0; u < stp_stk_modinfo[c].num_chip; u++) {
no_ps = stp_get_num_ports(stp_stk_modinfo[c].chip[u].chip_type);
if (pport < no_ps) {
return pport;
} else {
pport -= no_ps;
}
}
}
return pport;
#endif
}
/*
* translate between logical port number to SOC unit
*/
int
stp_port_l2unit(int lport)
{
return ((lport >> STP_LP_UNIT_SHIFTS) & 0x07);
#if 0
int pport, c, u;
int no_ps;
pport = lport-1;
for (c = 1; c <= stp_stk_num_cpu; c++) {
for (u = 0; u < stp_stk_modinfo[c].num_chip; u++) {
no_ps = stp_get_num_ports(stp_stk_modinfo[c].chip[u].chip_type);
if (pport < no_ps) {
return u;
} else {
pport -= no_ps;
}
}
}
return 0;
#endif
}
/*
* returns the module number this logical port belongs to
*/
int
stp_port_l2cpu(int lport)
{
return ((lport >> STP_LP_CPU_SHIFTS) & 0x0f);
#if 0
int pport, c, u;
int no_ps;
pport = lport-1;
for (c = 1; c <= stp_stk_num_cpu; c++) {
for (u = 0; u < stp_stk_modinfo[c].num_chip; u++) {
no_ps = stp_get_num_ports(stp_stk_modinfo[c].chip[u].chip_type);
if (pport < no_ps) {
return c;
} else {
pport -= no_ps;
}
}
}
return 1;
#endif
}
/*
* Function:
* stp_sys_alloc
* Purpose:
* Allocate DMA memory
* Parameters:
* unit - SOC unit #
* size - number of bytes
* flags -
* Returns:
* Pointer to allocated memory or NULL
*/
static void * stp_sys_alloc(int unit, int size, uint32 flags)
{
#if 0
return sal_dma_alloc(size, "stp");
#else
return NULL;
#endif
}
/*
* Function:
* stp_sys_free
* Purpose:
* Free DMA memory
* Parameters:
* unit - SOC unit #
* ptr - Pointer to memory to be freed
* Returns:
*/
static void stp_sys_free(int unit, void* ptr)
{
#if 0
sal_dma_free(ptr);
#else
printk("Shound not call this function to free buffer\n");
#endif
}
/*
* Function:
* stp_rcv_port_info
* Purpose:
* Handles port info packets received from other CPUs of stack
* Parameters:
* value - port info
*/
static void
stp_rcv_port_info(stp_id_t tree_id, void *value, int s_cpu)
{
spantree_t *stp;
stp_port_t *stport;
stp_rdp_port_t *pi;
int lport, type, status, porttype;
pi = (stp_rdp_port_t *)value;
lport = soc_ntohl(pi->lport);
porttype = pi->porttype;
type = pi->info_type;
status = soc_ntohs(pi->status);
stp = stp_lookup_from_stp_id(tree_id);
if (stp == NULL) {
return;
}
switch (type) {
case STP_PORT_INFO_STACK:
if (status == 1) {
stp_mark_stack_port(stp, lport);
}
break;
case STP_PORT_INFO_LINK:
if (status == 0) { /* link down */
trace(TRACE_STP, TR_VERBOSE, "stp_rcv_port_info:port %d down\n", lport);
stp_link_down(stp, lport);
} else {
trace(TRACE_STP, TR_VERBOSE, "stp_rcv_port_info:port %d up\n", lport);
if (stp_create_stp_port(&stport, stp, lport, "stp port") < 0) {
return;
}
stport->cpu = s_cpu;
stport->port_type = porttype;
stp_link_up(stp, stport, status); /* status is speed for link up */
}
break;
case STP_PORT_INFO_ENABLE:
if (status == 1) {
stp_port_enable(stp, lport);
} else {
stp_port_disable(stp, lport);
}
break;
}
return;
}
/*
* Function:
* stp_rcv_bpdu_info
* Purpose:
* Handles BPDU packets received from other modules of stack
* Parameters:
* value - bpdu info
*/
static void
stp_rcv_bpdu_info(stp_id_t tree_id, void *value, int s_cpu)
{
stp_bpdu_info_t *bpdu;
int lport;
bpdu = (stp_bpdu_info_t *)value;
lport = soc_ntohl(bpdu->lport);
stp_handle_bpdu_packet(tree_id, (uint8 *)bpdu->bpdu, lport);
return;
}
/*
* Function:
* stp_rcv_timer_info
* Purpose:
* Handles timer packets received from other modules of stack
* Parameters:
* data - timer info
*/
static void
stp_rcv_timer_info(stp_id_t tree_id, void *data, int s_cpu)
{
stp_rdp_timer_t *timer_info;
spantree_t *stp;
uint16 value;
uint16 type;
int unit;
timer_info = (stp_rdp_timer_t *)data;
stp = stp_lookup_from_stp_id(tree_id);
if (stp == NULL) {
return;
}
type = soc_ntohs(timer_info->type);
value = soc_ntohs(timer_info->value);
/* Set timer info in the local module */
switch (type) {
case STP_RDP_HELLO_TIME:
set_hello_interval_api(stp, value);
break;
case STP_RDP_MAX_AGE:
set_max_age_api(stp, value);
break;
case STP_RDP_FWD_DELAY:
set_forward_delay_api(stp, value);
break;
case STP_RDP_AGE_TIMER:
/* enable hardware aging of L2 table */
stp->l2_age = value;
for (unit = 0; unit < stp_all_units_onboard; unit++) {
bcm_l2_age_timer_set(unit, value);
}
break;
default:
break;
}
return;
}
/*
* Function:
* stp_rcv_rdp_data
* Purpose:
* Handle data exchanged between modules on the stack
* Parameters:
* data - packet pointer
* length - length of packet
*/
static void
stp_rcv_rdp_data(uint32 clientid, void *data, int length, int s_cpu)
{
stp_rdp_data_t *rdpd;
stp_id_t tree_id;
rdpd = (stp_rdp_data_t *)data;
tree_id = soc_ntohs(rdpd->tree_id);
switch (soc_ntohs(rdpd->type)) {
case STP_RDP_BPDU_DATA:
stp_rcv_bpdu_info(tree_id, (void*)rdpd->value, s_cpu);
break;
case STP_RDP_PORT_DATA:
stp_rcv_port_info(tree_id, (void *)rdpd->value, s_cpu);
break;
case STP_RDP_TIMER_DATA:
stp_rcv_timer_info(tree_id, (void *)rdpd->value, s_cpu);
break;
}
return;
}
/*
* RDP port/bpdu/timer information send call back function
*/
void
stp_rdp_send_callback(uint32 clientid, void *data, int status)
{
sal_free(data);
}
/*
* Function:
* stp_send_port_info
* Purpose:
* Send port info to other modules in the stack when
* local port status changes.
* Parameters:
* tree_id - STP instance ID
* lport - port whose link state changed
* type - what type of port info
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -