📄 transmit.c
字号:
/************************************************************************
* RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
* Copyright (C) 2001-2003 Optical Access
* Author: Alex Rozin
*
* This file is part of RSTP library.
*
* RSTP library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation; version 2.1
*
* RSTP library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
* General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with RSTP library; see the file COPYING. If not, write to the Free
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
**********************************************************************/
/* Port Transmit state machine : 17.27 */
#include "base.h"
#include "stpm.h"
#include "stp_to.h" /* for STP_OUT_get_port_mac & STP_OUT_tx_bpdu */
#include "in.h"
#define BPDU_LEN8023_OFF 12
#define STATES { \
CHOOSE(TRANSMIT_INIT), \
CHOOSE(TRANSMIT_PERIODIC), \
CHOOSE(IDLE), \
CHOOSE(TRANSMIT_CONFIG), \
CHOOSE(TRANSMIT_TCN), \
CHOOSE(TRANSMIT_RSTP), \
}
#define TRANSMIT_INIT 2
#define TRANSMIT_PERIODIC 3
#define IDLE 4
#define TRANSMIT_CONFIG 5
#define TRANSMIT_TCN 6
#define TRANSMIT_RSTP 7
#define GET_STATE_NAME STP_transmit_get_state_name
#include "choose.h"
#define MIN_FRAME_LENGTH 64
typedef struct tx_tcn_bpdu_t
{
MAC_HEADER_T mac;
ETH_HEADER_T eth;
BPDU_HEADER_T hdr;
}
TCN_BPDU_T;
typedef struct tx_stp_bpdu_t
{
MAC_HEADER_T mac;
ETH_HEADER_T eth;
BPDU_HEADER_T hdr;
BPDU_BODY_T body;
}
CONFIG_BPDU_T;
typedef struct tx_rstp_bpdu_t
{
MAC_HEADER_T mac;
ETH_HEADER_T eth;
BPDU_HEADER_T hdr;
BPDU_BODY_T body;
unsigned char ver_1_length[2];
}
RSTP_BPDU_T;
static RSTP_BPDU_T bpdu_packet = {
{ /* MAC_HEADER_T */
{0x01, 0x80, 0xc2, 0x00, 0x00, 0x00}, /* dst_mac */
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* src_mac */
},
{ /* ETH_HEADER_T */
{0x00, 0x00}, /* len8023 */
BPDU_L_SAP, BPDU_L_SAP, LLC_UI /* dsap, ssap, llc */
},
{ /* BPDU_HEADER_T */
{0x00, 0x00}, /* protocol */
BPDU_VERSION_ID, 0x00 /* version, bpdu_type */
},
{
0x00, /* flags; */
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* root_id[8]; */
{0x00, 0x00, 0x00, 0x00}, /* root_path_cost[4]; */
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* bridge_id[8]; */
{0x00, 0x00}, /* port_id[2]; */
{0x00, 0x00}, /* message_age[2]; */
{0x00, 0x00}, /* max_age[2]; */
{0x00, 0x00}, /* hello_time[2]; */
{0x00, 0x00}, /* forward_delay[2]; */
},
{0x00, 0x00}, /* ver_1_length[2]; */
};
/************************************************************************************
函数名称: build_bpdu_header
输入参数: port_index,bpdu_type,pkt_len
输出参数: pktlen,bpdu包长度
功能描述: 根据port_index,bpdu_type,pkt_len,写BPDU包头
返回值 :
备注 : 17.19.25.
作者 :
日期 :
************************************************************************************/
static size_t build_bpdu_header (struct net_bridge_port *port, unsigned char bpdu_type,
unsigned short pkt_len)
{
unsigned short len8023;
STP_OUT_get_port_mac (port, bpdu_packet.mac.src_mac);
bpdu_packet.hdr.bpdu_type = bpdu_type;
bpdu_packet.hdr.version =
(BPDU_RSTP == bpdu_type) ? BPDU_VERSION_RAPID_ID : BPDU_VERSION_ID;
/* NOTE: I suppose, that sizeof(unsigned short)=2 ! */
len8023 = htons ((unsigned short) (pkt_len + 3));
memcpy (&bpdu_packet.eth.len8023, &len8023, 2);
if (pkt_len < MIN_FRAME_LENGTH)
{
pkt_len = MIN_FRAME_LENGTH;
}
return pkt_len;
}
/************************************************************************************
函数名称:
输入参数:
输出参数:
功能描述:
返回值 :
备注 :
作者 :
日期 :
************************************************************************************/
static int txTcn (STATE_MACH_T * this)
{ /* 17.19.17 (page 68) & 9.3.2 (page 25) */
register size_t pkt_len;
register int port_index, vlan_id;
register struct net_bridge_port *testport;
testport = this->owner.port ;
#ifdef STP_DBG
if (this->owner.port->skip_tx > 0)
{
if (1 == this->owner.port->skip_tx)
stp_trace ("port %s stop tx skipping", this->owner.port->port_name);
this->owner.port->skip_tx--;
return STP_Nothing_To_Do;
}
#endif
if (testport->admin_non_stp)
{
return 1;
}
port_index = testport->port_no;
/* vlan_id = this->owner.port->owner->vlan_id;*/
pkt_len =
build_bpdu_header (port_index, BPDU_TOPO_CHANGE_TYPE,
sizeof (BPDU_HEADER_T));
#ifdef STP_DBG
if (this->debug)
stp_trace ("port %s txTcn", this->owner.port->port_name);
#endif
/*printf( "txTcn port %d\r\n",port_index);*/
return STP_OUT_tx_bpdu (port_index, (unsigned char *) &bpdu_packet,
pkt_len);
}
/************************************************************************************
函数名称:
输入参数:
输出参数:
功能描述:
返回值 :
备注 :
作者 :
日期 :
************************************************************************************/
static void build_config_bpdu (struct net_bridge_port * port, Bool set_topo_ack_flag)
{
unsigned long cost;
bpdu_packet.body.flags = 0;
if (port->tcWhile)
{
#ifdef STP_DBG
if (port->topoch->debug)
stp_trace ("tcWhile=%d =>tx TOLPLOGY_CHANGE_BIT to port %s",
(int) port->tcWhile, port->port_name);
#endif
bpdu_packet.body.flags |= TOLPLOGY_CHANGE_BIT;
}
if (set_topo_ack_flag && port->tcAck)
{
bpdu_packet.body.flags |= TOLPLOGY_CHANGE_ACK_BIT;
}
/*STP_VECT_set_vector (&port->portPrio, &bpdu_packet.body);*/
cost = port->operPCost+port->designated_cost;
/*printf("port_no = %d,port->operPCost = %d,cost = %d\r\n",port->port_no,port->operPCost,cost);*/
STP_VECT_set_vector(&port->portPrio,&bpdu_packet.body);
STP_set_times (&port->portTimes, &bpdu_packet.body);
}
/************************************************************************************
函数名称:
输入参数:
输出参数:
功能描述:
返回值 :
备注 :
作者 :
日期 :
************************************************************************************/
static int txConfig (STATE_MACH_T * this)
{ /* 17.19.15 (page 67) & 9.3.1 (page 23) */
register size_t pkt_len;
register struct net_bridge_port *port = NULL;
register int port_index, vlan_id;
/*printf("txConfig.\r\n");*/
#ifdef STP_DBG
if (this->owner.port->skip_tx > 0)
{
if (1 == this->owner.port->skip_tx)
stp_trace ("port %s stop tx skipping", this->owner.port->port_name);
this->owner.port->skip_tx--;
return STP_Nothing_To_Do;
}
#endif
port = this->owner.port;
/*printf("port %d,admin_no_stp:%d\r\n",port->port_no,port->admin_non_stp);*/
if (port->admin_non_stp)
{
return 1;
}
port_index = port->port_no;
/* vlan_id = port->owner->vlan_id;*/
pkt_len = build_bpdu_header (port->port_id, BPDU_CONFIG_TYPE,
sizeof (BPDU_HEADER_T) + sizeof (BPDU_BODY_T));
build_config_bpdu (port, True);
#ifdef STP_DBG
if (this->debug)
{
stp_trace ("port %s txConfig flags=0X%lx", port->port_name,
(unsigned long) bpdu_packet.body.flags);
}
#endif
/*printf( "txConfig,port %d\r\n",port_index);*/
return STP_OUT_tx_bpdu (port_index, (unsigned char *) &bpdu_packet,
pkt_len);
}
/************************************************************************************
函数名称:
输入参数:
输出参数:
功能描述:
返回值 :
备注 :
作者 :
日期 :
************************************************************************************/
static int txRstp (STATE_MACH_T * this)
{ /* 17.19.16 (page 68) & 9.3.3 (page 25) */
register unsigned int pkt_len;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -