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