📄 bridgestp.c
字号:
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);
}
int
bstp_root_bridge(sc)
struct bridge_softc *sc;
{
return (sc->sc_designated_root == sc->sc_bridge_id);
}
int
bstp_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);
}
void
bstp_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);
}
void
bstp_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;
}
void
bstp_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));
}
}
}
int
bstp_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));
}
void
bstp_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;
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);
}
void
bstp_configuration_update(sc)
struct bridge_softc *sc;
{
STP_OPERATION_LOG ((" %s \n", __FUNCTION__));
bstp_root_selection(sc);
bstp_designated_port_selection(sc);
}
void
bstp_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));
}
}
void
bstp_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);
}
}
void
bstp_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));
}
void
bstp_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);
}
}
}
void
bstp_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);
}
}
void
bstp_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) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -