⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stp_appl.c

📁 stp代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/***********************************************************************
* 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 + -