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

📄 bridgestp.c

📁 eCos/RedBoot for勤研ARM AnywhereII(4510) 含全部源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
//==========================================================================
//
//      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 + -