4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/************************************************************************
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Copyright (C) 2001-2003 Optical Access
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Author: Alex Rozin
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * This file is part of RSTP library.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * RSTP library is free software; you can redistribute it and/or modify it
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * under the terms of the GNU Lesser General Public License as published by the
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Free Software Foundation; version 2.1
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * RSTP library is distributed in the hope that it will be useful, but
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * WITHOUT ANY WARRANTY; without even the implied warranty of
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * General Public License for more details.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * You should have received a copy of the GNU Lesser General Public License
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * along with RSTP library; see the file COPYING. If not, write to the Free
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * 02111-1307, USA.
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai **********************************************************************/
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai/* Port Transmit state machine : 17.27 */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include "base.h"
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include "stpm.h"
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include "stp_to.h" /* for STP_OUT_get_port_mac & STP_OUT_tx_bpdu */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#define BPDU_LEN8023_OFF 12
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#define STATES { \
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai CHOOSE(TRANSMIT_INIT), \
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai CHOOSE(TRANSMIT_PERIODIC), \
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai CHOOSE(IDLE), \
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai CHOOSE(TRANSMIT_CONFIG), \
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai CHOOSE(TRANSMIT_TCN), \
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai CHOOSE(TRANSMIT_RSTP) \
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#define GET_STATE_NAME STP_transmit_get_state_name
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#include "choose.h"
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#define MIN_FRAME_LENGTH 64
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaitypedef struct tx_tcn_bpdu_t {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai MAC_HEADER_T mac;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ETH_HEADER_T eth;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai BPDU_HEADER_T hdr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai} TCN_BPDU_T;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaitypedef struct tx_stp_bpdu_t {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai MAC_HEADER_T mac;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ETH_HEADER_T eth;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai BPDU_HEADER_T hdr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai BPDU_BODY_T body;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai} CONFIG_BPDU_T;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaitypedef struct tx_rstp_bpdu_t {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai MAC_HEADER_T mac;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ETH_HEADER_T eth;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai BPDU_HEADER_T hdr;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai BPDU_BODY_T body;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai unsigned char ver_1_length[2];
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai} RSTP_BPDU_T;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic RSTP_BPDU_T bpdu_packet = {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai {/* MAC_HEADER_T */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai {0x01, 0x80, 0xc2, 0x00, 0x00, 0x00}, /* dst_mac */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* src_mac */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai },
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai { /* ETH_HEADER_T */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai {0x00, 0x00}, /* len8023 */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai BPDU_L_SAP, BPDU_L_SAP, LLC_UI /* dsap, ssap, llc */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai },
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai {/* BPDU_HEADER_T */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai {0x00, 0x00}, /* protocol */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai BPDU_VERSION_ID, 0x00 /* version, bpdu_type */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai },
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai 0x00, /* flags; */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* root_id[8]; */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai {0x00,0x00,0x00,0x00}, /* root_path_cost[4]; */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* bridge_id[8]; */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai {0x00,0x00}, /* port_id[2]; */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai {0x00,0x00}, /* message_age[2]; */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai {0x00,0x00}, /* max_age[2]; */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai {0x00,0x00}, /* hello_time[2]; */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai {0x00,0x00}, /* forward_delay[2]; */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai },
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai {0x00,0x00}, /* ver_1_length[2]; */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai};
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic size_t
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibuild_bpdu_header (int port_index,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai unsigned char bpdu_type,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai unsigned short pkt_len)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai unsigned short len8023;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai STP_OUT_get_port_mac (port_index, bpdu_packet.mac.src_mac);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bpdu_packet.hdr.bpdu_type = bpdu_type;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bpdu_packet.hdr.version = (BPDU_RSTP == bpdu_type) ?
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai BPDU_VERSION_RAPID_ID :
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai BPDU_VERSION_ID;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /* NOTE: I suppose, that sizeof(unsigned short)=2 ! */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai len8023 = htons ((unsigned short) (pkt_len + 3));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) memcpy (&bpdu_packet.eth.len8023, &len8023, 2);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (pkt_len < MIN_FRAME_LENGTH) pkt_len = MIN_FRAME_LENGTH;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return pkt_len;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic int
4eaa471005973e11a6110b69fe990530b3b95a38Rishi SrivatsavaitxTcn (STATE_MACH_T* this)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{ /* 17.19.17 (page 68) & 9.3.2 (page 25) */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai register size_t pkt_len;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai register int port_index, vlan_id;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#ifdef STP_DBG
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (this->owner.port->skip_tx > 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (1 == this->owner.port->skip_tx)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai stp_trace ("port %s stop tx skipping",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai this->owner.port->port_name);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai this->owner.port->skip_tx--;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return STP_Nothing_To_Do;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#endif
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (this->owner.port->admin_non_stp) return 1;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port_index = this->owner.port->port_index;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai vlan_id = this->owner.port->owner->vlan_id;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai pkt_len = build_bpdu_header (port_index,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai BPDU_TOPO_CHANGE_TYPE,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai sizeof (BPDU_HEADER_T));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#ifdef STP_DBG
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (this->debug)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai stp_trace ("port %s txTcn", this->owner.port->port_name);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#endif
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return STP_OUT_tx_bpdu (port_index, vlan_id,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (unsigned char *) &bpdu_packet,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai pkt_len);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic void
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaibuild_config_bpdu (PORT_T* port, Bool set_topo_ack_flag)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bpdu_packet.body.flags = 0;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (port->tcWhile) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#ifdef STP_DBG
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (port->topoch->debug)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai stp_trace ("tcWhile=%d =>tx TOPOLOGY_CHANGE_BIT to port %s",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (int) port->tcWhile, port->port_name);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#endif
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bpdu_packet.body.flags |= TOPOLOGY_CHANGE_BIT;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (set_topo_ack_flag && port->tcAck) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bpdu_packet.body.flags |= TOPOLOGY_CHANGE_ACK_BIT;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai STP_VECT_set_vector (&port->portPrio, &bpdu_packet.body);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai STP_set_times (&port->portTimes, &bpdu_packet.body);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic int
4eaa471005973e11a6110b69fe990530b3b95a38Rishi SrivatsavaitxConfig (STATE_MACH_T* this)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{/* 17.19.15 (page 67) & 9.3.1 (page 23) */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai register size_t pkt_len;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai register PORT_T* port = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai register int port_index, vlan_id;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#ifdef STP_DBG
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (this->owner.port->skip_tx > 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (1 == this->owner.port->skip_tx)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai stp_trace ("port %s stop tx skipping",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai this->owner.port->port_name);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai this->owner.port->skip_tx--;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return STP_Nothing_To_Do;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#endif
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port = this->owner.port;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (port->admin_non_stp) return 1;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port_index = port->port_index;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai vlan_id = port->owner->vlan_id;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai pkt_len = build_bpdu_header (port->port_index,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai BPDU_CONFIG_TYPE,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai sizeof (BPDU_HEADER_T) + sizeof (BPDU_BODY_T));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai build_config_bpdu (port, True);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#ifdef STP_DBG
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (this->debug)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai stp_trace ("port %s txConfig flags=0X%lx",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->port_name,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (unsigned long) bpdu_packet.body.flags);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#endif
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return STP_OUT_tx_bpdu (port_index, vlan_id,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (unsigned char *) &bpdu_packet,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai pkt_len);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaistatic int
4eaa471005973e11a6110b69fe990530b3b95a38Rishi SrivatsavaitxRstp (STATE_MACH_T* this)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{/* 17.19.16 (page 68) & 9.3.3 (page 25) */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai register size_t pkt_len;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai register PORT_T* port = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai register int port_index, vlan_id;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai unsigned char role;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#ifdef STP_DBG
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (this->owner.port->skip_tx > 0) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (1 == this->owner.port->skip_tx)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai stp_trace ("port %s stop tx skipping",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai this->owner.port->port_name);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai else
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai stp_trace ("port %s skip tx %d",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai this->owner.port->port_name, this->owner.port->skip_tx);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai this->owner.port->skip_tx--;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return STP_Nothing_To_Do;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#endif
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port = this->owner.port;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (port->admin_non_stp) return 1;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port_index = port->port_index;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai vlan_id = port->owner->vlan_id;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai pkt_len = build_bpdu_header (port->port_index,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai BPDU_RSTP,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai sizeof (BPDU_HEADER_T) + sizeof (BPDU_BODY_T) + 2);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai build_config_bpdu (port, False);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai switch (port->selectedRole) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai default:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case DisabledPort:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai role = RSTP_PORT_ROLE_UNKN;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case AlternatePort:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai role = RSTP_PORT_ROLE_ALTBACK;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case BackupPort:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai role = RSTP_PORT_ROLE_ALTBACK;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case RootPort:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai role = RSTP_PORT_ROLE_ROOT;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case DesignatedPort:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai role = RSTP_PORT_ROLE_DESGN;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bpdu_packet.body.flags |= (role << PORT_ROLE_OFFS);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (port->synced) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#if 0 /* def STP_DBG */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (port->roletrns->debug)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai stp_trace ("tx AGREEMENT_BIT to port %s", port->port_name);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#endif
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bpdu_packet.body.flags |= AGREEMENT_BIT;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (port->proposing) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#if 0 /* def STP_DBG */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (port->roletrns->debug)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai stp_trace ("tx PROPOSAL_BIT to port %s", port->port_name);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#endif
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai bpdu_packet.body.flags |= PROPOSAL_BIT;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#ifdef STP_DBG
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (this->debug)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai stp_trace ("port %s txRstp flags=0X%lx",
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->port_name,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (unsigned long) bpdu_packet.body.flags);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#endif
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return STP_OUT_tx_bpdu (port_index, vlan_id,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (unsigned char *) &bpdu_packet,
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai pkt_len);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaivoid
4eaa471005973e11a6110b69fe990530b3b95a38Rishi SrivatsavaiSTP_transmit_enter_state (STATE_MACH_T* this)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai register PORT_T* port = this->owner.port;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai switch (this->State) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case BEGIN:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case TRANSMIT_INIT:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->newInfo = False;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->helloWhen = 0;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->txCount = 0;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case TRANSMIT_PERIODIC:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->newInfo = port->newInfo ||
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ((port->role == DesignatedPort) ||
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ((port->role == RootPort) && port->tcWhile));
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->helloWhen = port->owner->rootTimes.HelloTime;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case IDLE:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case TRANSMIT_CONFIG:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->newInfo = False;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) txConfig (this);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->txCount++;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->tcAck = False;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case TRANSMIT_TCN:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->newInfo = False;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) txTcn (this);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->txCount++;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case TRANSMIT_RSTP:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->newInfo = False;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) txRstp (this);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->txCount++;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->tcAck = False;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai };
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi SrivatsavaiBool
4eaa471005973e11a6110b69fe990530b3b95a38Rishi SrivatsavaiSTP_transmit_check_conditions (STATE_MACH_T* this)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai{
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai register PORT_T* port = this->owner.port;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai switch (this->State) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case BEGIN:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return STP_hop_2_state (this, TRANSMIT_INIT);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case TRANSMIT_INIT:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return STP_hop_2_state (this, IDLE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case TRANSMIT_PERIODIC:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return STP_hop_2_state (this, IDLE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case IDLE:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!port->helloWhen) return STP_hop_2_state (this, TRANSMIT_PERIODIC);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!port->sendRSTP && port->newInfo &&
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (port->txCount < TxHoldCount) &&
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (port->role == DesignatedPort) &&
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->helloWhen)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return STP_hop_2_state (this, TRANSMIT_CONFIG);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (!port->sendRSTP && port->newInfo &&
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (port->txCount < TxHoldCount) &&
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (port->role == RootPort) &&
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai port->helloWhen)
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return STP_hop_2_state (this, TRANSMIT_TCN);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (port->sendRSTP && port->newInfo &&
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (port->txCount < TxHoldCount) &&
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai ((port->role == RootPort) ||
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (port->role == DesignatedPort)))
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return STP_hop_2_state (this, TRANSMIT_RSTP);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai break;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case TRANSMIT_CONFIG:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return STP_hop_2_state (this, IDLE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case TRANSMIT_TCN:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return STP_hop_2_state (this, IDLE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai case TRANSMIT_RSTP:
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return STP_hop_2_state (this, IDLE);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai };
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return False;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai}