Project

General

Profile

Feature #4133 » pf_pcp_source.diff

Source patch - Clement Barnier, 12/20/2014 08:34 AM

View differences:

/pfsense/src/sys/net/if.h 2014-08-23 20:54:01.000000000 +0200
caddr_t ifru_data;
int ifru_cap[2];
u_int ifru_fib;
u_char ifru_vlan_pcp;
} ifr_ifru;
#define ifr_addr ifr_ifru.ifru_addr /* address */
#define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-to-p link */
......
#define ifr_curcap ifr_ifru.ifru_cap[1] /* current capabilities */
#define ifr_index ifr_ifru.ifru_index /* interface index */
#define ifr_fib ifr_ifru.ifru_fib /* interface fib */
#define ifr_vlan_pcp ifr_ifru.ifru_vlan_pcp /* VLAN priority */
};
#define _SIZEOF_ADDR_IFREQ(ifr) \
/pfsense/src/sys/net/if_lagg.c 2014-08-23 20:54:01.000000000 +0200
* config EVENT
*/
static void
lagg_register_vlan(void *arg, struct ifnet *ifp, u_int16_t vtag)
lagg_register_vlan(void *arg, struct ifnet *ifp, u_int16_t vid)
{
struct lagg_softc *sc = ifp->if_softc;
struct lagg_port *lp;
......
LAGG_RLOCK(sc, &tracker);
if (!SLIST_EMPTY(&sc->sc_ports)) {
SLIST_FOREACH(lp, &sc->sc_ports, lp_entries)
EVENTHANDLER_INVOKE(vlan_config, lp->lp_ifp, vtag);
EVENTHANDLER_INVOKE(vlan_config, lp->lp_ifp, vid, 0);
}
LAGG_RUNLOCK(sc, &tracker);
}
......
* unconfig EVENT
*/
static void
lagg_unregister_vlan(void *arg, struct ifnet *ifp, u_int16_t vtag)
lagg_unregister_vlan(void *arg, struct ifnet *ifp)
{
struct lagg_softc *sc = ifp->if_softc;
struct lagg_port *lp;
......
LAGG_RLOCK(sc, &tracker);
if (!SLIST_EMPTY(&sc->sc_ports)) {
SLIST_FOREACH(lp, &sc->sc_ports, lp_entries)
EVENTHANDLER_INVOKE(vlan_unconfig, lp->lp_ifp, vtag);
EVENTHANDLER_INVOKE(vlan_unconfig, lp->lp_ifp);
}
LAGG_RUNLOCK(sc, &tracker);
}
/pfsense/src/sys/net/if_vlan.c 2014-09-12 19:06:25.000000000 +0200
int ifvm_mintu; /* min transmission unit */
uint16_t ifvm_proto; /* encapsulation ethertype */
uint16_t ifvm_tag; /* tag to apply on packets leaving if */
int16_t ifvm_vid; /* VLAN ID */
uint8_t ifvm_pcp; /* Priority Code Point (PCP). */
} ifv_mib;
SLIST_HEAD(, vlan_mc_entry) vlan_mc_listhead;
......
#endif
};
#define ifv_proto ifv_mib.ifvm_proto
#define ifv_vid ifv_mib.ifvm_tag
#define ifv_tag ifv_mib.ifvm_tag
#define ifv_vid ifv_mib.ifvm_vid
#define ifv_pcp ifv_mib.ifvm_pcp
#define ifv_encaplen ifv_mib.ifvm_encaplen
#define ifv_mtufudge ifv_mib.ifvm_mtufudge
......
static int vlan_setmulti(struct ifnet *ifp);
static void vlan_unconfig(struct ifnet *ifp);
static void vlan_unconfig_locked(struct ifnet *ifp, int departing);
static int vlan_config(struct ifvlan *ifv, struct ifnet *p, uint16_t tag);
static int vlan_config(struct ifvlan *ifv, struct ifnet *p, uint16_t vid, uint16_t pcp);
static void vlan_link_state(struct ifnet *ifp);
static void vlan_capabilities(struct ifvlan *ifv);
static void vlan_trunk_capabilities(struct ifnet *ifp);
......
vlan_tag_recalculate(struct ifvlan *ifv)
{
ifv->ifv_mib.ifvm_tag = EVL_MAKETAG(ifv->ifv_vid, ifv->ifv_pcp, 0);
ifv->ifv_tag = EVL_MAKETAG(ifv->ifv_vid, ifv->ifv_pcp, 0);
}
/*
......
int wildcard;
int unit;
int error;
int vid;
int vid, pcp;
int ethertag;
struct ifvlan *ifv;
struct ifnet *ifp;
......
p = ifunit(vlr.vlr_parent);
if (p == NULL)
return ENXIO;
/*
* Don't let the caller set up a VLAN VID with
* anything except VLID bits.
*/
if (vlr.vlr_tag & ~EVL_VLID_MASK)
return (EINVAL);
error = ifc_name2unit(name, &unit);
if (error != 0)
return (error);
ethertag = 1;
vid = vlr.vlr_tag;
vid = vlr.vlr_vid;
pcp = vlr.vlr_pcp;
wildcard = (unit < 0);
} else if ((p = vlan_clone_match_ethervid(ifc, name, &vid)) != NULL) {
ethertag = 1;
vid = vlr.vlr_vid;
pcp = 0; /* Default: Best Effort */
unit = -1;
wildcard = 0;
......
return (EINVAL);
} else {
ethertag = 0;
vid = -1;
pcp = -1;
error = ifc_name2unit(name, &unit);
if (error != 0)
......
sdl->sdl_type = IFT_L2VLAN;
if (ethertag) {
error = vlan_config(ifv, p, vid);
error = vlan_config(ifv, p, vid, pcp);
if (error != 0) {
/*
* Since we've partially failed, we need to back
......
MTAG_8021Q_PCP_OUT, NULL)) != NULL)
tag = EVL_MAKETAG(ifv->ifv_vid, *(uint8_t *)(mtag + 1), 0);
else
tag = EVL_MAKETAG(ifv->ifv_vid, ifv->ifv_pcp, 0);
tag = ifv->ifv_tag;
if (p->if_capenable & IFCAP_VLAN_HWTAGGING) {
m->m_pkthdr.ether_vtag = tag;
m->m_flags |= M_VLANTAG;
......
}
static int
vlan_config(struct ifvlan *ifv, struct ifnet *p, uint16_t vid)
vlan_config(struct ifvlan *ifv, struct ifnet *p, uint16_t vid, uint16_t pcp)
{
struct ifvlantrunk *trunk;
struct ifnet *ifp;
......
}
ifv->ifv_vid = vid; /* must set this before vlan_inshash() */
ifv->ifv_pcp = 0; /* Default: best effort delivery. */
ifv->ifv_pcp = pcp;
vlan_tag_recalculate(ifv);
error = vlan_inshash(trunk, ifv);
if (error)
......
done:
TRUNK_UNLOCK(trunk);
if (error == 0)
EVENTHANDLER_INVOKE(vlan_config, p, ifv->ifv_vid);
EVENTHANDLER_INVOKE(vlan_config, p, ifv->ifv_vid, ifv->ifv_pcp);
VLAN_UNLOCK();
return (error);
......
* to cleanup anyway.
*/
if (parent != NULL)
EVENTHANDLER_INVOKE(vlan_unconfig, parent, ifv->ifv_vid);
EVENTHANDLER_INVOKE(vlan_unconfig, parent);
}
/* Handle a reference counted flag that should be set on the parent as well */
......
error = ENOENT;
break;
}
/*
* Don't let the caller set up a VLAN VID with
* anything except VLID bits.
*/
if (vlr.vlr_tag & ~EVL_VLID_MASK) {
error = EINVAL;
break;
}
error = vlan_config(ifv, p, vlr.vlr_tag);
error = priv_check(curthread, PRIV_NET_SETVLANPCP);
if (error)
error = vlan_config(ifv, p, vlr.vlr_vid, 0); /* Set default PCP if privilege missing */
else
error = vlan_config(ifv, p, vlr.vlr_vid, vlr.vlr_pcp);
if (error)
break;
......
if (TRUNK(ifv) != NULL) {
strlcpy(vlr.vlr_parent, PARENT(ifv)->if_xname,
sizeof(vlr.vlr_parent));
vlr.vlr_tag = ifv->ifv_vid;
vlr.vlr_vid = ifv->ifv_vid;
vlr.vlr_pcp = ifv->ifv_pcp;
}
VLAN_UNLOCK();
error = copyout(&vlr, ifr->ifr_data, sizeof(vlr));
......
}
break;
case SIOCGVLANPCP:
#ifdef VIMAGE
if (ifp->if_vnet != ifp->if_home_vnet) {
error = EPERM;
break;
}
#endif
ifr->ifr_vlan_pcp = ifv->ifv_pcp;
break;
case SIOCSVLANPCP:
#ifdef VIMAGE
if (ifp->if_vnet != ifp->if_home_vnet) {
error = EPERM;
break;
}
#endif
error = priv_check(curthread, PRIV_NET_SETVLANPCP);
if (error)
break;
if (ifr->ifr_vlan_pcp > 7) {
error = EINVAL;
break;
}
ifv->ifv_pcp = ifr->ifr_vlan_pcp;
vlan_tag_recalculate(ifv);
break;
default:
error = EINVAL;
break;
/pfsense/src/sys/net/if_vlan_var.h 2014-08-23 20:54:01.000000000 +0200
*/
struct vlanreq {
char vlr_parent[IFNAMSIZ];
u_short vlr_tag;
u_short vlr_vid;
u_short vlr_pcp;
};
#define SIOCSETVLAN SIOCSIFGENERIC
#define SIOCGETVLAN SIOCGIFGENERIC
/pfsense/src/sys/sys/eventhandler.h 2014-08-23 20:54:01.000000000 +0200
/* VLAN state change events */
struct ifnet;
typedef void (*vlan_config_fn)(void *, struct ifnet *, uint16_t);
typedef void (*vlan_unconfig_fn)(void *, struct ifnet *, uint16_t);
typedef void (*vlan_config_fn)(void *, struct ifnet *, uint16_t, uint16_t);
typedef void (*vlan_unconfig_fn)(void *, struct ifnet *);
EVENTHANDLER_DECLARE(vlan_config, vlan_config_fn);
EVENTHANDLER_DECLARE(vlan_unconfig, vlan_unconfig_fn);
/pfsense/src/sbin/ifconfig/ifvlan.c 2014-08-23 20:54:01.000000000 +0200
"$FreeBSD$";
#endif
#define NOTAG ((u_short) -1)
#define NOPARAM ((u_short) -1)
static struct vlanreq params = {
.vlr_tag = NOTAG,
.vlr_vid = NOPARAM,
.vlr_pcp = NOPARAM,
};
static int
......
if (getvlan(s, &ifr, &vreq) == -1)
return;
printf("\tvlan: %d", vreq.vlr_tag);
if (ioctl(s, SIOCGVLANPCP, (caddr_t)&ifr) != -1)
printf(" vlanpcp: %u", ifr.ifr_vlan_pcp);
printf("\tvlan: %u", vreq.vlr_vid);
printf(" pcp: %u", vreq.vlr_pcp);
printf(" parent interface: %s", vreq.vlr_parent[0] == '\0' ?
"<none>" : vreq.vlr_parent);
printf("\n");
......
static void
vlan_create(int s, struct ifreq *ifr)
{
if (params.vlr_tag != NOTAG || params.vlr_parent[0] != '\0') {
if (params.vlr_vid != NOPARAM || params.vlr_parent[0] != '\0') {
/*
* One or both parameters were specified, make sure both.
*/
if (params.vlr_tag == NOTAG)
errx(1, "must specify a tag for vlan create");
if (params.vlr_vid == NOPARAM)
errx(1, "must specify a vid for vlan create");
if (params.vlr_parent[0] == '\0')
errx(1, "must specify a parent device for vlan create");
if (params.vlr_pcp == NOPARAM)
params.vlr_pcp = 0; /* Best Effort by default */
ifr->ifr_data = (caddr_t) &params;
}
if (ioctl(s, SIOCIFCREATE2, ifr) < 0)
......
static void
vlan_cb(int s, void *arg)
{
if ((params.vlr_tag != NOTAG) ^ (params.vlr_parent[0] != '\0'))
if ((params.vlr_vid != NOPARAM) ^ (params.vlr_parent[0] != '\0'))
errx(1, "both vlan and vlandev must be specified");
}
static void
vlan_set(int s, struct ifreq *ifr)
{
if (params.vlr_tag != NOTAG && params.vlr_parent[0] != '\0') {
if (params.vlr_vid != NOPARAM && params.vlr_parent[0] != '\0') {
if (params.vlr_pcp == NOPARAM)
params.vlr_pcp = 0; /* Set to Best Effort by default */
ifr->ifr_data = (caddr_t) &params;
if (ioctl(s, SIOCSETVLAN, (caddr_t)ifr) == -1)
err(1, "SIOCSETVLAN");
......
}
static
DECL_CMD_FUNC(setvlantag, val, d)
DECL_CMD_FUNC(setvlanvid, val, d)
{
struct vlanreq vreq;
u_long ul;
......
ul = strtoul(val, &endp, 0);
if (*endp != '\0')
errx(1, "invalid value for vlan");
params.vlr_tag = ul;
/* check if the value can be represented in vlr_tag */
if (params.vlr_tag != ul)
params.vlr_vid = ul;
/* check if the value can be represented in vlr_vid */
if (params.vlr_vid != ul)
errx(1, "value for vlan out of range");
if (getvlan(s, &ifr, &vreq) != -1)
......
static
DECL_CMD_FUNC(setvlanpcp, val, d)
{
struct vlanreq vreq;
u_long ul;
char *endp;
......
errx(1, "invalid value for vlanpcp");
if (ul > 7)
errx(1, "value for vlanpcp out of range");
ifr.ifr_vlan_pcp = ul;
if (ioctl(s, SIOCSVLANPCP, (caddr_t)&ifr) == -1)
err(1, "SIOCSVLANPCP");
params.vlr_pcp = ul;
if (getvlan(s, &ifr, &vreq) != -1)
vlan_set(s, &ifr);
}
static
......
err(1, "SIOCGETVLAN");
bzero((char *)&vreq.vlr_parent, sizeof(vreq.vlr_parent));
vreq.vlr_tag = 0;
if (ioctl(s, SIOCSETVLAN, (caddr_t)&ifr) == -1)
err(1, "SIOCSETVLAN");
}
static struct cmd vlan_cmds[] = {
DEF_CLONE_CMD_ARG("vlan", setvlantag),
DEF_CLONE_CMD_ARG("vlan", setvlanvid),
DEF_CLONE_CMD_ARG("vlandev", setvlandev),
DEF_CMD_ARG("vlanpcp", setvlanpcp),
/* NB: non-clone cmds */
DEF_CMD_ARG("vlan", setvlantag),
DEF_CMD_ARG("vlan", setvlanvid),
DEF_CMD_ARG("vlandev", setvlandev),
/* XXX For compatibility. Should become DEF_CMD() some day. */
DEF_CMD_OPTARG("-vlandev", unsetvlandev),
(2-2/4)