From: dv1tas Date: Thu, 6 Jun 2013 16:04:39 +0000 (+0000) Subject: Add support for the BPDU Guard functionality X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0312276473f910a9ef0f5fb86f7836a9045aaed0;p=people%2Fms%2Fmstpd.git Add support for the BPDU Guard functionality Signed-off-by: Satish Ashok Signed-off-by: Vitalii Demianets git-svn-id: svn://svn.code.sf.net/p/mstpd/code/trunk@42 fbe50366-0c72-4402-a84b-5d246361dba7 --- diff --git a/bridge_track.c b/bridge_track.c index 80a27b9..51bc04c 100644 --- a/bridge_track.c +++ b/bridge_track.c @@ -581,6 +581,12 @@ void MSTP_OUT_tx_bpdu(port_t * ifc, bpdu_t * bpdu, int size) packet_send(ifc->sysdeps.if_index, iov, 2, sizeof(h) + size); } +void MSTP_OUT_shutdown_port(port_t *prt) +{ + if(0 > if_shutdown(prt->sysdeps.name)) + ERROR_PRTNAME(prt->bridge, prt, "Couldn't shutdown port"); +} + /* User interface commands */ #define CTL_CHECK_BRIDGE \ diff --git a/ctl_main.c b/ctl_main.c index de07853..6aa79be 100644 --- a/ctl_main.c +++ b/ctl_main.c @@ -132,6 +132,8 @@ typedef enum { PARAM_RESTRTCN, PARAM_PORTHELLOTIME, PARAM_DISPUTED, + PARAM_BPDUGUARDPORT, + PARAM_BPDUGUARDERROR, } param_id_t; typedef struct { @@ -455,30 +457,32 @@ static int cmd_showtree(int argc, char *const *argv) }) 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_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" }, }; static int detail = 0; @@ -546,6 +550,10 @@ static int do_showport(int br_index, const char *bridge_name, BOOL_STR(s.restricted_tcn)); printf(" port hello time %-23hhu ", s.port_hello_time); printf("disputed %s\n", BOOL_STR(s.disputed)); + printf(" bpdu guard port %-23s ", + BOOL_STR(s.bpdu_guard_port)); + printf("bpdu guard error %s\n", + BOOL_STR(s.bpdu_guard_error)); } else { @@ -634,6 +642,12 @@ static int do_showport(int br_index, const char *bridge_name, case PARAM_DISPUTED: printf("%s\n", BOOL_STR(s.disputed)); break; + case PARAM_BPDUGUARDPORT: + printf("%s\n", BOOL_STR(s.bpdu_guard_port)); + break; + case PARAM_BPDUGUARDERROR: + printf("%s\n", BOOL_STR(s.bpdu_guard_error)); + break; default: return -2; /* -2 = unknown param */ } @@ -1078,6 +1092,17 @@ static int cmd_setportrestrtcn(int argc, char *const *argv) return set_port_cfg(restricted_tcn, getyesno(argv[3], "yes", "no")); } +static int cmd_setportbpduguard(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(bpdu_guard_port, getyesno(argv[3], "yes", "no")); +} + static int cmd_settreeportprio(int argc, char *const *argv) { int br_index = get_index(argv[1], "bridge"); @@ -1496,6 +1521,8 @@ static const struct command commands[] = "Restrict port ability to propagate received TCNs"}, {2, 0, "portmcheck", cmd_portmcheck, " ", "Try to get back from STP to rapid (RSTP/MSTP) mode"}, + {3, 0, "setbpduguard", cmd_setportbpduguard, + " {yes|no}", "Set bpdu guard state"}, /* Set tree port */ {4, 0, "settreeportprio", cmd_settreeportprio, " ", diff --git a/mstp.c b/mstp.c index c5bd3ca..012100f 100644 --- a/mstp.c +++ b/mstp.c @@ -243,6 +243,8 @@ bool MSTP_IN_port_create_and_add_tail(port_t *prt, __u16 portno) assign(prt->ExternalPortPathCost, MAX_PATH_COST); /* 13.37.1 */ prt->AdminEdgePort = false; /* 13.25 */ prt->AutoEdge = true; /* 13.25 */ + prt->BpduGuardPort = false; + prt->BpduGuardError = false; assign(prt->rapidAgeingWhile, 0u); prt->deleted = false; @@ -412,6 +414,7 @@ void MSTP_IN_set_port_enable(port_t *prt, bool up, int speed, int duplex) if(!prt->portEnabled) { prt->portEnabled = true; + prt->BpduGuardError = false; changed = true; } } @@ -480,6 +483,15 @@ void MSTP_IN_rx_bpdu(port_t *prt, bpdu_t *bpdu, int size) int mstis_size; bridge_t *br = prt->bridge; + if(prt->BpduGuardPort) + { + prt->BpduGuardError = true; + ERROR_PRTNAME(br, prt, + "Received BPDU on BPDU Guarded Port - Port Down"); + MSTP_OUT_shutdown_port(prt); + return; + } + if(!br->bridgeEnabled) { INFO_PRTNAME(br, prt, "Received BPDU while bridge is disabled"); @@ -874,6 +886,8 @@ void MSTP_IN_get_cist_port_status(port_t *prt, CIST_PortStatus *status) assign(status->admin_internal_port_path_cost, cist->AdminInternalPortPathCost); assign(status->internal_port_path_cost, cist->InternalPortPathCost); + status->bpdu_guard_port = prt->BpduGuardPort; + status->bpdu_guard_error = prt->BpduGuardError; } /* 12.8.2.2 Read MSTI Port Parameters */ @@ -903,6 +917,7 @@ int MSTP_IN_set_cist_port_config(port_t *prt, CIST_PortConfig *cfg) __u32 new_ExternalPathCost; bool new_p2p; per_tree_port_t *cist; + bridge_t *br = prt->bridge; /* Firstly, validation */ if(cfg->set_admin_p2p) @@ -998,6 +1013,15 @@ int MSTP_IN_set_cist_port_config(port_t *prt, CIST_PortConfig *cfg) } } + if(cfg->set_bpdu_guard_port) + { + if(prt->BpduGuardPort != cfg->bpdu_guard_port) + { + prt->BpduGuardPort = cfg->bpdu_guard_port; + INFO_PRTNAME(br, prt,"BpduGuardPort new=%d", prt->BpduGuardPort); + } + } + if(changed && prt->portEnabled) br_state_machines_run(prt->bridge); diff --git a/mstp.h b/mstp.h index 36de4bc..4eec4aa 100644 --- a/mstp.h +++ b/mstp.h @@ -472,6 +472,8 @@ typedef struct admin_p2p_t AdminP2P; /* 6.4.3 */ bool AdminEdgePort; /* 13.22.k */ bool AutoEdge; /* 13.22.m */ + bool BpduGuardPort; + bool BpduGuardError; unsigned int rapidAgeingWhile; @@ -573,6 +575,7 @@ void MSTP_OUT_set_state(per_tree_port_t *ptp, int new_state); void MSTP_OUT_flush_all_fids(per_tree_port_t *ptp); void MSTP_OUT_set_ageing_time(port_t *prt, unsigned int ageingTime); void MSTP_OUT_tx_bpdu(port_t *prt, bpdu_t *bpdu, int size); +void MSTP_OUT_shutdown_port(port_t *prt); /* Structures for communicating with user */ /* 12.8.1.1 Read CIST Bridge Protocol Parameters */ @@ -681,6 +684,8 @@ typedef struct __u32 designated_internal_cost; /* from portPriority */ __u32 admin_internal_port_path_cost; /* not in standard. 0 = auto */ __u32 internal_port_path_cost; /* not in standard */ + bool bpdu_guard_port; + bool bpdu_guard_error; } CIST_PortStatus; void MSTP_IN_get_cist_port_status(port_t *prt, CIST_PortStatus *status); @@ -732,6 +737,9 @@ typedef struct bool restricted_tcn; bool set_restricted_tcn; + + bool bpdu_guard_port; + bool set_bpdu_guard_port; } CIST_PortConfig; int MSTP_IN_set_cist_port_config(port_t *prt, CIST_PortConfig *cfg); diff --git a/netif_utils.c b/netif_utils.c index 159be86..29d4e87 100644 --- a/netif_utils.c +++ b/netif_utils.c @@ -78,6 +78,26 @@ int get_flags(char *ifname) return ifr.ifr_flags; } +int if_shutdown(char *ifname) +{ + struct ifreq ifr; + + memset(&ifr, 0, sizeof(ifr)); + /* TODO: Let's hope -1 is not a valid flag combination */ + if(-1 == (ifr.ifr_flags = get_flags(ifname))) + { + return -1; + } + ifr.ifr_flags &= ~IFF_UP; + strncpy(ifr.ifr_name, ifname, IFNAMSIZ); + if(0 > ioctl(netsock, SIOCSIFFLAGS, &ifr)) + { + ERROR("%s: set if_down flag failed: %m", ifname); + return -1; + } + return 0; +} + int ethtool_get_speed_duplex(char *ifname, int *speed, int *duplex) { struct ifreq ifr; diff --git a/netif_utils.h b/netif_utils.h index 915af84..0c54d26 100644 --- a/netif_utils.h +++ b/netif_utils.h @@ -32,6 +32,7 @@ int netsock_init(void); int get_hwaddr(char *ifname, unsigned char *hwaddr); int get_flags(char *ifname); +int if_shutdown(char *ifname); int ethtool_get_speed_duplex(char *ifname, int *speed, int *duplex);