stp_in.c
上传用户:allwinjm
上传日期:2021-08-29
资源大小:99k
文件大小:25k
源码类别:

Internet/IE编程

开发平台:

Unix_Linux

  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 
  11.  * 
  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. 
  16.  * 
  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.  **********************************************************************/
  22. /* This file contains API from an operation system to the RSTP library */
  23. #include "base.h"
  24. #include "stpm.h"
  25. #include "stp_in.h"
  26. #include "stp_to.h"
  27. int max_port = 1024;
  28. #define INCR100(nev) { nev++; if (nev > 99) nev = 0;}
  29. RSTP_EVENT_T tev = RSTP_EVENT_LAST_DUMMY;
  30. int  nev = 0;
  31. void *
  32. stp_in_stpm_create (int vlan_id, char* name, BITMAP_T* port_bmp, int* err_code)
  33. {
  34.   int port_index;
  35.   register STPM_T* this;
  36.   /* stp_trace ("stp_in_stpm_create(%s)", name); */
  37.   this = stpapi_stpm_find (vlan_id);
  38.   if (this) { /* it had just been created :( */
  39.     *err_code = STP_Nothing_To_Do;
  40.     return this;
  41.   }
  42.   this = STP_stpm_create (vlan_id, name);
  43.   if (! this) { /* can't create stpm :( */
  44.     *err_code = STP_Cannot_Create_Instance_For_Vlan;
  45.     return NULL;
  46.   }
  47.   for (port_index = 1; port_index <= max_port; port_index++) {
  48.     if (BitmapGetBit(port_bmp, (port_index - 1))) {
  49.       if (! STP_port_create (this, port_index)) {
  50.         /* can't add port :( */
  51.         stp_trace ("can't create port %d", (int) port_index);
  52.         STP_stpm_delete (this);
  53.         *err_code =STP_Cannot_Create_Instance_For_Port;
  54.         return NULL;
  55.       }
  56.     }
  57.   }
  58.   *err_code = STP_OK;
  59.   return this;
  60. }
  61. int
  62. _stp_in_stpm_enable (int vlan_id, char* name,
  63.                     BITMAP_T* port_bmp,
  64.                     UID_STP_MODE_T admin_state)
  65. {
  66.   register STPM_T* this;
  67.   Bool created_here = False;
  68.   int rc, err_code;
  69.   /* stp_trace ("_stp_in_stpm_enable(%s)", name); */
  70.   this = stpapi_stpm_find (vlan_id);
  71.   
  72.   if (STP_DISABLED != admin_state) {
  73.     if (! vlan_id) { /* STP_IN_stop_all (); */
  74.         register STPM_T* stpm;
  75.         for (stpm = STP_stpm_get_the_list (); stpm; stpm = stpm->next) {
  76.           if (STP_DISABLED != stpm->admin_state) {
  77.             STP_OUT_set_hardware_mode (stpm->vlan_id, STP_DISABLED);
  78.             STP_stpm_enable (stpm, STP_DISABLED);
  79.           }
  80.         }
  81.     }
  82.   }
  83.   if (! this) { /* it had not yet been created */
  84.     if (STP_ENABLED == admin_state) {/* try to create it */
  85.       stp_trace ("implicit create to vlan '%s'", name);
  86.       this = stp_in_stpm_create (vlan_id, name, port_bmp, &err_code);
  87.       if (! this) {
  88.         stp_trace ("implicit create to vlan '%s' failed", name);
  89.         return STP_Imlicite_Instance_Create_Failed;
  90.       }
  91.       created_here = True;
  92.     } else {/* try to disable nothing ? */
  93.       return 0;
  94.     }
  95.   }
  96.   if (this->admin_state == admin_state) { /* nothing to do :) */
  97.     return 0;
  98.   }
  99.   rc = STP_stpm_enable (this, admin_state);
  100.   if (! rc) {
  101.     STP_OUT_set_hardware_mode (vlan_id, admin_state);
  102.   }
  103.   if (rc && created_here) {
  104.     STP_stpm_delete (this);
  105.   }
  106.     
  107.   return rc;
  108. }
  109. STPM_T *
  110. stpapi_stpm_find (int vlan_id)
  111. {
  112.   register STPM_T* this;
  113.   for (this = STP_stpm_get_the_list (); this; this = this->next)
  114.     if (vlan_id == this->vlan_id)
  115.       return this;
  116.   return NULL;
  117. }
  118. static PORT_T *
  119. _stpapi_port_find (STPM_T* this, int port_index)
  120. {
  121.   register PORT_T* port;
  122.   for (port = this->ports; port; port = port->next)
  123.     if (port_index == port->port_index) {
  124.       return port;
  125.     }
  126.   return NULL;
  127. }
  128. static void
  129. _conv_br_id_2_uid (IN BRIDGE_ID* f, OUT UID_BRIDGE_ID_T* t)
  130. {
  131.   memcpy (t, f, sizeof (UID_BRIDGE_ID_T));
  132. }
  133. static int
  134. _check_stpm_config (IN UID_STP_CFG_T* uid_cfg)
  135. {
  136.   if (uid_cfg->bridge_priority < MIN_BR_PRIO) {
  137.     stp_trace ("%d bridge_priority small", (int) uid_cfg->bridge_priority);
  138.     return STP_Small_Bridge_Priority;
  139.   }
  140.   if (uid_cfg->bridge_priority > MAX_BR_PRIO) {
  141.     stp_trace ("%d bridge_priority large", (int) uid_cfg->bridge_priority);
  142.     return STP_Large_Bridge_Priority;
  143.   }
  144.   if (uid_cfg->hello_time < MIN_BR_HELLOT) {
  145.     stp_trace ("%d hello_time small", (int) uid_cfg->hello_time);
  146.     return STP_Small_Hello_Time;
  147.   }
  148.   if (uid_cfg->hello_time > MAX_BR_HELLOT) {
  149.     stp_trace ("%d hello_time large", (int) uid_cfg->hello_time);
  150.     return STP_Large_Hello_Time;
  151.   }
  152.   if (uid_cfg->max_age < MIN_BR_MAXAGE) {
  153.     stp_trace ("%d max_age small", (int) uid_cfg->max_age);
  154.     return STP_Small_Max_Age;
  155.   }
  156.   if (uid_cfg->max_age > MAX_BR_MAXAGE) {
  157.     stp_trace ("%d max_age large", (int) uid_cfg->max_age);
  158.     return STP_Large_Max_Age;
  159.   }
  160.   if (uid_cfg->forward_delay < MIN_BR_FWDELAY) {
  161.     stp_trace ("%d forward_delay small", (int) uid_cfg->forward_delay);
  162.     return STP_Small_Forward_Delay;
  163.   }
  164.   if (uid_cfg->forward_delay > MAX_BR_FWDELAY) {
  165.     stp_trace ("%d forward_delay large", (int) uid_cfg->forward_delay);
  166.     return STP_Large_Forward_Delay;
  167.   }
  168.   if (2 * (uid_cfg->forward_delay - 1) < uid_cfg->max_age) {
  169.     return STP_Forward_Delay_And_Max_Age_Are_Inconsistent;
  170.   }
  171.   if (uid_cfg->max_age < 2 * (uid_cfg->hello_time + 1)) {
  172.     return STP_Hello_Time_And_Max_Age_Are_Inconsistent;
  173.   }
  174.   return 0;
  175. }
  176. static void
  177. _stp_in_enable_port_on_stpm (STPM_T* stpm, int port_index, Bool enable)
  178. {
  179.   register PORT_T* port;
  180.   port = _stpapi_port_find (stpm, port_index);
  181.   if (! port) return; 
  182.   if (port->portEnabled == enable) {/* nothing to do :) */
  183.     return;
  184.   }
  185.   port->uptime = 0;
  186.   if (enable) { /* clear port statistics */ 
  187.     port->rx_cfg_bpdu_cnt =
  188.     port->rx_rstp_bpdu_cnt =
  189.     port->rx_tcn_bpdu_cnt = 0;
  190.   }  
  191. #ifdef STP_DBG
  192.   if (port->edge->debug) {
  193.     stp_trace ("Port %s became '%s' adminEdge=%c",
  194.         port->port_name, enable ? "enable" : "disable",
  195.         port->adminEdge ? 'Y' : 'N');
  196.   }
  197. #endif
  198.   port->adminEnable = enable;
  199.   STP_port_init (port, stpm, False);
  200.   port->reselect = True;
  201.   port->selected = False;  
  202. }
  203. void 
  204. STP_IN_init (int max_port_index)
  205. {
  206.   max_port = max_port_index;
  207.   RSTP_INIT_CRITICAL_PATH_PROTECTIO;
  208. }
  209. int
  210. STP_IN_stpm_get_cfg (IN int vlan_id, OUT UID_STP_CFG_T* uid_cfg)
  211. {
  212.   register STPM_T* this;
  213.   uid_cfg->field_mask = 0;
  214.   
  215.   RSTP_CRITICAL_PATH_START;  
  216.   this = stpapi_stpm_find (vlan_id);
  217.   if (!this) { /* it had not yet been created :( */
  218.     RSTP_CRITICAL_PATH_END;
  219.     return STP_Vlan_Had_Not_Yet_Been_Created;
  220.   }
  221.   if (this->admin_state != STP_DISABLED) {
  222.     uid_cfg->field_mask |= BR_CFG_STATE;
  223.   }
  224.   uid_cfg->stp_enabled = this->admin_state;
  225.   if (this->ForceVersion != 2) {
  226.     uid_cfg->field_mask |= BR_CFG_FORCE_VER;
  227.   }
  228.   uid_cfg->force_version = this->ForceVersion;
  229.   if (this->BrId.prio != DEF_BR_PRIO) {
  230.     uid_cfg->field_mask |= BR_CFG_PRIO;
  231.   }
  232.   uid_cfg->bridge_priority = this->BrId.prio;
  233.   if (this->BrTimes.MaxAge != DEF_BR_MAXAGE) {
  234.     uid_cfg->field_mask |= BR_CFG_AGE;
  235.   }
  236.   uid_cfg->max_age = this->BrTimes.MaxAge;
  237.   if (this->BrTimes.HelloTime != DEF_BR_HELLOT) {
  238.     uid_cfg->field_mask |= BR_CFG_HELLO;
  239.   }
  240.   uid_cfg->hello_time = this->BrTimes.HelloTime;
  241.   if (this->BrTimes.ForwardDelay != DEF_BR_FWDELAY) {
  242.     uid_cfg->field_mask |= BR_CFG_DELAY;
  243.   }
  244.   uid_cfg->forward_delay = this->BrTimes.ForwardDelay;
  245.   
  246.   uid_cfg->hold_time = TxHoldCount;
  247.   RSTP_CRITICAL_PATH_END;
  248.   return 0;
  249. }
  250.     
  251. int
  252. STP_IN_port_get_cfg (int vlan_id, int port_index, UID_STP_PORT_CFG_T* uid_cfg)
  253. {
  254.   register STPM_T* this;
  255.   register PORT_T* port;
  256.   
  257.   RSTP_CRITICAL_PATH_START;
  258.   this = stpapi_stpm_find (vlan_id);
  259.     
  260.   if (!this) { /* it had not yet been created :( */
  261.     RSTP_CRITICAL_PATH_END;
  262.     return STP_Vlan_Had_Not_Yet_Been_Created;
  263.   }
  264.   port = _stpapi_port_find (this, port_index);
  265.   if (! port) {/* port is absent in the stpm :( */
  266.     RSTP_CRITICAL_PATH_END;
  267.     return STP_Port_Is_Absent_In_The_Vlan;
  268.   }
  269.   uid_cfg->field_mask = 0;
  270.   uid_cfg->port_priority = port->port_id >> 8;
  271.   if (uid_cfg->port_priority != DEF_PORT_PRIO)
  272.     uid_cfg->field_mask |= PT_CFG_PRIO;
  273.   uid_cfg->admin_port_path_cost = port->adminPCost;
  274.   if (uid_cfg->admin_port_path_cost != ADMIN_PORT_PATH_COST_AUTO)
  275.     uid_cfg->field_mask |= PT_CFG_COST;
  276.   uid_cfg->admin_point2point = port->adminPointToPointMac;
  277.   if (uid_cfg->admin_point2point != DEF_P2P)
  278.     uid_cfg->field_mask |= PT_CFG_P2P;
  279.   uid_cfg->admin_edge = port->adminEdge;
  280.   if (uid_cfg->admin_edge != DEF_ADMIN_EDGE)
  281.     uid_cfg->field_mask |= PT_CFG_EDGE;
  282.     
  283.   RSTP_CRITICAL_PATH_END;
  284.   return 0;
  285. }
  286. int
  287. STP_IN_port_get_state (IN int vlan_id, INOUT UID_STP_PORT_STATE_T* entry)
  288. {
  289.   register STPM_T* this;
  290.   register PORT_T* port;
  291.   RSTP_CRITICAL_PATH_START;
  292.   this = stpapi_stpm_find (vlan_id);
  293.   if (!this) { /* it had not yet been created :( */
  294.     RSTP_CRITICAL_PATH_END;
  295.     return STP_Vlan_Had_Not_Yet_Been_Created;
  296.   }
  297.   port = _stpapi_port_find (this, entry->port_no);
  298.   if (! port) {/* port is absent in the stpm :( */
  299.     RSTP_CRITICAL_PATH_END;
  300.     return STP_Port_Is_Absent_In_The_Vlan;
  301.   }
  302.   entry->port_id = port->port_id;
  303.   if (DisabledPort == port->role) {
  304.     entry->state = UID_PORT_DISABLED;
  305.   } else if (! port->forward && ! port->learn) {
  306.     entry->state = UID_PORT_DISCARDING;
  307.   } else if (! port->forward && port->learn) {
  308.     entry->state = UID_PORT_LEARNING;
  309.   } else {
  310.     entry->state = UID_PORT_FORWARDING;
  311.   }
  312.   entry->uptime = port->uptime;
  313.   entry->path_cost = port->operPCost;
  314.   _conv_br_id_2_uid (&port->portPrio.root_bridge, &entry->designated_root);
  315.   entry->designated_cost = port->portPrio.root_path_cost;
  316.   _conv_br_id_2_uid (&port->portPrio.design_bridge, &entry->designated_bridge);
  317.   entry->designated_port = port->portPrio.design_port;
  318.   switch (port->role) {
  319.     case DisabledPort:   entry->role = ' '; break;
  320.     case AlternatePort:  entry->role = 'A'; break;
  321.     case BackupPort:     entry->role = 'B'; break;
  322.     case RootPort:       entry->role = 'R'; break;
  323.     case DesignatedPort: entry->role = 'D'; break;
  324.     case NonStpPort:     entry->role = '-'; break;
  325.     default:             entry->role = '?'; break;
  326.   }
  327.   if (DisabledPort == port->role || NonStpPort == port->role) {
  328.     memset (&entry->designated_root, 0, sizeof (UID_BRIDGE_ID_T));
  329.     memset (&entry->designated_bridge, 0, sizeof (UID_BRIDGE_ID_T));
  330.     entry->designated_cost = 0;
  331.     entry->designated_port = port->port_id;
  332.   }
  333.   if (DisabledPort == port->role) {
  334.     entry->oper_point2point = (P2P_FORCE_FALSE == port->adminPointToPointMac) ? 0 : 1;
  335.     entry->oper_edge = port->adminEdge;
  336.     entry->oper_stp_neigb = 0;
  337.   } else {
  338.     entry->oper_point2point = port->operPointToPointMac ? 1 : 0;
  339.     entry->oper_edge = port->operEdge                   ? 1 : 0;
  340.     entry->oper_stp_neigb = port->sendRSTP              ? 0 : 1;
  341.   }
  342.   entry->oper_port_path_cost = port->operPCost;
  343.   entry->rx_cfg_bpdu_cnt = port->rx_cfg_bpdu_cnt;
  344.   entry->rx_rstp_bpdu_cnt = port->rx_rstp_bpdu_cnt;
  345.   entry->rx_tcn_bpdu_cnt = port->rx_tcn_bpdu_cnt;
  346.   entry->fdWhile =       port->fdWhile;      /* 17.15.1 */
  347.   entry->helloWhen =     port->helloWhen;    /* 17.15.2 */
  348.   entry->mdelayWhile =   port->mdelayWhile;  /* 17.15.3 */
  349.   entry->rbWhile =       port->rbWhile;      /* 17.15.4 */
  350.   entry->rcvdInfoWhile = port->rcvdInfoWhile;/* 17.15.5 */
  351.   entry->rrWhile =       port->rrWhile;      /* 17.15.6 */
  352.   entry->tcWhile =       port->tcWhile;      /* 17.15.7 */
  353.   entry->txCount =       port->txCount;      /* 17.18.40 */
  354.   entry->lnkWhile =      port->lnkWhile;
  355.   entry->rcvdInfoWhile = port->rcvdInfoWhile;
  356.   entry->top_change_ack = port->tcAck;
  357.   entry->tc = port->tc;
  358.   
  359.   RSTP_CRITICAL_PATH_END;
  360.   return 0; 
  361. }
  362. int
  363. STP_IN_stpm_get_state (IN int vlan_id, OUT UID_STP_STATE_T* entry)
  364. {
  365.   register STPM_T* this;
  366.   RSTP_CRITICAL_PATH_START;
  367.   this = stpapi_stpm_find (vlan_id);
  368.   if (!this) { /* it had not yet been created :( */
  369.     RSTP_CRITICAL_PATH_END;
  370.     return STP_Vlan_Had_Not_Yet_Been_Created;
  371.   }
  372.   strncpy (entry->vlan_name, this->name, NAME_LEN);
  373.   entry->vlan_id = this->vlan_id;
  374.   _conv_br_id_2_uid (&this->rootPrio.root_bridge, &entry->designated_root);
  375.   entry->root_path_cost = this->rootPrio.root_path_cost;
  376.   entry->root_port = this->rootPortId;
  377.   entry->max_age =       this->rootTimes.MaxAge;
  378.   entry->forward_delay = this->rootTimes.ForwardDelay;
  379.   entry->hello_time =    this->rootTimes.HelloTime;
  380.   _conv_br_id_2_uid (&this->BrId, &entry->bridge_id);
  381.   entry->stp_enabled = this->admin_state;
  382.   entry->timeSince_Topo_Change = this->timeSince_Topo_Change;
  383.   entry->Topo_Change_Count = this->Topo_Change_Count;
  384.   entry->Topo_Change = this->Topo_Change;
  385.   
  386.   RSTP_CRITICAL_PATH_END;
  387.   return 0;
  388. }
  389. int
  390. STP_IN_stpm_get_name_by_vlan_id (int vlan_id, char* name, size_t buffsize)
  391. {
  392.   register STPM_T* stpm;
  393.   int iret = -1;
  394.   RSTP_CRITICAL_PATH_START;
  395.   for (stpm = STP_stpm_get_the_list (); stpm; stpm = stpm->next) {
  396.     if (vlan_id ==  stpm->vlan_id) {
  397.       if (stpm->name)
  398.         strncpy (name, stpm->name, buffsize);
  399.       else
  400.         memset (name, 0, buffsize);
  401.       iret = 0;
  402.       break;
  403.     }
  404.   }
  405.   RSTP_CRITICAL_PATH_END;
  406.   return iret;
  407. }
  408. int /* call it, when link Up/Down */
  409. STP_IN_enable_port (int port_index, Bool enable)
  410. {
  411.   register STPM_T* stpm;
  412.   RSTP_CRITICAL_PATH_START;
  413.   tev = enable ? RSTP_PORT_EN_T : RSTP_PORT_DIS_T; INCR100(nev);
  414.   if (! enable) {
  415. #ifdef STP_DBG
  416.     stp_trace("%s (p%02d, all, %s, '%s')",
  417.         "clearFDB", (int) port_index, "this port", "disable port");
  418. #endif
  419.     STP_OUT_flush_lt (port_index, 0, LT_FLASH_ONLY_THE_PORT, "disable port");
  420.   }
  421.   for (stpm = STP_stpm_get_the_list (); stpm; stpm = stpm->next) {
  422.     if (STP_ENABLED != stpm->admin_state) continue;
  423.     
  424.     _stp_in_enable_port_on_stpm (stpm, port_index, enable);
  425.    /* STP_stpm_update (stpm);*/
  426.   }
  427.   RSTP_CRITICAL_PATH_END;
  428.   return 0;
  429. }
  430. int /* call it, when port speed has been changed, speed in Kb/s  */
  431. STP_IN_changed_port_speed (int port_index, long speed)
  432. {
  433.   register STPM_T* stpm;
  434.   register PORT_T* port;
  435.   RSTP_CRITICAL_PATH_START;
  436.   tev = RSTP_PORT_SPEED_T; INCR100(nev);
  437.   for (stpm = STP_stpm_get_the_list (); stpm; stpm = stpm->next) {
  438.     if (STP_ENABLED != stpm->admin_state) continue;
  439.     
  440.     port = _stpapi_port_find (stpm, port_index);
  441.     if (! port) continue; 
  442.     port->operSpeed = speed;
  443. #ifdef STP_DBG
  444.     if (port->pcost->debug) {
  445.       stp_trace ("changed operSpeed=%lu", port->operSpeed);
  446.     }
  447. #endif
  448.     port->reselect = True;
  449.     port->selected = False;
  450.   }
  451.   RSTP_CRITICAL_PATH_END;
  452.   return 0;
  453. }
  454. int /* call it, when port duplex mode has been changed  */
  455. STP_IN_changed_port_duplex (int port_index)
  456. {
  457.   register STPM_T* stpm;
  458.   register PORT_T* port;
  459.   RSTP_CRITICAL_PATH_START;
  460.   tev = RSTP_PORT_DPLEX_T; INCR100(nev);
  461.   for (stpm = STP_stpm_get_the_list (); stpm; stpm = stpm->next) {
  462.     if (STP_ENABLED != stpm->admin_state) continue;
  463.     
  464.     port = _stpapi_port_find (stpm, port_index);
  465.     if (! port) continue; 
  466. #ifdef STP_DBG
  467.     if (port->p2p->debug) {
  468.       stp_trace ("STP_IN_changed_port_duplex(%s)", port->port_name);
  469.     }
  470. #endif
  471.     port->p2p_recompute = True;
  472.     port->reselect = True;
  473.     port->selected = False;
  474.   }
  475.   RSTP_CRITICAL_PATH_END;
  476.   return 0;
  477. }
  478. int
  479. STP_IN_check_bpdu_header (BPDU_T* bpdu, size_t len)
  480. {
  481.   unsigned short len8023;
  482.   len8023 = ntohs (*(unsigned short*) bpdu->eth.len8023);
  483.   if (len8023 > 1500) {/* big len8023 format :( */
  484.     return STP_Big_len8023_Format;
  485.   }
  486.   if (len8023 < MIN_BPDU) { /* small len8023 format :( */
  487.     return STP_Small_len8023_Format;
  488.   }
  489.   if (len8023 + 14 > len) { /* len8023 format gt len :( */
  490.     return STP_len8023_Format_Gt_Len;
  491.   }
  492.   if (bpdu->eth.dsap != BPDU_L_SAP                 ||
  493.       bpdu->eth.ssap != BPDU_L_SAP                 ||
  494.       bpdu->eth.llc != LLC_UI) {
  495.     /* this is not a proper 802.3 pkt! :( */
  496.     return STP_Not_Proper_802_3_Packet;
  497.   }
  498.   if (bpdu->hdr.protocol[0] || bpdu->hdr.protocol[1]) {
  499.     return STP_Invalid_Protocol;
  500.   }
  501. #if 0
  502.   if (bpdu->hdr.version != BPDU_VERSION_ID) {
  503.     return STP_Invalid_Version;  
  504.   }
  505. #endif
  506.   /* see also 9.3.4: think & TBD :( */
  507.   return 0;
  508. }
  509. #ifdef STP_DBG
  510. int dbg_rstp_deny = 0;
  511. #endif
  512. int
  513. STP_IN_rx_bpdu (int vlan_id, int port_index, BPDU_T* bpdu, size_t len)
  514. {
  515.   register PORT_T* port;
  516.   register STPM_T* this;
  517.   int              iret;
  518. #ifdef STP_DBG
  519.   if (1 == dbg_rstp_deny) {
  520.     return 0;
  521.   }
  522. #endif
  523.   RSTP_CRITICAL_PATH_START;
  524.   tev = RSTP_PORT_RX_T; INCR100(nev);
  525.   this = stpapi_stpm_find (vlan_id);
  526.   if (! this) { /*  the stpm had not yet been created :( */
  527.     RSTP_CRITICAL_PATH_END;
  528.     return STP_Vlan_Had_Not_Yet_Been_Created;
  529.   }
  530.   if (STP_DISABLED == this->admin_state) {/* the stpm had not yet been enabled :( */
  531.     RSTP_CRITICAL_PATH_END;
  532.     return STP_Had_Not_Yet_Been_Enabled_On_The_Vlan;
  533.   }
  534.   port = _stpapi_port_find (this, port_index);
  535.   if (! port) {/* port is absent in the stpm :( */
  536.     stp_trace ("RX bpdu vlan_id=%d port=%d port is absent in the stpm :(", (int) vlan_id, (int) port_index);
  537.     RSTP_CRITICAL_PATH_END;
  538.     return STP_Port_Is_Absent_In_The_Vlan;
  539.   }
  540. #ifdef STP_DBG
  541.   if (port->skip_rx > 0) {
  542.     if (1 == port->skip_rx)
  543.       stp_trace ("port %s stop rx skipping",
  544.                  port->port_name);
  545.     else
  546.       stp_trace ("port %s skip rx %d",
  547.                  port->port_name, port->skip_rx);
  548.     port->skip_rx--;
  549.     RSTP_CRITICAL_PATH_END;
  550.     return STP_Nothing_To_Do;
  551.   }
  552. #endif
  553.   if (port->operEdge && ! port->lnkWhile && port->portEnabled) {
  554. #ifdef STP_DBG
  555.   if (port->topoch->debug) {
  556.      stp_trace ("port %s tc=TRUE by operEdge", port->port_name);
  557.   }
  558. #endif
  559.     port->tc = True; /* IEEE 802.1y, 17.30 */
  560.   }
  561.   if (! port->portEnabled) {/* port link change indication will come later :( */
  562.     _stp_in_enable_port_on_stpm (this, port->port_index, True);
  563.   }
  564.   
  565. #ifdef STP_DBG
  566.   if (port->edge->debug && port->operEdge) {
  567.     stp_trace ("port %s not operEdge !", port->port_name);
  568.   }
  569. #endif
  570.   port->operEdge = False;
  571.   port->wasInitBpdu = True;
  572.   
  573.   iret = STP_port_rx_bpdu (port, bpdu, len);
  574.   STP_stpm_update (this);
  575.   RSTP_CRITICAL_PATH_END;
  576.   return iret;
  577. }
  578. int
  579. STP_IN_one_second (void)
  580. {
  581.   register STPM_T* stpm;
  582.   register int     dbg_cnt = 0;
  583.   RSTP_CRITICAL_PATH_START;
  584.   tev = RSTP_PORT_TIME_T; INCR100(nev);
  585.   for (stpm = STP_stpm_get_the_list (); stpm; stpm = stpm->next) {
  586.     if (STP_ENABLED == stpm->admin_state) {
  587.       /* stp_trace ("STP_IN_one_second vlan_id=%d", (int) stpm->vlan_id); */
  588.       STP_stpm_one_second (stpm);
  589.       dbg_cnt++;
  590.     }
  591.   }
  592.   
  593.   RSTP_CRITICAL_PATH_END;
  594.   return dbg_cnt;
  595. }
  596. int
  597. STP_IN_stpm_set_cfg (IN int vlan_id,
  598.                      IN BITMAP_T* port_bmp,
  599.                      IN UID_STP_CFG_T* uid_cfg)
  600. {
  601.   int rc = 0, prev_prio, err_code;
  602.   Bool created_here, enabled_here;
  603.   register STPM_T* this;
  604.   UID_STP_CFG_T old;
  605.            
  606.   /* stp_trace ("STP_IN_stpm_set_cfg"); */
  607.   if (0 != STP_IN_stpm_get_cfg (vlan_id, &old)) {
  608.     STP_OUT_get_init_stpm_cfg (vlan_id, &old);
  609.   }
  610.   
  611.   RSTP_CRITICAL_PATH_START;
  612.   tev = RSTP_PORT_MNGR_T; INCR100(nev);
  613.   if (BR_CFG_PRIO & uid_cfg->field_mask) {
  614.     old.bridge_priority = uid_cfg->bridge_priority;
  615.   }
  616.   if (BR_CFG_AGE & uid_cfg->field_mask) {
  617.     old.max_age = uid_cfg->max_age;
  618.   }
  619.   if (BR_CFG_HELLO & uid_cfg->field_mask) {
  620.     old.hello_time = uid_cfg->hello_time;
  621.   }
  622.   if (BR_CFG_DELAY & uid_cfg->field_mask) {
  623.     old.forward_delay = uid_cfg->forward_delay;
  624.   }
  625.   if (BR_CFG_FORCE_VER & uid_cfg->field_mask) {
  626.     old.force_version = uid_cfg->force_version;
  627.   }
  628.   rc = _check_stpm_config (&old);
  629.   if (0 != rc) {
  630.     stp_trace ("_check_stpm_config failed %d", (int) rc);
  631.     RSTP_CRITICAL_PATH_END;
  632.     return rc;
  633.   }
  634.   if ((BR_CFG_STATE & uid_cfg->field_mask) &&
  635.       (STP_DISABLED == uid_cfg->stp_enabled)) {
  636.     rc = _stp_in_stpm_enable (vlan_id, uid_cfg->vlan_name, port_bmp, STP_DISABLED);
  637.     if (0 != rc) {
  638.       stp_trace ("can't disable rc=%d", (int) rc);
  639.       RSTP_CRITICAL_PATH_END;
  640.       return rc;
  641.     }
  642.     uid_cfg->field_mask &= ! BR_CFG_STATE;
  643.     if (! uid_cfg->field_mask)  {
  644.       RSTP_CRITICAL_PATH_END;
  645.       return 0;
  646.     }
  647.   }
  648.   /* get current state */
  649.   this = stpapi_stpm_find (vlan_id);
  650.   created_here = False;
  651.   enabled_here = False;
  652.   if (! this) { /* it had not yet been created */
  653.     this = stp_in_stpm_create (vlan_id, uid_cfg->vlan_name, port_bmp, &err_code);/*STP_IN_stpm_set_cfg*/
  654.     if (! this) {
  655.       RSTP_CRITICAL_PATH_END;
  656.       return err_code;
  657.     }
  658.   }
  659.   prev_prio = this->BrId.prio;
  660.   this->BrId.prio = old.bridge_priority;
  661.   if (STP_ENABLED == this->admin_state) {
  662.     if (0 != STP_stpm_check_bridge_priority (this)) {
  663.       this->BrId.prio = prev_prio;
  664.       stp_trace ("%s", "STP_stpm_check_bridge_priority failed");
  665.       RSTP_CRITICAL_PATH_END;
  666.       return STP_Invalid_Bridge_Priority;
  667.     }
  668.   }
  669.   this->BrTimes.MaxAge = old.max_age;
  670.   this->BrTimes.HelloTime = old.hello_time;
  671.   this->BrTimes.ForwardDelay = old.forward_delay;
  672.   this->ForceVersion = (PROTOCOL_VERSION_T) old.force_version;
  673.   if ((BR_CFG_STATE & uid_cfg->field_mask) &&
  674.       STP_DISABLED != uid_cfg->stp_enabled &&
  675.       STP_DISABLED == this->admin_state) {
  676.     rc = _stp_in_stpm_enable (vlan_id, uid_cfg->vlan_name, port_bmp, uid_cfg->stp_enabled);
  677.     if (0 != rc) {
  678.       stp_trace ("%s", "cannot enable");
  679.       if (created_here) {
  680.         STP_stpm_delete (this);
  681.       }
  682.       RSTP_CRITICAL_PATH_END;
  683.       return rc;
  684.     }
  685.     enabled_here = True;
  686.   }
  687.   if (! enabled_here && STP_DISABLED != this->admin_state) {
  688.     STP_stpm_update_after_bridge_management (this);
  689.   }
  690.   RSTP_CRITICAL_PATH_END;
  691.   return 0;
  692. }
  693. int
  694. STP_IN_set_port_cfg (IN int vlan_id, IN UID_STP_PORT_CFG_T* uid_cfg)
  695. {
  696.   register STPM_T* this;
  697.   register PORT_T* port;
  698.   register int     port_no;
  699.   RSTP_CRITICAL_PATH_START;
  700.   tev = RSTP_PORT_MNGR_T; INCR100(nev);
  701.   this = stpapi_stpm_find (vlan_id);
  702.   if (! this) { /* it had not yet been created :( */
  703.     RSTP_CRITICAL_PATH_END;
  704.     Print ("RSTP instance with tag %d hasn't been createdn", (int) vlan_id);
  705.     return STP_Vlan_Had_Not_Yet_Been_Created;
  706.   }
  707.   for (port_no = 1; port_no <= max_port; port_no++) {
  708.     if (! BitmapGetBit(&uid_cfg->port_bmp, port_no - 1)) continue;
  709.   
  710.     port = _stpapi_port_find (this, port_no);
  711.     if (! port) {/* port is absent in the stpm :( */
  712.       continue;
  713.     }
  714.     if (PT_CFG_MCHECK & uid_cfg->field_mask) {
  715.       if (this->ForceVersion >= NORMAL_RSTP)
  716.         port->mcheck = True;
  717.     }
  718.     if (PT_CFG_COST & uid_cfg->field_mask) {
  719.       port->adminPCost = uid_cfg->admin_port_path_cost;
  720.     }
  721.   
  722.     if (PT_CFG_PRIO & uid_cfg->field_mask) {
  723.       port->port_id = (uid_cfg->port_priority << 8) + port_no;
  724.     }
  725.   
  726.     if (PT_CFG_P2P & uid_cfg->field_mask) {
  727.       port->adminPointToPointMac = uid_cfg->admin_point2point;
  728.       port->p2p_recompute = True;
  729.     }
  730.   
  731.     if (PT_CFG_EDGE & uid_cfg->field_mask) {
  732.       port->adminEdge = uid_cfg->admin_edge;
  733.       port->operEdge = port->adminEdge;
  734. #ifdef STP_DBG
  735.       if (port->edge->debug) {
  736.         stp_trace ("port %s is operEdge=%c in STP_IN_set_port_cfg",
  737.             port->port_name,
  738.             port->operEdge ? 'Y' : 'n');
  739.       }
  740. #endif
  741.     }
  742.     if (PT_CFG_NON_STP & uid_cfg->field_mask) {
  743. #ifdef STP_DBG
  744.       if (port->roletrns->debug && port->admin_non_stp != uid_cfg->admin_non_stp) {
  745.         stp_trace ("port %s is adminNonStp=%c in STP_IN_set_port_cfg",
  746.             port->port_name,
  747.             uid_cfg->admin_non_stp ? 'Y' : 'n');
  748.       }
  749. #endif
  750.       port->admin_non_stp = uid_cfg->admin_non_stp;
  751.     }
  752. #ifdef STP_DBG
  753.     if (PT_CFG_DBG_SKIP_RX & uid_cfg->field_mask) {
  754.       port->skip_rx = uid_cfg->skip_rx;
  755.     }
  756.     if (PT_CFG_DBG_SKIP_TX & uid_cfg->field_mask) {
  757.       port->skip_tx = uid_cfg->skip_tx;
  758.     }
  759. #endif
  760.     port->reselect = True;
  761.     port->selected = False;
  762.   }
  763.   
  764.   STP_stpm_update (this);
  765.   
  766.   RSTP_CRITICAL_PATH_END;
  767.   return 0;
  768. }
  769. #ifdef STP_DBG
  770. int
  771. STP_IN_dbg_set_port_trace (char* mach_name, int enadis,
  772.                            int vlan_id, BITMAP_T* ports,
  773.                            int is_print_err)
  774. {
  775.   register STPM_T* this;
  776.   register PORT_T* port;
  777.   register int     port_no;
  778.   RSTP_CRITICAL_PATH_START;
  779.   this = stpapi_stpm_find (vlan_id);
  780.   if (! this) { /* it had not yet been created :( */
  781.     RSTP_CRITICAL_PATH_END;
  782.     if (is_print_err) {
  783.         Print ("RSTP instance with tag %d hasn't been createdn", (int) vlan_id);
  784.     }
  785.     return STP_Vlan_Had_Not_Yet_Been_Created;
  786.   }
  787.   for (port_no = 1; port_no <= max_port; port_no++) {
  788.     if (! BitmapGetBit(ports, port_no - 1)) continue;
  789.   
  790.     port = _stpapi_port_find (this, port_no);
  791.     if (! port) {/* port is absent in the stpm :( */
  792.       continue;
  793.     }
  794.     STP_port_trace_state_machine (port, mach_name, enadis, vlan_id);
  795.   }
  796.   
  797.   RSTP_CRITICAL_PATH_END;
  798.   return 0;
  799. }
  800. #endif
  801. const char*
  802. STP_IN_get_error_explanation (int rstp_err_no)
  803. {
  804. #define CHOOSE(a) #a
  805. static char* rstp_error_names[] = RSTP_ERRORS;
  806. #undef CHOOSE
  807.   if (rstp_err_no < STP_OK) {
  808.     return "Too small error code :(";
  809.   }
  810.   if (rstp_err_no >= STP_LAST_DUMMY) {
  811.     return "Too big error code :(";
  812.   }
  813.   
  814.   return rstp_error_names[rstp_err_no];
  815. }