1*4eaa4710SRishi Srivatsavai /************************************************************************ 2*4eaa4710SRishi Srivatsavai * RSTP library - Rapid Spanning Tree (802.1t, 802.1w) 3*4eaa4710SRishi Srivatsavai * Copyright (C) 2001-2003 Optical Access 4*4eaa4710SRishi Srivatsavai * Author: Alex Rozin 5*4eaa4710SRishi Srivatsavai * 6*4eaa4710SRishi Srivatsavai * This file is part of RSTP library. 7*4eaa4710SRishi Srivatsavai * 8*4eaa4710SRishi Srivatsavai * RSTP library is free software; you can redistribute it and/or modify it 9*4eaa4710SRishi Srivatsavai * under the terms of the GNU Lesser General Public License as published by the 10*4eaa4710SRishi Srivatsavai * Free Software Foundation; version 2.1 11*4eaa4710SRishi Srivatsavai * 12*4eaa4710SRishi Srivatsavai * RSTP library is distributed in the hope that it will be useful, but 13*4eaa4710SRishi Srivatsavai * WITHOUT ANY WARRANTY; without even the implied warranty of 14*4eaa4710SRishi Srivatsavai * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 15*4eaa4710SRishi Srivatsavai * General Public License for more details. 16*4eaa4710SRishi Srivatsavai * 17*4eaa4710SRishi Srivatsavai * You should have received a copy of the GNU Lesser General Public License 18*4eaa4710SRishi Srivatsavai * along with RSTP library; see the file COPYING. If not, write to the Free 19*4eaa4710SRishi Srivatsavai * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 20*4eaa4710SRishi Srivatsavai * 02111-1307, USA. 21*4eaa4710SRishi Srivatsavai **********************************************************************/ 22*4eaa4710SRishi Srivatsavai 23*4eaa4710SRishi Srivatsavai /* Port Transmit state machine : 17.27 */ 24*4eaa4710SRishi Srivatsavai 25*4eaa4710SRishi Srivatsavai #include "base.h" 26*4eaa4710SRishi Srivatsavai #include "stpm.h" 27*4eaa4710SRishi Srivatsavai #include "stp_to.h" /* for STP_OUT_get_port_mac & STP_OUT_tx_bpdu */ 28*4eaa4710SRishi Srivatsavai 29*4eaa4710SRishi Srivatsavai #define BPDU_LEN8023_OFF 12 30*4eaa4710SRishi Srivatsavai 31*4eaa4710SRishi Srivatsavai #define STATES { \ 32*4eaa4710SRishi Srivatsavai CHOOSE(TRANSMIT_INIT), \ 33*4eaa4710SRishi Srivatsavai CHOOSE(TRANSMIT_PERIODIC), \ 34*4eaa4710SRishi Srivatsavai CHOOSE(IDLE), \ 35*4eaa4710SRishi Srivatsavai CHOOSE(TRANSMIT_CONFIG), \ 36*4eaa4710SRishi Srivatsavai CHOOSE(TRANSMIT_TCN), \ 37*4eaa4710SRishi Srivatsavai CHOOSE(TRANSMIT_RSTP) \ 38*4eaa4710SRishi Srivatsavai } 39*4eaa4710SRishi Srivatsavai 40*4eaa4710SRishi Srivatsavai #define GET_STATE_NAME STP_transmit_get_state_name 41*4eaa4710SRishi Srivatsavai #include "choose.h" 42*4eaa4710SRishi Srivatsavai 43*4eaa4710SRishi Srivatsavai #define MIN_FRAME_LENGTH 64 44*4eaa4710SRishi Srivatsavai 45*4eaa4710SRishi Srivatsavai 46*4eaa4710SRishi Srivatsavai typedef struct tx_tcn_bpdu_t { 47*4eaa4710SRishi Srivatsavai MAC_HEADER_T mac; 48*4eaa4710SRishi Srivatsavai ETH_HEADER_T eth; 49*4eaa4710SRishi Srivatsavai BPDU_HEADER_T hdr; 50*4eaa4710SRishi Srivatsavai } TCN_BPDU_T; 51*4eaa4710SRishi Srivatsavai 52*4eaa4710SRishi Srivatsavai typedef struct tx_stp_bpdu_t { 53*4eaa4710SRishi Srivatsavai MAC_HEADER_T mac; 54*4eaa4710SRishi Srivatsavai ETH_HEADER_T eth; 55*4eaa4710SRishi Srivatsavai BPDU_HEADER_T hdr; 56*4eaa4710SRishi Srivatsavai BPDU_BODY_T body; 57*4eaa4710SRishi Srivatsavai } CONFIG_BPDU_T; 58*4eaa4710SRishi Srivatsavai 59*4eaa4710SRishi Srivatsavai typedef struct tx_rstp_bpdu_t { 60*4eaa4710SRishi Srivatsavai MAC_HEADER_T mac; 61*4eaa4710SRishi Srivatsavai ETH_HEADER_T eth; 62*4eaa4710SRishi Srivatsavai BPDU_HEADER_T hdr; 63*4eaa4710SRishi Srivatsavai BPDU_BODY_T body; 64*4eaa4710SRishi Srivatsavai unsigned char ver_1_length[2]; 65*4eaa4710SRishi Srivatsavai } RSTP_BPDU_T; 66*4eaa4710SRishi Srivatsavai 67*4eaa4710SRishi Srivatsavai 68*4eaa4710SRishi Srivatsavai static RSTP_BPDU_T bpdu_packet = { 69*4eaa4710SRishi Srivatsavai {/* MAC_HEADER_T */ 70*4eaa4710SRishi Srivatsavai {0x01, 0x80, 0xc2, 0x00, 0x00, 0x00}, /* dst_mac */ 71*4eaa4710SRishi Srivatsavai {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* src_mac */ 72*4eaa4710SRishi Srivatsavai }, 73*4eaa4710SRishi Srivatsavai { /* ETH_HEADER_T */ 74*4eaa4710SRishi Srivatsavai {0x00, 0x00}, /* len8023 */ 75*4eaa4710SRishi Srivatsavai BPDU_L_SAP, BPDU_L_SAP, LLC_UI /* dsap, ssap, llc */ 76*4eaa4710SRishi Srivatsavai }, 77*4eaa4710SRishi Srivatsavai {/* BPDU_HEADER_T */ 78*4eaa4710SRishi Srivatsavai {0x00, 0x00}, /* protocol */ 79*4eaa4710SRishi Srivatsavai BPDU_VERSION_ID, 0x00 /* version, bpdu_type */ 80*4eaa4710SRishi Srivatsavai }, 81*4eaa4710SRishi Srivatsavai { 82*4eaa4710SRishi Srivatsavai 0x00, /* flags; */ 83*4eaa4710SRishi Srivatsavai {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* root_id[8]; */ 84*4eaa4710SRishi Srivatsavai {0x00,0x00,0x00,0x00}, /* root_path_cost[4]; */ 85*4eaa4710SRishi Srivatsavai {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* bridge_id[8]; */ 86*4eaa4710SRishi Srivatsavai {0x00,0x00}, /* port_id[2]; */ 87*4eaa4710SRishi Srivatsavai {0x00,0x00}, /* message_age[2]; */ 88*4eaa4710SRishi Srivatsavai {0x00,0x00}, /* max_age[2]; */ 89*4eaa4710SRishi Srivatsavai {0x00,0x00}, /* hello_time[2]; */ 90*4eaa4710SRishi Srivatsavai {0x00,0x00}, /* forward_delay[2]; */ 91*4eaa4710SRishi Srivatsavai }, 92*4eaa4710SRishi Srivatsavai {0x00,0x00}, /* ver_1_length[2]; */ 93*4eaa4710SRishi Srivatsavai }; 94*4eaa4710SRishi Srivatsavai 95*4eaa4710SRishi Srivatsavai static size_t 96*4eaa4710SRishi Srivatsavai build_bpdu_header (int port_index, 97*4eaa4710SRishi Srivatsavai unsigned char bpdu_type, 98*4eaa4710SRishi Srivatsavai unsigned short pkt_len) 99*4eaa4710SRishi Srivatsavai { 100*4eaa4710SRishi Srivatsavai unsigned short len8023; 101*4eaa4710SRishi Srivatsavai 102*4eaa4710SRishi Srivatsavai STP_OUT_get_port_mac (port_index, bpdu_packet.mac.src_mac); 103*4eaa4710SRishi Srivatsavai 104*4eaa4710SRishi Srivatsavai bpdu_packet.hdr.bpdu_type = bpdu_type; 105*4eaa4710SRishi Srivatsavai bpdu_packet.hdr.version = (BPDU_RSTP == bpdu_type) ? 106*4eaa4710SRishi Srivatsavai BPDU_VERSION_RAPID_ID : 107*4eaa4710SRishi Srivatsavai BPDU_VERSION_ID; 108*4eaa4710SRishi Srivatsavai 109*4eaa4710SRishi Srivatsavai /* NOTE: I suppose, that sizeof(unsigned short)=2 ! */ 110*4eaa4710SRishi Srivatsavai len8023 = htons ((unsigned short) (pkt_len + 3)); 111*4eaa4710SRishi Srivatsavai (void) memcpy (&bpdu_packet.eth.len8023, &len8023, 2); 112*4eaa4710SRishi Srivatsavai 113*4eaa4710SRishi Srivatsavai if (pkt_len < MIN_FRAME_LENGTH) pkt_len = MIN_FRAME_LENGTH; 114*4eaa4710SRishi Srivatsavai return pkt_len; 115*4eaa4710SRishi Srivatsavai } 116*4eaa4710SRishi Srivatsavai 117*4eaa4710SRishi Srivatsavai static int 118*4eaa4710SRishi Srivatsavai txTcn (STATE_MACH_T* this) 119*4eaa4710SRishi Srivatsavai { /* 17.19.17 (page 68) & 9.3.2 (page 25) */ 120*4eaa4710SRishi Srivatsavai register size_t pkt_len; 121*4eaa4710SRishi Srivatsavai register int port_index, vlan_id; 122*4eaa4710SRishi Srivatsavai 123*4eaa4710SRishi Srivatsavai #ifdef STP_DBG 124*4eaa4710SRishi Srivatsavai if (this->owner.port->skip_tx > 0) { 125*4eaa4710SRishi Srivatsavai if (1 == this->owner.port->skip_tx) 126*4eaa4710SRishi Srivatsavai stp_trace ("port %s stop tx skipping", 127*4eaa4710SRishi Srivatsavai this->owner.port->port_name); 128*4eaa4710SRishi Srivatsavai this->owner.port->skip_tx--; 129*4eaa4710SRishi Srivatsavai return STP_Nothing_To_Do; 130*4eaa4710SRishi Srivatsavai } 131*4eaa4710SRishi Srivatsavai #endif 132*4eaa4710SRishi Srivatsavai 133*4eaa4710SRishi Srivatsavai if (this->owner.port->admin_non_stp) return 1; 134*4eaa4710SRishi Srivatsavai port_index = this->owner.port->port_index; 135*4eaa4710SRishi Srivatsavai vlan_id = this->owner.port->owner->vlan_id; 136*4eaa4710SRishi Srivatsavai 137*4eaa4710SRishi Srivatsavai pkt_len = build_bpdu_header (port_index, 138*4eaa4710SRishi Srivatsavai BPDU_TOPO_CHANGE_TYPE, 139*4eaa4710SRishi Srivatsavai sizeof (BPDU_HEADER_T)); 140*4eaa4710SRishi Srivatsavai 141*4eaa4710SRishi Srivatsavai #ifdef STP_DBG 142*4eaa4710SRishi Srivatsavai if (this->debug) 143*4eaa4710SRishi Srivatsavai stp_trace ("port %s txTcn", this->owner.port->port_name); 144*4eaa4710SRishi Srivatsavai #endif 145*4eaa4710SRishi Srivatsavai return STP_OUT_tx_bpdu (port_index, vlan_id, 146*4eaa4710SRishi Srivatsavai (unsigned char *) &bpdu_packet, 147*4eaa4710SRishi Srivatsavai pkt_len); 148*4eaa4710SRishi Srivatsavai } 149*4eaa4710SRishi Srivatsavai 150*4eaa4710SRishi Srivatsavai static void 151*4eaa4710SRishi Srivatsavai build_config_bpdu (PORT_T* port, Bool set_topo_ack_flag) 152*4eaa4710SRishi Srivatsavai { 153*4eaa4710SRishi Srivatsavai bpdu_packet.body.flags = 0; 154*4eaa4710SRishi Srivatsavai if (port->tcWhile) { 155*4eaa4710SRishi Srivatsavai #ifdef STP_DBG 156*4eaa4710SRishi Srivatsavai if (port->topoch->debug) 157*4eaa4710SRishi Srivatsavai stp_trace ("tcWhile=%d =>tx TOPOLOGY_CHANGE_BIT to port %s", 158*4eaa4710SRishi Srivatsavai (int) port->tcWhile, port->port_name); 159*4eaa4710SRishi Srivatsavai #endif 160*4eaa4710SRishi Srivatsavai bpdu_packet.body.flags |= TOPOLOGY_CHANGE_BIT; 161*4eaa4710SRishi Srivatsavai } 162*4eaa4710SRishi Srivatsavai 163*4eaa4710SRishi Srivatsavai if (set_topo_ack_flag && port->tcAck) { 164*4eaa4710SRishi Srivatsavai bpdu_packet.body.flags |= TOPOLOGY_CHANGE_ACK_BIT; 165*4eaa4710SRishi Srivatsavai } 166*4eaa4710SRishi Srivatsavai 167*4eaa4710SRishi Srivatsavai STP_VECT_set_vector (&port->portPrio, &bpdu_packet.body); 168*4eaa4710SRishi Srivatsavai STP_set_times (&port->portTimes, &bpdu_packet.body); 169*4eaa4710SRishi Srivatsavai } 170*4eaa4710SRishi Srivatsavai 171*4eaa4710SRishi Srivatsavai static int 172*4eaa4710SRishi Srivatsavai txConfig (STATE_MACH_T* this) 173*4eaa4710SRishi Srivatsavai {/* 17.19.15 (page 67) & 9.3.1 (page 23) */ 174*4eaa4710SRishi Srivatsavai register size_t pkt_len; 175*4eaa4710SRishi Srivatsavai register PORT_T* port = NULL; 176*4eaa4710SRishi Srivatsavai register int port_index, vlan_id; 177*4eaa4710SRishi Srivatsavai 178*4eaa4710SRishi Srivatsavai #ifdef STP_DBG 179*4eaa4710SRishi Srivatsavai if (this->owner.port->skip_tx > 0) { 180*4eaa4710SRishi Srivatsavai if (1 == this->owner.port->skip_tx) 181*4eaa4710SRishi Srivatsavai stp_trace ("port %s stop tx skipping", 182*4eaa4710SRishi Srivatsavai this->owner.port->port_name); 183*4eaa4710SRishi Srivatsavai this->owner.port->skip_tx--; 184*4eaa4710SRishi Srivatsavai return STP_Nothing_To_Do; 185*4eaa4710SRishi Srivatsavai } 186*4eaa4710SRishi Srivatsavai #endif 187*4eaa4710SRishi Srivatsavai 188*4eaa4710SRishi Srivatsavai port = this->owner.port; 189*4eaa4710SRishi Srivatsavai if (port->admin_non_stp) return 1; 190*4eaa4710SRishi Srivatsavai port_index = port->port_index; 191*4eaa4710SRishi Srivatsavai vlan_id = port->owner->vlan_id; 192*4eaa4710SRishi Srivatsavai 193*4eaa4710SRishi Srivatsavai pkt_len = build_bpdu_header (port->port_index, 194*4eaa4710SRishi Srivatsavai BPDU_CONFIG_TYPE, 195*4eaa4710SRishi Srivatsavai sizeof (BPDU_HEADER_T) + sizeof (BPDU_BODY_T)); 196*4eaa4710SRishi Srivatsavai build_config_bpdu (port, True); 197*4eaa4710SRishi Srivatsavai 198*4eaa4710SRishi Srivatsavai #ifdef STP_DBG 199*4eaa4710SRishi Srivatsavai if (this->debug) 200*4eaa4710SRishi Srivatsavai stp_trace ("port %s txConfig flags=0X%lx", 201*4eaa4710SRishi Srivatsavai port->port_name, 202*4eaa4710SRishi Srivatsavai (unsigned long) bpdu_packet.body.flags); 203*4eaa4710SRishi Srivatsavai #endif 204*4eaa4710SRishi Srivatsavai return STP_OUT_tx_bpdu (port_index, vlan_id, 205*4eaa4710SRishi Srivatsavai (unsigned char *) &bpdu_packet, 206*4eaa4710SRishi Srivatsavai pkt_len); 207*4eaa4710SRishi Srivatsavai } 208*4eaa4710SRishi Srivatsavai 209*4eaa4710SRishi Srivatsavai static int 210*4eaa4710SRishi Srivatsavai txRstp (STATE_MACH_T* this) 211*4eaa4710SRishi Srivatsavai {/* 17.19.16 (page 68) & 9.3.3 (page 25) */ 212*4eaa4710SRishi Srivatsavai register size_t pkt_len; 213*4eaa4710SRishi Srivatsavai register PORT_T* port = NULL; 214*4eaa4710SRishi Srivatsavai register int port_index, vlan_id; 215*4eaa4710SRishi Srivatsavai unsigned char role; 216*4eaa4710SRishi Srivatsavai 217*4eaa4710SRishi Srivatsavai #ifdef STP_DBG 218*4eaa4710SRishi Srivatsavai if (this->owner.port->skip_tx > 0) { 219*4eaa4710SRishi Srivatsavai if (1 == this->owner.port->skip_tx) 220*4eaa4710SRishi Srivatsavai stp_trace ("port %s stop tx skipping", 221*4eaa4710SRishi Srivatsavai this->owner.port->port_name); 222*4eaa4710SRishi Srivatsavai else 223*4eaa4710SRishi Srivatsavai stp_trace ("port %s skip tx %d", 224*4eaa4710SRishi Srivatsavai this->owner.port->port_name, this->owner.port->skip_tx); 225*4eaa4710SRishi Srivatsavai 226*4eaa4710SRishi Srivatsavai this->owner.port->skip_tx--; 227*4eaa4710SRishi Srivatsavai return STP_Nothing_To_Do; 228*4eaa4710SRishi Srivatsavai } 229*4eaa4710SRishi Srivatsavai #endif 230*4eaa4710SRishi Srivatsavai 231*4eaa4710SRishi Srivatsavai port = this->owner.port; 232*4eaa4710SRishi Srivatsavai if (port->admin_non_stp) return 1; 233*4eaa4710SRishi Srivatsavai port_index = port->port_index; 234*4eaa4710SRishi Srivatsavai vlan_id = port->owner->vlan_id; 235*4eaa4710SRishi Srivatsavai 236*4eaa4710SRishi Srivatsavai pkt_len = build_bpdu_header (port->port_index, 237*4eaa4710SRishi Srivatsavai BPDU_RSTP, 238*4eaa4710SRishi Srivatsavai sizeof (BPDU_HEADER_T) + sizeof (BPDU_BODY_T) + 2); 239*4eaa4710SRishi Srivatsavai build_config_bpdu (port, False); 240*4eaa4710SRishi Srivatsavai 241*4eaa4710SRishi Srivatsavai switch (port->selectedRole) { 242*4eaa4710SRishi Srivatsavai default: 243*4eaa4710SRishi Srivatsavai case DisabledPort: 244*4eaa4710SRishi Srivatsavai role = RSTP_PORT_ROLE_UNKN; 245*4eaa4710SRishi Srivatsavai break; 246*4eaa4710SRishi Srivatsavai case AlternatePort: 247*4eaa4710SRishi Srivatsavai role = RSTP_PORT_ROLE_ALTBACK; 248*4eaa4710SRishi Srivatsavai break; 249*4eaa4710SRishi Srivatsavai case BackupPort: 250*4eaa4710SRishi Srivatsavai role = RSTP_PORT_ROLE_ALTBACK; 251*4eaa4710SRishi Srivatsavai break; 252*4eaa4710SRishi Srivatsavai case RootPort: 253*4eaa4710SRishi Srivatsavai role = RSTP_PORT_ROLE_ROOT; 254*4eaa4710SRishi Srivatsavai break; 255*4eaa4710SRishi Srivatsavai case DesignatedPort: 256*4eaa4710SRishi Srivatsavai role = RSTP_PORT_ROLE_DESGN; 257*4eaa4710SRishi Srivatsavai break; 258*4eaa4710SRishi Srivatsavai } 259*4eaa4710SRishi Srivatsavai 260*4eaa4710SRishi Srivatsavai bpdu_packet.body.flags |= (role << PORT_ROLE_OFFS); 261*4eaa4710SRishi Srivatsavai 262*4eaa4710SRishi Srivatsavai if (port->synced) { 263*4eaa4710SRishi Srivatsavai #if 0 /* def STP_DBG */ 264*4eaa4710SRishi Srivatsavai if (port->roletrns->debug) 265*4eaa4710SRishi Srivatsavai stp_trace ("tx AGREEMENT_BIT to port %s", port->port_name); 266*4eaa4710SRishi Srivatsavai #endif 267*4eaa4710SRishi Srivatsavai bpdu_packet.body.flags |= AGREEMENT_BIT; 268*4eaa4710SRishi Srivatsavai } 269*4eaa4710SRishi Srivatsavai 270*4eaa4710SRishi Srivatsavai if (port->proposing) { 271*4eaa4710SRishi Srivatsavai #if 0 /* def STP_DBG */ 272*4eaa4710SRishi Srivatsavai if (port->roletrns->debug) 273*4eaa4710SRishi Srivatsavai stp_trace ("tx PROPOSAL_BIT to port %s", port->port_name); 274*4eaa4710SRishi Srivatsavai #endif 275*4eaa4710SRishi Srivatsavai bpdu_packet.body.flags |= PROPOSAL_BIT; 276*4eaa4710SRishi Srivatsavai } 277*4eaa4710SRishi Srivatsavai 278*4eaa4710SRishi Srivatsavai #ifdef STP_DBG 279*4eaa4710SRishi Srivatsavai if (this->debug) 280*4eaa4710SRishi Srivatsavai stp_trace ("port %s txRstp flags=0X%lx", 281*4eaa4710SRishi Srivatsavai port->port_name, 282*4eaa4710SRishi Srivatsavai (unsigned long) bpdu_packet.body.flags); 283*4eaa4710SRishi Srivatsavai #endif 284*4eaa4710SRishi Srivatsavai 285*4eaa4710SRishi Srivatsavai return STP_OUT_tx_bpdu (port_index, vlan_id, 286*4eaa4710SRishi Srivatsavai (unsigned char *) &bpdu_packet, 287*4eaa4710SRishi Srivatsavai pkt_len); 288*4eaa4710SRishi Srivatsavai } 289*4eaa4710SRishi Srivatsavai 290*4eaa4710SRishi Srivatsavai void 291*4eaa4710SRishi Srivatsavai STP_transmit_enter_state (STATE_MACH_T* this) 292*4eaa4710SRishi Srivatsavai { 293*4eaa4710SRishi Srivatsavai register PORT_T* port = this->owner.port; 294*4eaa4710SRishi Srivatsavai 295*4eaa4710SRishi Srivatsavai switch (this->State) { 296*4eaa4710SRishi Srivatsavai case BEGIN: 297*4eaa4710SRishi Srivatsavai case TRANSMIT_INIT: 298*4eaa4710SRishi Srivatsavai port->newInfo = False; 299*4eaa4710SRishi Srivatsavai port->helloWhen = 0; 300*4eaa4710SRishi Srivatsavai port->txCount = 0; 301*4eaa4710SRishi Srivatsavai break; 302*4eaa4710SRishi Srivatsavai case TRANSMIT_PERIODIC: 303*4eaa4710SRishi Srivatsavai port->newInfo = port->newInfo || 304*4eaa4710SRishi Srivatsavai ((port->role == DesignatedPort) || 305*4eaa4710SRishi Srivatsavai ((port->role == RootPort) && port->tcWhile)); 306*4eaa4710SRishi Srivatsavai port->helloWhen = port->owner->rootTimes.HelloTime; 307*4eaa4710SRishi Srivatsavai break; 308*4eaa4710SRishi Srivatsavai case IDLE: 309*4eaa4710SRishi Srivatsavai break; 310*4eaa4710SRishi Srivatsavai case TRANSMIT_CONFIG: 311*4eaa4710SRishi Srivatsavai port->newInfo = False; 312*4eaa4710SRishi Srivatsavai (void) txConfig (this); 313*4eaa4710SRishi Srivatsavai port->txCount++; 314*4eaa4710SRishi Srivatsavai port->tcAck = False; 315*4eaa4710SRishi Srivatsavai break; 316*4eaa4710SRishi Srivatsavai case TRANSMIT_TCN: 317*4eaa4710SRishi Srivatsavai port->newInfo = False; 318*4eaa4710SRishi Srivatsavai (void) txTcn (this); 319*4eaa4710SRishi Srivatsavai port->txCount++; 320*4eaa4710SRishi Srivatsavai break; 321*4eaa4710SRishi Srivatsavai case TRANSMIT_RSTP: 322*4eaa4710SRishi Srivatsavai port->newInfo = False; 323*4eaa4710SRishi Srivatsavai (void) txRstp (this); 324*4eaa4710SRishi Srivatsavai port->txCount++; 325*4eaa4710SRishi Srivatsavai port->tcAck = False; 326*4eaa4710SRishi Srivatsavai break; 327*4eaa4710SRishi Srivatsavai }; 328*4eaa4710SRishi Srivatsavai } 329*4eaa4710SRishi Srivatsavai 330*4eaa4710SRishi Srivatsavai Bool 331*4eaa4710SRishi Srivatsavai STP_transmit_check_conditions (STATE_MACH_T* this) 332*4eaa4710SRishi Srivatsavai { 333*4eaa4710SRishi Srivatsavai register PORT_T* port = this->owner.port; 334*4eaa4710SRishi Srivatsavai 335*4eaa4710SRishi Srivatsavai switch (this->State) { 336*4eaa4710SRishi Srivatsavai case BEGIN: 337*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, TRANSMIT_INIT); 338*4eaa4710SRishi Srivatsavai case TRANSMIT_INIT: 339*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, IDLE); 340*4eaa4710SRishi Srivatsavai case TRANSMIT_PERIODIC: 341*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, IDLE); 342*4eaa4710SRishi Srivatsavai case IDLE: 343*4eaa4710SRishi Srivatsavai if (!port->helloWhen) return STP_hop_2_state (this, TRANSMIT_PERIODIC); 344*4eaa4710SRishi Srivatsavai if (!port->sendRSTP && port->newInfo && 345*4eaa4710SRishi Srivatsavai (port->txCount < TxHoldCount) && 346*4eaa4710SRishi Srivatsavai (port->role == DesignatedPort) && 347*4eaa4710SRishi Srivatsavai port->helloWhen) 348*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, TRANSMIT_CONFIG); 349*4eaa4710SRishi Srivatsavai if (!port->sendRSTP && port->newInfo && 350*4eaa4710SRishi Srivatsavai (port->txCount < TxHoldCount) && 351*4eaa4710SRishi Srivatsavai (port->role == RootPort) && 352*4eaa4710SRishi Srivatsavai port->helloWhen) 353*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, TRANSMIT_TCN); 354*4eaa4710SRishi Srivatsavai if (port->sendRSTP && port->newInfo && 355*4eaa4710SRishi Srivatsavai (port->txCount < TxHoldCount) && 356*4eaa4710SRishi Srivatsavai ((port->role == RootPort) || 357*4eaa4710SRishi Srivatsavai (port->role == DesignatedPort))) 358*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, TRANSMIT_RSTP); 359*4eaa4710SRishi Srivatsavai break; 360*4eaa4710SRishi Srivatsavai case TRANSMIT_CONFIG: 361*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, IDLE); 362*4eaa4710SRishi Srivatsavai case TRANSMIT_TCN: 363*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, IDLE); 364*4eaa4710SRishi Srivatsavai case TRANSMIT_RSTP: 365*4eaa4710SRishi Srivatsavai return STP_hop_2_state (this, IDLE); 366*4eaa4710SRishi Srivatsavai }; 367*4eaa4710SRishi Srivatsavai return False; 368*4eaa4710SRishi Srivatsavai } 369