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 + -
显示快捷键?