1 /************************************************************************
2 * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
3 * Copyright (C) 2001-2003 Optical Access
6 * This file is part of RSTP library.
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
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.
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
21 **********************************************************************/
23 /* This file contains API from an operation system to the RSTP library */
29 #include "rstp_bridge.h"
31 // Make this module C++ compatible: this is a keyword
33 #define USE_ENABLE_PORT_ON_STPM (1)
38 #define INCR100(nev) { nev++; if (nev > 99) nev = 0;}
41 RSTP_EVENT_T tev
= RSTP_EVENT_LAST_DUMMY
;
46 void *stp_in_stpm_create (rstp_bridge
*rstp
, int vlan_id
, char* name
, BITMAP_T
* port_bmp
, int* err_code
)
49 register STPM_T
* self
;
52 stp_trace ("stp_in_stpm_create(%s)", name
);
53 self
= stpapi_stpm_find(rstp
, vlan_id
);
55 if (self
) { /* it had just been created :( */
56 *err_code
= STP_Nothing_To_Do
;
60 self
= STP_stpm_create (rstp
, vlan_id
, name
);
61 if (! self
) { /* can't create stpm :( */
62 *err_code
= STP_Cannot_Create_Instance_For_Vlan
;
66 for (port_index
= 1; port_index
<= rstp
->max_port
; port_index
++) {
67 if (BitmapGetBit(port_bmp
, (port_index
- 1))) {
68 if (! STP_port_create (self
, port_index
)) {
69 /* can't add port :( */
70 stp_warn ("can't create port %d", (int) port_index
);
71 STP_stpm_delete (self
);
72 *err_code
=STP_Cannot_Create_Instance_For_Port
;
82 int _stp_in_stpm_enable (rstp_bridge
*rstp
, int vlan_id
, char* name
,
84 UID_STP_MODE_T admin_state
)
86 register STPM_T
* self
;
87 Bool created_here
= False
;
91 stp_trace ("_stp_in_stpm_enable(%s)", name
);
92 self
= stpapi_stpm_find (rstp
, vlan_id
);
94 if (STP_DISABLED
!= admin_state
) {
95 if (! vlan_id
) { /* STP_IN_stop_all (); */
96 register STPM_T
* stpm
;
98 for (stpm
= STP_stpm_get_the_list (rstp
); stpm
; stpm
= stpm
->next
) {
99 if (STP_DISABLED
!= stpm
->admin_state
) {
100 STP_OUT_set_hardware_mode (stpm
->rstp
, stpm
->vlan_id
, STP_DISABLED
);
101 STP_stpm_enable (stpm
, STP_DISABLED
);
107 if (! self
) { /* it had not yet been created */
108 if (STP_ENABLED
== admin_state
) {/* try to create it */
110 stp_trace ("implicit create to vlan '%s'", name
);
111 self
= (STPM_T
*) stp_in_stpm_create (rstp
, vlan_id
, name
, port_bmp
, &err_code
);
113 stp_warn ("implicit create to vlan '%s' failed", name
);
114 return STP_Imlicite_Instance_Create_Failed
;
117 } else {/* try to disable nothing ? */
122 if (self
->admin_state
== admin_state
) { /* nothing to do :) */
126 rc
= STP_stpm_enable (self
, admin_state
);
128 STP_OUT_set_hardware_mode (self
->rstp
, self
->vlan_id
, admin_state
);
131 if (rc
&& created_here
) {
132 STP_stpm_delete (self
);
138 STPM_T
*stpapi_stpm_find (rstp_bridge
*rstp
, int vlan_id
)
140 register STPM_T
* self
;
142 for (self
= STP_stpm_get_the_list (rstp
); self
; self
= self
->next
)
143 if (vlan_id
== self
->vlan_id
)
149 static PORT_T
*_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
) {
162 static void _conv_br_id_2_uid (IN BRIDGE_ID
* f
, OUT UID_BRIDGE_ID_T
* t
)
164 memcpy (t
, f
, sizeof (UID_BRIDGE_ID_T
));
167 static int _check_stpm_config (IN UID_STP_CFG_T
* uid_cfg
)
169 if (uid_cfg
->bridge_priority
< MIN_BR_PRIO
) {
170 stp_warn ("%d bridge_priority small", (int) uid_cfg
->bridge_priority
);
171 return STP_Small_Bridge_Priority
;
174 if (uid_cfg
->bridge_priority
> MAX_BR_PRIO
) {
175 stp_warn ("%d bridge_priority large", (int) uid_cfg
->bridge_priority
);
176 return STP_Large_Bridge_Priority
;
179 if (uid_cfg
->hello_time
< MIN_BR_HELLOT
) {
180 stp_warn ("%d hello_time small", (int) uid_cfg
->hello_time
);
181 return STP_Small_Hello_Time
;
184 if (uid_cfg
->hello_time
> MAX_BR_HELLOT
) {
185 stp_warn ("%d hello_time large", (int) uid_cfg
->hello_time
);
186 return STP_Large_Hello_Time
;
189 if (uid_cfg
->max_age
< MIN_BR_MAXAGE
) {
190 stp_warn ("%d max_age small", (int) uid_cfg
->max_age
);
191 return STP_Small_Max_Age
;
194 if (uid_cfg
->max_age
> MAX_BR_MAXAGE
) {
195 stp_warn ("%d max_age large", (int) uid_cfg
->max_age
);
196 return STP_Large_Max_Age
;
199 if (uid_cfg
->forward_delay
< MIN_BR_FWDELAY
) {
200 stp_warn ("%d forward_delay small", (int) uid_cfg
->forward_delay
);
201 return STP_Small_Forward_Delay
;
204 if (uid_cfg
->forward_delay
> MAX_BR_FWDELAY
) {
205 stp_warn ("%d forward_delay large", (int) uid_cfg
->forward_delay
);
206 return STP_Large_Forward_Delay
;
209 if (2 * (uid_cfg
->forward_delay
- 1) < uid_cfg
->max_age
) {
210 return STP_Forward_Delay_And_Max_Age_Are_Inconsistent
;
213 if (uid_cfg
->max_age
< 2 * (uid_cfg
->hello_time
+ 1)) {
214 return STP_Hello_Time_And_Max_Age_Are_Inconsistent
;
220 static void _stp_in_up_port(STPM_T
*stpm
, int port_index
, Bool enable
)
222 register PORT_T
* port
;
224 port
= _stpapi_port_find (stpm
, port_index
);
227 port
->macOperational
= enable
;
230 static void _stp_in_enable_port_on_stpm (STPM_T
* stpm
, int port_index
, Bool enable
)
232 register PORT_T
* port
;
234 port
= _stpapi_port_find (stpm
, port_index
);
236 if (portEnabled(port
) == enable
) {/* nothing to do :) */
241 if (enable
) { /* clear port statistics */
242 port
->rx_cfg_bpdu_cnt
=
243 port
->rx_rstp_bpdu_cnt
=
244 port
->rx_tcn_bpdu_cnt
= 0;
248 if (port
->brdec
->debug
) {
249 stp_trace ("Port %s became '%s' adminEdge=%c",
250 port
->port_name
, enable
? "enable" : "disable",
251 port
->adminEdge
? 'Y' : 'N');
255 port
->adminEnable
= enable
;
256 port
->macOperational
= enable
;
257 STP_port_init (port
, stpm
, False
);
259 port
->reselect
= True
;
260 port
->selected
= False
;
263 void STP_IN_init (rstp_bridge
*rstp
, int max_port_index
)
265 rstp
->max_port
= max_port_index
;
266 RSTP_INIT_CRITICAL_PATH_PROTECTIO
;
269 int STP_IN_stpm_get_cfg (IN rstp_bridge
*rstp
, int vlan_id
, OUT UID_STP_CFG_T
* uid_cfg
)
271 register STPM_T
* self
;
273 uid_cfg
->field_mask
= 0;
275 RSTP_CRITICAL_PATH_START
;
277 self
= stpapi_stpm_find (rstp
, vlan_id
);
279 if (!self
) { /* it had not yet been created :( */
280 RSTP_CRITICAL_PATH_END
;
281 return STP_Vlan_Had_Not_Yet_Been_Created
;
284 if (self
->admin_state
!= STP_DISABLED
) {
285 uid_cfg
->field_mask
|= BR_CFG_STATE
;
287 uid_cfg
->stp_enabled
= self
->admin_state
;
289 if (self
->ForceVersion
!= 2) {
290 uid_cfg
->field_mask
|= BR_CFG_FORCE_VER
;
292 uid_cfg
->force_version
= self
->ForceVersion
;
294 if (self
->BrId
.prio
!= DEF_BR_PRIO
) {
295 uid_cfg
->field_mask
|= BR_CFG_PRIO
;
297 uid_cfg
->bridge_priority
= self
->BrId
.prio
;
299 if (self
->BrTimes
.MaxAge
!= DEF_BR_MAXAGE
) {
300 uid_cfg
->field_mask
|= BR_CFG_AGE
;
302 uid_cfg
->max_age
= self
->BrTimes
.MaxAge
;
304 if (self
->BrTimes
.HelloTime
!= DEF_BR_HELLOT
) {
305 uid_cfg
->field_mask
|= BR_CFG_HELLO
;
307 uid_cfg
->hello_time
= self
->BrTimes
.HelloTime
;
309 if (self
->BrTimes
.ForwardDelay
!= DEF_BR_FWDELAY
) {
310 uid_cfg
->field_mask
|= BR_CFG_DELAY
;
312 uid_cfg
->forward_delay
= self
->BrTimes
.ForwardDelay
;
314 uid_cfg
->hold_time
= TxHoldCount
;
316 RSTP_CRITICAL_PATH_END
;
320 int STP_IN_port_get_state (IN rstp_bridge
*rstp
, int vlan_id
, INOUT UID_STP_PORT_STATE_T
* entry
)
322 register STPM_T
* self
;
323 register PORT_T
* port
;
325 RSTP_CRITICAL_PATH_START
;
326 self
= stpapi_stpm_find (rstp
, vlan_id
);
328 if (!self
) { /* it had not yet been created :( */
329 RSTP_CRITICAL_PATH_END
;
330 return STP_Vlan_Had_Not_Yet_Been_Created
;
333 port
= _stpapi_port_find (self
, entry
->port_no
);
334 if (! port
) {/* port is absent in the stpm :( */
335 RSTP_CRITICAL_PATH_END
;
336 return STP_Port_Is_Absent_In_The_Vlan
;
338 strncpy(entry
->vlan_name
, self
->name
, NAME_LEN
);
339 entry
->port_id
= port
->port_id
;
340 if (DisabledPort
== port
->role
) {
341 entry
->state
= UID_PORT_DISABLED
;
342 } else if (! port
->forward
&& ! port
->learn
) {
343 entry
->state
= UID_PORT_DISCARDING
;
344 } else if (! port
->forward
&& port
->learn
) {
345 entry
->state
= UID_PORT_LEARNING
;
347 entry
->state
= UID_PORT_FORWARDING
;
350 entry
->uptime
= port
->uptime
;
351 entry
->path_cost
= port
->operPCost
;
352 _conv_br_id_2_uid (&port
->portPrio
.root_bridge
, &entry
->designated_root
);
353 entry
->designated_cost
= port
->portPrio
.root_path_cost
;
354 _conv_br_id_2_uid (&port
->portPrio
.design_bridge
, &entry
->designated_bridge
);
355 entry
->designated_port
= port
->portPrio
.design_port
;
357 switch (port
->role
) {
358 case DisabledPort
: entry
->role
= ' '; break;
359 case AlternatePort
: entry
->role
= 'A'; break;
360 case BackupPort
: entry
->role
= 'B'; break;
361 case RootPort
: entry
->role
= 'R'; break;
362 case DesignatedPort
: entry
->role
= 'D'; break;
363 case NonStpPort
: entry
->role
= '-'; break;
364 default: entry
->role
= '?'; break;
367 if (DisabledPort
== port
->role
|| NonStpPort
== port
->role
) {
368 memset (&entry
->designated_root
, 0, sizeof (UID_BRIDGE_ID_T
));
369 memset (&entry
->designated_bridge
, 0, sizeof (UID_BRIDGE_ID_T
));
370 entry
->designated_cost
= 0;
371 entry
->designated_port
= port
->port_id
;
374 if (DisabledPort
== port
->role
) {
375 entry
->oper_point2point
= (P2P_FORCE_FALSE
== port
->adminPointToPointMac
) ? 0 : 1;
376 entry
->oper_edge
= port
->adminEdge
;
377 entry
->oper_edge
= port
->autoEdge
;
378 entry
->oper_stp_neigb
= 0;
380 entry
->oper_point2point
= port
->operPointToPointMac
? 1 : 0;
381 entry
->oper_edge
= port
->operEdge
? 1 : 0;
382 entry
->oper_stp_neigb
= port
->sendRSTP
? 0 : 1;
384 entry
->oper_port_path_cost
= port
->operPCost
;
386 entry
->rx_cfg_bpdu_cnt
= port
->rx_cfg_bpdu_cnt
;
387 entry
->rx_rstp_bpdu_cnt
= port
->rx_rstp_bpdu_cnt
;
388 entry
->rx_tcn_bpdu_cnt
= port
->rx_tcn_bpdu_cnt
;
390 entry
->fdWhile
= port
->fdWhile
; /* 17.15.1 */
391 entry
->helloWhen
= port
->helloWhen
; /* 17.15.2 */
392 entry
->mdelayWhile
= port
->mdelayWhile
; /* 17.15.3 */
393 entry
->rbWhile
= port
->rbWhile
; /* 17.15.4 */
394 entry
->rcvdInfoWhile
= port
->rcvdInfoWhile
;/* 17.15.5 */
395 entry
->rrWhile
= port
->rrWhile
; /* 17.15.6 */
396 entry
->tcWhile
= port
->tcWhile
; /* 17.15.7 */
397 entry
->txCount
= port
->txCount
; /* 17.18.40 */
398 entry
->lnkWhile
= port
->lnkWhile
;
400 entry
->rcvdInfoWhile
= port
->rcvdInfoWhile
;
401 entry
->top_change_ack
= port
->tcAck
;
402 entry
->tc
= port
->tc
;
404 RSTP_CRITICAL_PATH_END
;
408 int STP_IN_stpm_get_state (IN rstp_bridge
*rstp
, int vlan_id
, OUT UID_STP_STATE_T
* entry
)
410 register STPM_T
* self
;
412 RSTP_CRITICAL_PATH_START
;
413 self
= stpapi_stpm_find (rstp
, vlan_id
);
415 if (!self
) { /* it had not yet been created :( */
416 RSTP_CRITICAL_PATH_END
;
417 return STP_Vlan_Had_Not_Yet_Been_Created
;
420 strncpy (entry
->vlan_name
, self
->name
, NAME_LEN
);
421 entry
->vlan_id
= self
->vlan_id
;
422 _conv_br_id_2_uid (&self
->rootPrio
.root_bridge
, &entry
->designated_root
);
423 entry
->root_path_cost
= self
->rootPrio
.root_path_cost
;
424 entry
->root_port
= self
->rootPortId
;
425 entry
->max_age
= self
->rootTimes
.MaxAge
;
426 entry
->forward_delay
= self
->rootTimes
.ForwardDelay
;
427 entry
->hello_time
= self
->rootTimes
.HelloTime
;
429 _conv_br_id_2_uid (&self
->BrId
, &entry
->bridge_id
);
431 entry
->stp_enabled
= self
->admin_state
;
433 entry
->timeSince_Topo_Change
= self
->timeSince_Topo_Change
;
434 entry
->Topo_Change_Count
= self
->Topo_Change_Count
;
435 entry
->Topo_Change
= self
->Topo_Change
;
437 RSTP_CRITICAL_PATH_END
;
441 int STP_IN_stpm_get_name_by_vlan_id (rstp_bridge
*rstp
, int vlan_id
, char* name
, size_t buffsize
)
443 register STPM_T
* stpm
;
446 RSTP_CRITICAL_PATH_START
;
447 for (stpm
= STP_stpm_get_the_list (rstp
); stpm
; stpm
= stpm
->next
) {
448 if (vlan_id
== stpm
->vlan_id
) {
450 strncpy (name
, stpm
->name
, buffsize
);
452 memset (name
, 0, buffsize
);
457 RSTP_CRITICAL_PATH_END
;
461 int STP_IN_up_port(rstp_bridge
*rstp
, int port_index
, Bool enable
)
463 register STPM_T
* stpm
;
465 RSTP_CRITICAL_PATH_START
;
466 rstp
->tev
= enable
? RSTP_PORT_EN_T
: RSTP_PORT_DIS_T
; INCR100(rstp
->nev
);
471 stp_trace("%s (p%02d, all, %s, '%s')",
472 "clearFDB", (int) port_index
, "self port", "down port");
475 STP_OUT_flush_lt (rstp
, port_index
, 0, LT_FLASH_ONLY_THE_PORT
, "down port");
479 for (stpm
= STP_stpm_get_the_list (rstp
); stpm
; stpm
= stpm
->next
) {
480 if (STP_ENABLED
!= stpm
->admin_state
) continue;
482 #if (USE_ENABLE_PORT_ON_STPM == 1)
483 _stp_in_enable_port_on_stpm (stpm
, port_index
, enable
);
485 _stp_in_up_port(stpm
, port_index
, enable
);
487 STP_stpm_update (stpm
);
490 RSTP_CRITICAL_PATH_END
;
494 /* call it, when link Up/Down leu: NO us STP_IN_up_port instead */
495 int STP_IN_enable_port (rstp_bridge
*rstp
, int port_index
, Bool enable
)
497 register STPM_T
* stpm
;
499 RSTP_CRITICAL_PATH_START
;
500 rstp
->tev
= enable
? RSTP_PORT_EN_T
: RSTP_PORT_DIS_T
; INCR100(rstp
->nev
);
505 stp_trace("%s (p%02d, all, %s, '%s')",
506 "clearFDB", (int) port_index
, "self port", "disable port");
509 STP_OUT_flush_lt (rstp
, port_index
, 0, LT_FLASH_ONLY_THE_PORT
, "disable port");
513 for (stpm
= STP_stpm_get_the_list (rstp
); stpm
; stpm
= stpm
->next
) {
514 if (STP_ENABLED
!= stpm
->admin_state
) continue;
516 _stp_in_enable_port_on_stpm (stpm
, port_index
, enable
);
517 /* STP_stpm_update (stpm);*/
520 RSTP_CRITICAL_PATH_END
;
524 /* call it, when port speed has been changed, speed in Mb/s */
525 int STP_IN_changed_port_speed (rstp_bridge
*rstp
, int port_index
, long speed
)
527 register STPM_T
* stpm
;
528 register PORT_T
* port
;
530 RSTP_CRITICAL_PATH_START
;
531 rstp
->tev
= RSTP_PORT_SPEED_T
; INCR100(rstp
->nev
);
533 for (stpm
= STP_stpm_get_the_list (rstp
); stpm
; stpm
= stpm
->next
) {
534 if (STP_ENABLED
!= stpm
->admin_state
) continue;
536 port
= _stpapi_port_find (stpm
, port_index
);
537 if (! port
) continue;
538 port
->operSpeed
= speed
;
540 if (port
->pcost
->debug
) {
541 stp_trace ("changed operSpeed=%lu", port
->operSpeed
);
545 port
->reselect
= True
;
546 port
->selected
= False
;
547 STP_stpm_update(stpm
);
549 RSTP_CRITICAL_PATH_END
;
553 /* call it, when port duplex mode has been changed */
554 int STP_IN_changed_port_duplex (rstp_bridge
*rstp
, int port_index
)
556 register STPM_T
* stpm
;
557 register PORT_T
* port
;
559 RSTP_CRITICAL_PATH_START
;
560 rstp
->tev
= RSTP_PORT_DPLEX_T
; INCR100(rstp
->nev
);
562 for (stpm
= STP_stpm_get_the_list (rstp
); stpm
; stpm
= stpm
->next
) {
563 if (STP_ENABLED
!= stpm
->admin_state
) continue;
565 port
= _stpapi_port_find (stpm
, port_index
);
566 if (! port
) continue;
568 if (port
->p2p
->debug
) {
569 stp_trace ("STP_IN_changed_port_duplex(%s)", port
->port_name
);
572 port
->p2p_recompute
= True
;
573 port
->reselect
= True
;
574 port
->selected
= False
;
576 RSTP_CRITICAL_PATH_END
;
580 int STP_IN_check_bpdu_header (BPDU_T
* bpdu
, size_t len
)
582 unsigned short len8023
;
584 len8023
= ntohs (*(unsigned short*) bpdu
->eth
.len8023
);
585 if (len8023
> 1500) {/* big len8023 format :( */
586 return STP_Big_len8023_Format
;
589 if (len8023
< MIN_BPDU
) { /* small len8023 format :( */
590 return STP_Small_len8023_Format
;
593 if ((unsigned int) (len8023
+ 14) > len
) { /* len8023 format gt len :( */
594 return STP_len8023_Format_Gt_Len
;
597 if (bpdu
->eth
.dsap
!= BPDU_L_SAP
||
598 bpdu
->eth
.ssap
!= BPDU_L_SAP
||
599 bpdu
->eth
.llc
!= LLC_UI
) {
600 /* self is not a proper 802.3 pkt! :( */
601 return STP_Not_Proper_802_3_Packet
;
604 if (bpdu
->hdr
.protocol
[0] || bpdu
->hdr
.protocol
[1]) {
605 return STP_Invalid_Protocol
;
609 if (bpdu
->hdr
.version
!= BPDU_VERSION_ID
) {
610 return STP_Invalid_Version
;
613 /* see also 9.3.4: think & TBD :( */
619 int dbg_rstp_deny
= 0;
623 int STP_IN_rx_bpdu (rstp_bridge
*rstp
, int vlan_id
, int port_index
, BPDU_T
* bpdu
, size_t len
)
625 register PORT_T
* port
;
626 register STPM_T
* self
;
631 if (1 == dbg_rstp_deny
) {
637 RSTP_CRITICAL_PATH_START
;
638 rstp
->tev
= RSTP_PORT_RX_T
; INCR100(rstp
->nev
);
640 self
= stpapi_stpm_find (rstp
, vlan_id
);
641 if (! self
) { /* the stpm had not yet been created :( */
642 RSTP_CRITICAL_PATH_END
;
643 return STP_Vlan_Had_Not_Yet_Been_Created
;
646 if (STP_DISABLED
== self
->admin_state
) {/* the stpm had not yet been enabled :( */
647 RSTP_CRITICAL_PATH_END
;
648 return STP_Had_Not_Yet_Been_Enabled_On_The_Vlan
;
651 port
= _stpapi_port_find (self
, port_index
);
652 if (! port
) {/* port is absent in the stpm :( */
653 stp_warn ("RX bpdu vlan_id=%d port=%d port is absent in the stpm :(",
654 (int) vlan_id
, (int) port_index
);
655 RSTP_CRITICAL_PATH_END
;
656 return STP_Port_Is_Absent_In_The_Vlan
;
660 if (port
->skip_rx
> 0) {
661 if (1 == port
->skip_rx
)
663 stp_trace ("port %s stop rx skipping",
667 stp_trace ("port %s skip rx %d",
668 port
->port_name
, port
->skip_rx
);
670 RSTP_CRITICAL_PATH_END
;
671 return STP_Nothing_To_Do
;
675 if (port
->operEdge
&& ! port
->lnkWhile
&& portEnabled(port
)) {
677 if (port
->topoch
->debug
) {
678 stp_trace ("port %s tc=TRUE by operEdge", port
->port_name
);
681 port
->tc
= True
; /* IEEE 802.1y, 17.30 */
683 #if 0 /* leu: do we need this ? */
684 if (! portEnabled(port
)) {/* port link change indication will come later :( */
685 _stp_in_enable_port_on_stpm (self
, port
->port_index
, True
);
689 if (port
->brdec
->debug
&& port
->operEdge
) {
690 stp_trace ("port %s not operEdge !", port
->port_name
);
694 port
->operEdge
= False
;
695 port
->wasInitBpdu
= True
;
697 iret
= STP_port_rx_bpdu (port
, bpdu
, len
);
698 STP_stpm_update (self
);
699 RSTP_CRITICAL_PATH_END
;
704 int STP_IN_one_second (rstp_bridge
*rstp
)
706 register STPM_T
* stpm
;
707 register int dbg_cnt
= 0;
709 RSTP_CRITICAL_PATH_START
;
710 rstp
->tev
= RSTP_PORT_TIME_T
; INCR100(rstp
->nev
);
712 for (stpm
= STP_stpm_get_the_list (rstp
); stpm
; stpm
= stpm
->next
) {
713 if (STP_ENABLED
== stpm
->admin_state
) {
714 if (stpm
->debug
== 2)
715 stp_trace ("STP_IN_one_second vlan_id=%d", (int) stpm
->vlan_id
);
716 STP_stpm_one_second (stpm
);
721 RSTP_CRITICAL_PATH_END
;
726 int STP_IN_stpm_set_cfg (IN rstp_bridge
*rstp
, int vlan_id
,
727 IN BITMAP_T
* port_bmp
,
728 IN UID_STP_CFG_T
* uid_cfg
)
730 int rc
= 0, prev_prio
, err_code
;
731 Bool created_here
, enabled_here
;
732 register STPM_T
* self
;
735 if (rstp
->debug
== 2)
736 stp_trace ("STP_IN_stpm_set_cfg");
737 if (0 != STP_IN_stpm_get_cfg (rstp
, vlan_id
, &old
)) {
738 STP_OUT_get_init_stpm_cfg (rstp
, vlan_id
, &old
);
741 RSTP_CRITICAL_PATH_START
;
742 rstp
->tev
= RSTP_PORT_MNGR_T
; INCR100(rstp
->nev
);
743 if (BR_CFG_PRIO
& uid_cfg
->field_mask
) {
744 old
.bridge_priority
= uid_cfg
->bridge_priority
;
747 if (BR_CFG_AGE
& uid_cfg
->field_mask
) {
748 old
.max_age
= uid_cfg
->max_age
;
751 if (BR_CFG_HELLO
& uid_cfg
->field_mask
) {
752 old
.hello_time
= uid_cfg
->hello_time
;
755 if (BR_CFG_DELAY
& uid_cfg
->field_mask
) {
756 old
.forward_delay
= uid_cfg
->forward_delay
;
759 if (BR_CFG_HOLD_TIME
& uid_cfg
->field_mask
) {
760 old
.hold_time
= uid_cfg
->hold_time
;
763 if (BR_CFG_FORCE_VER
& uid_cfg
->field_mask
) {
764 old
.force_version
= uid_cfg
->force_version
;
767 rc
= _check_stpm_config (&old
);
769 stp_warn ("_check_stpm_config failed %d", (int) rc
);
770 RSTP_CRITICAL_PATH_END
;
774 if ((BR_CFG_STATE
& uid_cfg
->field_mask
) &&
775 (STP_DISABLED
== uid_cfg
->stp_enabled
)) {
776 rc
= _stp_in_stpm_enable (rstp
, vlan_id
, uid_cfg
->vlan_name
, port_bmp
, STP_DISABLED
);
778 stp_trace ("can't disable rc=%d", (int) rc
);
779 RSTP_CRITICAL_PATH_END
;
782 uid_cfg
->field_mask
&= ! BR_CFG_STATE
;
783 if (! uid_cfg
->field_mask
) {
784 RSTP_CRITICAL_PATH_END
;
789 /* get current state */
790 self
= stpapi_stpm_find (rstp
, vlan_id
);
791 created_here
= False
;
792 enabled_here
= False
;
793 if (! self
) { /* it had not yet been created */
794 self
= (STPM_T
*) stp_in_stpm_create (rstp
, vlan_id
, uid_cfg
->vlan_name
, port_bmp
, &err_code
);/*STP_IN_stpm_set_cfg*/
796 RSTP_CRITICAL_PATH_END
;
801 prev_prio
= self
->BrId
.prio
;
802 self
->BrId
.prio
= old
.bridge_priority
;
803 if (STP_ENABLED
== self
->admin_state
) {
804 if (0 != STP_stpm_check_bridge_priority (self
)) {
805 self
->BrId
.prio
= prev_prio
;
806 stp_warn ("%s", "STP_stpm_check_bridge_priority failed");
807 RSTP_CRITICAL_PATH_END
;
808 return STP_Invalid_Bridge_Priority
;
812 self
->BrTimes
.MaxAge
= old
.max_age
;
813 self
->BrTimes
.HelloTime
= old
.hello_time
;
814 self
->BrTimes
.ForwardDelay
= old
.forward_delay
;
815 self
->ForceVersion
= (PROTOCOL_VERSION_T
) old
.force_version
;
816 // TxHoldCount = old.hold_time;
818 if ((BR_CFG_STATE
& uid_cfg
->field_mask
) &&
819 STP_DISABLED
!= uid_cfg
->stp_enabled
&&
820 STP_DISABLED
== self
->admin_state
) {
821 rc
= _stp_in_stpm_enable (rstp
, vlan_id
, uid_cfg
->vlan_name
, port_bmp
, uid_cfg
->stp_enabled
);
823 stp_warn ("%s", "cannot enable");
825 STP_stpm_delete (self
);
827 RSTP_CRITICAL_PATH_END
;
833 if (! enabled_here
&& STP_DISABLED
!= self
->admin_state
) {
834 STP_stpm_update_after_bridge_management (self
);
836 RSTP_CRITICAL_PATH_END
;
840 int STP_IN_set_port_cfg (IN rstp_bridge
*rstp
, int vlan_id
, IN UID_STP_PORT_CFG_T
* uid_cfg
)
842 register STPM_T
* self
;
843 register PORT_T
* port
;
844 register int port_no
;
846 RSTP_CRITICAL_PATH_START
;
847 rstp
->tev
= RSTP_PORT_MNGR_T
; INCR100(rstp
->nev
);
848 self
= stpapi_stpm_find (rstp
, vlan_id
);
849 if (! self
) { /* it had not yet been created :( */
850 RSTP_CRITICAL_PATH_END
;
851 Print ("RSTP instance with tag %d hasn't been created\n", (int) vlan_id
);
852 return STP_Vlan_Had_Not_Yet_Been_Created
;
854 for (port_no
= 1; port_no
<= rstp
->max_port
; port_no
++) {
855 if (! BitmapGetBit(&uid_cfg
->port_bmp
, port_no
- 1)) continue;
857 port
= _stpapi_port_find (self
, port_no
);
858 if (! port
) {/* port is absent in the stpm :( */
862 if (PT_CFG_MCHECK
& uid_cfg
->field_mask
) {
863 if (self
->ForceVersion
>= NORMAL_RSTP
)
867 if (PT_CFG_COST
& uid_cfg
->field_mask
) {
868 port
->adminPCost
= uid_cfg
->admin_port_path_cost
;
871 if (PT_CFG_PRIO
& uid_cfg
->field_mask
) {
872 port
->port_id
= (uid_cfg
->port_priority
<< 8) + port_no
;
875 if (PT_CFG_P2P
& uid_cfg
->field_mask
) {
876 port
->adminPointToPointMac
= uid_cfg
->admin_point2point
;
877 port
->p2p_recompute
= True
;
880 if (PT_CFG_EDGE
& uid_cfg
->field_mask
) {
881 port
->adminEdge
= uid_cfg
->admin_edge
;
882 port
->operEdge
= port
->adminEdge
;
884 if (port
->brdec
->debug
) {
885 stp_trace ("port %s is operEdge=%c in STP_IN_set_port_cfg",
887 port
->operEdge
? 'Y' : 'n');
891 if (PT_CFG_NON_STP
& uid_cfg
->field_mask
) {
892 if (self
->ForceVersion
>= NORMAL_RSTP
)
893 port
->operEdge
= port
->autoEdge
;
896 if (PT_CFG_NON_STP
& uid_cfg
->field_mask
) {
898 if (port
->roletrns
->debug
&& port
->admin_non_stp
!= uid_cfg
->admin_non_stp
) {
899 stp_trace ("port %s is adminNonStp=%c in STP_IN_set_port_cfg",
901 uid_cfg
->admin_non_stp
? 'Y' : 'n');
904 port
->admin_non_stp
= uid_cfg
->admin_non_stp
;
908 if (PT_CFG_DBG_SKIP_RX
& uid_cfg
->field_mask
) {
909 port
->skip_rx
= uid_cfg
->skip_rx
;
912 if (PT_CFG_DBG_SKIP_TX
& uid_cfg
->field_mask
) {
913 port
->skip_tx
= uid_cfg
->skip_tx
;
917 port
->reselect
= True
;
918 port
->selected
= False
;
921 STP_stpm_update (self
);
923 RSTP_CRITICAL_PATH_END
;
929 int STP_IN_dbg_set_port_trace (char* mach_name
, int enadis
,
930 rstp_bridge
*rstp
, int vlan_id
, BITMAP_T
* ports
,
933 register STPM_T
* self
;
934 register PORT_T
* port
;
935 register int port_no
;
937 RSTP_CRITICAL_PATH_START
;
938 self
= stpapi_stpm_find (rstp
, vlan_id
);
939 if (! self
) { /* it had not yet been created :( */
940 RSTP_CRITICAL_PATH_END
;
942 Print ("RSTP instance with tag %d hasn't been created\n", (int) vlan_id
);
944 return STP_Vlan_Had_Not_Yet_Been_Created
;
947 for (port_no
= 1; port_no
<= rstp
->max_port
; port_no
++) {
948 if (! BitmapGetBit(ports
, port_no
- 1)) continue;
950 port
= _stpapi_port_find (self
, port_no
);
951 if (! port
) {/* port is absent in the stpm :( */
954 STP_port_trace_state_machine (port
, mach_name
, enadis
, vlan_id
);
957 RSTP_CRITICAL_PATH_END
;
962 int STP_IN_dbg_set_stpm_trace(int enadis
, rstp_bridge
*rstp
, int vlan_id
, int is_print_err
)
964 STPM_T
*self
= stpapi_stpm_find (rstp
, vlan_id
);
965 self
->debug
= enadis
;
970 const char* STP_IN_get_error_explanation (int rstp_err_no
)
973 static char* rstp_error_names
[] = RSTP_ERRORS
;
975 if (rstp_err_no
< STP_OK
) {
976 return "Too small error code :(";
978 if (rstp_err_no
>= STP_LAST_DUMMY
) {
979 return "Too big error code :(";
982 return rstp_error_names
[rstp_err_no
];