Sync with the OpenBSD port of RSTP

- use flags rather than sperate ioctls for edge, p2p
 - implement p2p and autop2p flags
 - define large pathcost constant as ULL
 - show bridgeid and rootid in ifconfig

Obtained from:	Reyk Floeter <reyk@openbsd.org>
This commit is contained in:
Andrew Thompson 2006-11-27 00:35:40 +00:00
parent 30ce3a1229
commit 6c32e05ca3
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=164653
5 changed files with 130 additions and 104 deletions

View File

@ -61,6 +61,16 @@ static const char rcsid[] =
#include "ifconfig.h"
#define PV2ID(pv, epri, eaddr) do { \
epri = pv >> 48; \
eaddr[0] = pv >> 40; \
eaddr[1] = pv >> 32; \
eaddr[2] = pv >> 24; \
eaddr[3] = pv >> 16; \
eaddr[4] = pv >> 8; \
eaddr[5] = pv >> 0; \
} while (0)
static const char *stpstates[] = {
"disabled",
"listening",
@ -193,15 +203,6 @@ bridge_interfaces(int s, const char *prefix)
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");
}
}
@ -250,6 +251,8 @@ bridge_status(int s)
struct ifbropreq param;
u_int16_t pri;
u_int8_t ht, fd, ma, hc, pro;
u_int8_t lladdr[ETHER_ADDR_LEN];
u_int16_t bprio;
if (do_cmd(s, BRDGPARAM, &param, sizeof(param), 0) < 0)
return;
@ -260,9 +263,16 @@ bridge_status(int s)
hc = param.ifbop_holdcount;
ma = param.ifbop_maxage;
printf("\tpriority %u hellotime %u fwddelay %u"
" maxage %u hc %u proto %s\n",
pri, ht, fd, ma, hc, stpproto[pro]);
PV2ID(param.ifbop_bridgeid, bprio, lladdr);
printf("\tid %s priority %u hellotime %u fwddelay %u\n",
ether_ntoa((struct ether_addr *)lladdr), pri, ht, fd);
printf("\tmaxage %u holdcnt %u proto %s\n",
ma, hc, stpproto[pro]);
PV2ID(param.ifbop_designated_root, bprio, lladdr);
printf("\troot id %s priority %d ifcost %u port %u\n",
ether_ntoa((struct ether_addr *)lladdr), bprio,
param.ifbop_root_path_cost, param.ifbop_root_port & 0xfff);
bridge_interfaces(s, "\tmember: ");
@ -373,49 +383,49 @@ 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);
do_bridgeflag(s, val, IFBIF_BSTP_EDGE, 1);
}
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);
do_bridgeflag(s, val, IFBIF_BSTP_EDGE, 0);
}
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);
do_bridgeflag(s, val, IFBIF_BSTP_AUTOEDGE, 1);
}
static void
unsetbridge_autoedge(const char *val, int d, int s, const struct afswtch *afp)
{
struct ifbreq req;
do_bridgeflag(s, val, IFBIF_BSTP_AUTOEDGE, 0);
}
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_p2p(const char *val, int d, int s, const struct afswtch *afp)
{
do_bridgeflag(s, val, IFBIF_BSTP_P2P, 1);
}
static void
unsetbridge_p2p(const char *val, int d, int s, const struct afswtch *afp)
{
do_bridgeflag(s, val, IFBIF_BSTP_P2P, 0);
}
static void
setbridge_autop2p(const char *val, int d, int s, const struct afswtch *afp)
{
do_bridgeflag(s, val, IFBIF_BSTP_AUTOP2P, 1);
}
static void
unsetbridge_autop2p(const char *val, int d, int s, const struct afswtch *afp)
{
do_bridgeflag(s, val, IFBIF_BSTP_AUTOP2P, 0);
}
static void
@ -663,6 +673,10 @@ static struct cmd bridge_cmds[] = {
DEF_CMD_ARG("-edge", unsetbridge_edge),
DEF_CMD_ARG("autoedge", setbridge_autoedge),
DEF_CMD_ARG("-autoedge", unsetbridge_autoedge),
DEF_CMD_ARG("p2p", setbridge_p2p),
DEF_CMD_ARG("-p2p", unsetbridge_p2p),
DEF_CMD_ARG("autop2p", setbridge_autop2p),
DEF_CMD_ARG("-autop2p", unsetbridge_autop2p),
DEF_CMD("flush", 0, setbridge_flush),
DEF_CMD("flushall", 0, setbridge_flushall),
DEF_CMD_ARG2("static", setbridge_static),

View File

@ -1658,6 +1658,33 @@ bstp_set_autoedge(struct bstp_port *bp, int set)
BSTP_UNLOCK(bs);
return (0);
}
int
bstp_set_p2p(struct bstp_port *bp, int set)
{
struct bstp_state *bs = bp->bp_bs;
BSTP_LOCK(bs);
bp->bp_p2p_link = set;
BSTP_UNLOCK(bs);
return (0);
}
int
bstp_set_autop2p(struct bstp_port *bp, int set)
{
struct bstp_state *bs = bp->bp_bs;
BSTP_LOCK(bs);
if (set) {
bp->bp_flags |= BSTP_PORT_AUTOP2P;
bstp_ifupdstatus(bs, bp);
} else
bp->bp_flags &= ~BSTP_PORT_AUTOP2P;
BSTP_UNLOCK(bs);
return (0);
}
/*
* Calculate the path cost according to the link speed.
*/
@ -1675,7 +1702,7 @@ bstp_calc_path_cost(struct bstp_port *bp)
return (BSTP_DEFAULT_PATH_COST);
/* formula from section 17.14, IEEE Std 802.1D-2004 */
path_cost = 20000000000 / (ifp->if_baudrate / 1000);
path_cost = 20000000000ULL / (ifp->if_baudrate / 1000);
if (path_cost > BSTP_MAX_PATH_COST)
path_cost = BSTP_MAX_PATH_COST;
@ -1774,7 +1801,10 @@ bstp_ifupdstatus(struct bstp_state *bs, struct bstp_port *bp)
if ((error == 0) && (ifp->if_flags & IFF_UP)) {
if (ifmr.ifm_status & IFM_ACTIVE) {
/* A full-duplex link is assumed to be point to point */
bp->bp_p2p_link = ifmr.ifm_active & IFM_FDX ? 1 : 0;
if (bp->bp_flags & BSTP_PORT_AUTOP2P) {
bp->bp_p2p_link =
ifmr.ifm_active & IFM_FDX ? 1 : 0;
}
if (bp->bp_role == BSTP_ROLE_DISABLED)
bstp_enable_port(bs, bp);
@ -2126,7 +2156,7 @@ bstp_create(struct bstp_state *bs, struct bstp_port *bp, struct ifnet *ifp)
/* Init state */
bp->bp_infois = BSTP_INFO_DISABLED;
bp->bp_flags = BSTP_PORT_AUTOEDGE;
bp->bp_flags = BSTP_PORT_AUTOEDGE|BSTP_PORT_AUTOP2P;
bstp_set_port_state(bp, BSTP_IFSTATE_DISCARDING);
bstp_set_port_proto(bp, bs->bs_protover);
bstp_set_port_role(bp, BSTP_ROLE_DISABLED);

View File

@ -108,6 +108,7 @@
#define BSTP_PORT_DISPUTED 0x0004
#define BSTP_PORT_ADMCOST 0x0008
#define BSTP_PORT_AUTOEDGE 0x0010
#define BSTP_PORT_AUTOP2P 0x0020
/* BPDU priority */
#define BSTP_PDU_SUPERIOR 1
@ -382,6 +383,8 @@ int bstp_set_port_priority(struct bstp_port *, int);
int bstp_set_path_cost(struct bstp_port *, uint32_t);
int bstp_set_edge(struct bstp_port *, int);
int bstp_set_autoedge(struct bstp_port *, int);
int bstp_set_p2p(struct bstp_port *, int);
int bstp_set_autop2p(struct bstp_port *, int);
struct mbuf *bstp_input(struct bstp_port *, struct ifnet *, struct mbuf *);
#endif /* _KERNEL */

View File

@ -309,8 +309,6 @@ static int bridge_ioctl_grte(struct bridge_softc *, void *);
static int bridge_ioctl_gifsstp(struct bridge_softc *, void *);
static int bridge_ioctl_sproto(struct bridge_softc *, void *);
static int bridge_ioctl_stxhc(struct bridge_softc *, void *);
static int bridge_ioctl_sedge(struct bridge_softc *, void *);
static int bridge_ioctl_saedge(struct bridge_softc *, void *);
static int bridge_pfil(struct mbuf **, struct ifnet *, struct ifnet *,
int);
static int bridge_ip_checkbasic(struct mbuf **mp);
@ -430,12 +428,6 @@ const struct bridge_control bridge_control_table[] = {
{ bridge_ioctl_stxhc, sizeof(struct ifbrparam),
BC_F_COPYIN|BC_F_SUSER },
{ bridge_ioctl_sedge, sizeof(struct ifbreq),
BC_F_COPYIN|BC_F_SUSER },
{ bridge_ioctl_saedge, sizeof(struct ifbreq),
BC_F_COPYIN|BC_F_SUSER },
};
const int bridge_control_table_size =
sizeof(bridge_control_table) / sizeof(bridge_control_table[0]);
@ -662,6 +654,7 @@ bridge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
struct ifbareq ifbareq;
struct ifbaconf ifbaconf;
struct ifbrparam ifbrparam;
struct ifbropreq ifbropreq;
} args;
struct ifdrv *ifd = (struct ifdrv *) data;
const struct bridge_control *bc;
@ -1021,10 +1014,16 @@ bridge_ioctl_gifflags(struct bridge_softc *sc, void *arg)
req->ifbr_proto = bp->bp_protover;
req->ifbr_role = bp->bp_role;
req->ifbr_stpflags = bp->bp_flags;
req->ifbr_edge = bp->bp_operedge;
req->ifbr_autoedge = (bp->bp_flags & BSTP_PORT_AUTOEDGE) ? 1 : 0;
req->ifbr_p2p = bp->bp_p2p_link;
/* Copy STP state options as flags */
if (bp->bp_operedge)
req->ifbr_ifsflags |= IFBIF_BSTP_EDGE;
if (bp->bp_flags & BSTP_PORT_AUTOEDGE)
req->ifbr_ifsflags |= IFBIF_BSTP_AUTOEDGE;
if (bp->bp_p2p_link)
req->ifbr_ifsflags |= IFBIF_BSTP_P2P;
if (bp->bp_flags & BSTP_PORT_AUTOP2P)
req->ifbr_ifsflags |= IFBIF_BSTP_AUTOP2P;
return (0);
}
@ -1033,11 +1032,13 @@ bridge_ioctl_sifflags(struct bridge_softc *sc, void *arg)
{
struct ifbreq *req = arg;
struct bridge_iflist *bif;
struct bstp_port *bp;
int error;
bif = bridge_lookup_member(sc, req->ifbr_ifsname);
if (bif == NULL)
return (ENOENT);
bp = &bif->bif_stp;
if (req->ifbr_ifsflags & IFBIF_SPAN)
/* SPAN is readonly */
@ -1054,7 +1055,14 @@ bridge_ioctl_sifflags(struct bridge_softc *sc, void *arg)
bstp_disable(&bif->bif_stp);
}
bif->bif_flags = req->ifbr_ifsflags;
/* Pass on STP flags */
bstp_set_edge(bp, req->ifbr_ifsflags & IFBIF_BSTP_EDGE ? 1 : 0);
bstp_set_autoedge(bp, req->ifbr_ifsflags & IFBIF_BSTP_AUTOEDGE ? 1 : 0);
bstp_set_p2p(bp, req->ifbr_ifsflags & IFBIF_BSTP_P2P ? 1 : 0);
bstp_set_autop2p(bp, req->ifbr_ifsflags & IFBIF_BSTP_AUTOP2P ? 1 : 0);
/* Save the bits relating to the bridge */
bif->bif_flags = req->ifbr_ifsflags & IFBIFMASK;
return (0);
}
@ -1085,7 +1093,6 @@ bridge_ioctl_gifs(struct bridge_softc *sc, void *arg)
{
struct ifbifconf *bifc = arg;
struct bridge_iflist *bif;
struct bstp_port *bp;
struct ifbreq breq;
int count, len, error = 0;
@ -1109,18 +1116,10 @@ bridge_ioctl_gifs(struct bridge_softc *sc, void *arg)
strlcpy(breq.ifbr_ifsname, bif->bif_ifp->if_xname,
sizeof(breq.ifbr_ifsname));
bp = &bif->bif_stp;
breq.ifbr_ifsflags = bif->bif_flags;
breq.ifbr_state = bp->bp_state;
breq.ifbr_priority = bp->bp_priority;
breq.ifbr_path_cost = bp->bp_path_cost;
breq.ifbr_portno = bif->bif_ifp->if_index & 0xfff;
breq.ifbr_proto = bp->bp_protover;
breq.ifbr_role = bp->bp_role;
breq.ifbr_stpflags = bp->bp_flags;
breq.ifbr_edge = bp->bp_operedge;
breq.ifbr_autoedge = (bp->bp_flags & BSTP_PORT_AUTOEDGE) ? 1:0;
breq.ifbr_p2p = bp->bp_p2p_link;
/* Fill in the ifbreq structure */
error = bridge_ioctl_gifflags(sc, &breq);
if (error)
break;
error = copyout(&breq, bifc->ifbic_req + count, sizeof(breq));
if (error)
break;
@ -1416,7 +1415,9 @@ bridge_ioctl_gbparam(struct bridge_softc *sc, void *arg)
req->ifbop_priority = bs->bs_bridge_priority;
req->ifbop_protocol = bs->bs_protover;
req->ifbop_root_path_cost = bs->bs_root_pv.pv_cost;
req->ifbop_bridgeid = bs->bs_bridge_pv.pv_dbridge_id;
req->ifbop_designated_root = bs->bs_root_pv.pv_root_id;
req->ifbop_designated_bridge = bs->bs_root_pv.pv_dbridge_id;
req->ifbop_last_tc_time.tv_sec = bs->bs_last_tc_time.tv_sec;
req->ifbop_last_tc_time.tv_usec = bs->bs_last_tc_time.tv_usec;
@ -1499,32 +1500,6 @@ bridge_ioctl_stxhc(struct bridge_softc *sc, void *arg)
return (bstp_set_holdcount(&sc->sc_stp, param->ifbrp_txhc));
}
static int
bridge_ioctl_sedge(struct bridge_softc *sc, void *arg)
{
struct ifbreq *req = arg;
struct bridge_iflist *bif;
bif = bridge_lookup_member(sc, req->ifbr_ifsname);
if (bif == NULL)
return (ENOENT);
return (bstp_set_edge(&bif->bif_stp, req->ifbr_edge));
}
static int
bridge_ioctl_saedge(struct bridge_softc *sc, void *arg)
{
struct ifbreq *req = arg;
struct bridge_iflist *bif;
bif = bridge_lookup_member(sc, req->ifbr_ifsname);
if (bif == NULL)
return (ENOENT);
return (bstp_set_autoedge(&bif->bif_stp, req->ifbr_autoedge));
}
/*
* bridge_ifdetach:
*

View File

@ -114,8 +114,6 @@
* (ifbpstpconf) */
#define BRDGSPROTO 28 /* set protocol (ifbrparam) */
#define BRDGSTXHC 29 /* set tx hold count (ifbrparam) */
#define BRDGSEDGE 30 /* set edge status (ifbreq) */
#define BRDGSAEDGE 31 /* set autoedge status (ifbreq) */
/*
* Generic bridge control request.
@ -124,9 +122,6 @@ struct ifbreq {
char ifbr_ifsname[IFNAMSIZ]; /* member if name */
uint32_t ifbr_ifsflags; /* member if flags */
uint32_t ifbr_stpflags; /* member if STP flags */
uint8_t ifbr_edge; /* member if STP edge */
uint8_t ifbr_autoedge; /* member if STP autoedge */
uint8_t ifbr_p2p; /* member if STP p2p */
uint32_t ifbr_path_cost; /* member if STP cost */
uint8_t ifbr_portno; /* member if port number */
uint8_t ifbr_priority; /* member if STP priority */
@ -136,13 +131,20 @@ struct ifbreq {
};
/* BRDGGIFFLAGS, BRDGSIFFLAGS */
#define IFBIF_LEARNING 0x01 /* if can learn */
#define IFBIF_DISCOVER 0x02 /* if sends packets w/ unknown dest. */
#define IFBIF_STP 0x04 /* if participates in spanning tree */
#define IFBIF_SPAN 0x08 /* if is a span port */
#define IFBIF_STICKY 0x10 /* if learned addresses stick */
#define IFBIF_LEARNING 0x0001 /* if can learn */
#define IFBIF_DISCOVER 0x0002 /* if sends packets w/ unknown dest. */
#define IFBIF_STP 0x0004 /* if participates in spanning tree */
#define IFBIF_SPAN 0x0008 /* if is a span port */
#define IFBIF_STICKY 0x0010 /* if learned addresses stick */
#define IFBIF_BSTP_EDGE 0x0020 /* member stp edge port */
#define IFBIF_BSTP_AUTOEDGE 0x0040 /* member stp autoedge enabled */
#define IFBIF_BSTP_P2P 0x0080 /* member stp p2p */
#define IFBIF_BSTP_AUTOP2P 0x0100 /* member stp autop2p enabled */
#define IFBIFBITS "\020\1LEARNING\2DISCOVER\3STP\4SPAN\5STICKY"
#define IFBIFBITS "\020\001LEARNING\002DISCOVER\003STP\004SPAN" \
"\005STICKY\006EDGE\007AUTOEDGE\010P2P\011AUTOP2P"
#define IFBIFMASK ~(IFBIF_BSTP_EDGE|IFBIF_BSTP_AUTOEDGE|IFBIF_BSTP_P2P| \
IFBIF_BSTP_AUTOP2P) /* not saved */
/* BRDGFLUSH */
#define IFBF_FLUSHDYN 0x00 /* flush learned addresses only */
@ -223,7 +225,9 @@ struct ifbropreq {
uint16_t ifbop_priority;
uint16_t ifbop_root_port;
uint32_t ifbop_root_path_cost;
uint64_t ifbop_bridgeid;
uint64_t ifbop_designated_root;
uint64_t ifbop_designated_bridge;
struct timeval ifbop_last_tc_time;
};