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

📄 bridgestp.c

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

void
bstp_set_port_state(bif, state)
	struct bridge_iflist *bif;
	u_int8_t state;
{
	bif->bif_state = state;
}

void
bstp_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;
}

void
bstp_topology_change_acknowledged(sc)
	struct bridge_softc *sc;
{
	sc->sc_topology_change_detected = 0;
	bstp_timer_stop(&sc->sc_tcn_timer);
}

void
bstp_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);
}

void
bstp_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);
                }
	}
}

void
bstp_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);
	}
}

void
bstp_hello_timer_expiry(sc)
	struct bridge_softc *sc;
{
	bstp_config_bpdu_generation(sc);
	bstp_timer_start(&sc->sc_hello_timer, 0);
}

void
bstp_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);
	}
}

void
bstp_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);
	}
}

int
bstp_designated_for_some_port(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->bif_designated_bridge == sc->sc_bridge_id)
			return (1);
	}
	return (0);
}

void
bstp_tcn_timer_expiry(sc)
	struct bridge_softc *sc;
{
        STPLOG (("  STP: tcn timer expired \n"));
	bstp_transmit_tcn(sc);
	bstp_timer_start(&sc->sc_tcn_timer, 0);
}

void
bstp_topology_change_timer_expiry(sc)
	struct bridge_softc *sc;
{
        STPLOG (("  STP: topology change timer expired \n"));
	sc->sc_topology_change_detected = 0;
	sc->sc_topology_change = 0;
}

void
bstp_hold_timer_expiry(sc, bif)
	struct bridge_softc *sc;
	struct bridge_iflist *bif;
{
	if (bif->bif_config_pending)
		bstp_transmit_config(sc, bif);
}

void
bstp_initialization(sc)
	struct bridge_softc *sc;
{
	struct bridge_iflist *bif, *mif;
	struct arpcom *ac, *mac;

	mif = NULL; mac = NULL;
        /* Browse through the ethernet address of each interface and pick the
         * one which has lowest value
         */
	LIST_FOREACH(bif, &sc->sc_iflist, next) {
		if (!(bif->bif_flags & IFBIF_STP)) {
			continue;
                }
		if (bif->ifp->if_type != IFT_ETHER) {
			continue;
                }
		bif->bif_port_id = (bif->bif_priority << 8) |
		    (bif->ifp->if_index & 0xff);

		if (mif == NULL) {
			mif = bif;
			mac = (struct arpcom *)bif->ifp;
			continue;
		}
		ac = (struct arpcom *)bif->ifp;
		if (memcmp(ac->ac_enaddr, mac->ac_enaddr, ETHER_ADDR_LEN) < 0) {
			mif = bif;
			mac = (struct arpcom *)bif->ifp;
			continue;
		}
	}

	if (mif == NULL) {
		bstp_stop(sc);
		return;
	}

        /* Configure bridge-id as specified in standards
         */
	sc->sc_bridge_id =
	    (((u_int64_t)sc->sc_bridge_priority) << 48) |
	    (((u_int64_t)mac->ac_enaddr[0]) << 40) |
	    (((u_int64_t)mac->ac_enaddr[1]) << 32) |
	    (mac->ac_enaddr[2] << 24) | (mac->ac_enaddr[3] << 16) |
	    (mac->ac_enaddr[4] << 8) | (mac->ac_enaddr[5]);

        /* Configure self as root bridge
         */
	sc->sc_designated_root = sc->sc_bridge_id;
	sc->sc_root_path_cost = 0;
	sc->sc_root_port = NULL;

	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;
	sc->sc_topology_change_detected = 0;
	sc->sc_topology_change = 0;
	bstp_timer_stop(&sc->sc_tcn_timer);
	bstp_timer_stop(&sc->sc_topology_change_timer);

        /* If there is a timeout already set on this, cancel it and restart.
         * The intent is to avoid setting duplicate timeouts. If the timeout
         * is already set, untimeout would cancel it.
         */
#ifdef __ECOS
        if (!bstp_init_done) {
          untimeout(bstp_tick, sc);
          timeout(bstp_tick, sc, hz);
          bstp_init_done = 1;
        }
#else
	if (!timeout_initialized(&sc->sc_bstptimeout))
		timeout_set(&sc->sc_bstptimeout, bstp_tick, sc);
	if (!timeout_pending(&sc->sc_bstptimeout))
		timeout_add(&sc->sc_bstptimeout, hz);
#endif // __ECOS

	LIST_FOREACH(bif, &sc->sc_iflist, next) {
		if (bif->bif_flags & IFBIF_STP) {
                        STPLOG (("%s:%s ..(en). \n", __FUNCTION__, bif->ifp->if_xname));
			bstp_enable_port(sc, bif);
                }

⌨️ 快捷键说明

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