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
37 #define INCR100(nev) { nev++; if (nev > 99) nev = 0;}
40 RSTP_EVENT_T tev = RSTP_EVENT_LAST_DUMMY;
46 stp_in_stpm_create (rstp_bridge *rstp, int vlan_id, char* name, BITMAP_T* port_bmp, int* err_code)
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;
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;
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;
82 _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;
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);
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);
111 stp_trace ("implicit create to vlan '%s' failed", name);
112 return STP_Imlicite_Instance_Create_Failed;
115 } else {/* try to disable nothing ? */
120 if (self->admin_state == admin_state) { /* nothing to do :) */
124 rc = STP_stpm_enable (self, admin_state);
126 STP_OUT_set_hardware_mode (self->rstp, self->vlan_id, admin_state);
129 if (rc && created_here) {
130 STP_stpm_delete (self);
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)
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) {
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));
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;
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;
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;
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;
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;
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;
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;
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;
211 if (2 * (uid_cfg->forward_delay - 1) < uid_cfg->max_age) {
212 return STP_Forward_Delay_And_Max_Age_Are_Inconsistent;
215 if (uid_cfg->max_age < 2 * (uid_cfg->hello_time + 1)) {
216 return STP_Hello_Time_And_Max_Age_Are_Inconsistent;
223 * Port operational state
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);
233 port->macOperational = enable;
237 * Port administrative state
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);
246 if (portEnabled(port) == enable) {/* nothing to do :) */
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;
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');
265 port->adminEnable = enable;
266 port->macOperational = enable;
267 STP_port_init (port, stpm, False);
269 port->reselect = True;
270 port->selected = False;
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;
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;
296 if (self->admin_state != STP_DISABLED) {
297 uid_cfg->field_mask |= BR_CFG_STATE;
299 uid_cfg->stp_enabled = self->admin_state;
301 if (self->ForceVersion != 2) {
302 uid_cfg->field_mask |= BR_CFG_FORCE_VER;
304 uid_cfg->force_version = self->ForceVersion;
306 if (self->BrId.prio != DEF_BR_PRIO) {
307 uid_cfg->field_mask |= BR_CFG_PRIO;
309 uid_cfg->bridge_priority = self->BrId.prio;
311 if (self->BrTimes.MaxAge != DEF_BR_MAXAGE) {
312 uid_cfg->field_mask |= BR_CFG_AGE;
314 uid_cfg->max_age = self->BrTimes.MaxAge;
316 if (self->BrTimes.HelloTime != DEF_BR_HELLOT) {
317 uid_cfg->field_mask |= BR_CFG_HELLO;
319 uid_cfg->hello_time = self->BrTimes.HelloTime;
321 if (self->BrTimes.ForwardDelay != DEF_BR_FWDELAY) {
322 uid_cfg->field_mask |= BR_CFG_DELAY;
324 uid_cfg->forward_delay = self->BrTimes.ForwardDelay;
326 uid_cfg->hold_time = TxHoldCount;
328 RSTP_CRITICAL_PATH_END;
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;
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;
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;
360 entry->state = UID_PORT_FORWARDING;
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;
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;
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;
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;
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;
417 RSTP_CRITICAL_PATH_END;
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;
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;
451 RSTP_CRITICAL_PATH_END;
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;
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) {
465 strncpy (name, stpm->name, buffsize);
467 memset (name, 0, buffsize);
472 RSTP_CRITICAL_PATH_END;
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);
485 stp_trace("%s (p%02d, all, %s, '%s')",
486 "clearFDB", (int) port_index, "self port", "down port");
488 STP_OUT_flush_lt (rstp, port_index, 0, LT_FLASH_ONLY_THE_PORT, "down port");
491 for (stpm = STP_stpm_get_the_list (rstp); stpm; stpm = stpm->next) {
492 if (STP_ENABLED != stpm->admin_state) continue;
494 _stp_in_up_port(stpm, port_index, enable);
495 STP_stpm_update (stpm);
498 RSTP_CRITICAL_PATH_END;
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);
512 stp_trace("%s (p%02d, all, %s, '%s')",
513 "clearFDB", (int) port_index, "self port", "disable port");
515 STP_OUT_flush_lt (rstp, port_index, 0, LT_FLASH_ONLY_THE_PORT, "disable port");
518 for (stpm = STP_stpm_get_the_list (rstp); stpm; stpm = stpm->next) {
519 if (STP_ENABLED != stpm->admin_state) continue;
521 _stp_in_enable_port_on_stpm (stpm, port_index, enable);
522 /* STP_stpm_update (stpm);*/
525 RSTP_CRITICAL_PATH_END;
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;
541 port = _stpapi_port_find (stpm, port_index);
542 if (! port) continue;
543 port->operSpeed = speed;
545 if (port->pcost->debug) {
546 stp_trace ("changed operSpeed=%lu", port->operSpeed);
550 port->reselect = True;
551 port->selected = False;
553 RSTP_CRITICAL_PATH_END;
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;
569 port = _stpapi_port_find (stpm, port_index);
570 if (! port) continue;
572 if (port->p2p->debug) {
573 stp_trace ("STP_IN_changed_port_duplex(%s)", port->port_name);
576 port->p2p_recompute = True;
577 port->reselect = True;
578 port->selected = False;
580 RSTP_CRITICAL_PATH_END;
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;
594 if (len8023 < MIN_BPDU) { /* small len8023 format :( */
595 return STP_Small_len8023_Format;
598 if ((unsigned int) (len8023 + 14) > len) { /* len8023 format gt len :( */
599 return STP_len8023_Format_Gt_Len;
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;
609 if (bpdu->hdr.protocol[0] || bpdu->hdr.protocol[1]) {
610 return STP_Invalid_Protocol;
614 if (bpdu->hdr.version != BPDU_VERSION_ID) {
615 return STP_Invalid_Version;
618 /* see also 9.3.4: think & TBD :( */
624 int dbg_rstp_deny = 0;
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;
637 if (1 == dbg_rstp_deny) {
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;
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;
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;
665 if (port->skip_rx > 0) {
666 if (1 == port->skip_rx)
667 stp_trace ("port %s stop rx skipping",
670 stp_trace ("port %s skip rx %d",
671 port->port_name, port->skip_rx);
673 RSTP_CRITICAL_PATH_END;
674 return STP_Nothing_To_Do;
678 if (port->operEdge && ! port->lnkWhile && portEnabled(port)) {
680 if (port->topoch->debug) {
681 stp_trace ("port %s tc=TRUE by operEdge", port->port_name);
684 port->tc = True; /* IEEE 802.1y, 17.30 */
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);
692 if (port->brdec->debug && port->operEdge) {
693 stp_trace ("port %s not operEdge !", port->port_name);
697 port->operEdge = False;
698 port->wasInitBpdu = True;
700 iret = STP_port_rx_bpdu (port, bpdu, len);
701 STP_stpm_update (self);
702 RSTP_CRITICAL_PATH_END;
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);
724 RSTP_CRITICAL_PATH_END;
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;
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);
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;
750 if (BR_CFG_AGE & uid_cfg->field_mask) {
751 old.max_age = uid_cfg->max_age;
754 if (BR_CFG_HELLO & uid_cfg->field_mask) {
755 old.hello_time = uid_cfg->hello_time;
758 if (BR_CFG_DELAY & uid_cfg->field_mask) {
759 old.forward_delay = uid_cfg->forward_delay;
762 if (BR_CFG_FORCE_VER & uid_cfg->field_mask) {
763 old.force_version = uid_cfg->force_version;
766 rc = _check_stpm_config (&old);
768 stp_trace ("_check_stpm_config failed %d", (int) rc);
769 RSTP_CRITICAL_PATH_END;
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);
777 stp_trace ("can't disable rc=%d", (int) rc);
778 RSTP_CRITICAL_PATH_END;
781 uid_cfg->field_mask &= ! BR_CFG_STATE;
782 if (! uid_cfg->field_mask) {
783 RSTP_CRITICAL_PATH_END;
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*/
795 RSTP_CRITICAL_PATH_END;
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;
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);
821 stp_trace ("%s", "cannot enable");
823 STP_stpm_delete (self);
825 RSTP_CRITICAL_PATH_END;
831 if (! enabled_here && STP_DISABLED != self->admin_state) {
832 STP_stpm_update_after_bridge_management (self);
834 RSTP_CRITICAL_PATH_END;
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;
853 for (port_no = 1; port_no <= rstp->max_port; port_no++) {
854 if (! BitmapGetBit(&uid_cfg->port_bmp, port_no - 1)) continue;
856 port = _stpapi_port_find (self, port_no);
857 if (! port) {/* port is absent in the stpm :( */
861 if (PT_CFG_MCHECK & uid_cfg->field_mask) {
862 if (self->ForceVersion >= NORMAL_RSTP)
866 if (PT_CFG_COST & uid_cfg->field_mask) {
867 port->adminPCost = uid_cfg->admin_port_path_cost;
870 if (PT_CFG_PRIO & uid_cfg->field_mask) {
871 port->port_id = (uid_cfg->port_priority << 8) + port_no;
874 if (PT_CFG_P2P & uid_cfg->field_mask) {
875 port->adminPointToPointMac = uid_cfg->admin_point2point;
876 port->p2p_recompute = True;
879 if (PT_CFG_EDGE & uid_cfg->field_mask) {
880 port->adminEdge = uid_cfg->admin_edge;
881 port->operEdge = port->adminEdge;
883 if (port->brdec->debug) {
884 stp_trace ("port %s is operEdge=%c in STP_IN_set_port_cfg",
886 port->operEdge ? 'Y' : 'n');
890 if (PT_CFG_NON_STP & uid_cfg->field_mask) {
891 if (self->ForceVersion >= NORMAL_RSTP)
892 port->operEdge = port->autoEdge;
895 if (PT_CFG_NON_STP & uid_cfg->field_mask) {
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",
900 uid_cfg->admin_non_stp ? 'Y' : 'n');
903 port->admin_non_stp = uid_cfg->admin_non_stp;
907 if (PT_CFG_DBG_SKIP_RX & uid_cfg->field_mask) {
908 port->skip_rx = uid_cfg->skip_rx;
911 if (PT_CFG_DBG_SKIP_TX & uid_cfg->field_mask) {
912 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;
930 STP_IN_dbg_set_port_trace (char* mach_name, int enadis,
931 rstp_bridge *rstp, int vlan_id, BITMAP_T* ports,
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;
943 Print ("RSTP instance with tag %d hasn't been created\n", (int) vlan_id);
945 return STP_Vlan_Had_Not_Yet_Been_Created;
948 for (port_no = 1; port_no <= rstp->max_port; port_no++) {
949 if (! BitmapGetBit(ports, port_no - 1)) continue;
951 port = _stpapi_port_find (self, port_no);
952 if (! port) {/* port is absent in the stpm :( */
955 STP_port_trace_state_machine (port, mach_name, enadis, vlan_id);
958 RSTP_CRITICAL_PATH_END;
966 STP_IN_get_error_explanation (int rstp_err_no)
969 static char* rstp_error_names[] = RSTP_ERRORS;
971 if (rstp_err_no < STP_OK) {
972 return "Too small error code :(";
974 if (rstp_err_no >= STP_LAST_DUMMY) {
975 return "Too big error code :(";
978 return rstp_error_names[rstp_err_no];