]> git.ipfire.org Git - people/ms/mstpd.git/commitdiff
Add support for the BPDU Guard functionality
authordv1tas <dv1tas@fbe50366-0c72-4402-a84b-5d246361dba7>
Thu, 6 Jun 2013 16:04:39 +0000 (16:04 +0000)
committerdv1tas <dv1tas@fbe50366-0c72-4402-a84b-5d246361dba7>
Thu, 6 Jun 2013 16:04:39 +0000 (16:04 +0000)
Signed-off-by: Satish Ashok <sashok@cumulusnetworks.com>
Signed-off-by: Vitalii Demianets <dvitasgs@gmail.com>
git-svn-id: svn://svn.code.sf.net/p/mstpd/code/trunk@42 fbe50366-0c72-4402-a84b-5d246361dba7

bridge_track.c
ctl_main.c
mstp.c
mstp.h
netif_utils.c
netif_utils.h

index 80a27b937ccb0aa6caecbe47eaff5b2988fb72b2..51bc04ccefc75f6619c2bda82d9f3229d3ac7a4e 100644 (file)
@@ -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                                       \
index de07853798a802540a9c886382eec1ae4c7a86fe..6aa79be5a91db1262c9ded6579a1fe82922cbc54 100644 (file)
@@ -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,
      "<bridge> <port>", "Try to get back from STP to rapid (RSTP/MSTP) mode"},
+    {3, 0, "setbpduguard", cmd_setportbpduguard,
+     "<bridge> <port> {yes|no}", "Set bpdu guard state"},
     /* Set tree port */
     {4, 0, "settreeportprio", cmd_settreeportprio,
      "<bridge> <port> <mstid> <priority>",
diff --git a/mstp.c b/mstp.c
index c5bd3caa8b842d4df90dbd9c6fb67e9fcd3b3c2c..012100f164cb32c956922d66d24dc1d87aa64afc 100644 (file)
--- 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 36de4bc7d6ff50e3b28b0b30909e33525a07b305..4eec4aa832a3dd124e075e9c3a08ba0fd7dcbac8 100644 (file)
--- 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);
index 159be86df41fc51569964d85d0d08729729a28ad..29d4e87e59f29787d5e4f65063aea36ba58408e0 100644 (file)
@@ -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;
index 915af84136cbd300eafd224a8adbc03e00709f42..0c54d26b7b586d72b0cc0a60ae0deb55bf0ffc1e 100644 (file)
@@ -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);