Feature #4133 » pf_pcp_source.diff
| /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) ¶ms;
|
||
|
}
|
||
|
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) ¶ms;
|
||
|
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),
|
||