removed apps
[luayats.git] / src / rstp / stp_in.c-1
blob968774f9d7a5ba329665dc2ce189caa7e046ef84
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  **********************************************************************/
23 /* This file contains API from an operation system to the RSTP library */
25 #include "base.h"
26 #include "stpm.h"
27 #include "stp_in.h"
28 #include "stp_to.h"
29 #include "rstp_bridge.h"
31 // Make this module C++ compatible: this is a keyword
34 #ifndef USELUA
35 int max_port = 1024;
36 #endif
37 #define INCR100(nev) { nev++; if (nev > 99) nev = 0;}
39 #ifndef USELUA
40 RSTP_EVENT_T tev = RSTP_EVENT_LAST_DUMMY;
41 int                      nev = 0;
42 #endif
45 void *
46 stp_in_stpm_create (rstp_bridge *rstp, int vlan_id, char* name, BITMAP_T* port_bmp, int* err_code)
48   int port_index;
49   register STPM_T* self;
51   /* stp_trace ("stp_in_stpm_create(%s)", name); */
52   self = stpapi_stpm_find(rstp, vlan_id);
54   if (self) { /* it had just been created :( */
55     *err_code = STP_Nothing_To_Do;
56     return self;
57   }
59   self = STP_stpm_create (rstp, vlan_id, name);
60   if (! self) { /* can't create stpm :( */
61     *err_code = STP_Cannot_Create_Instance_For_Vlan;
62     return NULL;
63   }
65   for (port_index = 1; port_index <= rstp->max_port; port_index++) {
66     if (BitmapGetBit(port_bmp, (port_index - 1))) {
67       if (! STP_port_create (self, port_index)) {
68         /* can't add port :( */
69         stp_trace ("can't create port %d", (int) port_index);
70         STP_stpm_delete (self);
71         *err_code =STP_Cannot_Create_Instance_For_Port;
72         return NULL;
73       }
74     }
75   }
77   *err_code = STP_OK;
78   return self;
81 int
82 _stp_in_stpm_enable (rstp_bridge *rstp, int vlan_id, char* name,
83                     BITMAP_T* port_bmp,
84                     UID_STP_MODE_T admin_state)
86   register STPM_T* self;
87   Bool created_here = False;
88   int rc, err_code;
90   /* stp_trace ("_stp_in_stpm_enable(%s)", name); */
91   self = stpapi_stpm_find (rstp, vlan_id);
93   if (STP_DISABLED != admin_state) {
94     if (! vlan_id) { /* STP_IN_stop_all (); */
95         register STPM_T* stpm;
97         for (stpm = STP_stpm_get_the_list (rstp); stpm; stpm = stpm->next) {
98           if (STP_DISABLED != stpm->admin_state) {
99             STP_OUT_set_hardware_mode (stpm->rstp, stpm->vlan_id, STP_DISABLED);
100             STP_stpm_enable (stpm, STP_DISABLED);
101           }
102         }
103     }
104   }
106   if (! self) { /* it had not yet been created */
107     if (STP_ENABLED == admin_state) {/* try to create it */
108       stp_trace ("implicit create to vlan '%s'", name);
109       self = (STPM_T*) stp_in_stpm_create (rstp, vlan_id, name, port_bmp, &err_code);
110       if (! self) {
111         stp_trace ("implicit create to vlan '%s' failed", name);
112         return STP_Imlicite_Instance_Create_Failed;
113       }
114       created_here = True;
115     } else {/* try to disable nothing ? */
116       return 0;
117     }
118   }
120   if (self->admin_state == admin_state) { /* nothing to do :) */
121     return 0;
122   }
124   rc = STP_stpm_enable (self, admin_state);
125   if (! rc) {
126     STP_OUT_set_hardware_mode (self->rstp, self->vlan_id, admin_state);
127   }
129   if (rc && created_here) {
130     STP_stpm_delete (self);
131   }
132     
133   return rc;
136 STPM_T *
137 stpapi_stpm_find (rstp_bridge *rstp, int vlan_id)
139   register STPM_T* self;
141   for (self = STP_stpm_get_the_list (rstp); self; self = self->next)
142     if (vlan_id == self->vlan_id)
143       return self;
145   return NULL;
148 static PORT_T *
149 _stpapi_port_find (STPM_T* self, int port_index)
151   register PORT_T* port;
153   for (port = self->ports; port; port = port->next)
154     if (port_index == port->port_index) {
155       return port;
156     }
158   return NULL;
162 static void
163 _conv_br_id_2_uid (IN BRIDGE_ID* f, OUT UID_BRIDGE_ID_T* t)
165   memcpy (t, f, sizeof (UID_BRIDGE_ID_T));
168 static int
169 _check_stpm_config (IN UID_STP_CFG_T* uid_cfg)
171   if (uid_cfg->bridge_priority < MIN_BR_PRIO) {
172     stp_trace ("%d bridge_priority small", (int) uid_cfg->bridge_priority);
173     return STP_Small_Bridge_Priority;
174   }
176   if (uid_cfg->bridge_priority > MAX_BR_PRIO) {
177     stp_trace ("%d bridge_priority large", (int) uid_cfg->bridge_priority);
178     return STP_Large_Bridge_Priority;
179   }
181   if (uid_cfg->hello_time < MIN_BR_HELLOT) {
182     stp_trace ("%d hello_time small", (int) uid_cfg->hello_time);
183     return STP_Small_Hello_Time;
184   }
186   if (uid_cfg->hello_time > MAX_BR_HELLOT) {
187     stp_trace ("%d hello_time large", (int) uid_cfg->hello_time);
188     return STP_Large_Hello_Time;
189   }
191   if (uid_cfg->max_age < MIN_BR_MAXAGE) {
192     stp_trace ("%d max_age small", (int) uid_cfg->max_age);
193     return STP_Small_Max_Age;
194   }
196   if (uid_cfg->max_age > MAX_BR_MAXAGE) {
197     stp_trace ("%d max_age large", (int) uid_cfg->max_age);
198     return STP_Large_Max_Age;
199   }
201   if (uid_cfg->forward_delay < MIN_BR_FWDELAY) {
202     stp_trace ("%d forward_delay small", (int) uid_cfg->forward_delay);
203     return STP_Small_Forward_Delay;
204   }
206   if (uid_cfg->forward_delay > MAX_BR_FWDELAY) {
207     stp_trace ("%d forward_delay large", (int) uid_cfg->forward_delay);
208     return STP_Large_Forward_Delay;
209   }
211   if (2 * (uid_cfg->forward_delay - 1) < uid_cfg->max_age) {
212     return STP_Forward_Delay_And_Max_Age_Are_Inconsistent;
213   }
215   if (uid_cfg->max_age < 2 * (uid_cfg->hello_time + 1)) {
216     return STP_Hello_Time_And_Max_Age_Are_Inconsistent;
217   }
219   return 0;
223  *  Port operational state
224  */
225 static void
226 _stp_in_up_port(STPM_T *stpm, int port_index, Bool enable)
228   register PORT_T* port;
230   port = _stpapi_port_find (stpm, port_index);
231   if (! port) return; 
233   port->macOperational = enable;
237  *  Port administrative state
238  */
239 static void
240 _stp_in_enable_port_on_stpm (STPM_T* stpm, int port_index, Bool enable)
242   register PORT_T* port;
244   port = _stpapi_port_find (stpm, port_index);
245   if (! port) return; 
246   if (portEnabled(port) == enable) {/* nothing to do :) */
247     return;
248   }
250   port->uptime = 0;
251   if (enable) { /* clear port statistics */ 
252     port->rx_cfg_bpdu_cnt =
253     port->rx_rstp_bpdu_cnt =
254     port->rx_tcn_bpdu_cnt = 0;
255   }  
257 #ifdef STP_DBG
258   if (port->brdec->debug) {
259     stp_trace ("Port %s became '%s' adminEdge=%c",
260         port->port_name, enable ? "enable" : "disable",
261         port->adminEdge ? 'Y' : 'N');
262   }
263 #endif
265   port->adminEnable = enable;
266   port->macOperational = enable;
267   STP_port_init (port, stpm, False);
269   port->reselect = True;
270   port->selected = False;  
273 void 
274 STP_IN_init (rstp_bridge *rstp, int max_port_index)
276   rstp->max_port = max_port_index;
277   RSTP_INIT_CRITICAL_PATH_PROTECTIO;
281 STP_IN_stpm_get_cfg (IN rstp_bridge *rstp, int vlan_id, OUT UID_STP_CFG_T* uid_cfg)
283   register STPM_T* self;
285   uid_cfg->field_mask = 0;
286   
287   RSTP_CRITICAL_PATH_START;  
289   self = stpapi_stpm_find (rstp, vlan_id);
291   if (!self) { /* it had not yet been created :( */
292     RSTP_CRITICAL_PATH_END;
293     return STP_Vlan_Had_Not_Yet_Been_Created;
294   }
296   if (self->admin_state != STP_DISABLED) {
297     uid_cfg->field_mask |= BR_CFG_STATE;
298   }
299   uid_cfg->stp_enabled = self->admin_state;
301   if (self->ForceVersion != 2) {
302     uid_cfg->field_mask |= BR_CFG_FORCE_VER;
303   }
304   uid_cfg->force_version = self->ForceVersion;
306   if (self->BrId.prio != DEF_BR_PRIO) {
307     uid_cfg->field_mask |= BR_CFG_PRIO;
308   }
309   uid_cfg->bridge_priority = self->BrId.prio;
311   if (self->BrTimes.MaxAge != DEF_BR_MAXAGE) {
312     uid_cfg->field_mask |= BR_CFG_AGE;
313   }
314   uid_cfg->max_age = self->BrTimes.MaxAge;
316   if (self->BrTimes.HelloTime != DEF_BR_HELLOT) {
317     uid_cfg->field_mask |= BR_CFG_HELLO;
318   }
319   uid_cfg->hello_time = self->BrTimes.HelloTime;
321   if (self->BrTimes.ForwardDelay != DEF_BR_FWDELAY) {
322     uid_cfg->field_mask |= BR_CFG_DELAY;
323   }
324   uid_cfg->forward_delay = self->BrTimes.ForwardDelay;
325   
326   uid_cfg->hold_time = TxHoldCount;
328   RSTP_CRITICAL_PATH_END;
329   return 0;
333 STP_IN_port_get_state (IN rstp_bridge *rstp, int vlan_id, INOUT UID_STP_PORT_STATE_T* entry)
335   register STPM_T* self;
336   register PORT_T* port;
338   RSTP_CRITICAL_PATH_START;
339   self = stpapi_stpm_find (rstp, vlan_id);
341   if (!self) { /* it had not yet been created :( */
342     RSTP_CRITICAL_PATH_END;
343     return STP_Vlan_Had_Not_Yet_Been_Created;
344   }
346   port = _stpapi_port_find (self, entry->port_no);
347   if (! port) {/* port is absent in the stpm :( */
348     RSTP_CRITICAL_PATH_END;
349     return STP_Port_Is_Absent_In_The_Vlan;
350   }
351   strncpy(entry->vlan_name, self->name, NAME_LEN);
352   entry->port_id = port->port_id;
353   if (DisabledPort == port->role) {
354     entry->state = UID_PORT_DISABLED;
355   } else if (! port->forward && ! port->learn) {
356     entry->state = UID_PORT_DISCARDING;
357   } else if (! port->forward && port->learn) {
358     entry->state = UID_PORT_LEARNING;
359   } else {
360     entry->state = UID_PORT_FORWARDING;
361   }
363   entry->uptime = port->uptime;
364   entry->path_cost = port->operPCost;
365   _conv_br_id_2_uid (&port->portPrio.root_bridge, &entry->designated_root);
366   entry->designated_cost = port->portPrio.root_path_cost;
367   _conv_br_id_2_uid (&port->portPrio.design_bridge, &entry->designated_bridge);
368   entry->designated_port = port->portPrio.design_port;
370   switch (port->role) {
371     case DisabledPort:   entry->role = ' '; break;
372     case AlternatePort:  entry->role = 'A'; break;
373     case BackupPort:     entry->role = 'B'; break;
374     case RootPort:       entry->role = 'R'; break;
375     case DesignatedPort: entry->role = 'D'; break;
376     case NonStpPort:     entry->role = '-'; break;
377     default:             entry->role = '?'; break;
378   }
380   if (DisabledPort == port->role || NonStpPort == port->role) {
381     memset (&entry->designated_root, 0, sizeof (UID_BRIDGE_ID_T));
382     memset (&entry->designated_bridge, 0, sizeof (UID_BRIDGE_ID_T));
383     entry->designated_cost = 0;
384     entry->designated_port = port->port_id;
385   }
387   if (DisabledPort == port->role) {
388     entry->oper_point2point = (P2P_FORCE_FALSE == port->adminPointToPointMac) ? 0 : 1;
389     entry->oper_edge = port->adminEdge;
390     entry->oper_edge = port->autoEdge;
391     entry->oper_stp_neigb = 0;
392   } else {
393     entry->oper_point2point = port->operPointToPointMac ? 1 : 0;
394     entry->oper_edge = port->operEdge                   ? 1 : 0;
395     entry->oper_stp_neigb = port->sendRSTP              ? 0 : 1;
396   }
397   entry->oper_port_path_cost = port->operPCost;
399   entry->rx_cfg_bpdu_cnt = port->rx_cfg_bpdu_cnt;
400   entry->rx_rstp_bpdu_cnt = port->rx_rstp_bpdu_cnt;
401   entry->rx_tcn_bpdu_cnt = port->rx_tcn_bpdu_cnt;
403   entry->fdWhile =       port->fdWhile;      /* 17.15.1 */
404   entry->helloWhen =     port->helloWhen;    /* 17.15.2 */
405   entry->mdelayWhile =   port->mdelayWhile;  /* 17.15.3 */
406   entry->rbWhile =       port->rbWhile;      /* 17.15.4 */
407   entry->rcvdInfoWhile = port->rcvdInfoWhile;/* 17.15.5 */
408   entry->rrWhile =       port->rrWhile;      /* 17.15.6 */
409   entry->tcWhile =       port->tcWhile;      /* 17.15.7 */
410   entry->txCount =       port->txCount;      /* 17.18.40 */
411   entry->lnkWhile =      port->lnkWhile;
413   entry->rcvdInfoWhile = port->rcvdInfoWhile;
414   entry->top_change_ack = port->tcAck;
415   entry->tc = port->tc;
416   
417   RSTP_CRITICAL_PATH_END;
418   return 0; 
422 STP_IN_stpm_get_state (IN rstp_bridge *rstp, int vlan_id, OUT UID_STP_STATE_T* entry)
424   register STPM_T* self;
426   RSTP_CRITICAL_PATH_START;
427   self = stpapi_stpm_find (rstp, vlan_id);
429   if (!self) { /* it had not yet been created :( */
430     RSTP_CRITICAL_PATH_END;
431     return STP_Vlan_Had_Not_Yet_Been_Created;
432   }
434   strncpy (entry->vlan_name, self->name, NAME_LEN);
435   entry->vlan_id = self->vlan_id;
436   _conv_br_id_2_uid (&self->rootPrio.root_bridge, &entry->designated_root);
437   entry->root_path_cost = self->rootPrio.root_path_cost;
438   entry->root_port = self->rootPortId;
439   entry->max_age =       self->rootTimes.MaxAge;
440   entry->forward_delay = self->rootTimes.ForwardDelay;
441   entry->hello_time =    self->rootTimes.HelloTime;
443   _conv_br_id_2_uid (&self->BrId, &entry->bridge_id);
445   entry->stp_enabled = self->admin_state;
447   entry->timeSince_Topo_Change = self->timeSince_Topo_Change;
448   entry->Topo_Change_Count = self->Topo_Change_Count;
449   entry->Topo_Change = self->Topo_Change;
450   
451   RSTP_CRITICAL_PATH_END;
452   return 0;
456 STP_IN_stpm_get_name_by_vlan_id (rstp_bridge *rstp, int vlan_id, char* name, size_t buffsize)
458   register STPM_T* stpm;
459   int iret = -1;
461   RSTP_CRITICAL_PATH_START;
462   for (stpm = STP_stpm_get_the_list (rstp); stpm; stpm = stpm->next) {
463     if (vlan_id ==  stpm->vlan_id) {
464       if (stpm->name)
465         strncpy (name, stpm->name, buffsize);
466       else
467         memset (name, 0, buffsize);
468       iret = 0;
469       break;
470     }
471   }
472   RSTP_CRITICAL_PATH_END;
473   return iret;
476 STP_IN_up_port(rstp_bridge *rstp, int port_index, Bool enable)
478   register STPM_T* stpm;
480   RSTP_CRITICAL_PATH_START;
481   rstp->tev = enable ? RSTP_PORT_EN_T : RSTP_PORT_DIS_T; INCR100(rstp->nev);
483   if (! enable) {
484 #ifdef STP_DBG
485     stp_trace("%s (p%02d, all, %s, '%s')",
486         "clearFDB", (int) port_index, "self port", "down port");
487 #endif
488     STP_OUT_flush_lt (rstp, port_index, 0, LT_FLASH_ONLY_THE_PORT, "down port");
489   }
491   for (stpm = STP_stpm_get_the_list (rstp); stpm; stpm = stpm->next) {
492     if (STP_ENABLED != stpm->admin_state) continue;
493     
494     _stp_in_up_port(stpm, port_index, enable);
495     STP_stpm_update (stpm);
496   }
498   RSTP_CRITICAL_PATH_END;
499   return 0;
502 int /* call it, when link Up/Down leu: NO us STP_IN_up_port instead */
503 STP_IN_enable_port (rstp_bridge *rstp, int port_index, Bool enable)
505   register STPM_T* stpm;
507   RSTP_CRITICAL_PATH_START;
508   rstp->tev = enable ? RSTP_PORT_EN_T : RSTP_PORT_DIS_T; INCR100(rstp->nev);
510   if (! enable) {
511 #ifdef STP_DBG
512     stp_trace("%s (p%02d, all, %s, '%s')",
513         "clearFDB", (int) port_index, "self port", "disable port");
514 #endif
515     STP_OUT_flush_lt (rstp, port_index, 0, LT_FLASH_ONLY_THE_PORT, "disable port");
516   }
518   for (stpm = STP_stpm_get_the_list (rstp); stpm; stpm = stpm->next) {
519     if (STP_ENABLED != stpm->admin_state) continue;
520     
521     _stp_in_enable_port_on_stpm (stpm, port_index, enable);
522         /* STP_stpm_update (stpm);*/
523   }
525   RSTP_CRITICAL_PATH_END;
526   return 0;
529 int /* call it, when port speed has been changed, speed in Kb/s  */
530 STP_IN_changed_port_speed (rstp_bridge *rstp, int port_index, long speed)
532   register STPM_T* stpm;
533   register PORT_T* port;
535   RSTP_CRITICAL_PATH_START;
536   rstp->tev = RSTP_PORT_SPEED_T; INCR100(rstp->nev);
538   for (stpm = STP_stpm_get_the_list (rstp); stpm; stpm = stpm->next) {
539     if (STP_ENABLED != stpm->admin_state) continue;
540     
541     port = _stpapi_port_find (stpm, port_index);
542     if (! port) continue; 
543     port->operSpeed = speed;
544 #ifdef STP_DBG
545     if (port->pcost->debug) {
546       stp_trace ("changed operSpeed=%lu", port->operSpeed);
547     }
548 #endif
550     port->reselect = True;
551     port->selected = False;
552   }
553   RSTP_CRITICAL_PATH_END;
554   return 0;
557 int /* call it, when port duplex mode has been changed  */
558 STP_IN_changed_port_duplex (rstp_bridge *rstp, int port_index)
560   register STPM_T* stpm;
561   register PORT_T* port;
563   RSTP_CRITICAL_PATH_START;
564   rstp->tev = RSTP_PORT_DPLEX_T; INCR100(rstp->nev);
566   for (stpm = STP_stpm_get_the_list (rstp); stpm; stpm = stpm->next) {
567     if (STP_ENABLED != stpm->admin_state) continue;
568     
569     port = _stpapi_port_find (stpm, port_index);
570     if (! port) continue; 
571 #ifdef STP_DBG
572     if (port->p2p->debug) {
573       stp_trace ("STP_IN_changed_port_duplex(%s)", port->port_name);
574     }
575 #endif
576     port->p2p_recompute = True;
577     port->reselect = True;
578     port->selected = False;
579   }
580   RSTP_CRITICAL_PATH_END;
581   return 0;
585 STP_IN_check_bpdu_header (BPDU_T* bpdu, size_t len)
587   unsigned short len8023;
589   len8023 = ntohs (*(unsigned short*) bpdu->eth.len8023);
590   if (len8023 > 1500) {/* big len8023 format :( */
591     return STP_Big_len8023_Format;
592   }
594   if (len8023 < MIN_BPDU) { /* small len8023 format :( */
595     return STP_Small_len8023_Format;
596   }
598   if ((unsigned int) (len8023 + 14) > len) { /* len8023 format gt len :( */
599     return STP_len8023_Format_Gt_Len;
600   }
602   if (bpdu->eth.dsap != BPDU_L_SAP                 ||
603       bpdu->eth.ssap != BPDU_L_SAP                 ||
604       bpdu->eth.llc != LLC_UI) {
605     /* self is not a proper 802.3 pkt! :( */
606     return STP_Not_Proper_802_3_Packet;
607   }
609   if (bpdu->hdr.protocol[0] || bpdu->hdr.protocol[1]) {
610     return STP_Invalid_Protocol;
611   }
613 #if 0
614   if (bpdu->hdr.version != BPDU_VERSION_ID) {
615     return STP_Invalid_Version;  
616   }
617 #endif
618   /* see also 9.3.4: think & TBD :( */
619   return 0;
622 #ifndef USELUA
623 #ifdef STP_DBG
624 int dbg_rstp_deny = 0;
625 #endif
626 #endif
629 STP_IN_rx_bpdu (rstp_bridge *rstp, int vlan_id, int port_index, BPDU_T* bpdu, size_t len)
631   register PORT_T* port;
632   register STPM_T* self;
633   int              iret;
635 #ifndef USELUA
636 #ifdef STP_DBG
637   if (1 == dbg_rstp_deny) {
638     return 0;
639   }
640 #endif
641 #endif
643   RSTP_CRITICAL_PATH_START;
644   rstp->tev = RSTP_PORT_RX_T; INCR100(rstp->nev);
646   self = stpapi_stpm_find (rstp, vlan_id);
647   if (! self) { /*  the stpm had not yet been created :( */
648     RSTP_CRITICAL_PATH_END;
649     return STP_Vlan_Had_Not_Yet_Been_Created;
650   }
652   if (STP_DISABLED == self->admin_state) {/* the stpm had not yet been enabled :( */
653     RSTP_CRITICAL_PATH_END;
654     return STP_Had_Not_Yet_Been_Enabled_On_The_Vlan;
655   }
657   port = _stpapi_port_find (self, port_index);
658   if (! port) {/* port is absent in the stpm :( */
659     stp_trace ("RX bpdu vlan_id=%d port=%d port is absent in the stpm :(", (int) vlan_id, (int) port_index);
660     RSTP_CRITICAL_PATH_END;
661     return STP_Port_Is_Absent_In_The_Vlan;
662   }
664 #ifdef STP_DBG
665   if (port->skip_rx > 0) {
666     if (1 == port->skip_rx)
667       stp_trace ("port %s stop rx skipping",
668                  port->port_name);
669     else
670       stp_trace ("port %s skip rx %d",
671                  port->port_name, port->skip_rx);
672     port->skip_rx--;
673     RSTP_CRITICAL_PATH_END;
674     return STP_Nothing_To_Do;
675   }
676 #endif
678   if (port->operEdge && ! port->lnkWhile && portEnabled(port)) {
679 #ifdef STP_DBG
680     if (port->topoch->debug) {
681       stp_trace ("port %s tc=TRUE by operEdge", port->port_name);
682     }
683 #endif
684     port->tc = True; /* IEEE 802.1y, 17.30 */
685   }
686 #if 0 /* leu: do we need this ? */
687   if (! portEnabled(port)) {/* port link change indication will come later :( */
688     _stp_in_enable_port_on_stpm (self, port->port_index, True);
689   }
690 #endif  
691 #ifdef STP_DBG
692   if (port->brdec->debug && port->operEdge) {
693     stp_trace ("port %s not operEdge !", port->port_name);
694   }
695 #endif
697   port->operEdge = False;
698   port->wasInitBpdu = True;
699   
700   iret = STP_port_rx_bpdu (port, bpdu, len);
701   STP_stpm_update (self);
702   RSTP_CRITICAL_PATH_END;
704   return iret;
708 STP_IN_one_second (rstp_bridge *rstp)
710   register STPM_T* stpm;
711   register int     dbg_cnt = 0;
713   RSTP_CRITICAL_PATH_START;
714   rstp->tev = RSTP_PORT_TIME_T; INCR100(rstp->nev);
716   for (stpm = STP_stpm_get_the_list (rstp); stpm; stpm = stpm->next) {
717     if (STP_ENABLED == stpm->admin_state) {
718       /* stp_trace ("STP_IN_one_second vlan_id=%d", (int) stpm->vlan_id); */
719       STP_stpm_one_second (stpm);
720       dbg_cnt++;
721     }
722   }
723   
724   RSTP_CRITICAL_PATH_END;
726   return dbg_cnt;
730 STP_IN_stpm_set_cfg (IN rstp_bridge *rstp, int vlan_id,
731                      IN BITMAP_T* port_bmp,
732                      IN UID_STP_CFG_T* uid_cfg)
734   int rc = 0, prev_prio, err_code;
735   Bool created_here, enabled_here;
736   register STPM_T* self;
737   UID_STP_CFG_T old;
738            
739   /* stp_trace ("STP_IN_stpm_set_cfg"); */
740   if (0 != STP_IN_stpm_get_cfg (rstp, vlan_id, &old)) {
741     STP_OUT_get_init_stpm_cfg (rstp, vlan_id, &old);
742   }
743   
744   RSTP_CRITICAL_PATH_START;
745   rstp->tev = RSTP_PORT_MNGR_T; INCR100(rstp->nev);
746   if (BR_CFG_PRIO & uid_cfg->field_mask) {
747     old.bridge_priority = uid_cfg->bridge_priority;
748   }
750   if (BR_CFG_AGE & uid_cfg->field_mask) {
751     old.max_age = uid_cfg->max_age;
752   }
754   if (BR_CFG_HELLO & uid_cfg->field_mask) {
755     old.hello_time = uid_cfg->hello_time;
756   }
758   if (BR_CFG_DELAY & uid_cfg->field_mask) {
759     old.forward_delay = uid_cfg->forward_delay;
760   }
762   if (BR_CFG_FORCE_VER & uid_cfg->field_mask) {
763     old.force_version = uid_cfg->force_version;
764   }
766   rc = _check_stpm_config (&old);
767   if (0 != rc) {
768     stp_trace ("_check_stpm_config failed %d", (int) rc);
769     RSTP_CRITICAL_PATH_END;
770     return rc;
771   }
773   if ((BR_CFG_STATE & uid_cfg->field_mask) &&
774       (STP_DISABLED == uid_cfg->stp_enabled)) {
775     rc = _stp_in_stpm_enable (rstp, vlan_id, uid_cfg->vlan_name, port_bmp, STP_DISABLED);
776     if (0 != rc) {
777       stp_trace ("can't disable rc=%d", (int) rc);
778       RSTP_CRITICAL_PATH_END;
779       return rc;
780     }
781     uid_cfg->field_mask &= ! BR_CFG_STATE;
782     if (! uid_cfg->field_mask)  {
783       RSTP_CRITICAL_PATH_END;
784       return 0;
785     }
786   }
788   /* get current state */
789   self = stpapi_stpm_find (rstp, vlan_id);
790   created_here = False;
791   enabled_here = False;
792   if (! self) { /* it had not yet been created */
793     self = (STPM_T*) stp_in_stpm_create (rstp, vlan_id, uid_cfg->vlan_name, port_bmp, &err_code);/*STP_IN_stpm_set_cfg*/
794     if (! self) {
795       RSTP_CRITICAL_PATH_END;
796       return err_code;
797     }
798   }
800   prev_prio = self->BrId.prio;
801   self->BrId.prio = old.bridge_priority;
802   if (STP_ENABLED == self->admin_state) {
803     if (0 != STP_stpm_check_bridge_priority (self)) {
804       self->BrId.prio = prev_prio;
805       stp_trace ("%s", "STP_stpm_check_bridge_priority failed");
806       RSTP_CRITICAL_PATH_END;
807       return STP_Invalid_Bridge_Priority;
808     }
809   }
811   self->BrTimes.MaxAge = old.max_age;
812   self->BrTimes.HelloTime = old.hello_time;
813   self->BrTimes.ForwardDelay = old.forward_delay;
814   self->ForceVersion = (PROTOCOL_VERSION_T) old.force_version;
816   if ((BR_CFG_STATE & uid_cfg->field_mask) &&
817       STP_DISABLED != uid_cfg->stp_enabled &&
818       STP_DISABLED == self->admin_state) {
819     rc = _stp_in_stpm_enable (rstp, vlan_id, uid_cfg->vlan_name, port_bmp, uid_cfg->stp_enabled);
820     if (0 != rc) {
821       stp_trace ("%s", "cannot enable");
822       if (created_here) {
823         STP_stpm_delete (self);
824       }
825       RSTP_CRITICAL_PATH_END;
826       return rc;
827     }
828     enabled_here = True;
829   }
831   if (! enabled_here && STP_DISABLED != self->admin_state) {
832     STP_stpm_update_after_bridge_management (self);
833   }
834   RSTP_CRITICAL_PATH_END;
835   return 0;
839 STP_IN_set_port_cfg (IN rstp_bridge *rstp, int vlan_id, IN UID_STP_PORT_CFG_T* uid_cfg)
841   register STPM_T* self;
842   register PORT_T* port;
843   register int     port_no;
845   RSTP_CRITICAL_PATH_START;
846   rstp->tev = RSTP_PORT_MNGR_T; INCR100(rstp->nev);
847   self = stpapi_stpm_find (rstp, vlan_id);
848   if (! self) { /* it had not yet been created :( */
849     RSTP_CRITICAL_PATH_END;
850     Print ("RSTP instance with tag %d hasn't been created\n", (int) vlan_id);
851     return STP_Vlan_Had_Not_Yet_Been_Created;
852   }
853   for (port_no = 1; port_no <= rstp->max_port; port_no++) {
854     if (! BitmapGetBit(&uid_cfg->port_bmp, port_no - 1)) continue;
855   
856     port = _stpapi_port_find (self, port_no);
857     if (! port) {/* port is absent in the stpm :( */
858       continue;
859     }
861     if (PT_CFG_MCHECK & uid_cfg->field_mask) {
862       if (self->ForceVersion >= NORMAL_RSTP)
863         port->mcheck = True;
864     }
866     if (PT_CFG_COST & uid_cfg->field_mask) {
867       port->adminPCost = uid_cfg->admin_port_path_cost;
868     }
869   
870     if (PT_CFG_PRIO & uid_cfg->field_mask) {
871       port->port_id = (uid_cfg->port_priority << 8) + port_no;
872     }
873   
874     if (PT_CFG_P2P & uid_cfg->field_mask) {
875       port->adminPointToPointMac = uid_cfg->admin_point2point;
876       port->p2p_recompute = True;
877     }
878   
879     if (PT_CFG_EDGE & uid_cfg->field_mask) {
880       port->adminEdge = uid_cfg->admin_edge;
881       port->operEdge = port->adminEdge;
882 #ifdef STP_DBG
883       if (port->brdec->debug) {
884         stp_trace ("port %s is operEdge=%c in STP_IN_set_port_cfg",
885             port->port_name,
886             port->operEdge ? 'Y' : 'n');
887       }
888 #endif
889     }
890     if (PT_CFG_NON_STP & uid_cfg->field_mask) {
891             if (self->ForceVersion >= NORMAL_RSTP)
892         port->operEdge = port->autoEdge;
893     }
895     if (PT_CFG_NON_STP & uid_cfg->field_mask) {
896 #ifdef STP_DBG
897       if (port->roletrns->debug && port->admin_non_stp != uid_cfg->admin_non_stp) {
898         stp_trace ("port %s is adminNonStp=%c in STP_IN_set_port_cfg",
899             port->port_name,
900             uid_cfg->admin_non_stp ? 'Y' : 'n');
901       }
902 #endif
903       port->admin_non_stp = uid_cfg->admin_non_stp;
904     }
906 #ifdef STP_DBG
907     if (PT_CFG_DBG_SKIP_RX & uid_cfg->field_mask) {
908       port->skip_rx = uid_cfg->skip_rx;
909     }
911     if (PT_CFG_DBG_SKIP_TX & uid_cfg->field_mask) {
912       port->skip_tx = uid_cfg->skip_tx;
913     }
915 #endif
917     port->reselect = True;
918     port->selected = False;
919   }
920   
921   STP_stpm_update (self);
922   
923   RSTP_CRITICAL_PATH_END;
925   return 0;
928 #ifdef STP_DBG
930 STP_IN_dbg_set_port_trace (char* mach_name, int enadis,
931                            rstp_bridge *rstp, int vlan_id, BITMAP_T* ports,
932                            int is_print_err)
934   register STPM_T* self;
935   register PORT_T* port;
936   register int     port_no;
938   RSTP_CRITICAL_PATH_START;
939   self = stpapi_stpm_find (rstp, vlan_id);
940   if (! self) { /* it had not yet been created :( */
941     RSTP_CRITICAL_PATH_END;
942     if (is_print_err) {
943         Print ("RSTP instance with tag %d hasn't been created\n", (int) vlan_id);
944     }
945     return STP_Vlan_Had_Not_Yet_Been_Created;
946   }
948   for (port_no = 1; port_no <= rstp->max_port; port_no++) {
949     if (! BitmapGetBit(ports, port_no - 1)) continue;
950   
951     port = _stpapi_port_find (self, port_no);
952     if (! port) {/* port is absent in the stpm :( */
953       continue;
954     }
955     STP_port_trace_state_machine (port, mach_name, enadis, vlan_id);
956   }
957   
958   RSTP_CRITICAL_PATH_END;
960   return 0;
963 #endif
965 const char*
966 STP_IN_get_error_explanation (int rstp_err_no)
968 #define CHOOSE(a) #a
969 static char* rstp_error_names[] = RSTP_ERRORS;
970 #undef CHOOSE
971   if (rstp_err_no < STP_OK) {
972     return "Too small error code :(";
973   }
974   if (rstp_err_no >= STP_LAST_DUMMY) {
975     return "Too big error code :(";
976   }
977   
978   return rstp_error_names[rstp_err_no];