⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stpm.c

📁 快速生成树协议的源代码
💻 C
字号:
/************************************************************************  * 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.  **********************************************************************/ /* STP machine instance : bridge per VLAN: 17.17 */ #include "base.h"#include "stpm.h"#include "stp_to.h" /* for STP_OUT_flush_lt */static STPM_T *bridges = NULL;static int_stp_stpm_init_machine (STATE_MACH_T* this){  this->State = BEGIN;  (*(this->concreteEnterState)) (this);  return 0;}static int_stp_stpm_iterate_machines (STPM_T* this,                           int (*iter_callb) (STATE_MACH_T*),                           Bool exit_on_non_zero_ret){  register STATE_MACH_T* stater;  register PORT_T*       port;  int                    iret, mret = 0;  /* state machines per bridge */  for (stater = this->machines; stater; stater = stater->next) {    iret = (*iter_callb) (stater);    if (exit_on_non_zero_ret && iret)      return iret;    else      mret += iret;  }  /* state machines per port */  for (port = this->ports; port; port = port->next) {    for (stater = port->machines; stater; stater = stater->next) {      iret = (*iter_callb) (stater);      if (exit_on_non_zero_ret && iret)        return iret;      else        mret += iret;    }  }    return mret;}void_stp_stpm_init_data (STPM_T* this){  STP_VECT_create (&this->rootPrio,                   &this->BrId,                   0,                   &this->BrId,                   0, 0);  this->BrTimes.MessageAge = 0;  STP_copy_times (&this->rootTimes, &this->BrTimes);}static unsigned char_check_topoch (STPM_T* this){  register PORT_T*  port;    for (port = this->ports; port; port = port->next) {    if (port->tcWhile) {      return 1;    }  }  return 0;}voidSTP_stpm_one_second (STPM_T* param){  STPM_T*           this = (STPM_T*) param;  register PORT_T*  port;  register int      iii;  if (STP_ENABLED != this->admin_state) return;  for (port = this->ports; port; port = port->next) {    for (iii = 0; iii < TIMERS_NUMBER; iii++) {      if (*(port->timers[iii]) > 0) {        (*port->timers[iii])--;      }    }        port->uptime++;  }  STP_stpm_update (this);  this->Topo_Change = _check_topoch (this);  if (this->Topo_Change) {    this->Topo_Change_Count++;    this->timeSince_Topo_Change = 0;  } else {    this->Topo_Change_Count = 0;    this->timeSince_Topo_Change++;  }}STPM_T*STP_stpm_create (int vlan_id, char* name){  STPM_T* this;  STP_NEW_IN_LIST(this, STPM_T, bridges, "stp instance");  this->admin_state = STP_DISABLED;    this->vlan_id = vlan_id;  if (name) {    STP_STRDUP(this->name, name, "stp bridge name");  }  this->machines = NULL;  this->ports = NULL;  STP_STATE_MACH_IN_LIST(rolesel);#ifdef STP_DBG  /* this->rolesel->debug = 2;  */#endif  return this;}intSTP_stpm_enable (STPM_T* this, UID_STP_MODE_T admin_state){  int rc = 0;  if (admin_state == this->admin_state) {    /* nothing to do :) */    return 0;  }  if (STP_ENABLED == admin_state) {    rc = STP_stpm_start (this);    this->admin_state = admin_state;  } else {    this->admin_state = admin_state;    STP_stpm_stop (this);  }    return rc;}voidSTP_stpm_delete (STPM_T* this){  register STPM_T*       tmp;  register STPM_T*       prev;  register STATE_MACH_T* stater;  register PORT_T*       port;  register void*         pv;  STP_stpm_enable (this, STP_DISABLED);    for (stater = this->machines; stater; ) {    pv = (void*) stater->next;    STP_state_mach_delete (stater);    this->machines = stater = (STATE_MACH_T*) pv;  }  for (port = this->ports; port; ) {    pv = (void*) port->next;    STP_port_delete (port);    this->ports = port = (PORT_T*) pv;  }  prev = NULL;  for (tmp = bridges; tmp; tmp = tmp->next) {    if (tmp->vlan_id == this->vlan_id) {      if (prev) {        prev->next = this->next;      } else {        bridges = this->next;      }            if (this->name)        STP_FREE(this->name, "stp bridge name");      STP_FREE(this, "stp instance");      break;    }    prev = tmp;  }}intSTP_stpm_start (STPM_T* this){  register PORT_T* port;  if (! this->ports) { /* there are not any ports :( */    return STP_There_Are_No_Ports;  }  if (! STP_compute_bridge_id (this)) {/* can't compute bridge id ? :( */    return STP_Cannot_Compute_Bridge_Prio;  }  /* check, that the stpm has unique bridge Id */  if (0 != STP_stpm_check_bridge_priority (this)) {    /* there is an enabled bridge with same ID :( */    return STP_Invalid_Bridge_Priority;  }  _stp_stpm_init_data (this);  for (port = this->ports; port; port = port->next) {    STP_port_init (port, this, True);  }#ifndef STRONGLY_SPEC_802_1W  /* A. see comment near STRONGLY_SPEC_802_1W in topoch.c */  /* B. port=0 here means: delete for all ports */#ifdef STP_DBG  stp_trace("%s (all, start stpm)",        "clearFDB");#endif  STP_OUT_flush_lt (0, this->vlan_id, LT_FLASH_ONLY_THE_PORT, "start stpm");#endif  _stp_stpm_iterate_machines (this, _stp_stpm_init_machine, False);  STP_stpm_update (this);  return 0;}voidSTP_stpm_stop (STPM_T* this){}intSTP_stpm_update (STPM_T* this) /* returns number of loops */{  register Bool     need_state_change;  register int      number_of_loops = 0;  need_state_change = False;     for (;;) {/* loop until not need changes */    need_state_change = _stp_stpm_iterate_machines (this,                                                   STP_check_condition,                                                   True);    if (! need_state_change) return number_of_loops;    number_of_loops++;    /* here we know, that at least one stater must be       updated (it has changed state) */    number_of_loops += _stp_stpm_iterate_machines (this,                                                  STP_change_state,                                                  False);  }  return number_of_loops;}BRIDGE_ID *STP_compute_bridge_id (STPM_T* this){  register PORT_T* port;  register PORT_T* min_num_port;  int              port_index = 0;  for (port = this->ports; port; port = port->next) {    if (! port_index || port->port_index < port_index) {      min_num_port = port;      port_index = port->port_index;    }  }  if (! min_num_port) return NULL; /* IMHO, it may not be */  STP_OUT_get_port_mac (min_num_port->port_index, this->BrId.addr);  return &this->BrId;}STPM_T*STP_stpm_get_the_list (void){  return bridges;}voidSTP_stpm_update_after_bridge_management (STPM_T* this){  register PORT_T* port;  for (port = this->ports; port; port = port->next) {    port->reselect = True;    port->selected = False;  }}intSTP_stpm_check_bridge_priority (STPM_T* this){  register STPM_T* oth;  for (oth = bridges; oth; oth = oth->next) {    if (STP_ENABLED == oth->admin_state && oth != this &&        ! STP_VECT_compare_bridge_id (&this->BrId, &oth->BrId)) {      return STP_Invalid_Bridge_Priority;    }  }  return 0;}const char*STP_stpm_get_port_name_by_id (STPM_T* this, PORT_ID port_id){  register PORT_T* port;  for (port = this->ports; port; port = port->next) {    if (port_id == port->port_id) {        return port->port_name;    }  }  return "Undef?";}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -