📄 bridgestp.c
字号:
//==========================================================================
//
// sys/net/bridgestp.c
//
//
//
//==========================================================================
//####COPYRIGHTBEGIN####
//
// -------------------------------------------
// The contents of this file are subject to the Red Hat eCos Public License
// Version 1.1 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://www.redhat.com/
//
// Software distributed under the License is distributed on an "AS IS"
// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
// License for the specific language governing rights and limitations under
// the License.
//
// The Original Code is eCos - Embedded Configurable Operating System,
// released September 30, 1998.
//
// The Initial Developer of the Original Code is Red Hat.
// Portions created by Red Hat are
// Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
// All Rights Reserved.
// -------------------------------------------
//
//####COPYRIGHTEND####
//####BSDCOPYRIGHTBEGIN####
//
// -------------------------------------------
//
// Portions of this software may have been derived from OpenBSD or other sources,
// and are covered by the appropriate copyright disclaimers included herein.
//
// -------------------------------------------
//
//####BSDCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): Jason L. Wright (jason@thought.net)
// Contributors: Manu Sharma (manu.sharma@ascom.com)
// Date: 2000-07-18
// Purpose: Implementation of the spanning tree protocol as defined in
// ISO/IEC Final DIS 15802-3 (IEEE P802.1D/D17), May 25, 1998.
// (In English: IEEE 802.1D, Draft 17, 1998)
// Description:
//
//
//####DESCRIPTIONEND####
//
//==========================================================================
//
/* $OpenBSD: bridgestp.c,v 1.15 2002/12/10 13:22:55 markus Exp $ */
/*
* Copyright (c) 2000 Jason L. Wright (jason@thought.net)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Implementation of the spanning tree protocol as defined in
* ISO/IEC Final DIS 15802-3 (IEEE P802.1D/D17), May 25, 1998.
* (In English: IEEE 802.1D, Draft 17, 1998)
*/
#ifdef __ECOS
#include <pkgconf/net.h>
#include <stdio.h>
#else
#include "bridge.h"
#endif
#ifdef CYGPKG_NET_BRIDGE_STP_CODE
#if NBRIDGE
#include <sys/param.h>
#ifndef __ECOS
#include <sys/systm.h>
#endif
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#ifndef __ECOS
#include <sys/device.h>
#endif
#include <sys/kernel.h>
#include <net/if.h>
#include <net/if_types.h>
#include <net/if_llc.h>
#include <net/netisr.h>
#ifdef INET
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/in_var.h>
#include <netinet/ip.h>
#include <netinet/if_ether.h>
#endif
#if NBPFILTER > 0
#include <net/bpf.h>
#endif
#include <net/if_bridge.h>
#define STP_DEBUG
#define STP_DETAILED_DEBUG
#ifdef STP_DEBUG
#define STPLOG(x) diag_printf x
#else
#define STPLOG(x)
#endif
#ifdef STP_DETAILED_DEBUG
#define STP_OPERATION_LOG(x) diag_printf x
#else
#define STP_OPERATION_LOG(x)
#endif
/* BPDU message types */
#define BSTP_MSGTYPE_CFG 0x00 /* Configuration */
#define BSTP_MSGTYPE_TCN 0x80 /* Topology chg notification */
/* BPDU flags */
#define BSTP_FLAG_TC 0x01 /* Topology change */
#define BSTP_FLAG_TCA 0x80 /* Topology change ack */
#define BSTP_MESSAGE_AGE_INCR (1 * 256) /* in 256ths of a second */
#define BSTP_TICK_VAL (1 * 256) /* in 256ths of a second */
/*
* Because BPDU's do not make nicely aligned structures, two different
* declarations are used: bstp_?bpdu (wire representation, packed) and
* bstp_*_unit (internal, nicely aligned version).
*/
/* configuration bridge protocol data unit */
struct bstp_cbpdu {
u_int8_t cbu_dsap; /* LLC: destination sap */
u_int8_t cbu_ssap; /* LLC: source sap */
u_int8_t cbu_ctl; /* LLC: control */
u_int16_t cbu_protoid; /* protocol id */
u_int8_t cbu_protover; /* protocol version */
u_int8_t cbu_bpdutype; /* message type */
u_int8_t cbu_flags; /* flags (below) */
/* root id */
u_int16_t cbu_rootpri; /* root priority */
u_int8_t cbu_rootaddr[6]; /* root address */
u_int32_t cbu_rootpathcost; /* root path cost */
/* bridge id */
u_int16_t cbu_bridgepri; /* bridge priority */
u_int8_t cbu_bridgeaddr[6]; /* bridge address */
u_int16_t cbu_portid; /* port id */
u_int16_t cbu_messageage; /* current message age */
u_int16_t cbu_maxage; /* maximum age */
u_int16_t cbu_hellotime; /* hello time */
u_int16_t cbu_forwarddelay; /* forwarding delay */
} __attribute__((__packed__));
/* topology change notification bridge protocol data unit */
struct bstp_tbpdu {
u_int8_t tbu_dsap; /* LLC: destination sap */
u_int8_t tbu_ssap; /* LLC: source sap */
u_int8_t tbu_ctl; /* LLC: control */
u_int16_t tbu_protoid; /* protocol id */
u_int8_t tbu_protover; /* protocol version */
u_int8_t tbu_bpdutype; /* message type */
} __attribute__((__packed__));
u_int8_t bstp_etheraddr[] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 };
u_int8_t bstp_init_done;
void bstp_initialization(struct bridge_softc *);
void bstp_stop(struct bridge_softc *);
void bstp_initialize_port(struct bridge_softc *, struct bridge_iflist *);
void bstp_ifupdstatus(struct bridge_softc *, struct bridge_iflist *);
void bstp_enable_port(struct bridge_softc *, struct bridge_iflist *);
void bstp_disable_port(struct bridge_softc *, struct bridge_iflist *);
void bstp_enable_change_detection(struct bridge_iflist *);
void bstp_disable_change_detection(struct bridge_iflist *);
int bstp_root_bridge(struct bridge_softc *sc);
int bstp_supersedes_port_info(struct bridge_softc *, struct bridge_iflist *,
struct bstp_config_unit *);
int bstp_designated_port(struct bridge_softc *, struct bridge_iflist *);
int bstp_designated_for_some_port(struct bridge_softc *);
void bstp_transmit_config(struct bridge_softc *, struct bridge_iflist *);
void bstp_transmit_tcn(struct bridge_softc *);
struct mbuf *bstp_input(struct bridge_softc *, struct ifnet *,
struct ether_header *, struct mbuf *);
void bstp_received_config_bpdu(struct bridge_softc *, struct bridge_iflist *,
struct bstp_config_unit *);
void bstp_received_tcn_bpdu(struct bridge_softc *, struct bridge_iflist *,
struct bstp_tcn_unit *);
void bstp_record_config_information(struct bridge_softc *,
struct bridge_iflist *, struct bstp_config_unit *);
void bstp_record_config_timeout_values(struct bridge_softc *,
struct bstp_config_unit *);
void bstp_config_bpdu_generation(struct bridge_softc *);
void bstp_send_config_bpdu(struct bridge_iflist *, struct bstp_config_unit *);
void bstp_configuration_update(struct bridge_softc *);
void bstp_root_selection(struct bridge_softc *);
void bstp_designated_port_selection(struct bridge_softc *);
void bstp_become_designated_port(struct bridge_softc *, struct bridge_iflist *);
void bstp_port_state_selection(struct bridge_softc *);
void bstp_make_forwarding(struct bridge_softc *, struct bridge_iflist *);
void bstp_make_blocking(struct bridge_softc *, struct bridge_iflist *);
void bstp_set_port_state(struct bridge_iflist *, u_int8_t);
void bstp_set_bridge_priority(struct bridge_softc *, u_int64_t);
void bstp_set_port_priority(struct bridge_softc *, struct bridge_iflist *,
u_int16_t);
void bstp_set_path_cost(struct bridge_softc *, struct bridge_iflist *,
u_int32_t);
void bstp_topology_change_detection(struct bridge_softc *);
void bstp_topology_change_acknowledged(struct bridge_softc *);
void bstp_acknowledge_topology_change(struct bridge_softc *,
struct bridge_iflist *);
void bstp_tick(void *);
void bstp_timer_start(struct bridge_timer *, u_int16_t);
void bstp_timer_stop(struct bridge_timer *);
int bstp_timer_expired(struct bridge_timer *, u_int16_t);
void bstp_hold_timer_expiry(struct bridge_softc *, struct bridge_iflist *);
void bstp_message_age_timer_expiry(struct bridge_softc *,
struct bridge_iflist *);
void bstp_forward_delay_timer_expiry(struct bridge_softc *,
struct bridge_iflist *);
void bstp_topology_change_timer_expiry(struct bridge_softc *);
void bstp_tcn_timer_expiry(struct bridge_softc *);
void bstp_hello_timer_expiry(struct bridge_softc *);
char stp_buf [32];
char *
stp_port_state (unsigned int state) {
memset (stp_buf, 0x0, 32);
switch (state) {
case BSTP_IFSTATE_DISABLED : sprintf (stp_buf, " Disabled "); break;
case BSTP_IFSTATE_LISTENING : sprintf (stp_buf, " Listn'ng "); break;
case BSTP_IFSTATE_LEARNING : sprintf (stp_buf, " Lrn'ng "); break;
case BSTP_IFSTATE_FORWARDING : sprintf (stp_buf, " Fwd'ng "); break;
case BSTP_IFSTATE_BLOCKING : sprintf (stp_buf, " Blk'ng "); break;
default: sprintf (stp_buf, " UNKNOWN "); break;
}
return stp_buf;
}
void
bstp_transmit_config(sc, bif)
struct bridge_softc *sc;
struct bridge_iflist *bif;
{
if (bif->bif_hold_timer.active) {
bif->bif_config_pending = 1;
return;
}
bif->bif_config_bpdu.cu_message_type = BSTP_MSGTYPE_CFG;
bif->bif_config_bpdu.cu_rootid = sc->sc_designated_root;
bif->bif_config_bpdu.cu_root_path_cost = sc->sc_root_path_cost;
bif->bif_config_bpdu.cu_bridge_id = sc->sc_bridge_id;
bif->bif_config_bpdu.cu_port_id = bif->bif_port_id;
if (bstp_root_bridge(sc))
bif->bif_config_bpdu.cu_message_age = 0;
else
bif->bif_config_bpdu.cu_message_age =
sc->sc_root_port->bif_message_age_timer.value +
BSTP_MESSAGE_AGE_INCR;
bif->bif_config_bpdu.cu_max_age = sc->sc_max_age;
bif->bif_config_bpdu.cu_hello_time = sc->sc_hello_time;
bif->bif_config_bpdu.cu_forward_delay = sc->sc_forward_delay;
bif->bif_config_bpdu.cu_topology_change_acknowledgment
= bif->bif_topology_change_acknowledge;
bif->bif_config_bpdu.cu_topology_change = sc->sc_topology_change;
if (bif->bif_config_bpdu.cu_message_age < sc->sc_max_age) {
bif->bif_topology_change_acknowledge = 0;
bif->bif_config_pending = 0;
bstp_send_config_bpdu(bif, &bif->bif_config_bpdu);
bstp_timer_start(&bif->bif_hold_timer, 0);
}
}
void
bstp_send_config_bpdu(bif, cu)
struct bridge_iflist *bif;
struct bstp_config_unit *cu;
{
struct arpcom *arp;
struct ifnet *ifp;
struct mbuf *m;
struct ether_header eh;
struct bstp_cbpdu bpdu;
int s, error;
s = splimp();
ifp = bif->ifp;
arp = (struct arpcom *)ifp;
if ((ifp->if_flags & IFF_RUNNING) == 0) {
splx(s);
return;
}
#ifdef ALTQ
if (!ALTQ_IS_ENABLED(&ifp->if_snd))
#endif
if (IF_QFULL(&ifp->if_snd)) {
splx(s);
return;
}
MGETHDR(m, M_DONTWAIT, MT_DATA);
if (m == NULL) {
splx(s);
return;
}
m->m_pkthdr.rcvif = ifp;
m->m_pkthdr.len = sizeof(eh) + sizeof(bpdu);
m->m_len = m->m_pkthdr.len;
bpdu.cbu_ssap = bpdu.cbu_dsap = LLC_8021D_LSAP;
bpdu.cbu_ctl = LLC_UI;
bpdu.cbu_protoid = htons(0);
bpdu.cbu_protover = 0;
bpdu.cbu_bpdutype = cu->cu_message_type;
bpdu.cbu_flags = (cu->cu_topology_change ? BSTP_FLAG_TC : 0) |
(cu->cu_topology_change_acknowledgment ? BSTP_FLAG_TCA : 0);
bpdu.cbu_rootpri = htons(cu->cu_rootid >> 48);
bpdu.cbu_rootaddr[0] = cu->cu_rootid >> 40;
bpdu.cbu_rootaddr[1] = cu->cu_rootid >> 32;
bpdu.cbu_rootaddr[2] = cu->cu_rootid >> 24;
bpdu.cbu_rootaddr[3] = cu->cu_rootid >> 16;
bpdu.cbu_rootaddr[4] = cu->cu_rootid >> 8;
bpdu.cbu_rootaddr[5] = cu->cu_rootid >> 0;
bpdu.cbu_rootpathcost = htonl(cu->cu_root_path_cost);
bpdu.cbu_bridgepri = htons(cu->cu_rootid >> 48);
bpdu.cbu_bridgeaddr[0] = cu->cu_rootid >> 40;
bpdu.cbu_bridgeaddr[1] = cu->cu_rootid >> 32;
bpdu.cbu_bridgeaddr[2] = cu->cu_rootid >> 24;
bpdu.cbu_bridgeaddr[3] = cu->cu_rootid >> 16;
bpdu.cbu_bridgeaddr[4] = cu->cu_rootid >> 8;
bpdu.cbu_bridgeaddr[5] = cu->cu_rootid >> 0;
bpdu.cbu_portid = htons(cu->cu_port_id);
bpdu.cbu_messageage = htons(cu->cu_message_age);
bpdu.cbu_maxage = htons(cu->cu_max_age);
bpdu.cbu_hellotime = htons(cu->cu_hello_time);
bpdu.cbu_forwarddelay = htons(cu->cu_forward_delay);
bcopy(arp->ac_enaddr, eh.ether_shost, ETHER_ADDR_LEN);
bcopy(bstp_etheraddr, eh.ether_dhost, ETHER_ADDR_LEN);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -