PARAM_DISPUTED,
PARAM_BPDUGUARDPORT,
PARAM_BPDUGUARDERROR,
+ PARAM_NETWORKPORT,
+ PARAM_BA_INCONSISTENT,
} param_id_t;
typedef struct {
})
static const cmd_param_t cist_port_params[] = {
- { PARAM_ENABLED, "enabled" },
- { PARAM_ROLE, "role" },
- { PARAM_STATE, "state" },
- { PARAM_PORTID, "port-id" },
- { PARAM_EXTPORTCOST, "external-port-cost" },
- { PARAM_ADMINEXTCOST, "admin-external-cost" },
- { PARAM_INTPORTCOST, "internal-port-cost" },
- { PARAM_ADMININTCOST, "admin-internal-cost" },
- { PARAM_DSGNROOT, "designated-root" },
- { PARAM_DSGNEXTCOST, "dsgn-external-cost" },
- { PARAM_DSGNRROOT, "dsgn-regional-root" },
- { PARAM_DSGNINTCOST, "dsgn-internal-cost" },
- { PARAM_DSGNBR, "designated-bridge" },
- { PARAM_DSGNPORT, "designated-port" },
- { PARAM_ADMINEDGEPORT, "admin-edge-port" },
- { PARAM_AUTOEDGEPORT, "auto-edge-port" },
- { PARAM_OPEREDGEPORT, "oper-edge-port" },
- { PARAM_TOPCHNGACK, "topology-change-ack" },
- { PARAM_P2P, "point-to-point" },
- { PARAM_ADMINP2P, "admin-point-to-point" },
- { PARAM_RESTRROLE, "restricted-role" },
- { PARAM_RESTRTCN, "restricted-TCN" },
- { PARAM_PORTHELLOTIME, "port-hello-time" },
- { PARAM_DISPUTED, "disputed" },
- { PARAM_BPDUGUARDPORT, "bpdu-guard-port" },
- { PARAM_BPDUGUARDERROR,"bpdu-guard-error" },
+ { PARAM_ENABLED, "enabled" },
+ { PARAM_ROLE, "role" },
+ { PARAM_STATE, "state" },
+ { PARAM_PORTID, "port-id" },
+ { PARAM_EXTPORTCOST, "external-port-cost" },
+ { PARAM_ADMINEXTCOST, "admin-external-cost" },
+ { PARAM_INTPORTCOST, "internal-port-cost" },
+ { PARAM_ADMININTCOST, "admin-internal-cost" },
+ { PARAM_DSGNROOT, "designated-root" },
+ { PARAM_DSGNEXTCOST, "dsgn-external-cost" },
+ { PARAM_DSGNRROOT, "dsgn-regional-root" },
+ { PARAM_DSGNINTCOST, "dsgn-internal-cost" },
+ { PARAM_DSGNBR, "designated-bridge" },
+ { PARAM_DSGNPORT, "designated-port" },
+ { PARAM_ADMINEDGEPORT, "admin-edge-port" },
+ { PARAM_AUTOEDGEPORT, "auto-edge-port" },
+ { PARAM_OPEREDGEPORT, "oper-edge-port" },
+ { PARAM_TOPCHNGACK, "topology-change-ack" },
+ { PARAM_P2P, "point-to-point" },
+ { PARAM_ADMINP2P, "admin-point-to-point" },
+ { PARAM_RESTRROLE, "restricted-role" },
+ { PARAM_RESTRTCN, "restricted-TCN" },
+ { PARAM_PORTHELLOTIME, "port-hello-time" },
+ { PARAM_DISPUTED, "disputed" },
+ { PARAM_BPDUGUARDPORT, "bpdu-guard-port" },
+ { PARAM_BPDUGUARDERROR, "bpdu-guard-error" },
+ { PARAM_NETWORKPORT, "network-port" },
+ { PARAM_BA_INCONSISTENT,"ba-inconsistent" },
};
static int detail = 0;
BOOL_STR(s.bpdu_guard_port));
printf("bpdu guard error %s\n",
BOOL_STR(s.bpdu_guard_error));
+ printf(" network port %-23s ",
+ BOOL_STR(s.network_port));
+ printf("BA inconsistent %s\n",
+ BOOL_STR(s.ba_inconsistent));
}
else
{
case PARAM_BPDUGUARDERROR:
printf("%s\n", BOOL_STR(s.bpdu_guard_error));
break;
+ case PARAM_NETWORKPORT:
+ printf("%s\n", BOOL_STR(s.network_port));
+ break;
+ case PARAM_BA_INCONSISTENT:
+ printf("%s\n", BOOL_STR(s.ba_inconsistent));
+ break;
default:
return -2; /* -2 = unknown param */
}
return set_port_cfg(bpdu_guard_port, getyesno(argv[3], "yes", "no"));
}
+static int cmd_setportnetwork(int argc, char *const *argv)
+{
+ int br_index = get_index(argv[1], "bridge");
+ if (0 > br_index)
+ return br_index;
+ int port_index = get_index(argv[2], "port");
+ if (0 > port_index)
+ return port_index;
+ return set_port_cfg(network_port, getyesno(argv[3], "yes", "no"));
+}
+
+static int cmd_setportdonttxmt(int argc, char *const *argv)
+{
+ int br_index = get_index(argv[1], "bridge");
+ if (0 > br_index)
+ return br_index;
+ int port_index = get_index(argv[2], "port");
+ if (0 > port_index)
+ return port_index;
+ return set_port_cfg(dont_txmt, getyesno(argv[3], "yes", "no"));
+}
+
static int cmd_settreeportprio(int argc, char *const *argv)
{
int br_index = get_index(argv[1], "bridge");
{4, 0, "settreeportcost", cmd_settreeportcost,
"<bridge> <port> <mstid> <cost>",
"Set port internal path cost for the given MSTI (0 = auto)"},
+ {3, 0, "setportnetwork", cmd_setportnetwork,
+ "<bridge> <port> {yes|no}", "Set port network state"},
+ {3, 0, "setportdonttxmt", cmd_setportdonttxmt,
+ "<bridge> <port> {yes|no}", "Disable/Enable sending BPDU"},
/* Other */
{1, 0, "debuglevel", cmd_debuglevel, "<level>", "Level of verbosity"},
for(i = 0; i < COUNT_OF(commands); ++i)
{
- printf("-%s:\n %-16s %s\n", commands[i].help, commands[i].name,
+ if(strcmp("setportdonttxmt", commands[i].name))
+ printf("-%s:\n %-16s %s\n", commands[i].help, commands[i].name,
commands[i].format);
}
}
static void prt_state_machines_begin(port_t *prt);
static void tree_state_machines_begin(tree_t *tree);
static void br_state_machines_run(bridge_t *br);
+static void updtbrAssuRcvdInfoWhile(port_t *prt);
#define FOREACH_PORT_IN_BRIDGE(port, bridge) \
list_for_each_entry((port), &(bridge)->ports, br_list)
/* 17.20.11 of 802.1D */
#define rstpVersion(br) ((br)->ForceProtocolVersion >= protoRSTP)
-
+/* Bridge assurance is operational only when NetworkPort type is configured
+ * and the operation status is pointToPoint and version is RSTP/MSTP
+ */
+#define assurancePort(prt) ((prt)->NetworkPort && (prt)->operPointToPointMAC \
+ && (prt)->sendRSTP)
/*
* Recalculate configuration digest. (13.7)
*/
prt->BpduGuardPort = false;
prt->BpduGuardError = false;
assign(prt->rapidAgeingWhile, 0u);
+ assign(prt->brAssuRcvdInfoWhile, 0u);
+ prt->NetworkPort = false;
+ prt->BaInconsistent = false;
+ prt->dontTxmtBpdu = false;
prt->deleted = false;
/* The following are initialized in BEGIN state:
{
prt->portEnabled = true;
prt->BpduGuardError = false;
+ prt->BaInconsistent = false;
changed = true;
+ /* When port is enabled, initialize bridge assurance timer,
+ * so that enough time is given before port is put in
+ * inconsistent state.
+ */
+ updtbrAssuRcvdInfoWhile(prt);
}
}
else
assign(prt->rcvdBpduData, *bpdu);
prt->rcvdBpdu = true;
+ /* Reset bridge assurance on receipt of valid BPDU */
+ if(prt->BaInconsistent)
+ {
+ prt->BaInconsistent = false;
+ INFO_PRTNAME(br, prt, "Clear Bridge assurance inconsistency");
+ }
+ updtbrAssuRcvdInfoWhile(prt);
+
br_state_machines_run(br);
}
assign(status->internal_port_path_cost, cist->InternalPortPathCost);
status->bpdu_guard_port = prt->BpduGuardPort;
status->bpdu_guard_error = prt->BpduGuardError;
+ status->network_port = prt->NetworkPort;
+ status->ba_inconsistent = prt->BaInconsistent;
}
/* 12.8.2.2 Read MSTI Port Parameters */
}
}
+ if(cfg->set_network_port)
+ {
+ if(prt->NetworkPort != cfg->network_port)
+ {
+ prt->NetworkPort = cfg->network_port;
+ INFO_PRTNAME(br, prt, "NetworkPort new=%d", prt->NetworkPort);
+ /* When Network port config is removed and bridge assurance
+ * inconsistency is set, clear the inconsistency.
+ */
+ if(!prt->NetworkPort && prt->BaInconsistent)
+ {
+ prt->BaInconsistent = false;
+ INFO_PRTNAME(br, prt, "Clear Bridge assurance inconsistency");
+ }
+ changed = true;
+ }
+ }
+
+ if(cfg->set_dont_txmt)
+ {
+ if(prt->dontTxmtBpdu != cfg->dont_txmt)
+ {
+ prt->dontTxmtBpdu = cfg->dont_txmt;
+ INFO_PRTNAME(br, prt, "donttxmt new=%d", prt->dontTxmtBpdu);
+ }
+ }
+
if(changed && prt->portEnabled)
br_state_machines_run(prt->bridge);
bpdu_t b;
per_tree_port_t *cist = GET_CIST_PTP_FROM_PORT(prt);
- if(prt->deleted)
+ if(prt->deleted || prt->dontTxmtBpdu)
return;
b.protocolIdentifier = 0;
per_tree_port_t *ptp;
msti_configuration_message_t *msti_msg;
- if(prt->deleted)
+ if(prt->deleted || prt->dontTxmtBpdu)
return;
b.protocolIdentifier = 0;
{
bpdu_t b;
- if(prt->deleted)
+ if(prt->deleted || prt->dontTxmtBpdu)
return;
b.protocolIdentifier = 0;
ptp->rcvdInfoWhile = 0;
}
+static void updtbrAssuRcvdInfoWhile(port_t *prt)
+{
+ per_tree_port_t *cist = GET_CIST_PTP_FROM_PORT(prt);
+ unsigned int Hello_Time = cist->portTimes.Hello_Time;
+
+ prt->brAssuRcvdInfoWhile = 3 * cist->portTimes.Hello_Time;
+}
+
/* 13.26.24 updtRolesDisabledTree */
static void updtRolesDisabledTree(tree_t *tree)
{
--(prt->edgeDelayWhile);
if(prt->txCount)
--(prt->txCount);
+ if(prt->brAssuRcvdInfoWhile)
+ --(prt->brAssuRcvdInfoWhile);
FOREACH_PTP_IN_PORT(ptp, prt)
{
return false;
if(prt->sendRSTP)
{ /* implement MSTP */
- if(prt->newInfo || (prt->newInfoMsti && !mstiMasterPort))
+ if(prt->newInfo || (prt->newInfoMsti && !mstiMasterPort)
+ || assurancePort(prt)
+ )
{
if(dry_run) /* state change */
return true;
PRTSM_to_DESIGNATED_PROPOSE(ptp);
return false;
}
+ /* Dont transition to learn/forward when BA inconsistent */
if(((0 == ptp->fdWhile) || ptp->agreed || prt->operEdge)
&& ((0 == ptp->rrWhile) || !ptp->reRoot) && !ptp->sync
+ && !ptp->port->BaInconsistent
)
{
if(!ptp->learn)
return false;
}
}
+ /* Transition to discarding when BA inconsistent */
if(((ptp->sync && !ptp->synced)
|| (ptp->reRoot && (0 != ptp->rrWhile))
|| ptp->disputed
+ || ptp->port->BaInconsistent
)
&& !prt->operEdge && (ptp->learn || ptp->forward)
)
per_tree_port_t *ptp;
tree_t *tree;
+ /* Check if bridge assurance timer expires */
+ FOREACH_PORT_IN_BRIDGE(prt, br)
+ {
+ if(prt->portEnabled && assurancePort(prt)
+ && (0 == prt->brAssuRcvdInfoWhile) && !prt->BaInconsistent
+ )
+ {
+ if(dry_run) /* state change */
+ return true;
+ prt->BaInconsistent = true;
+ ERROR_PRTNAME(prt->bridge, prt, "Bridge assurance inconsistent");
+ }
+ }
+
/* 13.28 Port Receive state machine */
FOREACH_PORT_IN_BRIDGE(prt, br)
{