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 */
30 #define _stp_in_stpm_enable stp_in_stpm_enable
32 STP_VECTORS_T
*stp_vectors
;
35 stp_in_stpm_create (int vlan_id
, char* name
, int* err_code
)
37 register STPM_T
* this;
39 /* stp_trace ("stp_in_stpm_create(%s)", name); */
40 this = stpapi_stpm_find (vlan_id
);
41 if (this) { /* it had just been created :( */
42 *err_code
= STP_Nothing_To_Do
;
46 this = STP_stpm_create (vlan_id
, name
);
47 if (! this) { /* can't create stpm :( */
48 *err_code
= STP_Cannot_Create_Instance_For_Vlan
;
57 _stp_in_stpm_enable (int vlan_id
, char* name
,
58 UID_STP_MODE_T admin_state
)
60 register STPM_T
* this;
61 Bool created_here
= False
;
64 /* stp_trace ("_stp_in_stpm_enable(%s)", name); */
65 this = stpapi_stpm_find (vlan_id
);
67 if (STP_DISABLED
!= admin_state
) {
68 if (! vlan_id
) { /* STP_IN_stop_all (); */
69 register STPM_T
* stpm
;
71 for (stpm
= STP_stpm_get_the_list (); stpm
; stpm
= stpm
->next
) {
72 if (STP_DISABLED
!= stpm
->admin_state
) {
73 STP_OUT_set_hardware_mode (stpm
->vlan_id
, STP_DISABLED
);
74 (void) STP_stpm_enable (stpm
, STP_DISABLED
);
80 if (! this) { /* it had not yet been created */
81 if (STP_ENABLED
== admin_state
) {/* try to create it */
82 stp_trace ("implicit create to vlan '%s'", name
);
83 this = stp_in_stpm_create (vlan_id
, name
, &err_code
);
85 stp_trace ("implicit create to vlan '%s' failed", name
);
86 return STP_Implicit_Instance_Create_Failed
;
89 } else {/* try to disable nothing ? */
94 if (this->admin_state
== admin_state
) { /* nothing to do :) */
98 rc
= STP_stpm_enable (this, admin_state
);
100 STP_OUT_set_hardware_mode (vlan_id
, admin_state
);
103 if (rc
&& created_here
) {
104 STP_stpm_delete (this);
112 stpapi_stpm_find (int vlan_id
)
114 register STPM_T
* this;
116 for (this = STP_stpm_get_the_list (); this; this = this->next
)
117 if (vlan_id
== this->vlan_id
)
124 _stpapi_port_find (STPM_T
* this, int port_index
)
126 register PORT_T
* port
;
128 for (port
= this->ports
; port
; port
= port
->next
)
129 if (port_index
== port
->port_index
) {
138 _conv_br_id_2_uid (IN BRIDGE_ID
* f
, OUT UID_BRIDGE_ID_T
* t
)
140 (void) memcpy (t
, f
, sizeof (UID_BRIDGE_ID_T
));
144 _check_stpm_config (IN UID_STP_CFG_T
* uid_cfg
)
146 if (uid_cfg
->bridge_priority
< MIN_BR_PRIO
) {
147 stp_trace ("%d bridge_priority small", (int) uid_cfg
->bridge_priority
);
148 return STP_Small_Bridge_Priority
;
151 if (uid_cfg
->bridge_priority
> MAX_BR_PRIO
) {
152 stp_trace ("%d bridge_priority large", (int) uid_cfg
->bridge_priority
);
153 return STP_Large_Bridge_Priority
;
156 if (uid_cfg
->hello_time
< MIN_BR_HELLOT
) {
157 stp_trace ("%d hello_time small", (int) uid_cfg
->hello_time
);
158 return STP_Small_Hello_Time
;
161 if (uid_cfg
->hello_time
> MAX_BR_HELLOT
) {
162 stp_trace ("%d hello_time large", (int) uid_cfg
->hello_time
);
163 return STP_Large_Hello_Time
;
166 if (uid_cfg
->max_age
< MIN_BR_MAXAGE
) {
167 stp_trace ("%d max_age small", (int) uid_cfg
->max_age
);
168 return STP_Small_Max_Age
;
171 if (uid_cfg
->max_age
> MAX_BR_MAXAGE
) {
172 stp_trace ("%d max_age large", (int) uid_cfg
->max_age
);
173 return STP_Large_Max_Age
;
176 if (uid_cfg
->forward_delay
< MIN_BR_FWDELAY
) {
177 stp_trace ("%d forward_delay small", (int) uid_cfg
->forward_delay
);
178 return STP_Small_Forward_Delay
;
181 if (uid_cfg
->forward_delay
> MAX_BR_FWDELAY
) {
182 stp_trace ("%d forward_delay large", (int) uid_cfg
->forward_delay
);
183 return STP_Large_Forward_Delay
;
186 if (2 * (uid_cfg
->forward_delay
- 1) < uid_cfg
->max_age
) {
187 return STP_Forward_Delay_And_Max_Age_Are_Inconsistent
;
190 if (uid_cfg
->max_age
< 2 * (uid_cfg
->hello_time
+ 1)) {
191 return STP_Hello_Time_And_Max_Age_Are_Inconsistent
;
198 _stp_in_enable_port_on_stpm (STPM_T
* stpm
, int port_index
, Bool enable
)
200 register PORT_T
* port
;
202 port
= _stpapi_port_find (stpm
, port_index
);
204 if (port
->portEnabled
== enable
) {/* nothing to do :) */
209 if (enable
) { /* clear port statistics */
210 port
->rx_cfg_bpdu_cnt
=
211 port
->rx_rstp_bpdu_cnt
=
212 port
->rx_tcn_bpdu_cnt
= 0;
216 if (port
->edge
->debug
) {
217 stp_trace ("Port %s became '%s' adminEdge=%c",
218 port
->port_name
, enable
? "enable" : "disable",
219 port
->adminEdge
? 'Y' : 'N');
223 port
->adminEnable
= enable
;
224 STP_port_init (port
, stpm
, False
);
226 port
->reselect
= True
;
227 port
->selected
= False
;
231 STP_IN_init (STP_VECTORS_T
*vectors
)
233 RSTP_INIT_CRITICAL_PATH_PROTECTIO
;
234 stp_vectors
= vectors
;
238 STP_IN_stpm_get_cfg (IN
int vlan_id
, OUT UID_STP_CFG_T
* uid_cfg
)
240 register STPM_T
* this;
242 uid_cfg
->field_mask
= 0;
244 RSTP_CRITICAL_PATH_START
;
245 this = stpapi_stpm_find (vlan_id
);
247 if (!this) { /* it had not yet been created :( */
248 RSTP_CRITICAL_PATH_END
;
249 return STP_Vlan_Had_Not_Yet_Been_Created
;
252 if (this->admin_state
!= STP_DISABLED
) {
253 uid_cfg
->field_mask
|= BR_CFG_STATE
;
255 uid_cfg
->stp_enabled
= this->admin_state
;
257 if (this->ForceVersion
!= 2) {
258 uid_cfg
->field_mask
|= BR_CFG_FORCE_VER
;
260 uid_cfg
->force_version
= this->ForceVersion
;
262 if (this->BrId
.prio
!= DEF_BR_PRIO
) {
263 uid_cfg
->field_mask
|= BR_CFG_PRIO
;
265 uid_cfg
->bridge_priority
= this->BrId
.prio
;
267 if (this->BrTimes
.MaxAge
!= DEF_BR_MAXAGE
) {
268 uid_cfg
->field_mask
|= BR_CFG_AGE
;
270 uid_cfg
->max_age
= this->BrTimes
.MaxAge
;
272 if (this->BrTimes
.HelloTime
!= DEF_BR_HELLOT
) {
273 uid_cfg
->field_mask
|= BR_CFG_HELLO
;
275 uid_cfg
->hello_time
= this->BrTimes
.HelloTime
;
277 if (this->BrTimes
.ForwardDelay
!= DEF_BR_FWDELAY
) {
278 uid_cfg
->field_mask
|= BR_CFG_DELAY
;
280 uid_cfg
->forward_delay
= this->BrTimes
.ForwardDelay
;
282 uid_cfg
->hold_time
= TxHoldCount
;
284 RSTP_CRITICAL_PATH_END
;
289 STP_IN_port_get_cfg (int vlan_id
, int port_index
, UID_STP_PORT_CFG_T
* uid_cfg
)
291 register STPM_T
* this;
292 register PORT_T
* port
;
294 RSTP_CRITICAL_PATH_START
;
295 this = stpapi_stpm_find (vlan_id
);
297 if (!this) { /* it had not yet been created :( */
298 RSTP_CRITICAL_PATH_END
;
299 return STP_Vlan_Had_Not_Yet_Been_Created
;
302 port
= _stpapi_port_find (this, port_index
);
303 if (! port
) {/* port is absent in the stpm :( */
304 RSTP_CRITICAL_PATH_END
;
305 return STP_Port_Is_Absent_In_The_Vlan
;
308 uid_cfg
->field_mask
= 0;
310 uid_cfg
->port_priority
= port
->port_id
>> 8;
311 if (uid_cfg
->port_priority
!= DEF_PORT_PRIO
)
312 uid_cfg
->field_mask
|= PT_CFG_PRIO
;
314 uid_cfg
->admin_port_path_cost
= port
->adminPCost
;
315 if (uid_cfg
->admin_port_path_cost
!= ADMIN_PORT_PATH_COST_AUTO
)
316 uid_cfg
->field_mask
|= PT_CFG_COST
;
318 uid_cfg
->admin_point2point
= port
->adminPointToPointMac
;
319 if (uid_cfg
->admin_point2point
!= DEF_P2P
)
320 uid_cfg
->field_mask
|= PT_CFG_P2P
;
322 uid_cfg
->admin_edge
= port
->adminEdge
;
323 if (uid_cfg
->admin_edge
!= DEF_ADMIN_EDGE
)
324 uid_cfg
->field_mask
|= PT_CFG_EDGE
;
326 uid_cfg
->admin_non_stp
= port
->admin_non_stp
;
327 if (uid_cfg
->admin_non_stp
!= DEF_ADMIN_NON_STP
)
328 uid_cfg
->field_mask
|= PT_CFG_NON_STP
;
331 uid_cfg
->field_mask
|= PT_CFG_MCHECK
;
333 RSTP_CRITICAL_PATH_END
;
338 STP_IN_port_get_state (IN
int vlan_id
, INOUT UID_STP_PORT_STATE_T
* entry
)
340 register STPM_T
* this;
341 register PORT_T
* port
;
343 RSTP_CRITICAL_PATH_START
;
344 this = stpapi_stpm_find (vlan_id
);
346 if (!this) { /* it had not yet been created :( */
347 RSTP_CRITICAL_PATH_END
;
348 return STP_Vlan_Had_Not_Yet_Been_Created
;
351 port
= _stpapi_port_find (this, entry
->port_no
);
352 if (! port
) {/* port is absent in the stpm :( */
353 RSTP_CRITICAL_PATH_END
;
354 return STP_Port_Is_Absent_In_The_Vlan
;
357 entry
->port_id
= port
->port_id
;
358 if (DisabledPort
== port
->role
) {
359 entry
->state
= UID_PORT_DISABLED
;
360 } else if (! port
->forward
&& ! port
->learn
) {
361 entry
->state
= UID_PORT_DISCARDING
;
362 } else if (! port
->forward
&& port
->learn
) {
363 entry
->state
= UID_PORT_LEARNING
;
365 entry
->state
= UID_PORT_FORWARDING
;
368 entry
->uptime
= port
->uptime
;
369 entry
->path_cost
= port
->operPCost
;
370 _conv_br_id_2_uid (&port
->portPrio
.root_bridge
, &entry
->designated_root
);
371 entry
->designated_cost
= port
->portPrio
.root_path_cost
;
372 _conv_br_id_2_uid (&port
->portPrio
.design_bridge
, &entry
->designated_bridge
);
373 entry
->designated_port
= port
->portPrio
.design_port
;
375 switch (port
->role
) {
376 case DisabledPort
: entry
->role
= ' '; break;
377 case AlternatePort
: entry
->role
= 'A'; break;
378 case BackupPort
: entry
->role
= 'B'; break;
379 case RootPort
: entry
->role
= 'R'; break;
380 case DesignatedPort
: entry
->role
= 'D'; break;
381 case NonStpPort
: entry
->role
= '-'; break;
382 default: entry
->role
= '?'; break;
385 if (DisabledPort
== port
->role
|| NonStpPort
== port
->role
) {
386 (void) memset (&entry
->designated_root
, 0, sizeof (UID_BRIDGE_ID_T
));
387 (void) memset (&entry
->designated_bridge
, 0, sizeof (UID_BRIDGE_ID_T
));
388 entry
->designated_cost
= 0;
389 entry
->designated_port
= port
->port_id
;
392 if (DisabledPort
== port
->role
) {
393 entry
->oper_point2point
= (P2P_FORCE_FALSE
== port
->adminPointToPointMac
) ? 0 : 1;
394 entry
->oper_edge
= port
->adminEdge
;
395 entry
->oper_stp_neigb
= 0;
397 entry
->oper_point2point
= port
->operPointToPointMac
? 1 : 0;
398 entry
->oper_edge
= port
->operEdge
? 1 : 0;
399 entry
->oper_stp_neigb
= port
->sendRSTP
? 0 : 1;
401 entry
->oper_port_path_cost
= port
->operPCost
;
403 entry
->rx_cfg_bpdu_cnt
= port
->rx_cfg_bpdu_cnt
;
404 entry
->rx_rstp_bpdu_cnt
= port
->rx_rstp_bpdu_cnt
;
405 entry
->rx_tcn_bpdu_cnt
= port
->rx_tcn_bpdu_cnt
;
407 entry
->fdWhile
= port
->fdWhile
; /* 17.15.1 */
408 entry
->helloWhen
= port
->helloWhen
; /* 17.15.2 */
409 entry
->mdelayWhile
= port
->mdelayWhile
; /* 17.15.3 */
410 entry
->rbWhile
= port
->rbWhile
; /* 17.15.4 */
411 entry
->rcvdInfoWhile
= port
->rcvdInfoWhile
;/* 17.15.5 */
412 entry
->rrWhile
= port
->rrWhile
; /* 17.15.6 */
413 entry
->tcWhile
= port
->tcWhile
; /* 17.15.7 */
414 entry
->txCount
= port
->txCount
; /* 17.18.40 */
415 entry
->lnkWhile
= port
->lnkWhile
;
417 entry
->rcvdInfoWhile
= port
->rcvdInfoWhile
;
418 entry
->top_change_ack
= port
->tcAck
;
419 entry
->tc
= port
->tc
;
421 RSTP_CRITICAL_PATH_END
;
426 STP_IN_stpm_get_state (IN
int vlan_id
, OUT UID_STP_STATE_T
* entry
)
428 register STPM_T
* this;
430 RSTP_CRITICAL_PATH_START
;
431 this = stpapi_stpm_find (vlan_id
);
433 if (!this) { /* it had not yet been created :( */
434 RSTP_CRITICAL_PATH_END
;
435 return STP_Vlan_Had_Not_Yet_Been_Created
;
438 (void) strncpy (entry
->vlan_name
, this->name
, NAME_LEN
);
439 entry
->vlan_id
= this->vlan_id
;
440 _conv_br_id_2_uid (&this->rootPrio
.root_bridge
, &entry
->designated_root
);
441 entry
->root_path_cost
= this->rootPrio
.root_path_cost
;
442 entry
->root_port
= this->rootPortId
;
443 entry
->max_age
= this->rootTimes
.MaxAge
;
444 entry
->forward_delay
= this->rootTimes
.ForwardDelay
;
445 entry
->hello_time
= this->rootTimes
.HelloTime
;
447 _conv_br_id_2_uid (&this->BrId
, &entry
->bridge_id
);
449 entry
->stp_enabled
= this->admin_state
;
451 entry
->timeSince_Topo_Change
= this->timeSince_Topo_Change
;
452 entry
->Topo_Change_Count
= this->Topo_Change_Count
;
453 entry
->Topo_Change
= this->Topo_Change
;
455 RSTP_CRITICAL_PATH_END
;
460 STP_IN_stpm_get_name_by_vlan_id (int vlan_id
, char* name
, size_t buffsize
)
462 register STPM_T
* stpm
;
465 RSTP_CRITICAL_PATH_START
;
466 for (stpm
= STP_stpm_get_the_list (); stpm
; stpm
= stpm
->next
) {
467 if (vlan_id
== stpm
->vlan_id
) {
469 (void) strncpy (name
, stpm
->name
, buffsize
);
471 (void) memset (name
, 0, buffsize
);
476 RSTP_CRITICAL_PATH_END
;
480 int /* call it, when link Up/Down */
481 STP_IN_enable_port (int port_index
, Bool enable
)
483 register STPM_T
* stpm
;
485 RSTP_CRITICAL_PATH_START
;
488 stp_trace("%s (p%02d, all, %s, '%s')",
489 "clearFDB", (int) port_index
, "this port", "disable port");
491 STP_OUT_flush_lt (port_index
, 0, LT_FLASH_ONLY_THE_PORT
, "disable port");
494 for (stpm
= STP_stpm_get_the_list (); stpm
; stpm
= stpm
->next
) {
495 if (STP_ENABLED
!= stpm
->admin_state
) continue;
497 _stp_in_enable_port_on_stpm (stpm
, port_index
, enable
);
498 /* STP_stpm_update (stpm);*/
501 RSTP_CRITICAL_PATH_END
;
505 int /* call it, when port speed has been changed, speed in Kb/s */
506 STP_IN_changed_port_speed (int port_index
, long speed
)
508 register STPM_T
* stpm
;
509 register PORT_T
* port
;
511 RSTP_CRITICAL_PATH_START
;
512 for (stpm
= STP_stpm_get_the_list (); stpm
; stpm
= stpm
->next
) {
513 if (STP_ENABLED
!= stpm
->admin_state
) continue;
515 port
= _stpapi_port_find (stpm
, port_index
);
516 if (! port
) continue;
517 port
->operSpeed
= speed
;
519 if (port
->pcost
->debug
) {
520 stp_trace ("changed operSpeed=%lu", port
->operSpeed
);
524 port
->reselect
= True
;
525 port
->selected
= False
;
527 RSTP_CRITICAL_PATH_END
;
531 int /* call it, when port duplex mode has been changed */
532 STP_IN_changed_port_duplex (int port_index
)
534 register STPM_T
* stpm
;
535 register PORT_T
* port
;
537 RSTP_CRITICAL_PATH_START
;
538 for (stpm
= STP_stpm_get_the_list (); stpm
; stpm
= stpm
->next
) {
539 if (STP_ENABLED
!= stpm
->admin_state
) continue;
541 port
= _stpapi_port_find (stpm
, port_index
);
542 if (! port
) continue;
544 if (port
->p2p
->debug
) {
545 stp_trace ("STP_IN_changed_port_duplex(%s)", port
->port_name
);
548 port
->p2p_recompute
= True
;
549 port
->reselect
= True
;
550 port
->selected
= False
;
552 RSTP_CRITICAL_PATH_END
;
557 STP_IN_check_bpdu_header (BPDU_T
* bpdu
, size_t len
)
559 unsigned short len8023
;
561 /* LINTED: alignment */
562 len8023
= ntohs (*(unsigned short*) bpdu
->eth
.len8023
);
563 if (len8023
> 1500) {/* big len8023 format :( */
564 return STP_Big_len8023_Format
;
567 if (len8023
< MIN_BPDU
) { /* small len8023 format :( */
568 return STP_Small_len8023_Format
;
571 if (len8023
+ 14 > len
) { /* len8023 format gt len :( */
572 return STP_len8023_Format_Gt_Len
;
575 if (bpdu
->eth
.dsap
!= BPDU_L_SAP
||
576 bpdu
->eth
.ssap
!= BPDU_L_SAP
||
577 bpdu
->eth
.llc
!= LLC_UI
) {
578 /* this is not a proper 802.3 pkt! :( */
579 return STP_Not_Proper_802_3_Packet
;
582 if (bpdu
->hdr
.protocol
[0] || bpdu
->hdr
.protocol
[1]) {
583 return STP_Invalid_Protocol
;
587 if (bpdu
->hdr
.version
!= BPDU_VERSION_ID
) {
588 return STP_Invalid_Version
;
591 /* see also 9.3.4: think & TBD :( */
596 int dbg_rstp_deny
= 0;
601 STP_IN_rx_bpdu (int vlan_id
, int port_index
, BPDU_T
* bpdu
, size_t len
)
603 register PORT_T
* port
;
604 register STPM_T
* this;
608 if (1 == dbg_rstp_deny
) {
613 RSTP_CRITICAL_PATH_START
;
614 this = stpapi_stpm_find (vlan_id
);
615 if (! this) { /* the stpm had not yet been created :( */
616 RSTP_CRITICAL_PATH_END
;
617 return STP_Vlan_Had_Not_Yet_Been_Created
;
620 if (STP_DISABLED
== this->admin_state
) {/* the stpm had not yet been enabled :( */
621 RSTP_CRITICAL_PATH_END
;
622 return STP_Had_Not_Yet_Been_Enabled_On_The_Vlan
;
625 port
= _stpapi_port_find (this, port_index
);
626 if (! port
) {/* port is absent in the stpm :( */
628 stp_trace ("RX bpdu vlan_id=%d port=%d port is absent in the stpm :(", (int) vlan_id
, (int) port_index
);
630 RSTP_CRITICAL_PATH_END
;
631 return STP_Port_Is_Absent_In_The_Vlan
;
635 if (port
->skip_rx
> 0) {
636 if (1 == port
->skip_rx
)
637 stp_trace ("port %s stop rx skipping",
640 stp_trace ("port %s skip rx %d",
641 port
->port_name
, port
->skip_rx
);
643 RSTP_CRITICAL_PATH_END
;
644 return STP_Nothing_To_Do
;
648 if (port
->operEdge
&& ! port
->lnkWhile
&& port
->portEnabled
) {
650 if (port
->topoch
->debug
) {
651 stp_trace ("port %s tc=TRUE by operEdge", port
->port_name
);
654 port
->tc
= True
; /* IEEE 802.1y, 17.30 */
657 /* port link change indication will come later :( */
658 if (! port
->portEnabled
&&
659 STP_OUT_get_port_link_status (port
->port_index
)) {
660 _stp_in_enable_port_on_stpm (this, port
->port_index
, True
);
664 if (port
->edge
->debug
&& port
->operEdge
) {
665 stp_trace ("port %s not operEdge !", port
->port_name
);
669 port
->operEdge
= False
;
670 port
->wasInitBpdu
= True
;
672 iret
= STP_port_rx_bpdu (port
, bpdu
, len
);
673 (void) STP_stpm_update (this);
674 RSTP_CRITICAL_PATH_END
;
680 STP_IN_one_second (void)
682 register STPM_T
* stpm
;
683 register int dbg_cnt
= 0;
685 RSTP_CRITICAL_PATH_START
;
686 for (stpm
= STP_stpm_get_the_list (); stpm
; stpm
= stpm
->next
) {
687 if (STP_ENABLED
== stpm
->admin_state
) {
688 /* stp_trace ("STP_IN_one_second vlan_id=%d", (int) stpm->vlan_id); */
689 STP_stpm_one_second (stpm
);
694 RSTP_CRITICAL_PATH_END
;
700 STP_IN_stpm_set_cfg (IN
int vlan_id
,
701 IN UID_STP_CFG_T
* uid_cfg
)
703 int rc
= 0, prev_prio
, err_code
;
704 Bool created_here
, enabled_here
;
705 register STPM_T
* this;
708 /* stp_trace ("STP_IN_stpm_set_cfg"); */
709 if (0 != STP_IN_stpm_get_cfg (vlan_id
, &old
)) {
710 STP_OUT_get_init_stpm_cfg (vlan_id
, &old
);
713 RSTP_CRITICAL_PATH_START
;
714 if (BR_CFG_PRIO
& uid_cfg
->field_mask
) {
715 old
.bridge_priority
= uid_cfg
->bridge_priority
;
718 if (BR_CFG_AGE
& uid_cfg
->field_mask
) {
719 old
.max_age
= uid_cfg
->max_age
;
722 if (BR_CFG_HELLO
& uid_cfg
->field_mask
) {
723 old
.hello_time
= uid_cfg
->hello_time
;
726 if (BR_CFG_DELAY
& uid_cfg
->field_mask
) {
727 old
.forward_delay
= uid_cfg
->forward_delay
;
730 if (BR_CFG_FORCE_VER
& uid_cfg
->field_mask
) {
731 old
.force_version
= uid_cfg
->force_version
;
734 rc
= _check_stpm_config (&old
);
736 stp_trace ("_check_stpm_config failed %d", (int) rc
);
737 RSTP_CRITICAL_PATH_END
;
741 if ((BR_CFG_STATE
& uid_cfg
->field_mask
) &&
742 (STP_DISABLED
== uid_cfg
->stp_enabled
)) {
743 rc
= _stp_in_stpm_enable (vlan_id
, uid_cfg
->vlan_name
, STP_DISABLED
);
745 stp_trace ("can't disable rc=%d", (int) rc
);
746 RSTP_CRITICAL_PATH_END
;
749 uid_cfg
->field_mask
&= ~BR_CFG_STATE
;
750 if (! uid_cfg
->field_mask
) {
751 RSTP_CRITICAL_PATH_END
;
756 /* get current state */
757 this = stpapi_stpm_find (vlan_id
);
758 created_here
= False
;
759 enabled_here
= False
;
760 if (! this) { /* it had not yet been created */
761 this = stp_in_stpm_create (vlan_id
, uid_cfg
->vlan_name
, &err_code
);
763 RSTP_CRITICAL_PATH_END
;
768 prev_prio
= this->BrId
.prio
;
769 this->BrId
.prio
= old
.bridge_priority
;
770 if (STP_ENABLED
== this->admin_state
) {
771 if (0 != STP_stpm_check_bridge_priority (this)) {
772 this->BrId
.prio
= prev_prio
;
773 stp_trace ("%s", "STP_stpm_check_bridge_priority failed");
774 RSTP_CRITICAL_PATH_END
;
775 return STP_Invalid_Bridge_Priority
;
779 this->BrTimes
.MaxAge
= old
.max_age
;
780 this->BrTimes
.HelloTime
= old
.hello_time
;
781 this->BrTimes
.ForwardDelay
= old
.forward_delay
;
782 this->ForceVersion
= (PROTOCOL_VERSION_T
) old
.force_version
;
784 if ((BR_CFG_STATE
& uid_cfg
->field_mask
) &&
785 STP_DISABLED
!= uid_cfg
->stp_enabled
&&
786 STP_DISABLED
== this->admin_state
) {
787 rc
= _stp_in_stpm_enable (vlan_id
, uid_cfg
->vlan_name
, uid_cfg
->stp_enabled
);
789 stp_trace ("%s", "cannot enable");
791 STP_stpm_delete (this);
793 RSTP_CRITICAL_PATH_END
;
799 if (! enabled_here
&& STP_DISABLED
!= this->admin_state
) {
800 STP_stpm_update_after_bridge_management (this);
802 RSTP_CRITICAL_PATH_END
;
807 STP_IN_port_set_cfg (IN
int vlan_id
, IN
int port_index
,
808 IN UID_STP_PORT_CFG_T
* uid_cfg
)
810 register STPM_T
* this;
811 register PORT_T
* port
;
813 RSTP_CRITICAL_PATH_START
;
814 this = stpapi_stpm_find (vlan_id
);
815 if (! this) { /* it had not yet been created :( */
816 RSTP_CRITICAL_PATH_END
;
817 stp_trace ("RSTP instance with tag %d hasn't been created\n", vlan_id
);
818 return STP_Vlan_Had_Not_Yet_Been_Created
;
821 port
= _stpapi_port_find (this, port_index
);
822 if (! port
) {/* port is absent in the stpm :( */
823 return STP_Port_Is_Absent_In_The_Vlan
;
826 if (PT_CFG_MCHECK
& uid_cfg
->field_mask
) {
827 if (this->ForceVersion
>= NORMAL_RSTP
)
831 if (PT_CFG_COST
& uid_cfg
->field_mask
) {
832 port
->adminPCost
= uid_cfg
->admin_port_path_cost
;
835 if (PT_CFG_PRIO
& uid_cfg
->field_mask
) {
836 port
->port_id
= (uid_cfg
->port_priority
<< 8) + port_index
;
839 if (PT_CFG_P2P
& uid_cfg
->field_mask
) {
840 port
->adminPointToPointMac
= uid_cfg
->admin_point2point
;
841 port
->p2p_recompute
= True
;
844 if (PT_CFG_EDGE
& uid_cfg
->field_mask
) {
845 port
->adminEdge
= uid_cfg
->admin_edge
;
846 port
->operEdge
= port
->adminEdge
;
848 if (port
->edge
->debug
) {
849 stp_trace ("port %s is operEdge=%c in STP_IN_port_set_cfg",
851 port
->operEdge
? 'Y' : 'n');
856 if (PT_CFG_NON_STP
& uid_cfg
->field_mask
) {
858 if (port
->roletrns
->debug
&& port
->admin_non_stp
!= uid_cfg
->admin_non_stp
) {
859 stp_trace ("port %s is adminNonStp=%c in STP_IN_port_set_cfg",
861 uid_cfg
->admin_non_stp
? 'Y' : 'n');
864 port
->admin_non_stp
= uid_cfg
->admin_non_stp
;
868 if (PT_CFG_DBG_SKIP_RX
& uid_cfg
->field_mask
) {
869 port
->skip_rx
= uid_cfg
->skip_rx
;
872 if (PT_CFG_DBG_SKIP_TX
& uid_cfg
->field_mask
) {
873 port
->skip_tx
= uid_cfg
->skip_tx
;
878 port
->reselect
= True
;
879 port
->selected
= False
;
881 (void) STP_stpm_update (this);
883 RSTP_CRITICAL_PATH_END
;
891 STP_IN_dbg_set_port_trace (char* mach_name
, int enadis
,
892 int vlan_id
, int port_no
)
894 register STPM_T
* this;
895 register PORT_T
* port
;
898 RSTP_CRITICAL_PATH_START
;
899 this = stpapi_stpm_find (vlan_id
);
900 if (! this) { /* it had not yet been created :( */
901 RSTP_CRITICAL_PATH_END
;
902 stp_trace ("RSTP instance with tag %d hasn't been created\n", vlan_id
);
903 return STP_Vlan_Had_Not_Yet_Been_Created
;
906 port
= _stpapi_port_find (this, port_no
);
907 if (! port
) {/* port is absent in the stpm :( */
908 return STP_Port_Is_Absent_In_The_Vlan
;
910 rc
= STP_port_trace_state_machine (port
, mach_name
, enadis
);
912 RSTP_CRITICAL_PATH_END
;
920 STP_IN_get_error_explanation (int rstp_err_no
)
923 static char* rstp_error_names
[] = RSTP_ERRORS
;
925 if (rstp_err_no
< STP_OK
) {
926 return "Too small error code :(";
928 if (rstp_err_no
>= STP_LAST_DUMMY
) {
929 return "Too big error code :(";
932 return rstp_error_names
[rstp_err_no
];
936 STP_IN_port_add(int vlan_id
, int port_index
)
942 RSTP_CRITICAL_PATH_START
;
943 this = stpapi_stpm_find (vlan_id
);
945 if (!this) { /* it had not yet been created :( */
946 RSTP_CRITICAL_PATH_END
;
947 return STP_Vlan_Had_Not_Yet_Been_Created
;
952 if (! STP_port_create (this, port_index
)) {
953 /* can't add port :( */
954 stp_trace ("can't create port %d", port_index
);
955 RSTP_CRITICAL_PATH_END
;
956 return STP_Cannot_Create_Instance_For_Port
;
960 rc
= STP_stpm_start (this);
962 RSTP_CRITICAL_PATH_END
;
968 STP_IN_port_remove(int vlan_id
, int port_index
)
973 RSTP_CRITICAL_PATH_START
;
974 this = stpapi_stpm_find (vlan_id
);
976 if (!this) { /* it had not yet been created :( */
977 RSTP_CRITICAL_PATH_END
;
978 return STP_Vlan_Had_Not_Yet_Been_Created
;
981 port
= _stpapi_port_find (this, port_index
);
982 if (! port
) {/* port is absent in the stpm :( */
983 RSTP_CRITICAL_PATH_END
;
984 return STP_Port_Is_Absent_In_The_Vlan
;
987 STP_port_delete (port
);
990 STP_stpm_stop (this);
991 RSTP_CRITICAL_PATH_END
;
997 STP_IN_get_bridge_id(int vlan_id
, unsigned short *priority
, unsigned char *mac
)
1001 RSTP_CRITICAL_PATH_START
;
1002 this = stpapi_stpm_find (vlan_id
);
1003 *priority
= this->BrId
.prio
;
1004 (void) memcpy(mac
, this->BrId
.addr
, 6);
1005 RSTP_CRITICAL_PATH_END
;
1009 STP_IN_state2str(RSTP_PORT_STATE state
)
1012 case UID_PORT_DISABLED
:
1013 return ("disabled");
1014 case UID_PORT_DISCARDING
:
1015 return ("discarding");
1016 case UID_PORT_LEARNING
:
1017 return ("learning");
1018 case UID_PORT_FORWARDING
:
1019 return ("forwarding");
1020 case UID_PORT_NON_STP
:
1022 case UID_PORT_BADSDU
: /* synthetic state used by daemon */