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/ifconfig/ifbridge.c | |
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/ifconfig/ifbridge.c')
-rw-r--r-- | sbin/ifconfig/ifbridge.c | 173 |
1 files changed, 145 insertions, 28 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), |