bridgestp.c
来自「eCos操作系统源码」· C语言 代码 · 共 1,538 行 · 第 1/3 页
C
1,538 行
//==========================================================================//// 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;}voidbstp_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); }}voidbstp_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); eh.ether_type = htons(sizeof(bpdu)); bcopy(&eh, m->m_data, sizeof(eh)); bcopy(&bpdu, m->m_data + sizeof(eh), sizeof(bpdu)); STPLOG ((" - <%s>: Tx with Port 0x%x; Age %d; Flags %d\n", bif->ifp->if_xname, cu->cu_port_id, cu->cu_message_age, bpdu.cbu_flags)); IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error); if (error == 0 && (ifp->if_flags & IFF_OACTIVE) == 0) (*ifp->if_start)(ifp); splx(s);}intbstp_root_bridge(sc) struct bridge_softc *sc;{ return (sc->sc_designated_root == sc->sc_bridge_id);}intbstp_supersedes_port_info(sc, bif, cu) struct bridge_softc *sc; struct bridge_iflist *bif; struct bstp_config_unit *cu;{ if (cu->cu_rootid < bif->bif_designated_root) { return (1); } if (cu->cu_rootid > bif->bif_designated_root) { return (0); } if (cu->cu_root_path_cost < bif->bif_designated_cost) { return (1); } if (cu->cu_root_path_cost > bif->bif_designated_cost) { return (0); } if (cu->cu_bridge_id < bif->bif_designated_bridge) { return (1); } if (cu->cu_bridge_id > bif->bif_designated_bridge) { return (0); } if (sc->sc_bridge_id != cu->cu_bridge_id) { return (1); } if (cu->cu_port_id <= bif->bif_designated_port) { return (1); } return (0);}voidbstp_record_config_information(sc, bif, cu) struct bridge_softc *sc; struct bridge_iflist *bif; struct bstp_config_unit *cu;{ bif->bif_designated_root = cu->cu_rootid; bif->bif_designated_cost = cu->cu_root_path_cost; bif->bif_designated_bridge = cu->cu_bridge_id; bif->bif_designated_port = cu->cu_port_id; bstp_timer_start(&bif->bif_message_age_timer, cu->cu_message_age);}voidbstp_record_config_timeout_values(sc, config) struct bridge_softc *sc; struct bstp_config_unit *config;{ sc->sc_max_age = config->cu_max_age; sc->sc_hello_time = config->cu_hello_time; sc->sc_forward_delay = config->cu_forward_delay; sc->sc_topology_change = config->cu_topology_change;}voidbstp_config_bpdu_generation(sc) struct bridge_softc *sc;{ struct bridge_iflist *bif; STPLOG (("STP : Tx Hello BPDU ...\n")); LIST_FOREACH(bif, &sc->sc_iflist, next) { if (!(bif->bif_flags & IFBIF_STP)) continue; if (bstp_designated_port(sc, bif) && (bif->bif_state != BSTP_IFSTATE_DISABLED)) { bstp_transmit_config(sc, bif); } else { STPLOG ((" - <%s>: No Tx\n", bif->ifp->if_xname)); } }}intbstp_designated_port(sc, bif) struct bridge_softc *sc; struct bridge_iflist *bif;{ return ((bif->bif_designated_bridge == sc->sc_bridge_id) && (bif->bif_designated_port == bif->bif_port_id));}voidbstp_transmit_tcn(sc) struct bridge_softc *sc;{ struct bstp_tbpdu bpdu; struct bridge_iflist *bif = sc->sc_root_port; struct ifnet *ifp = bif->ifp; struct arpcom *arp = (struct arpcom *)ifp; struct ether_header *eh; struct mbuf *m; int s, error; if ((ifp->if_flags & IFF_RUNNING) == 0) return; MGETHDR(m, M_DONTWAIT, MT_DATA); if (m == NULL) return;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?