8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / lib / librstp / common / stp_in.c
blobf8bd6954f03d3f124dcfecddda235cb888f3ddc9
1 /************************************************************************
2 * RSTP library - Rapid Spanning Tree (802.1t, 802.1w)
3 * Copyright (C) 2001-2003 Optical Access
4 * Author: Alex Rozin
5 *
6 * This file is part of RSTP library.
7 *
8 * RSTP library is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published by the
10 * Free Software Foundation; version 2.1
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
20 * 02111-1307, USA.
21 **********************************************************************/
23 /* This file contains API from an operation system to the RSTP library */
25 #include "base.h"
26 #include "stpm.h"
27 #include "stp_in.h"
28 #include "stp_to.h"
30 #define _stp_in_stpm_enable stp_in_stpm_enable
32 STP_VECTORS_T *stp_vectors;
34 void *
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;
43 return this;
46 this = STP_stpm_create (vlan_id, name);
47 if (! this) { /* can't create stpm :( */
48 *err_code = STP_Cannot_Create_Instance_For_Vlan;
49 return NULL;
52 *err_code = STP_OK;
53 return this;
56 int
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;
62 int rc, err_code;
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);
84 if (! this) {
85 stp_trace ("implicit create to vlan '%s' failed", name);
86 return STP_Implicit_Instance_Create_Failed;
88 created_here = True;
89 } else {/* try to disable nothing ? */
90 return 0;
94 if (this->admin_state == admin_state) { /* nothing to do :) */
95 return 0;
98 rc = STP_stpm_enable (this, admin_state);
99 if (! rc) {
100 STP_OUT_set_hardware_mode (vlan_id, admin_state);
103 if (rc && created_here) {
104 STP_stpm_delete (this);
107 return rc;
111 STPM_T *
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)
118 return this;
120 return NULL;
123 static PORT_T *
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) {
130 return port;
133 return NULL;
137 static void
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));
143 static int
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;
194 return 0;
197 static void
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);
203 if (! port) return;
204 if (port->portEnabled == enable) {/* nothing to do :) */
205 return;
208 port->uptime = 0;
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;
215 #ifdef STP_DBG
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');
221 #endif
223 port->adminEnable = enable;
224 STP_port_init (port, stpm, False);
226 port->reselect = True;
227 port->selected = False;
230 void
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;
285 return 0;
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;
330 if (port->mcheck)
331 uid_cfg->field_mask |= PT_CFG_MCHECK;
333 RSTP_CRITICAL_PATH_END;
334 return 0;
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;
364 } else {
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;
396 } else {
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;
422 return 0;
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;
456 return 0;
460 STP_IN_stpm_get_name_by_vlan_id (int vlan_id, char* name, size_t buffsize)
462 register STPM_T* stpm;
463 int iret = -1;
465 RSTP_CRITICAL_PATH_START;
466 for (stpm = STP_stpm_get_the_list (); stpm; stpm = stpm->next) {
467 if (vlan_id == stpm->vlan_id) {
468 if (stpm->name)
469 (void) strncpy (name, stpm->name, buffsize);
470 else
471 (void) memset (name, 0, buffsize);
472 iret = 0;
473 break;
476 RSTP_CRITICAL_PATH_END;
477 return iret;
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;
486 if (! enable) {
487 #ifdef STP_DBG
488 stp_trace("%s (p%02d, all, %s, '%s')",
489 "clearFDB", (int) port_index, "this port", "disable port");
490 #endif
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;
502 return 0;
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;
518 #ifdef STP_DBG
519 if (port->pcost->debug) {
520 stp_trace ("changed operSpeed=%lu", port->operSpeed);
522 #endif
524 port->reselect = True;
525 port->selected = False;
527 RSTP_CRITICAL_PATH_END;
528 return 0;
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;
543 #ifdef STP_DBG
544 if (port->p2p->debug) {
545 stp_trace ("STP_IN_changed_port_duplex(%s)", port->port_name);
547 #endif
548 port->p2p_recompute = True;
549 port->reselect = True;
550 port->selected = False;
552 RSTP_CRITICAL_PATH_END;
553 return 0;
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;
586 #if 0
587 if (bpdu->hdr.version != BPDU_VERSION_ID) {
588 return STP_Invalid_Version;
590 #endif
591 /* see also 9.3.4: think & TBD :( */
592 return 0;
595 #ifdef STP_DBG
596 int dbg_rstp_deny = 0;
597 #endif
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;
605 int iret;
607 #ifdef STP_DBG
608 if (1 == dbg_rstp_deny) {
609 return 0;
611 #endif
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 :( */
627 #ifdef STP_DBG
628 stp_trace ("RX bpdu vlan_id=%d port=%d port is absent in the stpm :(", (int) vlan_id, (int) port_index);
629 #endif
630 RSTP_CRITICAL_PATH_END;
631 return STP_Port_Is_Absent_In_The_Vlan;
634 #ifdef STP_DBG
635 if (port->skip_rx > 0) {
636 if (1 == port->skip_rx)
637 stp_trace ("port %s stop rx skipping",
638 port->port_name);
639 else
640 stp_trace ("port %s skip rx %d",
641 port->port_name, port->skip_rx);
642 port->skip_rx--;
643 RSTP_CRITICAL_PATH_END;
644 return STP_Nothing_To_Do;
646 #endif
648 if (port->operEdge && ! port->lnkWhile && port->portEnabled) {
649 #ifdef STP_DBG
650 if (port->topoch->debug) {
651 stp_trace ("port %s tc=TRUE by operEdge", port->port_name);
653 #endif
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);
663 #ifdef STP_DBG
664 if (port->edge->debug && port->operEdge) {
665 stp_trace ("port %s not operEdge !", port->port_name);
667 #endif
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;
676 return iret;
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);
690 dbg_cnt++;
694 RSTP_CRITICAL_PATH_END;
696 return dbg_cnt;
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;
706 UID_STP_CFG_T old;
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);
735 if (0 != rc) {
736 stp_trace ("_check_stpm_config failed %d", (int) rc);
737 RSTP_CRITICAL_PATH_END;
738 return rc;
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);
744 if (0 != rc) {
745 stp_trace ("can't disable rc=%d", (int) rc);
746 RSTP_CRITICAL_PATH_END;
747 return rc;
749 uid_cfg->field_mask &= ~BR_CFG_STATE;
750 if (! uid_cfg->field_mask) {
751 RSTP_CRITICAL_PATH_END;
752 return 0;
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);
762 if (! this) {
763 RSTP_CRITICAL_PATH_END;
764 return err_code;
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);
788 if (0 != rc) {
789 stp_trace ("%s", "cannot enable");
790 if (created_here) {
791 STP_stpm_delete (this);
793 RSTP_CRITICAL_PATH_END;
794 return rc;
796 enabled_here = True;
799 if (! enabled_here && STP_DISABLED != this->admin_state) {
800 STP_stpm_update_after_bridge_management (this);
802 RSTP_CRITICAL_PATH_END;
803 return 0;
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)
828 port->mcheck = True;
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;
847 #ifdef STP_DBG
848 if (port->edge->debug) {
849 stp_trace ("port %s is operEdge=%c in STP_IN_port_set_cfg",
850 port->port_name,
851 port->operEdge ? 'Y' : 'n');
853 #endif
856 if (PT_CFG_NON_STP & uid_cfg->field_mask) {
857 #ifdef STP_DBG
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",
860 port->port_name,
861 uid_cfg->admin_non_stp ? 'Y' : 'n');
863 #endif
864 port->admin_non_stp = uid_cfg->admin_non_stp;
867 #ifdef STP_DBG
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;
876 #endif
878 port->reselect = True;
879 port->selected = False;
881 (void) STP_stpm_update (this);
883 RSTP_CRITICAL_PATH_END;
885 return 0;
888 #ifdef STP_DBG
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;
896 int rc;
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;
914 return rc;
917 #endif
919 const char*
920 STP_IN_get_error_explanation (int rstp_err_no)
922 #define CHOOSE(a) #a
923 static char* rstp_error_names[] = RSTP_ERRORS;
924 #undef CHOOSE
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)
938 STPM_T *this;
939 PORT_T *port;
940 int rc = STP_OK;
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;
950 port = this->ports;
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;
959 if (!port)
960 rc = STP_stpm_start (this);
962 RSTP_CRITICAL_PATH_END;
964 return rc;
968 STP_IN_port_remove(int vlan_id, int port_index)
970 STPM_T *this;
971 PORT_T *port;
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);
989 if (!this->ports)
990 STP_stpm_stop (this);
991 RSTP_CRITICAL_PATH_END;
993 return STP_OK;
996 void
997 STP_IN_get_bridge_id(int vlan_id, unsigned short *priority, unsigned char *mac)
999 STPM_T *this;
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;
1008 const char *
1009 STP_IN_state2str(RSTP_PORT_STATE state)
1011 switch (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:
1021 return ("non-stp");
1022 case UID_PORT_BADSDU: /* synthetic state used by daemon */
1023 return ("bad-mtu");
1025 return ("unknown");