port.c revision 10491:8893b747ecdf
1/************************************************************************
2 * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
3 * Copyright (C) 2001-2003 Optical Access
4 * Author: Alex Rozin
5 *
6 * This file is part of RSTP library.
7 *
8 * RSTP library is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published by the
10 * Free Software Foundation; version 2.1
11 *
12 * RSTP library is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with RSTP library; see the file COPYING.  If not, write to the Free
19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 * 02111-1307, USA.
21 **********************************************************************/
22
23/* STP PORT instance : 17.18, 17.15 */
24
25#include "base.h"
26#include "stpm.h"
27#include "stp_in.h"
28
29/* #include "rolesel.h" */
30#include "portinfo.h"
31#include "roletrns.h"
32#include "sttrans.h"
33#include "topoch.h"
34#include "migrate.h"
35#include "transmit.h"
36#include "p2p.h"
37#include "pcost.h"
38#include "edge.h"
39
40#include "stp_to.h" /* for STP_OUT_get_port_name & STP_OUT_get_port_link_status */
41
42int port_trace_flags;
43
44PORT_T *
45STP_port_create (STPM_T* stpm, int port_index)
46{
47  PORT_T*        this;
48  UID_STP_PORT_CFG_T port_cfg;
49  register int   iii;
50  unsigned short port_prio;
51
52  /* check, if the port has just been added */
53  for (this = stpm->ports; this; this = this->next) {
54    if (this->port_index == port_index) {
55      return NULL;
56    }
57  }
58
59  STP_NEW_IN_LIST(this, PORT_T, stpm->ports, "port create");
60
61  this->owner = stpm;
62  this->machines = NULL;
63  this->port_index = port_index;
64  this->port_name = strdup (STP_OUT_get_port_name (port_index));
65  this->uptime = 0;
66
67  STP_OUT_get_init_port_cfg (stpm->vlan_id, port_index, &port_cfg);
68  port_prio =                  port_cfg.port_priority;
69  this->admin_non_stp =        port_cfg.admin_non_stp;
70  this->adminEdge =            port_cfg.admin_edge;
71  this->adminPCost =           port_cfg.admin_port_path_cost;
72  this->adminPointToPointMac = port_cfg.admin_point2point;
73
74  this->LinkDelay = DEF_LINK_DELAY;
75  this->port_id = (port_prio << 8) + port_index;
76
77  iii = 0;
78  this->timers[iii++] = &this->fdWhile;
79  this->timers[iii++] = &this->helloWhen;
80  this->timers[iii++] = &this->mdelayWhile;
81  this->timers[iii++] = &this->rbWhile;
82  this->timers[iii++] = &this->rcvdInfoWhile;
83  this->timers[iii++] = &this->rrWhile;
84  this->timers[iii++] = &this->tcWhile;
85  this->timers[iii++] = &this->txCount;
86  this->timers[iii++] = &this->lnkWhile;
87
88  /* create and bind port state machines */
89  STP_STATE_MACH_IN_LIST(topoch);
90
91  STP_STATE_MACH_IN_LIST(migrate);
92
93  STP_STATE_MACH_IN_LIST(p2p);
94
95  STP_STATE_MACH_IN_LIST(edge);
96
97  STP_STATE_MACH_IN_LIST(pcost)
98
99  STP_STATE_MACH_IN_LIST(info);
100
101  STP_STATE_MACH_IN_LIST(roletrns);
102
103  STP_STATE_MACH_IN_LIST(sttrans);
104
105  STP_STATE_MACH_IN_LIST(transmit);
106
107#ifdef STP_DBG
108
109#if 0
110  this->roletrns->ignoreHop2State = 14; /* DESIGNATED_PORT; */
111  this->info->ignoreHop2State =      3; /* CURRENT */
112  this->transmit->ignoreHop2State =  3; /* IDLE */
113  this->edge->ignoreHop2State =      0; /* DISABLED; */
114#endif
115
116#if 0
117  this->info->debug = 1;
118  this->pcost->debug = 1;
119  this->p2p->debug = 1;
120  this->edge->debug = 1;
121  this->migrate->debug = 1;
122  this->sttrans->debug = 1;
123  this->topoch->debug = 1;
124  this->roletrns->debug = 1;
125#endif
126  this->sttrans->debug = 1;
127
128#endif
129  return this;
130}
131
132void
133STP_port_init (PORT_T* this, STPM_T* stpm, Bool check_link)
134{
135  if (check_link) {
136    this->adminEnable = STP_OUT_get_port_link_status (this->port_index);
137    STP_VECT_create (&this->designPrio,
138                   &stpm->BrId,
139                   0,
140                   &stpm->BrId,
141                   this->port_id,
142                   this->port_id);
143    STP_copy_times (&this->designTimes, &stpm->rootTimes);
144  }
145
146  /* reset timers */
147  this->fdWhile =
148  this->helloWhen =
149  this->mdelayWhile =
150  this->rbWhile =
151  this->rcvdInfoWhile =
152  this->rrWhile =
153  this->tcWhile =
154  this->txCount = 0;
155
156  this->msgPortRole = RSTP_PORT_ROLE_UNKN;
157  this->selectedRole = DisabledPort;
158  this->sendRSTP = True;
159  this->operSpeed = STP_OUT_get_port_oper_speed (this->port_index);
160  this->p2p_recompute = True;
161}
162
163void
164STP_port_delete (PORT_T* this)
165{
166  STPM_T*                   stpm;
167  register PORT_T*          prev;
168  register PORT_T*          tmp;
169  register STATE_MACH_T*    stater;
170  register void*            pv;
171
172  stpm = this->owner;
173
174  free (this->port_name);
175  for (stater = this->machines; stater; ) {
176    pv = (void*) stater->next;
177    STP_state_mach_delete (stater);
178    stater = (STATE_MACH_T*) pv;
179  }
180
181  prev = NULL;
182  for (tmp = stpm->ports; tmp; tmp = tmp->next) {
183    if (tmp->port_index == this->port_index) {
184      if (prev) {
185        prev->next = this->next;
186      } else {
187        stpm->ports = this->next;
188      }
189      STP_FREE(this, "stp instance");
190      break;
191    }
192    prev = tmp;
193  }
194}
195
196int
197STP_port_rx_bpdu (PORT_T* this, BPDU_T* bpdu, size_t len)
198{
199  STP_info_rx_bpdu (this, bpdu, len);
200
201  return 0;
202}
203
204#ifdef STP_DBG
205int STP_port_trace_state_machine (PORT_T* this, char* mach_name, int enadis)
206{
207    STATE_MACH_T *stater;
208    int nmatch = 0;
209
210    for (stater = this->machines; stater; stater = stater->next) {
211        if (! strcmp (mach_name, "all") || ! strcmp (mach_name, stater->name)) {
212            if (stater->debug != enadis)
213            {
214                stp_trace ("port %s on %s trace %-8s (was %s) now %s",
215                    this->port_name, this->owner->name,
216                    stater->name,
217                    stater->debug ? " enabled" :"disabled",
218                    enadis        ? " enabled" :"disabled");
219            }
220            stater->debug = enadis;
221	    nmatch++;
222        }
223    }
224
225    if (nmatch == 0) {
226	stp_trace("port %s no such state machine as '%s'", this->port_name,
227	    mach_name);
228	return STP_No_Such_State_Machine;
229    }
230
231    return 0;
232}
233
234void STP_port_trace_flags (char* title, PORT_T* this)
235{
236    unsigned long flag = 0L;
237
238    if (!port_trace_flags) return;
239
240    if (this->reRoot)   flag |= 0x000001L;
241    if (this->sync)     flag |= 0x000002L;
242    if (this->synced)   flag |= 0x000004L;
243
244    if (this->proposed)  flag |= 0x000010L;
245    if (this->proposing) flag |= 0x000020L;
246    if (this->agreed)    flag |= 0x000040L;
247    if (this->updtInfo)  flag |= 0x000080L;
248
249    if (this->operEdge)   flag |= 0x000100L;
250    stp_trace ("         %-12s: flags=0x%04lx fdWhile=%d port=%s", title, flag, this->fdWhile, this->port_name);
251}
252
253#endif
254