/************************************************************************ * RSTP library - Rapid Spanning Tree (802.1t, 802.1w) * Copyright (C) 2001-2003 Optical Access * Author: Alex Rozin * * This file is part of RSTP library. * * RSTP library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; version 2.1 * * RSTP library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with RSTP library; see the file COPYING. If not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. **********************************************************************/ /* This file contains API from an operation system to the RSTP library */ #include "base.h" #include "stpm.h" #include "stp_in.h" #include "stp_to.h" #define _stp_in_stpm_enable stp_in_stpm_enable STP_VECTORS_T *stp_vectors; void * stp_in_stpm_create (int vlan_id, char* name, int* err_code) { register STPM_T* this; /* stp_trace ("stp_in_stpm_create(%s)", name); */ this = stpapi_stpm_find (vlan_id); if (this) { /* it had just been created :( */ *err_code = STP_Nothing_To_Do; return this; } this = STP_stpm_create (vlan_id, name); if (! this) { /* can't create stpm :( */ *err_code = STP_Cannot_Create_Instance_For_Vlan; return NULL; } *err_code = STP_OK; return this; } int _stp_in_stpm_enable (int vlan_id, char* name, UID_STP_MODE_T admin_state) { register STPM_T* this; Bool created_here = False; int rc, err_code; /* stp_trace ("_stp_in_stpm_enable(%s)", name); */ this = stpapi_stpm_find (vlan_id); if (STP_DISABLED != admin_state) { if (! vlan_id) { /* STP_IN_stop_all (); */ register STPM_T* stpm; for (stpm = STP_stpm_get_the_list (); stpm; stpm = stpm->next) { if (STP_DISABLED != stpm->admin_state) { STP_OUT_set_hardware_mode (stpm->vlan_id, STP_DISABLED); (void) STP_stpm_enable (stpm, STP_DISABLED); } } } } if (! this) { /* it had not yet been created */ if (STP_ENABLED == admin_state) {/* try to create it */ stp_trace ("implicit create to vlan '%s'", name); this = stp_in_stpm_create (vlan_id, name, &err_code); if (! this) { stp_trace ("implicit create to vlan '%s' failed", name); return STP_Implicit_Instance_Create_Failed; } created_here = True; } else {/* try to disable nothing ? */ return 0; } } if (this->admin_state == admin_state) { /* nothing to do :) */ return 0; } rc = STP_stpm_enable (this, admin_state); if (! rc) { STP_OUT_set_hardware_mode (vlan_id, admin_state); } if (rc && created_here) { STP_stpm_delete (this); } return rc; } STPM_T * stpapi_stpm_find (int vlan_id) { register STPM_T* this; for (this = STP_stpm_get_the_list (); this; this = this->next) if (vlan_id == this->vlan_id) return this; return NULL; } static PORT_T * _stpapi_port_find (STPM_T* this, int port_index) { register PORT_T* port; for (port = this->ports; port; port = port->next) if (port_index == port->port_index) { return port; } return NULL; } static void _conv_br_id_2_uid (IN BRIDGE_ID* f, OUT UID_BRIDGE_ID_T* t) { (void) memcpy (t, f, sizeof (UID_BRIDGE_ID_T)); } static int _check_stpm_config (IN UID_STP_CFG_T* uid_cfg) { if (uid_cfg->bridge_priority < MIN_BR_PRIO) { stp_trace ("%d bridge_priority small", (int) uid_cfg->bridge_priority); return STP_Small_Bridge_Priority; } if (uid_cfg->bridge_priority > MAX_BR_PRIO) { stp_trace ("%d bridge_priority large", (int) uid_cfg->bridge_priority); return STP_Large_Bridge_Priority; } if (uid_cfg->hello_time < MIN_BR_HELLOT) { stp_trace ("%d hello_time small", (int) uid_cfg->hello_time); return STP_Small_Hello_Time; } if (uid_cfg->hello_time > MAX_BR_HELLOT) { stp_trace ("%d hello_time large", (int) uid_cfg->hello_time); return STP_Large_Hello_Time; } if (uid_cfg->max_age < MIN_BR_MAXAGE) { stp_trace ("%d max_age small", (int) uid_cfg->max_age); return STP_Small_Max_Age; } if (uid_cfg->max_age > MAX_BR_MAXAGE) { stp_trace ("%d max_age large", (int) uid_cfg->max_age); return STP_Large_Max_Age; } if (uid_cfg->forward_delay < MIN_BR_FWDELAY) { stp_trace ("%d forward_delay small", (int) uid_cfg->forward_delay); return STP_Small_Forward_Delay; } if (uid_cfg->forward_delay > MAX_BR_FWDELAY) { stp_trace ("%d forward_delay large", (int) uid_cfg->forward_delay); return STP_Large_Forward_Delay; } if (2 * (uid_cfg->forward_delay - 1) < uid_cfg->max_age) { return STP_Forward_Delay_And_Max_Age_Are_Inconsistent; } if (uid_cfg->max_age < 2 * (uid_cfg->hello_time + 1)) { return STP_Hello_Time_And_Max_Age_Are_Inconsistent; } return 0; } static void _stp_in_enable_port_on_stpm (STPM_T* stpm, int port_index, Bool enable) { register PORT_T* port; port = _stpapi_port_find (stpm, port_index); if (! port) return; if (port->portEnabled == enable) {/* nothing to do :) */ return; } port->uptime = 0; if (enable) { /* clear port statistics */ port->rx_cfg_bpdu_cnt = port->rx_rstp_bpdu_cnt = port->rx_tcn_bpdu_cnt = 0; } #ifdef STP_DBG if (port->edge->debug) { stp_trace ("Port %s became '%s' adminEdge=%c", port->port_name, enable ? "enable" : "disable", port->adminEdge ? 'Y' : 'N'); } #endif port->adminEnable = enable; STP_port_init (port, stpm, False); port->reselect = True; port->selected = False; } void STP_IN_init (STP_VECTORS_T *vectors) { RSTP_INIT_CRITICAL_PATH_PROTECTIO; stp_vectors = vectors; } int STP_IN_stpm_get_cfg (IN int vlan_id, OUT UID_STP_CFG_T* uid_cfg) { register STPM_T* this; uid_cfg->field_mask = 0; RSTP_CRITICAL_PATH_START; this = stpapi_stpm_find (vlan_id); if (!this) { /* it had not yet been created :( */ RSTP_CRITICAL_PATH_END; return STP_Vlan_Had_Not_Yet_Been_Created; } if (this->admin_state != STP_DISABLED) { uid_cfg->field_mask |= BR_CFG_STATE; } uid_cfg->stp_enabled = this->admin_state; if (this->ForceVersion != 2) { uid_cfg->field_mask |= BR_CFG_FORCE_VER; } uid_cfg->force_version = this->ForceVersion; if (this->BrId.prio != DEF_BR_PRIO) { uid_cfg->field_mask |= BR_CFG_PRIO; } uid_cfg->bridge_priority = this->BrId.prio; if (this->BrTimes.MaxAge != DEF_BR_MAXAGE) { uid_cfg->field_mask |= BR_CFG_AGE; } uid_cfg->max_age = this->BrTimes.MaxAge; if (this->BrTimes.HelloTime != DEF_BR_HELLOT) { uid_cfg->field_mask |= BR_CFG_HELLO; } uid_cfg->hello_time = this->BrTimes.HelloTime; if (this->BrTimes.ForwardDelay != DEF_BR_FWDELAY) { uid_cfg->field_mask |= BR_CFG_DELAY; } uid_cfg->forward_delay = this->BrTimes.ForwardDelay; uid_cfg->hold_time = TxHoldCount; RSTP_CRITICAL_PATH_END; return 0; } int STP_IN_port_get_cfg (int vlan_id, int port_index, UID_STP_PORT_CFG_T* uid_cfg) { register STPM_T* this; register PORT_T* port; RSTP_CRITICAL_PATH_START; this = stpapi_stpm_find (vlan_id); if (!this) { /* it had not yet been created :( */ RSTP_CRITICAL_PATH_END; return STP_Vlan_Had_Not_Yet_Been_Created; } port = _stpapi_port_find (this, port_index); if (! port) {/* port is absent in the stpm :( */ RSTP_CRITICAL_PATH_END; return STP_Port_Is_Absent_In_The_Vlan; } uid_cfg->field_mask = 0; uid_cfg->port_priority = port->port_id >> 8; if (uid_cfg->port_priority != DEF_PORT_PRIO) uid_cfg->field_mask |= PT_CFG_PRIO; uid_cfg->admin_port_path_cost = port->adminPCost; if (uid_cfg->admin_port_path_cost != ADMIN_PORT_PATH_COST_AUTO) uid_cfg->field_mask |= PT_CFG_COST; uid_cfg->admin_point2point = port->adminPointToPointMac; if (uid_cfg->admin_point2point != DEF_P2P) uid_cfg->field_mask |= PT_CFG_P2P; uid_cfg->admin_edge = port->adminEdge; if (uid_cfg->admin_edge != DEF_ADMIN_EDGE) uid_cfg->field_mask |= PT_CFG_EDGE; uid_cfg->admin_non_stp = port->admin_non_stp; if (uid_cfg->admin_non_stp != DEF_ADMIN_NON_STP) uid_cfg->field_mask |= PT_CFG_NON_STP; if (port->mcheck) uid_cfg->field_mask |= PT_CFG_MCHECK; RSTP_CRITICAL_PATH_END; return 0; } int STP_IN_port_get_state (IN int vlan_id, INOUT UID_STP_PORT_STATE_T* entry) { register STPM_T* this; register PORT_T* port; RSTP_CRITICAL_PATH_START; this = stpapi_stpm_find (vlan_id); if (!this) { /* it had not yet been created :( */ RSTP_CRITICAL_PATH_END; return STP_Vlan_Had_Not_Yet_Been_Created; } port = _stpapi_port_find (this, entry->port_no); if (! port) {/* port is absent in the stpm :( */ RSTP_CRITICAL_PATH_END; return STP_Port_Is_Absent_In_The_Vlan; } entry->port_id = port->port_id; if (DisabledPort == port->role) { entry->state = UID_PORT_DISABLED; } else if (! port->forward && ! port->learn) { entry->state = UID_PORT_DISCARDING; } else if (! port->forward && port->learn) { entry->state = UID_PORT_LEARNING; } else { entry->state = UID_PORT_FORWARDING; } entry->uptime = port->uptime; entry->path_cost = port->operPCost; _conv_br_id_2_uid (&port->portPrio.root_bridge, &entry->designated_root); entry->designated_cost = port->portPrio.root_path_cost; _conv_br_id_2_uid (&port->portPrio.design_bridge, &entry->designated_bridge); entry->designated_port = port->portPrio.design_port; switch (port->role) { case DisabledPort: entry->role = ' '; break; case AlternatePort: entry->role = 'A'; break; case BackupPort: entry->role = 'B'; break; case RootPort: entry->role = 'R'; break; case DesignatedPort: entry->role = 'D'; break; case NonStpPort: entry->role = '-'; break; default: entry->role = '?'; break; } if (DisabledPort == port->role || NonStpPort == port->role) { (void) memset (&entry->designated_root, 0, sizeof (UID_BRIDGE_ID_T)); (void) memset (&entry->designated_bridge, 0, sizeof (UID_BRIDGE_ID_T)); entry->designated_cost = 0; entry->designated_port = port->port_id; } if (DisabledPort == port->role) { entry->oper_point2point = (P2P_FORCE_FALSE == port->adminPointToPointMac) ? 0 : 1; entry->oper_edge = port->adminEdge; entry->oper_stp_neigb = 0; } else { entry->oper_point2point = port->operPointToPointMac ? 1 : 0; entry->oper_edge = port->operEdge ? 1 : 0; entry->oper_stp_neigb = port->sendRSTP ? 0 : 1; } entry->oper_port_path_cost = port->operPCost; entry->rx_cfg_bpdu_cnt = port->rx_cfg_bpdu_cnt; entry->rx_rstp_bpdu_cnt = port->rx_rstp_bpdu_cnt; entry->rx_tcn_bpdu_cnt = port->rx_tcn_bpdu_cnt; entry->fdWhile = port->fdWhile; /* 17.15.1 */ entry->helloWhen = port->helloWhen; /* 17.15.2 */ entry->mdelayWhile = port->mdelayWhile; /* 17.15.3 */ entry->rbWhile = port->rbWhile; /* 17.15.4 */ entry->rcvdInfoWhile = port->rcvdInfoWhile;/* 17.15.5 */ entry->rrWhile = port->rrWhile; /* 17.15.6 */ entry->tcWhile = port->tcWhile; /* 17.15.7 */ entry->txCount = port->txCount; /* 17.18.40 */ entry->lnkWhile = port->lnkWhile; entry->rcvdInfoWhile = port->rcvdInfoWhile; entry->top_change_ack = port->tcAck; entry->tc = port->tc; RSTP_CRITICAL_PATH_END; return 0; } int STP_IN_stpm_get_state (IN int vlan_id, OUT UID_STP_STATE_T* entry) { register STPM_T* this; RSTP_CRITICAL_PATH_START; this = stpapi_stpm_find (vlan_id); if (!this) { /* it had not yet been created :( */ RSTP_CRITICAL_PATH_END; return STP_Vlan_Had_Not_Yet_Been_Created; } (void) strncpy (entry->vlan_name, this->name, NAME_LEN); entry->vlan_id = this->vlan_id; _conv_br_id_2_uid (&this->rootPrio.root_bridge, &entry->designated_root); entry->root_path_cost = this->rootPrio.root_path_cost; entry->root_port = this->rootPortId; entry->max_age = this->rootTimes.MaxAge; entry->forward_delay = this->rootTimes.ForwardDelay; entry->hello_time = this->rootTimes.HelloTime; _conv_br_id_2_uid (&this->BrId, &entry->bridge_id); entry->stp_enabled = this->admin_state; entry->timeSince_Topo_Change = this->timeSince_Topo_Change; entry->Topo_Change_Count = this->Topo_Change_Count; entry->Topo_Change = this->Topo_Change; RSTP_CRITICAL_PATH_END; return 0; } int STP_IN_stpm_get_name_by_vlan_id (int vlan_id, char* name, size_t buffsize) { register STPM_T* stpm; int iret = -1; RSTP_CRITICAL_PATH_START; for (stpm = STP_stpm_get_the_list (); stpm; stpm = stpm->next) { if (vlan_id == stpm->vlan_id) { if (stpm->name) (void) strncpy (name, stpm->name, buffsize); else (void) memset (name, 0, buffsize); iret = 0; break; } } RSTP_CRITICAL_PATH_END; return iret; } int /* call it, when link Up/Down */ STP_IN_enable_port (int port_index, Bool enable) { register STPM_T* stpm; RSTP_CRITICAL_PATH_START; if (! enable) { #ifdef STP_DBG stp_trace("%s (p%02d, all, %s, '%s')", "clearFDB", (int) port_index, "this port", "disable port"); #endif STP_OUT_flush_lt (port_index, 0, LT_FLASH_ONLY_THE_PORT, "disable port"); } for (stpm = STP_stpm_get_the_list (); stpm; stpm = stpm->next) { if (STP_ENABLED != stpm->admin_state) continue; _stp_in_enable_port_on_stpm (stpm, port_index, enable); /* STP_stpm_update (stpm);*/ } RSTP_CRITICAL_PATH_END; return 0; } int /* call it, when port speed has been changed, speed in Kb/s */ STP_IN_changed_port_speed (int port_index, long speed) { register STPM_T* stpm; register PORT_T* port; RSTP_CRITICAL_PATH_START; for (stpm = STP_stpm_get_the_list (); stpm; stpm = stpm->next) { if (STP_ENABLED != stpm->admin_state) continue; port = _stpapi_port_find (stpm, port_index); if (! port) continue; port->operSpeed = speed; #ifdef STP_DBG if (port->pcost->debug) { stp_trace ("changed operSpeed=%lu", port->operSpeed); } #endif port->reselect = True; port->selected = False; } RSTP_CRITICAL_PATH_END; return 0; } int /* call it, when port duplex mode has been changed */ STP_IN_changed_port_duplex (int port_index) { register STPM_T* stpm; register PORT_T* port; RSTP_CRITICAL_PATH_START; for (stpm = STP_stpm_get_the_list (); stpm; stpm = stpm->next) { if (STP_ENABLED != stpm->admin_state) continue; port = _stpapi_port_find (stpm, port_index); if (! port) continue; #ifdef STP_DBG if (port->p2p->debug) { stp_trace ("STP_IN_changed_port_duplex(%s)", port->port_name); } #endif port->p2p_recompute = True; port->reselect = True; port->selected = False; } RSTP_CRITICAL_PATH_END; return 0; } int STP_IN_check_bpdu_header (BPDU_T* bpdu, size_t len) { unsigned short len8023; /* LINTED: alignment */ len8023 = ntohs (*(unsigned short*) bpdu->eth.len8023); if (len8023 > 1500) {/* big len8023 format :( */ return STP_Big_len8023_Format; } if (len8023 < MIN_BPDU) { /* small len8023 format :( */ return STP_Small_len8023_Format; } if (len8023 + 14 > len) { /* len8023 format gt len :( */ return STP_len8023_Format_Gt_Len; } if (bpdu->eth.dsap != BPDU_L_SAP || bpdu->eth.ssap != BPDU_L_SAP || bpdu->eth.llc != LLC_UI) { /* this is not a proper 802.3 pkt! :( */ return STP_Not_Proper_802_3_Packet; } if (bpdu->hdr.protocol[0] || bpdu->hdr.protocol[1]) { return STP_Invalid_Protocol; } #if 0 if (bpdu->hdr.version != BPDU_VERSION_ID) { return STP_Invalid_Version; } #endif /* see also 9.3.4: think & TBD :( */ return 0; } #ifdef STP_DBG int dbg_rstp_deny = 0; #endif int STP_IN_rx_bpdu (int vlan_id, int port_index, BPDU_T* bpdu, size_t len) { register PORT_T* port; register STPM_T* this; int iret; #ifdef STP_DBG if (1 == dbg_rstp_deny) { return 0; } #endif RSTP_CRITICAL_PATH_START; this = stpapi_stpm_find (vlan_id); if (! this) { /* the stpm had not yet been created :( */ RSTP_CRITICAL_PATH_END; return STP_Vlan_Had_Not_Yet_Been_Created; } if (STP_DISABLED == this->admin_state) {/* the stpm had not yet been enabled :( */ RSTP_CRITICAL_PATH_END; return STP_Had_Not_Yet_Been_Enabled_On_The_Vlan; } port = _stpapi_port_find (this, port_index); if (! port) {/* port is absent in the stpm :( */ #ifdef STP_DBG stp_trace ("RX bpdu vlan_id=%d port=%d port is absent in the stpm :(", (int) vlan_id, (int) port_index); #endif RSTP_CRITICAL_PATH_END; return STP_Port_Is_Absent_In_The_Vlan; } #ifdef STP_DBG if (port->skip_rx > 0) { if (1 == port->skip_rx) stp_trace ("port %s stop rx skipping", port->port_name); else stp_trace ("port %s skip rx %d", port->port_name, port->skip_rx); port->skip_rx--; RSTP_CRITICAL_PATH_END; return STP_Nothing_To_Do; } #endif if (port->operEdge && ! port->lnkWhile && port->portEnabled) { #ifdef STP_DBG if (port->topoch->debug) { stp_trace ("port %s tc=TRUE by operEdge", port->port_name); } #endif port->tc = True; /* IEEE 802.1y, 17.30 */ } /* port link change indication will come later :( */ if (! port->portEnabled && STP_OUT_get_port_link_status (port->port_index)) { _stp_in_enable_port_on_stpm (this, port->port_index, True); } #ifdef STP_DBG if (port->edge->debug && port->operEdge) { stp_trace ("port %s not operEdge !", port->port_name); } #endif port->operEdge = False; port->wasInitBpdu = True; iret = STP_port_rx_bpdu (port, bpdu, len); (void) STP_stpm_update (this); RSTP_CRITICAL_PATH_END; return iret; } int STP_IN_one_second (void) { register STPM_T* stpm; register int dbg_cnt = 0; RSTP_CRITICAL_PATH_START; for (stpm = STP_stpm_get_the_list (); stpm; stpm = stpm->next) { if (STP_ENABLED == stpm->admin_state) { /* stp_trace ("STP_IN_one_second vlan_id=%d", (int) stpm->vlan_id); */ STP_stpm_one_second (stpm); dbg_cnt++; } } RSTP_CRITICAL_PATH_END; return dbg_cnt; } int STP_IN_stpm_set_cfg (IN int vlan_id, IN UID_STP_CFG_T* uid_cfg) { int rc = 0, prev_prio, err_code; Bool created_here, enabled_here; register STPM_T* this; UID_STP_CFG_T old; /* stp_trace ("STP_IN_stpm_set_cfg"); */ if (0 != STP_IN_stpm_get_cfg (vlan_id, &old)) { STP_OUT_get_init_stpm_cfg (vlan_id, &old); } RSTP_CRITICAL_PATH_START; if (BR_CFG_PRIO & uid_cfg->field_mask) { old.bridge_priority = uid_cfg->bridge_priority; } if (BR_CFG_AGE & uid_cfg->field_mask) { old.max_age = uid_cfg->max_age; } if (BR_CFG_HELLO & uid_cfg->field_mask) { old.hello_time = uid_cfg->hello_time; } if (BR_CFG_DELAY & uid_cfg->field_mask) { old.forward_delay = uid_cfg->forward_delay; } if (BR_CFG_FORCE_VER & uid_cfg->field_mask) { old.force_version = uid_cfg->force_version; } rc = _check_stpm_config (&old); if (0 != rc) { stp_trace ("_check_stpm_config failed %d", (int) rc); RSTP_CRITICAL_PATH_END; return rc; } if ((BR_CFG_STATE & uid_cfg->field_mask) && (STP_DISABLED == uid_cfg->stp_enabled)) { rc = _stp_in_stpm_enable (vlan_id, uid_cfg->vlan_name, STP_DISABLED); if (0 != rc) { stp_trace ("can't disable rc=%d", (int) rc); RSTP_CRITICAL_PATH_END; return rc; } uid_cfg->field_mask &= ~BR_CFG_STATE; if (! uid_cfg->field_mask) { RSTP_CRITICAL_PATH_END; return 0; } } /* get current state */ this = stpapi_stpm_find (vlan_id); created_here = False; enabled_here = False; if (! this) { /* it had not yet been created */ this = stp_in_stpm_create (vlan_id, uid_cfg->vlan_name, &err_code); if (! this) { RSTP_CRITICAL_PATH_END; return err_code; } } prev_prio = this->BrId.prio; this->BrId.prio = old.bridge_priority; if (STP_ENABLED == this->admin_state) { if (0 != STP_stpm_check_bridge_priority (this)) { this->BrId.prio = prev_prio; stp_trace ("%s", "STP_stpm_check_bridge_priority failed"); RSTP_CRITICAL_PATH_END; return STP_Invalid_Bridge_Priority; } } this->BrTimes.MaxAge = old.max_age; this->BrTimes.HelloTime = old.hello_time; this->BrTimes.ForwardDelay = old.forward_delay; this->ForceVersion = (PROTOCOL_VERSION_T) old.force_version; if ((BR_CFG_STATE & uid_cfg->field_mask) && STP_DISABLED != uid_cfg->stp_enabled && STP_DISABLED == this->admin_state) { rc = _stp_in_stpm_enable (vlan_id, uid_cfg->vlan_name, uid_cfg->stp_enabled); if (0 != rc) { stp_trace ("%s", "cannot enable"); if (created_here) { STP_stpm_delete (this); } RSTP_CRITICAL_PATH_END; return rc; } enabled_here = True; } if (! enabled_here && STP_DISABLED != this->admin_state) { STP_stpm_update_after_bridge_management (this); } RSTP_CRITICAL_PATH_END; return 0; } int STP_IN_port_set_cfg (IN int vlan_id, IN int port_index, IN UID_STP_PORT_CFG_T* uid_cfg) { register STPM_T* this; register PORT_T* port; RSTP_CRITICAL_PATH_START; this = stpapi_stpm_find (vlan_id); if (! this) { /* it had not yet been created :( */ RSTP_CRITICAL_PATH_END; stp_trace ("RSTP instance with tag %d hasn't been created\n", vlan_id); return STP_Vlan_Had_Not_Yet_Been_Created; } port = _stpapi_port_find (this, port_index); if (! port) {/* port is absent in the stpm :( */ return STP_Port_Is_Absent_In_The_Vlan; } if (PT_CFG_MCHECK & uid_cfg->field_mask) { if (this->ForceVersion >= NORMAL_RSTP) port->mcheck = True; } if (PT_CFG_COST & uid_cfg->field_mask) { port->adminPCost = uid_cfg->admin_port_path_cost; } if (PT_CFG_PRIO & uid_cfg->field_mask) { port->port_id = (uid_cfg->port_priority << 8) + port_index; } if (PT_CFG_P2P & uid_cfg->field_mask) { port->adminPointToPointMac = uid_cfg->admin_point2point; port->p2p_recompute = True; } if (PT_CFG_EDGE & uid_cfg->field_mask) { port->adminEdge = uid_cfg->admin_edge; port->operEdge = port->adminEdge; #ifdef STP_DBG if (port->edge->debug) { stp_trace ("port %s is operEdge=%c in STP_IN_port_set_cfg", port->port_name, port->operEdge ? 'Y' : 'n'); } #endif } if (PT_CFG_NON_STP & uid_cfg->field_mask) { #ifdef STP_DBG if (port->roletrns->debug && port->admin_non_stp != uid_cfg->admin_non_stp) { stp_trace ("port %s is adminNonStp=%c in STP_IN_port_set_cfg", port->port_name, uid_cfg->admin_non_stp ? 'Y' : 'n'); } #endif port->admin_non_stp = uid_cfg->admin_non_stp; } #ifdef STP_DBG if (PT_CFG_DBG_SKIP_RX & uid_cfg->field_mask) { port->skip_rx = uid_cfg->skip_rx; } if (PT_CFG_DBG_SKIP_TX & uid_cfg->field_mask) { port->skip_tx = uid_cfg->skip_tx; } #endif port->reselect = True; port->selected = False; (void) STP_stpm_update (this); RSTP_CRITICAL_PATH_END; return 0; } #ifdef STP_DBG int STP_IN_dbg_set_port_trace (char* mach_name, int enadis, int vlan_id, int port_no) { register STPM_T* this; register PORT_T* port; int rc; RSTP_CRITICAL_PATH_START; this = stpapi_stpm_find (vlan_id); if (! this) { /* it had not yet been created :( */ RSTP_CRITICAL_PATH_END; stp_trace ("RSTP instance with tag %d hasn't been created\n", vlan_id); return STP_Vlan_Had_Not_Yet_Been_Created; } port = _stpapi_port_find (this, port_no); if (! port) {/* port is absent in the stpm :( */ return STP_Port_Is_Absent_In_The_Vlan; } rc = STP_port_trace_state_machine (port, mach_name, enadis); RSTP_CRITICAL_PATH_END; return rc; } #endif const char* STP_IN_get_error_explanation (int rstp_err_no) { #define CHOOSE(a) #a static char* rstp_error_names[] = RSTP_ERRORS; #undef CHOOSE if (rstp_err_no < STP_OK) { return "Too small error code :("; } if (rstp_err_no >= STP_LAST_DUMMY) { return "Too big error code :("; } return rstp_error_names[rstp_err_no]; } int STP_IN_port_add(int vlan_id, int port_index) { STPM_T *this; PORT_T *port; int rc = STP_OK; RSTP_CRITICAL_PATH_START; this = stpapi_stpm_find (vlan_id); if (!this) { /* it had not yet been created :( */ RSTP_CRITICAL_PATH_END; return STP_Vlan_Had_Not_Yet_Been_Created; } port = this->ports; if (! STP_port_create (this, port_index)) { /* can't add port :( */ stp_trace ("can't create port %d", port_index); RSTP_CRITICAL_PATH_END; return STP_Cannot_Create_Instance_For_Port; } if (!port) rc = STP_stpm_start (this); RSTP_CRITICAL_PATH_END; return rc; } int STP_IN_port_remove(int vlan_id, int port_index) { STPM_T *this; PORT_T *port; RSTP_CRITICAL_PATH_START; this = stpapi_stpm_find (vlan_id); if (!this) { /* it had not yet been created :( */ RSTP_CRITICAL_PATH_END; return STP_Vlan_Had_Not_Yet_Been_Created; } port = _stpapi_port_find (this, port_index); if (! port) {/* port is absent in the stpm :( */ RSTP_CRITICAL_PATH_END; return STP_Port_Is_Absent_In_The_Vlan; } STP_port_delete (port); if (!this->ports) STP_stpm_stop (this); RSTP_CRITICAL_PATH_END; return STP_OK; } void STP_IN_get_bridge_id(int vlan_id, unsigned short *priority, unsigned char *mac) { STPM_T *this; RSTP_CRITICAL_PATH_START; this = stpapi_stpm_find (vlan_id); *priority = this->BrId.prio; (void) memcpy(mac, this->BrId.addr, 6); RSTP_CRITICAL_PATH_END; } const char * STP_IN_state2str(RSTP_PORT_STATE state) { switch (state) { case UID_PORT_DISABLED: return ("disabled"); case UID_PORT_DISCARDING: return ("discarding"); case UID_PORT_LEARNING: return ("learning"); case UID_PORT_FORWARDING: return ("forwarding"); case UID_PORT_NON_STP: return ("non-stp"); case UID_PORT_BADSDU: /* synthetic state used by daemon */ return ("bad-mtu"); } return ("unknown"); }