📄 stp_api.c
字号:
stport->next = stport;
stport->prev = stport;
stport->stp = stp;
stport->lport = lport;
stport->namestring = namestring;
stport->state = STP_DISABLED; /* Disable port until it is enabled */
/* stport->port_id = (uint16)((STP_DEF_PORT_PRIORITY << 12) | lport);*/
/* zhouguis changed this 2005-12-22 */
stport->port_id = (uint16)(STP_DEF_PORT_PRIORITY << 8);
stport->path_cost = STP_PATH_COST_100MB; /* default */
stport->port_type = STP_PORT_TYPE_FE;
stport->link_flags = 0;
stport->bpdu_out = 0;
stport->bpdu_in = 0;
/* default port mac address, use stp_set_stport_mac_address to change it */
/* changed by zhouguis 2005-11-25 */
/*
sal_memcpy(stport->mac_addr, (stp->bridge_id + 2), 6);
stport->mac_addr[4] += lport / 256;
stport->mac_addr[5] = lport % 256;
*/
sysSwitchAddrGet(mac);
sal_memcpy(stport->mac_addr, mac, 6);
stport->mac_addr[4] += lport / 256;
stport->mac_addr[5] = lport % 256;
stp_port_list_insert(stp, stport);
stp->port_count++;
*stport_out = stport;
return 0;
}
/*
* Delete a spanning tree port data structure
*/
int
stp_delete_stp_port(stp_port_t *stport)
{
spantree_t *stp;
stp = stport->stp;
/* tell stp to stop timers and etc */
if (stport->state != STP_DISABLED) {
disable_port(stp, stport);
stp_port_state_set(stp, stport, STP_FORWARDING);
}
/* unlink the port from the STP port list */
dll_remove(stport);
stp->port_count--;
sal_free(stport);
return 0;
}
/*
* Delete all ports from STP
*/
int
stp_delete_all_port(spantree_t *stp)
{
stp_port_t *port;
while (stp->port_list.next != &stp->port_list) {
port = stp->port_list.next;
dll_remove(port);
sal_free(port);
}
stp->port_count = 0;
return 0;
}
/*
* Set the MAC address for a spanning tree port
*/
int
stp_set_stport_mac_address(stp_port_t *port, uint8 *port_mac)
{
sal_memcpy(port->mac_addr, port_mac, 6);
return (0);
}
/*
* return the MAC address of a spanning tree port
*/
int
stp_get_stport_mac_address(stp_port_t *port, uint8 *port_mac)
{
if (port_mac == NULL) {
return (-1);
} else {
sal_memcpy(port_mac, port->mac_addr, 6);
}
return (0);
}
/*
* Initialize bridge wide parameters to default values
*/
void
stp_config_params_set(spantree_t *stp, stp_params_t *in)
{
if (in == NULL) {
stp->bridge_max_age = STP_DEF_MAX_AGE;
stp->bridge_hello_time = STP_DEF_HELLO_TIME;
stp->bridge_forward_delay = STP_DEF_FWD_DELAY;
stp->hold_time = STP_HOLD_TIME;
stp->saved_priority = STP_DEF_BRIDGE_PRIORITY;
} else {
stp->bridge_max_age = in->max_age_interval;
stp->bridge_hello_time = in->hello_interval;
stp->bridge_forward_delay = in->forward_delay;
stp->hold_time = in->hold_time;
}
stp->topology_change_time = stp->bridge_max_age + stp->bridge_forward_delay;
}
/*
* return the configuration parameters of a spanning tree
*/
int
stp_get_spanning_tree_parms(spantree_t *stp, stp_params_t *out)
{
out->max_age_interval = stp->bridge_max_age;
out->hello_interval = stp->bridge_hello_time;
out->forward_delay = stp->bridge_forward_delay;
out->hold_time = stp->hold_time;
return (0);
}
/*
* Set forward delay time value
*/
void
set_forward_delay_api(spantree_t *stp, uint16 t)
{
if (t < STP_MIN_FWD_DELAY || t > STP_MAX_FWD_DELAY) {
return;
}
stp->bridge_forward_delay = t;
stp->topology_change_time = stp->bridge_max_age + stp->bridge_forward_delay;
}
/*
* Set max age timer value
*/
void
set_max_age_api(spantree_t *stp, uint16 t)
{
if (t < STP_MIN_MAX_AGE || t > STP_MAX_MAX_AGE) {
return;
}
stp->bridge_max_age = t;
stp->topology_change_time =
stp->bridge_max_age + stp->bridge_forward_delay;
}
/*
* Set STP HELLO interval
*/
void
set_hello_interval_api(spantree_t *stp, uint16 t)
{
if (t < STP_MIN_HELLO_TIME || t > STP_MAX_HELLO_TIME) {
return;
}
stp->bridge_hello_time = t;
}
/*
* Function:
* stp_send_config_bpdu
* Purpose:
* Send config BPDU packet out on lport(called from stp.c)
* Parameters:
* lport - logical port
* bpdu - BPDU message
* Returns:
* none
*/
void
stp_send_config_bpdu(spantree_t *stp, stp_port_t *stport, Config_bpdu *bpdu)
{
tag_bpdu_packet_t *enet_hdr;
bpdu_config_t *bpdu_msg;
int enet_hdr_len, plen;
int flag;
pbmp_t pbm, upbm;
if (!stp_is_running(stp)) {
return;
}
/* Only send BPDU for local ports in stacking mode */
if (!(stport->link_flags & STP_LF_LOCAL)) {
return;
}
/*
* BPDU ethernet header
*/
sal_memset(stp->bpdu_send_buff, 0, sizeof(stp->bpdu_send_buff));
enet_hdr = (tag_bpdu_packet_t *)stp->bpdu_send_buff;
enet_hdr_len = STP_BPDU_TAG_802_LEN; /* STP_BPDU_802_LEN */
bpdu_msg = (bpdu_config_t *)((uint8*)stp->bpdu_send_buff + enet_hdr_len);
/* 802.3 destination MAC address */
sal_memcpy(enet_hdr->da, stp->bpdu_mac, 6);
/* 802.3 source MAC address */
sal_memcpy(enet_hdr->sa, stport->mac_addr, 6);
/* tagged 802 packet */
enet_hdr->type = soc_htons(0x8100);
enet_hdr->vtag = soc_htons(stp->external_id);
/*enet_hdr->vtag = soc_htons(0x0002);*/
/* 802 tagged length */
enet_hdr->tlen = soc_htons(STP_CONFIG_BPDU_LENGTH + 3);
/* LSAP for BPDU is 0x42(0100 0010), 802.3 CTL is 0x03 */
enet_hdr->dsap = BPDU_SAP;
enet_hdr->ssap = BPDU_SAP;
enet_hdr->ctrl = 0x03;
/*
* BPDU data
*/
/* Protocol identifier (Always 0) */
bpdu_msg->identifier[0] = 0;
bpdu_msg->identifier[1] = 0;
/* Protocol Version (Always 0) */
bpdu_msg->version = 0;
/* message type */
bpdu_msg->msg_type = bpdu->type;
/* TCA, TC flags */
bpdu_msg->flags = (bpdu->tc_acknowledgment ? 0x80 : 0x00);
if (bpdu->topology_change) {
bpdu_msg->flags |= 0x01;
}
/* root ID */
sal_memcpy(bpdu_msg->root_id, bpdu->root_id, ID_BYTES);
/* root path cost */
soc_htonl_store(bpdu_msg->root_path_cost, bpdu->root_path_cost);
/* bridge ID */
sal_memcpy(bpdu_msg->bridge_id, bpdu->bridge_id, ID_BYTES);
/* port ID */
soc_htons_store(bpdu_msg->port_id, bpdu->port_id);
/* Message age */
soc_htons_store(bpdu_msg->message_age, (bpdu->message_age << 8));
/* max age */
soc_htons_store(bpdu_msg->max_age, (bpdu->max_age << 8));
/* hello time */
soc_htons_store(bpdu_msg->hello_time, (bpdu->hello_time << 8));
/* forward delay */
soc_htons_store(bpdu_msg->forward_delay, (bpdu->forward_delay << 8));
trace(TRACE_STP, TR_VERBOSE, "Send config BPDU on port: %d\n", get_global_port(stport->unit,stport->port));
trace(TRACE_STP, TR_VERBOSE,
"Type %x RootId:%08x%08x PathCost:%d BridgeId:%08x%08x\n",
bpdu->type, soc_ntohl_load(bpdu->root_id),
soc_ntohl_load(bpdu->root_id + 4),
bpdu->root_path_cost, soc_ntohl_load(bpdu->bridge_id),
soc_ntohl_load(bpdu->bridge_id + 4));
trace(TRACE_STP, TR_VERBOSE,
"PortId %04x MsgAge %d MaxAge %d HelloTime %d, FwdDelay %d",
bpdu->port_id, bpdu->message_age, bpdu->max_age,
bpdu->hello_time, bpdu->forward_delay);
trace(TRACE_STP, TR_VERBOSE, " ACK %d top %d\n",
bpdu->tc_acknowledgment, bpdu->topology_change);
{ /*对于非TRUNK口 我们应该只对这个端口发送 2005-12-09*/
/* Must send 802.1Q tagged packet, otherwise the VLAN ID will be lost */
SOC_PBMP_CLEAR(pbm);
SOC_PBMP_CLEAR(upbm);
SOC_PBMP_PORT_ADD(upbm, stport->port);
SOC_PBMP_PORT_ADD(pbm, stport->port);
plen = (STP_CONFIG_BPDU_LENGTH + enet_hdr_len + 3)&~0x3; /* round to x*4 bytes */
flag = BCM_PACKET_CRC_APPEND | BCM_PACKET_COS(1);
bcm_packet_send_pbmp(stport->unit, pbm, upbm,
stp->bpdu_send_buff, plen, flag);
}
stport->bpdu_out++;
#ifdef STP_DEBUG
stk_pak_dump(stp->bpdu_send_buff, plen);
#endif
return;
}
/*
* Function:
* stp_send_tcn_bpdu
* Purpose:
* send TCN BPDU out the designated port
* Parameters:
* lport - port
* bpdu - TCN BPDU message
* Returns:
* none
*/
void
stp_send_tcn_bpdu(spantree_t *stp, stp_port_t *stport, Tcn_bpdu * bpdu)
{
tag_bpdu_packet_t *enet_hdr;
bpdu_config_t *tcn_msg;
int enet_hdr_len, plen;
int flag;
pbmp_t pbm, upbm;
if (!stp_is_running(stp)) {
return;
}
/* Only send TCN BPDU on local ports(for stacking mode) */
if (!(stport->link_flags & STP_LF_LOCAL)) {
return;
}
/*
* BPDU ethernet header
*/
sal_memset(stp->bpdu_send_buff, 0, sizeof(stp->bpdu_send_buff));
enet_hdr = (tag_bpdu_packet_t *)stp->bpdu_send_buff;
enet_hdr_len = STP_BPDU_TAG_802_LEN; /* STP_BPDU_802_LEN */
tcn_msg = (bpdu_config_t *)((uint8*)stp->bpdu_send_buff + enet_hdr_len);
/* 802.3 destination MAC address */
sal_memcpy(enet_hdr->da, stp->bpdu_mac, 6);
/* 802.3 source MAC address */
sal_memcpy(enet_hdr->sa, stport->mac_addr, 6);
/* tagged 802 packet */
enet_hdr->type = soc_htons(0x8100);
enet_hdr->vtag = soc_htons(stp->external_id);
/* debugk(DK_STP,"stp packets vlan tag = %d\n", enet_hdr->vtag);*/
/* 802 tagged length */
enet_hdr->tlen = soc_htons(STP_TCN_BPDU_LENGTH + 3);
/* LSAP for BPDU is 0x42(0100 0010), 802.3 CTL is 0x03 */
enet_hdr->dsap = BPDU_SAP;
enet_hdr->ssap = BPDU_SAP;
enet_hdr->ctrl = 0x03;
/*
* TCN BPDU data
*/
/* Protocol identifier (Always 0) */
tcn_msg->identifier[0] = 0;
tcn_msg->identifier[1] = 0;
/* Protocol Version (Always 0) */
tcn_msg->version = 0;
/* message type */
tcn_msg->msg_type = bpdu->type;
{ /*对于非TRUNK口 我们应该只对这个端口发送 zhouguis 2005-12-09*/
/* Must send 802.1Q tagged packet, otherwise the VLAN ID will be lost */
plen = (STP_TCN_BPDU_LENGTH + enet_hdr_len + 3) & ~0x3; /* round to x*4 bytes */
flag = BCM_PACKET_CRC_APPEND | BCM_PACKET_COS(1);
SOC_PBMP_CLEAR(pbm);
SOC_PBMP_CLEAR(upbm);
SOC_PBMP_PORT_ADD(pbm, stport->port);
/* debugk(DK_STP,"send packets to port %d\n",stport->port);*/
bcm_packet_send_pbmp(stport->unit, pbm, upbm, stp->bpdu_send_buff, plen, flag);
}
stport->bpdu_out++;
#ifdef STP_DEBUG
trace(TRACE_STP, TR_LOGIT, "Send TCN BPDU on port: %d\n", stport->lport);
stk_pak_dump(stp->bpdu_send_buff, plen);
#endif
return;
}
/*
* Function:
* stp_rcv_bpdu_config
* Purpose:
* handles incoming BPDU packets
* Parameters:
* bpdu - the received BPDU message
* port - the port on which this is received
* Returns:
* none
*/
void
stp_rcv_bpdu_config(spantree_t *stp, bpdu_config_t *bpdu_msg, stp_port_t *stport)
{
Config_bpdu bpdu;
uint16 message_age, max_age, hello_time, forward_delay;
uint8 flags;
/* flag */
flags = bpdu_msg->flags;
bpdu.tc_acknowledgment = (flags >> 7) & 0x01;
bpdu.topology_change = flags & 0x01;
/* message type */
bpdu.type = bpdu_msg->msg_type;
/* root ID */
sal_memcpy(bpdu.root_id, bpdu_msg->root_id, ID_BYTES);
/* root path cost */
bpdu.root_path_cost = soc_ntohl_load(bpdu_msg->root_path_cost);
/* bridge ID */
sal_memcpy(bpdu.bridge_id, bpdu_msg->bridge_id, ID_BYTES);
/* port ID */
bpdu.port_id = soc_ntohs_load(bpdu_msg->port_id);
/* message age */
message_age = soc_ntohs_load(bpdu_msg->message_age);
bpdu.message_age = message_age >> 8;
/* max age */
max_age = soc_ntohs_load(bpdu_msg->max_age);
bpdu.max_age = max_age >> 8;
/* hello time */
hello_time = soc_ntohs_load(bpdu_msg->hello_time);
bpdu.hello_time = hello_time >> 8;
/* forward delay */
forward_delay = soc_ntohs_load(bpdu_msg->forward_delay);
bpdu.forward_delay = forward_delay >> 8;
if ((bpdu.max_age < STP_MIN_MAX_AGE) ||
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -