bridgestp.c

来自「eCos操作系统源码」· C语言 代码 · 共 1,538 行 · 第 1/3 页

C
1,538
字号
        STPLOG (("STP : Tx TCN BPDU on <%s> ...\n", ifp->if_xname));	m->m_pkthdr.rcvif = ifp;	m->m_pkthdr.len = sizeof(*eh) + sizeof(bpdu);	m->m_len = m->m_pkthdr.len;	eh = mtod(m, struct ether_header *);	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));	bpdu.tbu_ssap = bpdu.tbu_dsap = LLC_8021D_LSAP;	bpdu.tbu_ctl = LLC_UI;	bpdu.tbu_protoid = 0;	bpdu.tbu_protover = 0;	bpdu.tbu_bpdutype = BSTP_MSGTYPE_TCN;	bcopy(&bpdu, m->m_data + sizeof(*eh), sizeof(bpdu));	s = splimp();	IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error);	if (error == 0 && (ifp->if_flags & IFF_OACTIVE) == 0)		(*ifp->if_start)(ifp);	m = NULL;	splx(s);	if (m != NULL)		m_freem(m);}voidbstp_configuration_update(sc)	struct bridge_softc *sc;{        STP_OPERATION_LOG (("   %s \n", __FUNCTION__));	bstp_root_selection(sc);	bstp_designated_port_selection(sc);}voidbstp_root_selection(sc)	struct bridge_softc *sc;{	struct bridge_iflist *root_port = NULL, *bif;        STP_OPERATION_LOG (("   => Root Port selection ...\n", __FUNCTION__));	LIST_FOREACH(bif, &sc->sc_iflist, next) {                STP_OPERATION_LOG (("      - <%s>", bif->ifp->if_xname));		if (!(bif->bif_flags & IFBIF_STP)) {                        STP_OPERATION_LOG ((" STP not configured\n"));			continue;                }		if (bstp_designated_port(sc, bif)) {                        STP_OPERATION_LOG ((" dsgntd port\n"));			continue;                }		if (bif->bif_state == BSTP_IFSTATE_DISABLED) {                        STP_OPERATION_LOG ((" .. in state DISABLED \n"));			continue;                }		if (bif->bif_designated_root >= sc->sc_bridge_id) {                        STP_OPERATION_LOG ((" root: ifp dsgntd >= sc\n"));			continue;                }		if (root_port == NULL) {                        STP_OPERATION_LOG ((" Set as Root Port\n"));			goto set_port;                }		if (bif->bif_designated_root < root_port->bif_designated_root) {                        STP_OPERATION_LOG ((" ifp dsgntd < root dsgntd; Set as Root Port \n"));			goto set_port;                }		if (bif->bif_designated_root > root_port->bif_designated_root) {                        STP_OPERATION_LOG ((" root: ifp dsgntd > root dsgntd \n"));			continue;                }		if ((bif->bif_designated_cost + bif->bif_path_cost) <		    (root_port->bif_designated_cost + root_port->bif_path_cost)) {                        STP_OPERATION_LOG ((" (dsgntd_cost+path_cost): ifp < root; Set as Root Port \n"));			goto set_port;                }		if ((bif->bif_designated_cost + bif->bif_path_cost) >		    (root_port->bif_designated_cost + root_port->bif_path_cost)) {                        STP_OPERATION_LOG ((" (dsgntd_cost+path_cost): ifp > root \n"));			continue;                }		if (bif->bif_designated_bridge < root_port->bif_designated_bridge) {                        STP_OPERATION_LOG ((" bridge: ifp dsgntd < root dsgntd; Set as Root Port \n"));			goto set_port;                }		if (bif->bif_designated_bridge > root_port->bif_designated_bridge) {                        STP_OPERATION_LOG ((" bridge: ifp dsgntd > root dsgntd \n"));			continue;                }		if (bif->bif_designated_port < root_port->bif_designated_port) {                        STP_OPERATION_LOG ((" port: ifp dsgntd (%d) < root dsgntd (%d); Set as Root Port\n",                                 bif->bif_designated_port, root_port->bif_designated_port));			goto set_port;                }		if (bif->bif_designated_port > root_port->bif_designated_port) {                        STP_OPERATION_LOG ((" port: ifp dsgntd (%d) > root dsgntd (%d)\n",                                 bif->bif_designated_port, root_port->bif_designated_port));			continue;                }		if (bif->bif_port_id >= root_port->bif_port_id) {                        STP_OPERATION_LOG ((" ifp port_id (%d) >= root port_id (%d) 8 \n",                                 bif->bif_port_id, root_port->bif_port_id));			continue;                }set_port:		root_port = bif;	}	sc->sc_root_port = root_port;	if (root_port == NULL) {		sc->sc_designated_root = sc->sc_bridge_id;		sc->sc_root_path_cost = 0;                STPLOG (("      Root Port : <SELF ROOT>, Path Cost : 0\n"));	} else {		sc->sc_designated_root = root_port->bif_designated_root;		sc->sc_root_path_cost = root_port->bif_designated_cost +		    root_port->bif_path_cost;                STPLOG (("      Root Port : <%s>, Path Cost : 0\n",                           root_port->ifp->if_xname, sc->sc_root_path_cost));	}}voidbstp_designated_port_selection(sc)	struct bridge_softc *sc;{	struct bridge_iflist *bif;        STP_OPERATION_LOG (("   => Designated Port selection ...\n"));	LIST_FOREACH(bif, &sc->sc_iflist, next) {		if (!(bif->bif_flags & IFBIF_STP))			continue;		if (bstp_designated_port(sc, bif)) {                        STPLOG (("      - <%s>: already designated \n", bif->ifp->if_xname));			goto designated;                }		if (bif->bif_designated_root != sc->sc_designated_root) {                        STPLOG (("      - <%s>: becomes designated\n", bif->ifp->if_xname));			goto designated;                }                /*                  * PLC network is special, we cannot go as per standards because of                 * our network topology and behavior                 *		if (sc->sc_root_path_cost < bif->bif_designated_cost) {                        STPLOG (("        - <%s>: becomes designated path cost (1)\n", bif->ifp->if_xname));			goto designated;                }		if (sc->sc_root_path_cost > bif->bif_designated_cost) {                        STPLOG (("        - <%s>: Cannot be designated; Root cost (%d) > Desig cost (%d) \n",                                  bif->ifp->if_xname, sc->sc_root_path_cost, bif->bif_designated_cost));			continue;                }                */		if (sc->sc_bridge_id < bif->bif_designated_bridge) {                        STPLOG (("      - <%s>: becomes dsgntd (self-brdgid < dsgntd-brdgid); \n", bif->ifp->if_xname));			goto designated;                }		if (sc->sc_bridge_id > bif->bif_designated_bridge) {                        STPLOG (("      - <%s>: Cannot be dsgntd (self-brdgid > dsgntd-brdgid); \n", bif->ifp->if_xname));			continue;                }		if (bif->bif_port_id > bif->bif_designated_port) {                        STPLOG (("      - <%s>: Cannot be dsgntd (self-portid > bsgntd-portid); \n", bif->ifp->if_xname));			continue;                }                /*                  * PLC network is special, we cannot go as per standards because of                 * our network topology and behavior                 */		if (sc->sc_root_path_cost < bif->bif_designated_cost) {                        STPLOG (("      - <%s>: becomes dsgntd path cost (1)\n", bif->ifp->if_xname));			goto designated;                }		if (sc->sc_root_path_cost > bif->bif_designated_cost) {                        STPLOG (("      - <%s>: Cannot be dsgntd; Root cost (%d) > Desig cost (%d) \n",                                  bif->ifp->if_xname, sc->sc_root_path_cost, bif->bif_designated_cost));			continue;                }designated:		bstp_become_designated_port(sc, bif);	}}voidbstp_become_designated_port(sc, bif)	struct bridge_softc *sc;	struct bridge_iflist *bif;{	bif->bif_designated_root = sc->sc_designated_root;	bif->bif_designated_cost = sc->sc_root_path_cost;	bif->bif_designated_bridge = sc->sc_bridge_id;	bif->bif_designated_port = bif->bif_port_id;        STP_OPERATION_LOG (("               => %s values (cost:%d, port:0x%x)\n",                             __FUNCTION__, bif->ifp->if_xname, bif->bif_designated_cost, bif->bif_designated_port));        //STP_OPERATION_LOG (("(cost:%d, port:0x%x)\n", bif->bif_designated_cost, bif->bif_designated_port));}voidbstp_port_state_selection(sc)	struct bridge_softc *sc;{	struct bridge_iflist *bif;	LIST_FOREACH(bif, &sc->sc_iflist, next) {		if (!(bif->bif_flags & IFBIF_STP))			continue;		if (bif == sc->sc_root_port) {			bif->bif_config_pending = 0;			bif->bif_topology_change_acknowledge = 0;			bstp_make_forwarding(sc, bif);		} else if (bstp_designated_port(sc, bif)) {			bstp_timer_stop(&bif->bif_message_age_timer);			bstp_make_forwarding(sc, bif);		} else {			bif->bif_config_pending = 0;			bif->bif_topology_change_acknowledge = 0;			bstp_make_blocking(sc, bif);		}	}}voidbstp_make_forwarding(sc, bif)	struct bridge_softc *sc;	struct bridge_iflist *bif;{	if (bif->bif_state == BSTP_IFSTATE_BLOCKING) {		bstp_set_port_state(bif, BSTP_IFSTATE_LISTENING);		bstp_timer_start(&bif->bif_forward_delay_timer, 0);	}}voidbstp_make_blocking(sc, bif)	struct bridge_softc *sc;	struct bridge_iflist *bif;{	if ((bif->bif_state != BSTP_IFSTATE_DISABLED) &&	    (bif->bif_state != BSTP_IFSTATE_BLOCKING)) {		if ((bif->bif_state == BSTP_IFSTATE_FORWARDING) ||		    (bif->bif_state == BSTP_IFSTATE_LEARNING)) {			if (bif->bif_change_detection_enabled) {				bstp_topology_change_detection(sc);			}			bridge_rtdelete(sc, bif->ifp, 1);		}		bstp_set_port_state(bif, BSTP_IFSTATE_BLOCKING);		bstp_timer_stop(&bif->bif_forward_delay_timer);	}}voidbstp_set_port_state(bif, state)	struct bridge_iflist *bif;	u_int8_t state;{	bif->bif_state = state;}voidbstp_topology_change_detection(sc)	struct bridge_softc *sc;{	if (bstp_root_bridge(sc)) {                STPLOG (("   -> %s : Root Bridge\n", __FUNCTION__));		sc->sc_topology_change = 1;		bstp_timer_start(&sc->sc_topology_change_timer, 0);	} else if (!sc->sc_topology_change_detected) {                STPLOG (("   -> %s : NOT Root Bridge, Tx TCN\n", __FUNCTION__));		bstp_transmit_tcn(sc);		bstp_timer_start(&sc->sc_tcn_timer, 0);	}	sc->sc_topology_change_detected = 1;}voidbstp_topology_change_acknowledged(sc)	struct bridge_softc *sc;{	sc->sc_topology_change_detected = 0;	bstp_timer_stop(&sc->sc_tcn_timer);}voidbstp_acknowledge_topology_change(sc, bif)	struct bridge_softc *sc;	struct bridge_iflist *bif;{	bif->bif_topology_change_acknowledge = 1;	bstp_transmit_config(sc, bif);}struct mbuf *bstp_input(sc, ifp, eh, m)	struct bridge_softc *sc;	struct ifnet *ifp;	struct ether_header *eh;	struct mbuf *m;{	struct bridge_iflist *bif = NULL;	struct bstp_tbpdu tpdu;	struct bstp_cbpdu cpdu;	struct bstp_config_unit cu;	struct bstp_tcn_unit tu;	u_int16_t len;	LIST_FOREACH(bif, &sc->sc_iflist, next) {		if (!(bif->bif_flags & IFBIF_STP))			continue;		if (bif->ifp == ifp)			break;	}	if (bif == NULL)		goto out;	len = ntohs(eh->ether_type);	if (len < sizeof(tpdu)) {		goto out;        }	if (m->m_pkthdr.len > len)		m_adj(m, len - m->m_pkthdr.len);	if ((m = m_pullup(m, sizeof(tpdu))) == NULL) {		goto out;        }	bcopy(mtod(m, struct tpdu *), &tpdu, sizeof(tpdu));	if (tpdu.tbu_dsap != LLC_8021D_LSAP ||	    tpdu.tbu_ssap != LLC_8021D_LSAP ||	    tpdu.tbu_ctl != LLC_UI) {		goto out;        }	if (tpdu.tbu_protoid != 0 || tpdu.tbu_protover != 0) {		goto out;         }	switch (tpdu.tbu_bpdutype) {	case BSTP_MSGTYPE_TCN:                STPLOG (("STP : Rx TCN on <%s> from %02X:%02X:%02X:%02X:%02X:%02X \n", bif->ifp->if_xname,                      eh->ether_shost[0], eh->ether_shost[1], eh->ether_shost[2],                      eh->ether_shost[3], eh->ether_shost[4], eh->ether_shost[5]));		tu.tu_message_type = tpdu.tbu_bpdutype;		bstp_received_tcn_bpdu(sc, bif, &tu);		break;	case BSTP_MSGTYPE_CFG:                STPLOG (("STP : Rx CFG on <%s> from %02X:%02X:%02X:%02X:%02X:%02X \n", bif->ifp->if_xname,                      eh->ether_shost[0], eh->ether_shost[1], eh->ether_shost[2],                      eh->ether_shost[3], eh->ether_shost[4], eh->ether_shost[5]));		if ((m = m_pullup(m, sizeof(cpdu))) == NULL)			goto out;		bcopy(mtod(m, struct bstp_cpdu *), &cpdu, sizeof(cpdu));		cu.cu_rootid =		    (((u_int64_t)ntohs(cpdu.cbu_rootpri)) << 48) |		    (((u_int64_t)cpdu.cbu_rootaddr[0]) << 40) |		    (((u_int64_t)cpdu.cbu_rootaddr[1]) << 32) |		    (((u_int64_t)cpdu.cbu_rootaddr[2]) << 24) |		    (((u_int64_t)cpdu.cbu_rootaddr[3]) << 16) |		    (((u_int64_t)cpdu.cbu_rootaddr[4]) << 8) |		    (((u_int64_t)cpdu.cbu_rootaddr[5]) << 0);		cu.cu_bridge_id =		    (((u_int64_t)ntohs(cpdu.cbu_bridgepri)) << 48) |		    (((u_int64_t)cpdu.cbu_bridgeaddr[0]) << 40) |		    (((u_int64_t)cpdu.cbu_bridgeaddr[1]) << 32) |		    (((u_int64_t)cpdu.cbu_bridgeaddr[2]) << 24) |		    (((u_int64_t)cpdu.cbu_bridgeaddr[3]) << 16) |		    (((u_int64_t)cpdu.cbu_bridgeaddr[4]) << 8) |		    (((u_int64_t)cpdu.cbu_bridgeaddr[5]) << 0);		cu.cu_root_path_cost = ntohl(cpdu.cbu_rootpathcost);		cu.cu_message_age = ntohs(cpdu.cbu_messageage);		cu.cu_max_age = ntohs(cpdu.cbu_maxage);		cu.cu_hello_time = ntohs(cpdu.cbu_hellotime);		cu.cu_forward_delay = ntohs(cpdu.cbu_forwarddelay);		cu.cu_port_id = ntohs(cpdu.cbu_portid);		cu.cu_message_type = cpdu.cbu_bpdutype;		cu.cu_topology_change_acknowledgment =		    (cpdu.cbu_flags & BSTP_FLAG_TCA) ? 1 : 0;		cu.cu_topology_change =		    (cpdu.cbu_flags & BSTP_FLAG_TC) ? 1 : 0;		bstp_received_config_bpdu(sc, bif, &cu);		break;	default:		goto out;	}out:	if (m)		m_freem(m);	return (NULL);}voidbstp_received_config_bpdu(sc, bif, cu)	struct bridge_softc *sc;	struct bridge_iflist *bif;	struct bstp_config_unit *cu;{	int root;	root = bstp_root_bridge(sc);	if (bif->bif_state != BSTP_IFSTATE_DISABLED) {		if (bstp_supersedes_port_info(sc, bif, cu)) {                        STPLOG (("   Rx CFG on <%s> superseds port info; RE-Evaluating...\n", bif->ifp->if_xname));			bstp_record_config_information(sc, bif, cu);			bstp_configuration_update(sc);			bstp_port_state_selection(sc);			if ((!bstp_root_bridge(sc)) && root) {				bstp_timer_stop(&sc->sc_hello_timer);				if (sc->sc_topology_change_detected) {					bstp_timer_stop(&sc->sc_topology_change_timer);					bstp_transmit_tcn(sc);					bstp_timer_start(&sc->sc_tcn_timer, 0);				}			}			if (bif == sc->sc_root_port) {				bstp_record_config_timeout_values(sc, cu);				bstp_config_bpdu_generation(sc);				if (cu->cu_topology_change_acknowledgment) {					bstp_topology_change_acknowledged(sc);                                }			}		} else if (bstp_designated_port(sc, bif)) {                        STPLOG (("   Port <%s> supersedes Rx CFG info\n", bif->ifp->if_xname));			bstp_transmit_config(sc, bif);                }	}}voidbstp_received_tcn_bpdu(sc, bif, tcn)	struct bridge_softc *sc;	struct bridge_iflist *bif;	struct bstp_tcn_unit *tcn;{	if (bif->bif_state != BSTP_IFSTATE_DISABLED &&	    bstp_designated_port(sc, bif)) {		bstp_topology_change_detection(sc);		bstp_acknowledge_topology_change(sc, bif);	}}voidbstp_hello_timer_expiry(sc)	struct bridge_softc *sc;{	bstp_config_bpdu_generation(sc);	bstp_timer_start(&sc->sc_hello_timer, 0);}voidbstp_message_age_timer_expiry(sc, bif)	struct bridge_softc *sc;	struct bridge_iflist *bif;{	int root;	root = bstp_root_bridge(sc);	bstp_become_designated_port(sc, bif);	bstp_configuration_update(sc);	bstp_port_state_selection(sc);	if ((bstp_root_bridge(sc)) && (!root)) {		sc->sc_max_age = sc->sc_bridge_max_age;		sc->sc_hello_time = sc->sc_bridge_hello_time;		sc->sc_forward_delay = sc->sc_bridge_forward_delay;		bstp_topology_change_detection(sc);		bstp_timer_stop(&sc->sc_tcn_timer);		bstp_config_bpdu_generation(sc);		bstp_timer_start(&sc->sc_hello_timer, 0);	}}voidbstp_forward_delay_timer_expiry(sc, bif)	struct bridge_softc *sc;	struct bridge_iflist *bif;{	if (bif->bif_state == BSTP_IFSTATE_LISTENING) {		bstp_set_port_state(bif, BSTP_IFSTATE_LEARNING);		bstp_timer_start(&bif->bif_forward_delay_timer, 0);	} else if (bif->bif_state == BSTP_IFSTATE_LEARNING) {		bstp_set_port_state(bif, BSTP_IFSTATE_FORWARDING);		if (bstp_designated_for_some_port(sc) &&		    bif->bif_change_detection_enabled)			bstp_topology_change_detection(sc);	}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?