xref: /titanic_44/usr/src/lib/librstp/common/port.c (revision 4eaa471005973e11a6110b69fe990530b3b95a38)
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  
42  int port_trace_flags;
43  
44  PORT_T *
STP_port_create(STPM_T * stpm,int port_index)45  STP_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  
132  void
STP_port_init(PORT_T * this,STPM_T * stpm,Bool check_link)133  STP_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  
163  void
STP_port_delete(PORT_T * this)164  STP_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  
196  int
STP_port_rx_bpdu(PORT_T * this,BPDU_T * bpdu,size_t len)197  STP_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
STP_port_trace_state_machine(PORT_T * this,char * mach_name,int enadis)205  int 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  
STP_port_trace_flags(char * title,PORT_T * this)234  void 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