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