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 */
32 #define INCR100(nev) { nev++; if (nev > 99) nev = 0;}
34 RSTP_EVENT_T tev
= RSTP_EVENT_LAST_DUMMY
;
38 stp_in_stpm_create (int vlan_id
, char* name
, BITMAP_T
* port_bmp
, int* err_code
)
41 register STPM_T
* this;
43 /* stp_trace ("stp_in_stpm_create(%s)", name); */
44 this = stpapi_stpm_find (vlan_id
);
45 if (this) { /* it had just been created :( */
46 *err_code
= STP_Nothing_To_Do
;
50 this = STP_stpm_create (vlan_id
, name
);
51 if (! this) { /* can't create stpm :( */
52 *err_code
= STP_Cannot_Create_Instance_For_Vlan
;
56 for (port_index
= 1; port_index
<= max_port
; port_index
++) {
57 if (BitmapGetBit(port_bmp
, (port_index
- 1))) {
58 if (! STP_port_create (this, port_index
)) {
59 /* can't add port :( */
60 stp_trace ("can't create port %d", (int) port_index
);
61 STP_stpm_delete (this);
62 *err_code
=STP_Cannot_Create_Instance_For_Port
;
73 _stp_in_stpm_enable (int vlan_id
, char* name
,
75 UID_STP_MODE_T admin_state
)
77 register STPM_T
* this;
78 Bool created_here
= False
;
81 /* stp_trace ("_stp_in_stpm_enable(%s)", name); */
82 this = stpapi_stpm_find (vlan_id
);
84 if (STP_DISABLED
!= admin_state
) {
85 if (! vlan_id
) { /* STP_IN_stop_all (); */
86 register STPM_T
* stpm
;
88 for (stpm
= STP_stpm_get_the_list (); stpm
; stpm
= stpm
->next
) {
89 if (STP_DISABLED
!= stpm
->admin_state
) {
90 STP_OUT_set_hardware_mode (stpm
->vlan_id
, STP_DISABLED
);
91 STP_stpm_enable (stpm
, STP_DISABLED
);
97 if (! this) { /* it had not yet been created */
98 if (STP_ENABLED
== admin_state
) {/* try to create it */
99 stp_trace ("implicit create to vlan '%s'", name
);
100 this = stp_in_stpm_create (vlan_id
, name
, port_bmp
, &err_code
);
102 stp_trace ("implicit create to vlan '%s' failed", name
);
103 return STP_Imlicite_Instance_Create_Failed
;
106 } else {/* try to disable nothing ? */
111 if (this->admin_state
== admin_state
) { /* nothing to do :) */
115 rc
= STP_stpm_enable (this, admin_state
);
117 STP_OUT_set_hardware_mode (vlan_id
, admin_state
);
120 if (rc
&& created_here
) {
121 STP_stpm_delete (this);
129 stpapi_stpm_find (int vlan_id
)
131 register STPM_T
* this;
133 for (this = STP_stpm_get_the_list (); this; this = this->next
)
134 if (vlan_id
== this->vlan_id
)
141 _stpapi_port_find (STPM_T
* this, int port_index
)
143 register PORT_T
* port
;
145 for (port
= this->ports
; port
; port
= port
->next
)
146 if (port_index
== port
->port_index
) {
155 _conv_br_id_2_uid (IN BRIDGE_ID
* f
, OUT UID_BRIDGE_ID_T
* t
)
157 memcpy (t
, f
, sizeof (UID_BRIDGE_ID_T
));
161 _check_stpm_config (IN UID_STP_CFG_T
* uid_cfg
)
163 if (uid_cfg
->bridge_priority
< MIN_BR_PRIO
) {
164 stp_trace ("%d bridge_priority small", (int) uid_cfg
->bridge_priority
);
165 return STP_Small_Bridge_Priority
;
168 if (uid_cfg
->bridge_priority
> MAX_BR_PRIO
) {
169 stp_trace ("%d bridge_priority large", (int) uid_cfg
->bridge_priority
);
170 return STP_Large_Bridge_Priority
;
173 if (uid_cfg
->bridge_priority
& ~MASK_BR_PRIO
) {
174 stp_trace ("%d bridge_priority must be a multiple of 4096", (int) uid_cfg
->bridge_priority
);
175 return STP_Bridge_Priority_Not_A_Multiple_Of_4096
;
178 if (uid_cfg
->hello_time
< MIN_BR_HELLOT
) {
179 stp_trace ("%d hello_time small", (int) uid_cfg
->hello_time
);
180 return STP_Small_Hello_Time
;
183 if (uid_cfg
->hello_time
> MAX_BR_HELLOT
) {
184 stp_trace ("%d hello_time large", (int) uid_cfg
->hello_time
);
185 return STP_Large_Hello_Time
;
188 if (uid_cfg
->max_age
< MIN_BR_MAXAGE
) {
189 stp_trace ("%d max_age small", (int) uid_cfg
->max_age
);
190 return STP_Small_Max_Age
;
193 if (uid_cfg
->max_age
> MAX_BR_MAXAGE
) {
194 stp_trace ("%d max_age large", (int) uid_cfg
->max_age
);
195 return STP_Large_Max_Age
;
198 if (uid_cfg
->forward_delay
< MIN_BR_FWDELAY
) {
199 stp_trace ("%d forward_delay small", (int) uid_cfg
->forward_delay
);
200 return STP_Small_Forward_Delay
;
203 if (uid_cfg
->forward_delay
> MAX_BR_FWDELAY
) {
204 stp_trace ("%d forward_delay large", (int) uid_cfg
->forward_delay
);
205 return STP_Large_Forward_Delay
;
208 if (2 * (uid_cfg
->forward_delay
- 1) < uid_cfg
->max_age
) {
209 return STP_Forward_Delay_And_Max_Age_Are_Inconsistent
;
212 if (uid_cfg
->max_age
< 2 * (uid_cfg
->hello_time
+ 1)) {
213 return STP_Hello_Time_And_Max_Age_Are_Inconsistent
;
220 _stp_in_enable_port_on_stpm (STPM_T
* stpm
, int port_index
, Bool enable
)
222 register PORT_T
* port
;
224 port
= _stpapi_port_find (stpm
, port_index
);
226 if (port
->portEnabled
== enable
) {/* nothing to do :) */
231 if (enable
) { /* clear port statistics */
232 port
->rx_cfg_bpdu_cnt
=
233 port
->rx_rstp_bpdu_cnt
=
234 port
->rx_tcn_bpdu_cnt
= 0;
238 if (port
->edge
->debug
) {
239 stp_trace ("Port %s became '%s' adminEdge=%c",
240 port
->port_name
, enable
? "enable" : "disable",
241 port
->adminEdge
? 'Y' : 'N');
245 port
->adminEnable
= enable
;
246 STP_port_init (port
, stpm
, False
);
248 port
->reselect
= True
;
249 port
->selected
= False
;
253 STP_IN_init (int max_port_index
)
255 max_port
= max_port_index
;
256 RSTP_INIT_CRITICAL_PATH_PROTECTIO
;
260 STP_IN_stpm_get_cfg (IN
int vlan_id
, OUT UID_STP_CFG_T
* uid_cfg
)
262 register STPM_T
* this;
264 uid_cfg
->field_mask
= 0;
266 RSTP_CRITICAL_PATH_START
;
267 this = stpapi_stpm_find (vlan_id
);
269 if (!this) { /* it had not yet been created :( */
270 RSTP_CRITICAL_PATH_END
;
271 return STP_Vlan_Had_Not_Yet_Been_Created
;
274 if (this->admin_state
!= STP_DISABLED
) {
275 uid_cfg
->field_mask
|= BR_CFG_STATE
;
277 uid_cfg
->stp_enabled
= this->admin_state
;
279 if (this->ForceVersion
!= 2) {
280 uid_cfg
->field_mask
|= BR_CFG_FORCE_VER
;
282 uid_cfg
->force_version
= this->ForceVersion
;
284 if (this->BrId
.prio
!= DEF_BR_PRIO
) {
285 uid_cfg
->field_mask
|= BR_CFG_PRIO
;
287 uid_cfg
->bridge_priority
= this->BrId
.prio
;
289 if (this->BrTimes
.MaxAge
!= DEF_BR_MAXAGE
) {
290 uid_cfg
->field_mask
|= BR_CFG_AGE
;
292 uid_cfg
->max_age
= this->BrTimes
.MaxAge
;
294 if (this->BrTimes
.HelloTime
!= DEF_BR_HELLOT
) {
295 uid_cfg
->field_mask
|= BR_CFG_HELLO
;
297 uid_cfg
->hello_time
= this->BrTimes
.HelloTime
;
299 if (this->BrTimes
.ForwardDelay
!= DEF_BR_FWDELAY
) {
300 uid_cfg
->field_mask
|= BR_CFG_DELAY
;
302 uid_cfg
->forward_delay
= this->BrTimes
.ForwardDelay
;
304 uid_cfg
->hold_time
= TxHoldCount
;
306 RSTP_CRITICAL_PATH_END
;
311 STP_IN_port_get_cfg (int vlan_id
, int port_index
, UID_STP_PORT_CFG_T
* uid_cfg
)
313 register STPM_T
* this;
314 register PORT_T
* port
;
316 RSTP_CRITICAL_PATH_START
;
317 this = stpapi_stpm_find (vlan_id
);
319 if (!this) { /* it had not yet been created :( */
320 RSTP_CRITICAL_PATH_END
;
321 return STP_Vlan_Had_Not_Yet_Been_Created
;
324 port
= _stpapi_port_find (this, port_index
);
325 if (! port
) {/* port is absent in the stpm :( */
326 RSTP_CRITICAL_PATH_END
;
327 return STP_Port_Is_Absent_In_The_Vlan
;
330 uid_cfg
->field_mask
= 0;
332 uid_cfg
->port_priority
= port
->port_id
>> 8;
333 if (uid_cfg
->port_priority
!= DEF_PORT_PRIO
)
334 uid_cfg
->field_mask
|= PT_CFG_PRIO
;
336 uid_cfg
->admin_port_path_cost
= port
->adminPCost
;
337 if (uid_cfg
->admin_port_path_cost
!= ADMIN_PORT_PATH_COST_AUTO
)
338 uid_cfg
->field_mask
|= PT_CFG_COST
;
340 uid_cfg
->admin_point2point
= port
->adminPointToPointMac
;
341 if (uid_cfg
->admin_point2point
!= DEF_P2P
)
342 uid_cfg
->field_mask
|= PT_CFG_P2P
;
344 uid_cfg
->admin_edge
= port
->adminEdge
;
345 if (uid_cfg
->admin_edge
!= DEF_ADMIN_EDGE
)
346 uid_cfg
->field_mask
|= PT_CFG_EDGE
;
348 RSTP_CRITICAL_PATH_END
;
353 STP_IN_port_get_state (IN
int vlan_id
, INOUT UID_STP_PORT_STATE_T
* entry
)
355 register STPM_T
* this;
356 register PORT_T
* port
;
358 RSTP_CRITICAL_PATH_START
;
359 this = stpapi_stpm_find (vlan_id
);
361 if (!this) { /* it had not yet been created :( */
362 RSTP_CRITICAL_PATH_END
;
363 return STP_Vlan_Had_Not_Yet_Been_Created
;
366 port
= _stpapi_port_find (this, entry
->port_no
);
367 if (! port
) {/* port is absent in the stpm :( */
368 RSTP_CRITICAL_PATH_END
;
369 return STP_Port_Is_Absent_In_The_Vlan
;
372 entry
->port_id
= port
->port_id
;
373 if (DisabledPort
== port
->role
) {
374 entry
->state
= UID_PORT_DISABLED
;
375 } else if (! port
->forward
&& ! port
->learn
) {
376 entry
->state
= UID_PORT_DISCARDING
;
377 } else if (! port
->forward
&& port
->learn
) {
378 entry
->state
= UID_PORT_LEARNING
;
380 entry
->state
= UID_PORT_FORWARDING
;
383 entry
->uptime
= port
->uptime
;
384 entry
->path_cost
= port
->operPCost
;
385 _conv_br_id_2_uid (&port
->portPrio
.root_bridge
, &entry
->designated_root
);
386 entry
->designated_cost
= port
->portPrio
.root_path_cost
;
387 _conv_br_id_2_uid (&port
->portPrio
.design_bridge
, &entry
->designated_bridge
);
388 entry
->designated_port
= port
->portPrio
.design_port
;
390 switch (port
->role
) {
391 case DisabledPort
: entry
->role
= ' '; break;
392 case AlternatePort
: entry
->role
= 'A'; break;
393 case BackupPort
: entry
->role
= 'B'; break;
394 case RootPort
: entry
->role
= 'R'; break;
395 case DesignatedPort
: entry
->role
= 'D'; break;
396 case NonStpPort
: entry
->role
= '-'; break;
397 default: entry
->role
= '?'; break;
400 if (DisabledPort
== port
->role
|| NonStpPort
== port
->role
) {
401 memset (&entry
->designated_root
, 0, sizeof (UID_BRIDGE_ID_T
));
402 memset (&entry
->designated_bridge
, 0, sizeof (UID_BRIDGE_ID_T
));
403 entry
->designated_cost
= 0;
404 entry
->designated_port
= port
->port_id
;
407 if (DisabledPort
== port
->role
) {
408 entry
->oper_point2point
= (P2P_FORCE_FALSE
== port
->adminPointToPointMac
) ? 0 : 1;
409 entry
->oper_edge
= port
->adminEdge
;
410 entry
->oper_stp_neigb
= 0;
412 entry
->oper_point2point
= port
->operPointToPointMac
? 1 : 0;
413 entry
->oper_edge
= port
->operEdge
? 1 : 0;
414 entry
->oper_stp_neigb
= port
->sendRSTP
? 0 : 1;
416 entry
->oper_port_path_cost
= port
->operPCost
;
418 entry
->rx_cfg_bpdu_cnt
= port
->rx_cfg_bpdu_cnt
;
419 entry
->rx_rstp_bpdu_cnt
= port
->rx_rstp_bpdu_cnt
;
420 entry
->rx_tcn_bpdu_cnt
= port
->rx_tcn_bpdu_cnt
;
422 entry
->fdWhile
= port
->fdWhile
; /* 17.15.1 */
423 entry
->helloWhen
= port
->helloWhen
; /* 17.15.2 */
424 entry
->mdelayWhile
= port
->mdelayWhile
; /* 17.15.3 */
425 entry
->rbWhile
= port
->rbWhile
; /* 17.15.4 */
426 entry
->rcvdInfoWhile
= port
->rcvdInfoWhile
;/* 17.15.5 */
427 entry
->rrWhile
= port
->rrWhile
; /* 17.15.6 */
428 entry
->tcWhile
= port
->tcWhile
; /* 17.15.7 */
429 entry
->txCount
= port
->txCount
; /* 17.18.40 */
430 entry
->lnkWhile
= port
->lnkWhile
;
432 entry
->rcvdInfoWhile
= port
->rcvdInfoWhile
;
433 entry
->top_change_ack
= port
->tcAck
;
434 entry
->tc
= port
->tc
;
436 RSTP_CRITICAL_PATH_END
;
441 STP_IN_stpm_get_state (IN
int vlan_id
, OUT UID_STP_STATE_T
* entry
)
443 register STPM_T
* this;
445 RSTP_CRITICAL_PATH_START
;
446 this = stpapi_stpm_find (vlan_id
);
448 if (!this) { /* it had not yet been created :( */
449 RSTP_CRITICAL_PATH_END
;
450 return STP_Vlan_Had_Not_Yet_Been_Created
;
453 strncpy (entry
->vlan_name
, this->name
, NAME_LEN
);
454 entry
->vlan_id
= this->vlan_id
;
455 _conv_br_id_2_uid (&this->rootPrio
.root_bridge
, &entry
->designated_root
);
456 entry
->root_path_cost
= this->rootPrio
.root_path_cost
;
457 entry
->root_port
= this->rootPortId
;
458 entry
->max_age
= this->rootTimes
.MaxAge
;
459 entry
->forward_delay
= this->rootTimes
.ForwardDelay
;
460 entry
->hello_time
= this->rootTimes
.HelloTime
;
462 _conv_br_id_2_uid (&this->BrId
, &entry
->bridge_id
);
464 entry
->stp_enabled
= this->admin_state
;
466 entry
->timeSince_Topo_Change
= this->timeSince_Topo_Change
;
467 entry
->Topo_Change_Count
= this->Topo_Change_Count
;
468 entry
->Topo_Change
= this->Topo_Change
;
470 RSTP_CRITICAL_PATH_END
;
475 STP_IN_stpm_get_name_by_vlan_id (int vlan_id
, char* name
, size_t buffsize
)
477 register STPM_T
* stpm
;
480 RSTP_CRITICAL_PATH_START
;
481 for (stpm
= STP_stpm_get_the_list (); stpm
; stpm
= stpm
->next
) {
482 if (vlan_id
== stpm
->vlan_id
) {
484 strncpy (name
, stpm
->name
, buffsize
);
486 memset (name
, 0, buffsize
);
491 RSTP_CRITICAL_PATH_END
;
495 int /* call it, when link Up/Down */
496 STP_IN_enable_port (int port_index
, Bool enable
)
498 register STPM_T
* stpm
;
500 RSTP_CRITICAL_PATH_START
;
501 tev
= enable
? RSTP_PORT_EN_T
: RSTP_PORT_DIS_T
; INCR100(nev
);
504 stp_trace("%s (p%02d, all, %s, '%s')",
505 "clearFDB", (int) port_index
, "this port", "disable port");
507 STP_OUT_flush_lt (port_index
, 0, LT_FLASH_ONLY_THE_PORT
, "disable port");
510 for (stpm
= STP_stpm_get_the_list (); stpm
; stpm
= stpm
->next
) {
511 if (STP_ENABLED
!= stpm
->admin_state
) continue;
513 _stp_in_enable_port_on_stpm (stpm
, port_index
, enable
);
514 /* STP_stpm_update (stpm);*/
517 RSTP_CRITICAL_PATH_END
;
521 int /* call it, when port speed has been changed, speed in Kb/s */
522 STP_IN_changed_port_speed (int port_index
, long speed
)
524 register STPM_T
* stpm
;
525 register PORT_T
* port
;
527 RSTP_CRITICAL_PATH_START
;
528 tev
= RSTP_PORT_SPEED_T
; INCR100(nev
);
529 for (stpm
= STP_stpm_get_the_list (); stpm
; stpm
= stpm
->next
) {
530 if (STP_ENABLED
!= stpm
->admin_state
) continue;
532 port
= _stpapi_port_find (stpm
, port_index
);
533 if (! port
) continue;
534 port
->operSpeed
= speed
;
536 if (port
->pcost
->debug
) {
537 stp_trace ("changed operSpeed=%lu", port
->operSpeed
);
541 port
->reselect
= True
;
542 port
->selected
= False
;
544 RSTP_CRITICAL_PATH_END
;
548 int /* call it, when port duplex mode has been changed */
549 STP_IN_changed_port_duplex (int port_index
)
551 register STPM_T
* stpm
;
552 register PORT_T
* port
;
554 RSTP_CRITICAL_PATH_START
;
555 tev
= RSTP_PORT_DPLEX_T
; INCR100(nev
);
556 for (stpm
= STP_stpm_get_the_list (); stpm
; stpm
= stpm
->next
) {
557 if (STP_ENABLED
!= stpm
->admin_state
) continue;
559 port
= _stpapi_port_find (stpm
, port_index
);
560 if (! port
) continue;
562 if (port
->p2p
->debug
) {
563 stp_trace ("STP_IN_changed_port_duplex(%s)", port
->port_name
);
566 port
->p2p_recompute
= True
;
567 port
->reselect
= True
;
568 port
->selected
= False
;
570 RSTP_CRITICAL_PATH_END
;
575 STP_IN_check_bpdu_header (BPDU_T
* bpdu
, size_t len
)
577 unsigned short len8023
;
579 len8023
= ntohs (*(unsigned short*) bpdu
->eth
.len8023
);
580 if (len8023
> 1500) {/* big len8023 format :( */
581 return STP_Big_len8023_Format
;
584 if (len8023
< MIN_BPDU
) { /* small len8023 format :( */
585 return STP_Small_len8023_Format
;
588 if (len8023
+ 14 > len
) { /* len8023 format gt len :( */
589 return STP_len8023_Format_Gt_Len
;
592 if (bpdu
->eth
.dsap
!= BPDU_L_SAP
||
593 bpdu
->eth
.ssap
!= BPDU_L_SAP
||
594 bpdu
->eth
.llc
!= LLC_UI
) {
595 /* this is not a proper 802.3 pkt! :( */
596 return STP_Not_Proper_802_3_Packet
;
599 if (bpdu
->hdr
.protocol
[0] || bpdu
->hdr
.protocol
[1]) {
600 return STP_Invalid_Protocol
;
604 if (bpdu
->hdr
.version
!= BPDU_VERSION_ID
) {
605 return STP_Invalid_Version
;
608 /* see also 9.3.4: think & TBD :( */
613 int dbg_rstp_deny
= 0;
618 STP_IN_rx_bpdu (int vlan_id
, int port_index
, BPDU_T
* bpdu
, size_t len
)
620 register PORT_T
* port
;
621 register STPM_T
* this;
625 if (1 == dbg_rstp_deny
) {
630 RSTP_CRITICAL_PATH_START
;
631 tev
= RSTP_PORT_RX_T
; INCR100(nev
);
632 this = stpapi_stpm_find (vlan_id
);
633 if (! this) { /* the stpm had not yet been created :( */
634 RSTP_CRITICAL_PATH_END
;
635 return STP_Vlan_Had_Not_Yet_Been_Created
;
638 if (STP_DISABLED
== this->admin_state
) {/* the stpm had not yet been enabled :( */
639 RSTP_CRITICAL_PATH_END
;
640 return STP_Had_Not_Yet_Been_Enabled_On_The_Vlan
;
643 port
= _stpapi_port_find (this, port_index
);
644 if (! port
) {/* port is absent in the stpm :( */
645 stp_trace ("RX bpdu vlan_id=%d port=%d port is absent in the stpm :(", (int) vlan_id
, (int) port_index
);
646 RSTP_CRITICAL_PATH_END
;
647 return STP_Port_Is_Absent_In_The_Vlan
;
651 if (port
->skip_rx
> 0) {
652 if (1 == port
->skip_rx
)
653 stp_trace ("port %s stop rx skipping",
656 stp_trace ("port %s skip rx %d",
657 port
->port_name
, port
->skip_rx
);
659 RSTP_CRITICAL_PATH_END
;
660 return STP_Nothing_To_Do
;
664 if (port
->operEdge
&& ! port
->lnkWhile
&& port
->portEnabled
) {
666 if (port
->topoch
->debug
) {
667 stp_trace ("port %s tc=TRUE by operEdge", port
->port_name
);
670 port
->tc
= True
; /* IEEE 802.1y, 17.30 */
673 if (! port
->portEnabled
) {/* port link change indication will come later :( */
674 _stp_in_enable_port_on_stpm (this, port
->port_index
, True
);
678 if (port
->edge
->debug
&& port
->operEdge
) {
679 stp_trace ("port %s not operEdge !", port
->port_name
);
683 port
->operEdge
= False
;
684 port
->wasInitBpdu
= True
;
686 iret
= STP_port_rx_bpdu (port
, bpdu
, len
);
687 STP_stpm_update (this);
688 RSTP_CRITICAL_PATH_END
;
694 STP_IN_one_second (void)
696 register STPM_T
* stpm
;
697 register int dbg_cnt
= 0;
699 RSTP_CRITICAL_PATH_START
;
700 tev
= RSTP_PORT_TIME_T
; INCR100(nev
);
701 for (stpm
= STP_stpm_get_the_list (); stpm
; stpm
= stpm
->next
) {
702 if (STP_ENABLED
== stpm
->admin_state
) {
703 /* stp_trace ("STP_IN_one_second vlan_id=%d", (int) stpm->vlan_id); */
704 STP_stpm_one_second (stpm
);
709 RSTP_CRITICAL_PATH_END
;
715 STP_IN_stpm_set_cfg (IN
int vlan_id
,
716 IN BITMAP_T
* port_bmp
,
717 IN UID_STP_CFG_T
* uid_cfg
)
719 int rc
= 0, prev_prio
, err_code
;
720 Bool created_here
, enabled_here
;
721 register STPM_T
* this;
724 /* stp_trace ("STP_IN_stpm_set_cfg"); */
725 if (0 != STP_IN_stpm_get_cfg (vlan_id
, &old
)) {
726 STP_OUT_get_init_stpm_cfg (vlan_id
, &old
);
729 RSTP_CRITICAL_PATH_START
;
730 tev
= RSTP_PORT_MNGR_T
; INCR100(nev
);
731 if (BR_CFG_PRIO
& uid_cfg
->field_mask
) {
732 old
.bridge_priority
= uid_cfg
->bridge_priority
;
735 if (BR_CFG_AGE
& uid_cfg
->field_mask
) {
736 old
.max_age
= uid_cfg
->max_age
;
739 if (BR_CFG_HELLO
& uid_cfg
->field_mask
) {
740 old
.hello_time
= uid_cfg
->hello_time
;
743 if (BR_CFG_DELAY
& uid_cfg
->field_mask
) {
744 old
.forward_delay
= uid_cfg
->forward_delay
;
747 if (BR_CFG_FORCE_VER
& uid_cfg
->field_mask
) {
748 old
.force_version
= uid_cfg
->force_version
;
751 rc
= _check_stpm_config (&old
);
753 stp_trace ("_check_stpm_config failed %d", (int) rc
);
754 RSTP_CRITICAL_PATH_END
;
758 if ((BR_CFG_STATE
& uid_cfg
->field_mask
) &&
759 (STP_DISABLED
== uid_cfg
->stp_enabled
)) {
760 rc
= _stp_in_stpm_enable (vlan_id
, uid_cfg
->vlan_name
, port_bmp
, STP_DISABLED
);
762 stp_trace ("can't disable rc=%d", (int) rc
);
763 RSTP_CRITICAL_PATH_END
;
766 uid_cfg
->field_mask
&= ! BR_CFG_STATE
;
767 if (! uid_cfg
->field_mask
) {
768 RSTP_CRITICAL_PATH_END
;
773 /* get current state */
774 this = stpapi_stpm_find (vlan_id
);
775 created_here
= False
;
776 enabled_here
= False
;
777 if (! this) { /* it had not yet been created */
778 this = stp_in_stpm_create (vlan_id
, uid_cfg
->vlan_name
, port_bmp
, &err_code
);/*STP_IN_stpm_set_cfg*/
780 RSTP_CRITICAL_PATH_END
;
785 prev_prio
= this->BrId
.prio
;
786 this->BrId
.prio
= old
.bridge_priority
;
787 if (STP_ENABLED
== this->admin_state
) {
788 if (0 != STP_stpm_check_bridge_priority (this)) {
789 this->BrId
.prio
= prev_prio
;
790 stp_trace ("%s", "STP_stpm_check_bridge_priority failed");
791 RSTP_CRITICAL_PATH_END
;
792 return STP_Invalid_Bridge_Priority
;
796 this->BrTimes
.MaxAge
= old
.max_age
;
797 this->BrTimes
.HelloTime
= old
.hello_time
;
798 this->BrTimes
.ForwardDelay
= old
.forward_delay
;
799 this->ForceVersion
= (PROTOCOL_VERSION_T
) old
.force_version
;
801 if ((BR_CFG_STATE
& uid_cfg
->field_mask
) &&
802 STP_DISABLED
!= uid_cfg
->stp_enabled
&&
803 STP_DISABLED
== this->admin_state
) {
804 rc
= _stp_in_stpm_enable (vlan_id
, uid_cfg
->vlan_name
, port_bmp
, uid_cfg
->stp_enabled
);
806 stp_trace ("%s", "cannot enable");
808 STP_stpm_delete (this);
810 RSTP_CRITICAL_PATH_END
;
816 if (! enabled_here
&& STP_DISABLED
!= this->admin_state
) {
817 STP_stpm_update_after_bridge_management (this);
819 RSTP_CRITICAL_PATH_END
;
825 STP_IN_set_port_cfg (IN
int vlan_id
, IN UID_STP_PORT_CFG_T
* uid_cfg
)
828 STP_IN_set_port_cfg (int vlan_id
, int port_index
, UID_STP_PORT_CFG_T
* uid_cfg
)
831 register STPM_T
* this;
832 register PORT_T
* port
;
833 register int port_no
;
835 RSTP_CRITICAL_PATH_START
;
836 tev
= RSTP_PORT_MNGR_T
; INCR100(nev
);
837 this = stpapi_stpm_find (vlan_id
);
838 if (! this) { /* it had not yet been created :( */
839 RSTP_CRITICAL_PATH_END
;
840 Print ("RSTP instance with tag %d hasn't been created\n", (int) vlan_id
);
841 return STP_Vlan_Had_Not_Yet_Been_Created
;
845 for (port_no
= 1; port_no
<= max_port
; port_no
++) {
846 if (! BitmapGetBit(&uid_cfg
->port_bmp
, port_no
- 1)) continue;
848 port_no
= port_index
;
852 port
= _stpapi_port_find (this, port_no
);
853 if (! port
) {/* port is absent in the stpm :( */
857 return STP_Port_Is_Absent_In_The_Vlan
;
861 if (PT_CFG_MCHECK
& uid_cfg
->field_mask
) {
862 if (this->ForceVersion
>= NORMAL_RSTP
)
866 if (PT_CFG_COST
& uid_cfg
->field_mask
) {
867 if (uid_cfg
->admin_port_path_cost
> MAX_PORT_PCOST
)
868 return STP_Large_Port_PCost
;
869 port
->adminPCost
= uid_cfg
->admin_port_path_cost
;
872 if (PT_CFG_PRIO
& uid_cfg
->field_mask
) {
873 if (uid_cfg
->port_priority
< MIN_PORT_PRIO
)
874 return STP_Small_Port_Priority
;
875 if (uid_cfg
->port_priority
> MAX_PORT_PRIO
)
876 return STP_Large_Port_Priority
;
877 if (uid_cfg
->port_priority
& ~MASK_PORT_PRIO
)
878 return STP_Port_Priority_Not_A_Multiple_Of_16
;
879 port
->port_id
= (uid_cfg
->port_priority
<< 8) + port_no
;
882 if (PT_CFG_P2P
& uid_cfg
->field_mask
) {
883 port
->adminPointToPointMac
= uid_cfg
->admin_point2point
;
884 port
->p2p_recompute
= True
;
887 if (PT_CFG_EDGE
& uid_cfg
->field_mask
) {
888 port
->adminEdge
= uid_cfg
->admin_edge
;
889 port
->operEdge
= port
->adminEdge
;
891 if (port
->edge
->debug
) {
892 stp_trace ("port %s is operEdge=%c in STP_IN_set_port_cfg",
894 port
->operEdge
? 'Y' : 'n');
899 if (PT_CFG_NON_STP
& uid_cfg
->field_mask
) {
901 if (port
->roletrns
->debug
&& port
->admin_non_stp
!= uid_cfg
->admin_non_stp
) {
902 stp_trace ("port %s is adminNonStp=%c in STP_IN_set_port_cfg",
904 uid_cfg
->admin_non_stp
? 'Y' : 'n');
907 port
->admin_non_stp
= uid_cfg
->admin_non_stp
;
911 if (PT_CFG_DBG_SKIP_RX
& uid_cfg
->field_mask
) {
912 port
->skip_rx
= uid_cfg
->skip_rx
;
915 if (PT_CFG_DBG_SKIP_TX
& uid_cfg
->field_mask
) {
916 port
->skip_tx
= uid_cfg
->skip_tx
;
921 port
->reselect
= True
;
922 port
->selected
= False
;
925 STP_stpm_update (this);
927 RSTP_CRITICAL_PATH_END
;
934 STP_IN_dbg_set_port_trace (char* mach_name
, int enadis
,
935 int vlan_id
, BITMAP_T
* ports
,
938 register STPM_T
* this;
939 register PORT_T
* port
;
940 register int port_no
;
942 RSTP_CRITICAL_PATH_START
;
943 this = stpapi_stpm_find (vlan_id
);
944 if (! this) { /* it had not yet been created :( */
945 RSTP_CRITICAL_PATH_END
;
947 Print ("RSTP instance with tag %d hasn't been created\n", (int) vlan_id
);
949 return STP_Vlan_Had_Not_Yet_Been_Created
;
952 for (port_no
= 1; port_no
<= max_port
; port_no
++) {
953 if (! BitmapGetBit(ports
, port_no
- 1)) continue;
955 port
= _stpapi_port_find (this, port_no
);
956 if (! port
) {/* port is absent in the stpm :( */
959 STP_port_trace_state_machine (port
, mach_name
, enadis
, vlan_id
);
962 RSTP_CRITICAL_PATH_END
;
970 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
];
985 /*---------------- Dynamic port create / delete ------------------*/
987 int STP_IN_port_create(int vlan_id
, int port_index
)
989 register STPM_T
* this;
991 this = stpapi_stpm_find (vlan_id
);
993 if (! this) { /* can't create stpm :( */
994 return STP_Vlan_Had_Not_Yet_Been_Created
;
997 PORT_T
*port
= STP_port_create (this, port_index
);
999 /* can't add port :( */
1000 stp_trace ("can't create port %d", (int) port_index
);
1001 return STP_Cannot_Create_Instance_For_Port
;
1003 STP_port_init(port
, this, True
);
1005 STP_compute_bridge_id(this);
1006 STP_stpm_update_after_bridge_management (this);
1007 STP_stpm_update (this);
1011 int STP_IN_port_delete(int vlan_id
, int port_index
)
1013 register STPM_T
* this;
1016 this = stpapi_stpm_find (vlan_id
);
1018 if (! this) { /* can't find stpm :( */
1019 return STP_Vlan_Had_Not_Yet_Been_Created
;
1022 port
= _stpapi_port_find (this, port_index
);
1024 return STP_Port_Is_Absent_In_The_Vlan
;
1027 STP_port_delete (port
);
1029 STP_compute_bridge_id(this);
1030 STP_stpm_update_after_bridge_management (this);
1031 STP_stpm_update (this);
1036 /*--- For multiple STP instances - non multithread use ---*/
1044 int max_port
; /* Remove this */
1049 struct stp_instance
*STP_IN_instance_create(void)
1051 struct stp_instance
*p
;
1052 p
= malloc(sizeof(*p
));
1056 p
->dbg_rstp_deny
= 0;
1059 p
->tev
= RSTP_EVENT_LAST_DUMMY
;
1064 void STP_IN_instance_begin(struct stp_instance
*p
)
1066 bridges
= p
->bridges
;
1068 dbg_rstp_deny
= p
->dbg_rstp_deny
;
1070 max_port
= p
->max_port
;
1075 void STP_IN_instance_end(struct stp_instance
*p
)
1077 p
->bridges
= bridges
;
1079 p
->dbg_rstp_deny
= dbg_rstp_deny
;
1081 p
->max_port
= max_port
;
1086 void STP_IN_instance_delete(struct stp_instance
*p
)
1088 STP_IN_instance_begin(p
);
1089 STP_IN_delete_all();
1090 STP_IN_instance_end(p
);