/* stp-8021d-d17.c - Spanning Tree Algorithm and Protocol */
/* Copyright 2001 Wind River Systems, Inc. */
/* Copyright 1998-2000 Wind River Systems, Inc. */
/* Copyright 1999 Wind River Systems, Inc. */
/* Copyright 1998-1999 XACT, Inc. */
#include "copyright_wrs.h"
/*
modification history
--------------------
00g,12jun01,tf In transmit_tcn(), port_no was being tested before even set.
00f,18apr01,kc Replaced "extern" with "IMPORT".
00e,10dec00,ajw Changes to comments for refgen web pages
01c,16nov00,kw Ran thru lint.
01b,24sep00,kw Change the code to handle Identifier as a structure and not
a unsigned long long value. Using the 64 bit word has some
little endian problems for the pcSwitch.
01a,24sep00,kw Updated.
*/
/*
DESCRIPTION:
The routines in this midule interface spanLib to the lower level Spanning Tree
routines.
*
INCLUDES:
\ml
\m tmsTypes.h
\m spantree.h
\m spanglob.h
\m trap.h
\me
*/
#define INCLUDE_ID_ROUTINES
/* includes */
#include <STP types.h>
#include <STP spantree.h>
#include <STP spanglob.h>
/* defines */
/* typedefs */
/* locals */
#ifndef _lint
char * span_version =
"STP Version: ISO/IEC Final DIS 15802-3 (IEEE P802.1D/D17) May 25, 1998\n";
#endif
Bridge_data bridge_info; /* (8.5.3) */
Port_data* port_info; /* (8.5.5) */
Config_bpdu* config_bpdu;
Tcn_bpdu* tcn_bpdu;
Timer hello_timer; /* (8.5.4.1) */
Timer tcn_timer; /* (8.5.4.2) */
Timer topology_change_timer; /* (8.5.4.3) */
Timer* message_age_timer; /* (8.5.6.1) */
Timer* forward_delay_timer; /* (8.5.6.2) */
Timer* hold_timer; /* (8.5.6.3) */
Timer since_topology_change;
/* globals */
/* forward declarations */
IMPORT STATUS No_of_ports;
/*******************************************************************************
* transmit_config -
*
* INPUTS:
*
* RETURNS:
*
* ERRORS:
*
* ERRNO:
*
* NOMANUAL <THIS later removed be will>
*/
void transmit_config
(
Int port_no
) /* (8.6.1) */
{
if (hold_timer[port_no].active) /* (8.6.1.3.1) */
{
port_info[port_no].config_pending = True; /* (8.6.1.3.1) */
}
else
/* (8.6.1.3.2) */
{
config_bpdu[port_no].type = Config_bpdu_type;
id_equate(config_bpdu[port_no].root_id, bridge_info.designated_root);
/* (8.6.1.3.2(a)) */
config_bpdu[port_no].root_path_cost = bridge_info.root_path_cost;
/* (8.6.1.3.2(b)) */
id_equate(config_bpdu[port_no].bridge_id, bridge_info.bridge_id);
/* (8.6.1.3.2(c)) */
config_bpdu[port_no].port_id = port_info[port_no].port_id;
/* (8.6.1.3.2(d)) */
if (root_bridge())
{
config_bpdu[port_no].message_age = Zero; /* (8.6.1.3.2(e)) */
}
else
{
config_bpdu[port_no].message_age
= message_age_timer[bridge_info.root_port].value
+ Message_age_increment; /* (8.6.1.3.2(f)) */
}
config_bpdu[port_no].max_age = bridge_info.max_age; /* (8.6.1.3.2(g)) */
config_bpdu[port_no].hello_time = bridge_info.hello_time;
config_bpdu[port_no].forward_delay = bridge_info.forward_delay;
config_bpdu[port_no].topology_change_acknowledgment
= (uchar_t)port_info[port_no].topology_change_acknowledge;
/* (8.6.1.3.2(h)) */
config_bpdu[port_no].topology_change
= (uchar_t)bridge_info.topology_change; /* (8.6.1.3.2(i)) */
if (config_bpdu[port_no].message_age < bridge_info.max_age)
{
port_info[port_no].topology_change_acknowledge = False;
/* (8.6.1.3.3) */
port_info[port_no].config_pending = False; /* (8.6.1.3.3) */
send_config_bpdu(port_no, &config_bpdu[port_no]);
start_hold_timer(port_no); /* (8.6.3.3(b)) */
}
}
}
/*******************************************************************************
* send_config_bpdu -
*
* INPUTS:
*
* RETURNS:
*
* ERRORS:
*
* ERRNO:
*
* NOMANUAL <THIS later removed be will>
*/
void send_config_bpdu
(
Int port_no,
Config_bpdu * bpdu
)
{
span_send_config_bpdu(port_no, bpdu);
}
/*******************************************************************************
* root_bridge -
*
* INPUTS:
*
* RETURNS:
*
* ERRORS:
*
* ERRNO:
*
* NOMANUAL <THIS later removed be will>
*/
Boolean root_bridge
(
void
)
{
return (id_eq(bridge_info.designated_root, bridge_info.bridge_id));
}
/*******************************************************************************
* supersedes_port_info -
*
* INPUTS:
*
* RETURNS:
*
* ERRORS:
*
* ERRNO:
*
* NOMANUAL <THIS later removed be will>
*/ /* (8.6.2.2) */
Boolean supersedes_port_info
(
Int port_no,
Config_bpdu * config
)
{
return (
/* (8.6.2.2.1) */
(id_lt(config->root_id, port_info[port_no].designated_root))
||
(
(id_eq(config->root_id, port_info[port_no].designated_root))
&&
/* (8.6.2.2.2) */
(
(config->root_path_cost < port_info[port_no].designated_cost)
||
(
(config->root_path_cost == port_info[port_no].designated_cost)
&&
/* (8.6.2.2.3) */
(
(id_lt(config->bridge_id, port_info[port_no].designated_bridge))
||
/* (8.6.2.2.4) */
(
(id_eq(config->bridge_id, port_info[port_no].designated_bridge))
&&
/* (8.6.2.2.4(a)) */
(
(id_neq(config->bridge_id, bridge_info.bridge_id))
||
/* (8.6.2.2.4(b)) */
(config->port_id <= port_info[port_no].designated_port)
)
)
)
)
)
)
);
}
/*******************************************************************************
* record_config_information -
*
* INPUTS:
*
* RETURNS:
*
* ERRORS:
*
* ERRNO:
*
* NOMANUAL <THIS later removed be will>
*/
LOCAL void record_config_information
(
Int port_no,
Config_bpdu * config
) /* (8.6.2) */
{
/* (8.6.2.3.1) */
id_equate(port_info[port_no].designated_root, config->root_id);
port_info[port_no].designated_cost = config->root_path_cost;
id_equate(port_info[port_no].designated_bridge, config->bridge_id);
port_info[port_no].designated_port = config->port_id;
start_message_age_timer(port_no, config->message_age); /* (8.6.2.3.2) */
}
/*******************************************************************************
* record_config_timeout_values -
*
* INPUTS:
*
* RETURNS:
*
* ERRORS:
*
* ERRNO:
*
* N