diff options
author | thompsa <thompsa@FreeBSD.org> | 2006-11-01 09:07:47 +0000 |
---|---|---|
committer | thompsa <thompsa@FreeBSD.org> | 2006-11-01 09:07:47 +0000 |
commit | 905c36ce8074bad2f741ebcef77cfdc91cd2f2d9 (patch) | |
tree | 16428f9402e25da25aee2aed4b8426fbdc3b197d /sbin | |
parent | 7f880f15f45632bc40511ee0d3775b38e5ae2628 (diff) | |
download | FreeBSD-src-905c36ce8074bad2f741ebcef77cfdc91cd2f2d9.zip FreeBSD-src-905c36ce8074bad2f741ebcef77cfdc91cd2f2d9.tar.gz |
Bring in support for the Rapid Spanning Tree Protocol (802.1w).
RSTP provides faster spanning tree convergence, the protocol will exchange
information with neighboring switches to quickly transition to forwarding
without creating loops. The code will default to RSTP mode but will downgrade
any port connected to a legacy STP network so is fully backward compatible.
Reviewed by: syrinx
Tested by: syrinx
Diffstat (limited to 'sbin')
-rw-r--r-- | sbin/ifconfig/ifbridge.c | 173 | ||||
-rw-r--r-- | sbin/ifconfig/ifconfig.8 | 43 |
2 files changed, 181 insertions, 35 deletions
diff --git a/sbin/ifconfig/ifbridge.c b/sbin/ifconfig/ifbridge.c index c42213f..3f708b2 100644 --- a/sbin/ifconfig/ifbridge.c +++ b/sbin/ifconfig/ifbridge.c @@ -61,6 +61,27 @@ static const char rcsid[] = #include "ifconfig.h" +static const char *stpstates[] = { + "disabled", + "listening", + "learning", + "forwarding", + "blocking", + "discarding" +}; +static const char *stpproto[] = { + "stp", + "-", + "rstp" +}; +static const char *stproles[] = { + "disabled", + "root", + "designated", + "alternate", + "backup" +}; + static int get_val(const char *cp, u_long *valp) { @@ -113,13 +134,6 @@ do_bridgeflag(int sock, const char *ifs, int flag, int set) static void bridge_interfaces(int s, const char *prefix) { - static const char *stpstates[] = { - "disabled", - "listening", - "learning", - "forwarding", - "blocking", - }; struct ifbifconf bifc; struct ifbreq *req; char *inbuf = NULL, *ninbuf; @@ -159,12 +173,35 @@ bridge_interfaces(int s, const char *prefix) printf("port %u priority %u", req->ifbr_portno, req->ifbr_priority); printf(" path cost %u", req->ifbr_path_cost); + if (req->ifbr_proto < + sizeof(stpproto) / sizeof(stpproto[0])) + printf(" proto %s", stpproto[req->ifbr_proto]); + else + printf(" <unknown proto %d>", + req->ifbr_proto); + + printf("\n%s", pad); + if (req->ifbr_role < + sizeof(stproles) / sizeof(stproles[0])) + printf("role %s", stproles[req->ifbr_role]); + else + printf("<unknown role %d>", + req->ifbr_role); if (req->ifbr_state < sizeof(stpstates) / sizeof(stpstates[0])) - printf(" %s", stpstates[req->ifbr_state]); + printf(" state %s", stpstates[req->ifbr_state]); else printf(" <unknown state %d>", req->ifbr_state); + + if (req->ifbr_p2p) + printf(" p2p"); + else + printf(" shared"); + if (req->ifbr_edge) + printf(" edge"); + if (req->ifbr_autoedge) + printf(" autoedge"); printf("\n"); } } @@ -210,28 +247,22 @@ bridge_addresses(int s, const char *prefix) static void bridge_status(int s) { - struct ifbrparam param; + struct ifbropreq param; u_int16_t pri; - u_int8_t ht, fd, ma; - - if (do_cmd(s, BRDGGPRI, ¶m, sizeof(param), 0) < 0) - return; - pri = param.ifbrp_prio; - - if (do_cmd(s, BRDGGHT, ¶m, sizeof(param), 0) < 0) - return; - ht = param.ifbrp_hellotime; - - if (do_cmd(s, BRDGGFD, ¶m, sizeof(param), 0) < 0) - return; - fd = param.ifbrp_fwddelay; + u_int8_t ht, fd, ma, hc, pro; - if (do_cmd(s, BRDGGMA, ¶m, sizeof(param), 0) < 0) + if (do_cmd(s, BRDGPARAM, ¶m, sizeof(param), 0) < 0) return; - ma = param.ifbrp_maxage; + pri = param.ifbop_priority; + pro = param.ifbop_protocol; + ht = param.ifbop_hellotime; + fd = param.ifbop_fwddelay; + hc = param.ifbop_holdcount; + ma = param.ifbop_maxage; - printf("\tpriority %u hellotime %u fwddelay %u maxage %u\n", - pri, ht, fd, ma); + printf("\tpriority %u hellotime %u fwddelay %u" + " maxage %u hc %u proto %s\n", + pri, ht, fd, ma, hc, stpproto[pro]); bridge_interfaces(s, "\tmember: "); @@ -326,6 +357,54 @@ unsetbridge_stp(const char *val, int d, int s, const struct afswtch *afp) } static void +setbridge_edge(const char *val, int d, int s, const struct afswtch *afp) +{ + struct ifbreq req; + + memset(&req, 0, sizeof(req)); + strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname)); + req.ifbr_edge = 1; + if (do_cmd(s, BRDGSEDGE, &req, sizeof(req), 1) < 0) + err(1, "BRDGSEDGE %s", val); +} + +static void +unsetbridge_edge(const char *val, int d, int s, const struct afswtch *afp) +{ + struct ifbreq req; + + memset(&req, 0, sizeof(req)); + strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname)); + req.ifbr_edge = 0; + if (do_cmd(s, BRDGSEDGE, &req, sizeof(req), 1) < 0) + err(1, "BRDGSEDGE %s", val); +} + +static void +setbridge_autoedge(const char *val, int d, int s, const struct afswtch *afp) +{ + struct ifbreq req; + + memset(&req, 0, sizeof(req)); + strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname)); + req.ifbr_autoedge = 1; + if (do_cmd(s, BRDGSAEDGE, &req, sizeof(req), 1) < 0) + err(1, "BRDGSAEDGE %s", val); +} + +static void +unsetbridge_autoedge(const char *val, int d, int s, const struct afswtch *afp) +{ + struct ifbreq req; + + memset(&req, 0, sizeof(req)); + strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname)); + req.ifbr_autoedge = 0; + if (do_cmd(s, BRDGSAEDGE, &req, sizeof(req), 1) < 0) + err(1, "BRDGSAEDGE %s", val); +} + +static void setbridge_flush(const char *val, int d, int s, const struct afswtch *afp) { struct ifbreq req; @@ -469,6 +548,38 @@ setbridge_priority(const char *arg, int d, int s, const struct afswtch *afp) } static void +setbridge_protocol(const char *arg, int d, int s, const struct afswtch *afp) +{ + struct ifbrparam param; + + if (strcasecmp(arg, "stp") == 0) { + param.ifbrp_proto = 0; + } else if (strcasecmp(arg, "rstp") == 0) { + param.ifbrp_proto = 2; + } else { + errx(1, "unknown stp protocol"); + } + + if (do_cmd(s, BRDGSPROTO, ¶m, sizeof(param), 1) < 0) + err(1, "BRDGSPROTO %s", arg); +} + +static void +setbridge_holdcount(const char *arg, int d, int s, const struct afswtch *afp) +{ + struct ifbrparam param; + u_long val; + + if (get_val(arg, &val) < 0 || (val & ~0xff) != 0) + errx(1, "invalid value: %s", arg); + + param.ifbrp_txhc = val & 0xff; + + if (do_cmd(s, BRDGSTXHC, ¶m, sizeof(param), 1) < 0) + err(1, "BRDGSTXHC %s", arg); +} + +static void setbridge_ifpriority(const char *ifn, const char *pri, int s, const struct afswtch *afp) { @@ -496,11 +607,11 @@ setbridge_ifpathcost(const char *ifn, const char *cost, int s, memset(&req, 0, sizeof(req)); - if (get_val(cost, &val) < 0 || (val & ~0xff) != 0) + if (get_val(cost, &val) < 0) errx(1, "invalid value: %s", cost); strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname)); - req.ifbr_path_cost = val & 0xffff; + req.ifbr_path_cost = val; if (do_cmd(s, BRDGSIFCOST, &req, sizeof(req), 1) < 0) err(1, "BRDGSIFCOST %s", cost); @@ -532,6 +643,10 @@ static struct cmd bridge_cmds[] = { DEF_CMD_ARG("-span", unsetbridge_span), DEF_CMD_ARG("stp", setbridge_stp), DEF_CMD_ARG("-stp", unsetbridge_stp), + DEF_CMD_ARG("edge", setbridge_edge), + DEF_CMD_ARG("-edge", unsetbridge_edge), + DEF_CMD_ARG("autoedge", setbridge_autoedge), + DEF_CMD_ARG("-autoedge", unsetbridge_autoedge), DEF_CMD("flush", 0, setbridge_flush), DEF_CMD("flushall", 0, setbridge_flushall), DEF_CMD_ARG2("static", setbridge_static), @@ -542,6 +657,8 @@ static struct cmd bridge_cmds[] = { DEF_CMD_ARG("fwddelay", setbridge_fwddelay), DEF_CMD_ARG("maxage", setbridge_maxage), DEF_CMD_ARG("priority", setbridge_priority), + DEF_CMD_ARG("proto", setbridge_protocol), + DEF_CMD_ARG("holdcount", setbridge_holdcount), DEF_CMD_ARG2("ifpriority", setbridge_ifpriority), DEF_CMD_ARG2("ifpathcost", setbridge_ifpathcost), DEF_CMD_ARG("timeout", setbridge_timeout), diff --git a/sbin/ifconfig/ifconfig.8 b/sbin/ifconfig/ifconfig.8 index ec58dc1..0221909 100644 --- a/sbin/ifconfig/ifconfig.8 +++ b/sbin/ifconfig/ifconfig.8 @@ -1267,38 +1267,67 @@ Spanning Tree is used to detect and remove loops in a network topology. Disable Spanning Tree protocol on .Ar interface . This is the default for all interfaces added to a bridge. +.It Cm edge Ar interface +Set +.Ar interface +as an edge port. +An edge port connects directly to end stations cannot create bridging +loops in the network, this allows it to transition straight to forwarding. +.It Cm -edge Ar interface +Disable edge status on +.Ar interface . +.It Cm autoedge Ar interface +Allow +.Ar interface +to automatically detect edge status. +This is the default for all interfaces added to a bridge. +.It Cm -autoedge Ar interface +Disable automatic edge status on +.Ar interface . .It Cm maxage Ar seconds Set the time that a Spanning Tree protocol configuration is valid. The default is 20 seconds. -The minimum is 1 second and the maximum is 255 seconds. +The minimum is 6 seconds and the maximum is 40 seconds. .It Cm fwddelay Ar seconds Set the time that must pass before an interface begins forwarding packets when Spanning Tree is enabled. The default is 15 seconds. -The minimum is 1 second and the maximum is 255 seconds. +The minimum is 4 seconds and the maximum is 30 seconds. .It Cm hellotime Ar seconds Set the time between broadcasting of Spanning Tree protocol configuration messages. +The hello time may only be changed when operating in legacy stp mode. The default is 2 seconds. -The minimum is 1 second and the maximum is 255 seconds. +The minimum is 1 second and the maximum is 2 seconds. .It Cm priority Ar value Set the bridge priority for Spanning Tree. The default is 32768. -The minimum is 0 and the maximum is 65536. +The minimum is 0 and the maximum is 61440. +.It Cm protocol Ar value +Set the Spanning Tree protocol. +The default is rstp. +The available options are stp and rstp. +.It Cm holdcount Ar value +Set the transmit hold count for Spanning Tree. +This is the number of packets transmitted before being rate limited. +The default is 6. +The minimum is 1 and the maximum is 10. .It Cm ifpriority Ar interface Ar value Set the Spanning Tree priority of .Ar interface to .Ar value . The default is 128. -The minimum is 0 and the maximum is 255. +The minimum is 0 and the maximum is 240. .It Cm ifpathcost Ar interface Ar value Set the Spanning Tree path cost of .Ar interface to .Ar value . -The default is 55. -The minimum is 0 and the maximum is 65535. +The default is calculated from the link speed. +To change a previously selected path cost back to automatic, set the +cost to 0. +The minimum is 1 and the maximum is 200000000. .El .Pp The following parameters are specific to IP tunnel interfaces, |