Feature #4133 » pf_pcp_source.diff
/pfsense/src/sys/net/if.h 2014-08-23 20:54:01.000000000 +0200 | ||
---|---|---|
392 | 392 |
caddr_t ifru_data; |
393 | 393 |
int ifru_cap[2]; |
394 | 394 |
u_int ifru_fib; |
395 |
u_char ifru_vlan_pcp; |
|
396 | 395 |
} ifr_ifru; |
397 | 396 |
#define ifr_addr ifr_ifru.ifru_addr /* address */ |
398 | 397 |
#define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-to-p link */ |
... | ... | |
410 | 409 |
#define ifr_curcap ifr_ifru.ifru_cap[1] /* current capabilities */ |
411 | 410 |
#define ifr_index ifr_ifru.ifru_index /* interface index */ |
412 | 411 |
#define ifr_fib ifr_ifru.ifru_fib /* interface fib */ |
413 |
#define ifr_vlan_pcp ifr_ifru.ifru_vlan_pcp /* VLAN priority */ |
|
414 | 412 |
}; |
415 | 413 | |
416 | 414 |
#define _SIZEOF_ADDR_IFREQ(ifr) \ |
/pfsense/src/sys/net/if_lagg.c 2014-08-23 20:54:01.000000000 +0200 | ||
---|---|---|
234 | 234 |
* config EVENT |
235 | 235 |
*/ |
236 | 236 |
static void |
237 |
lagg_register_vlan(void *arg, struct ifnet *ifp, u_int16_t vtag)
|
|
237 |
lagg_register_vlan(void *arg, struct ifnet *ifp, u_int16_t vid)
|
|
238 | 238 |
{ |
239 | 239 |
struct lagg_softc *sc = ifp->if_softc; |
240 | 240 |
struct lagg_port *lp; |
... | ... | |
246 | 246 |
LAGG_RLOCK(sc, &tracker); |
247 | 247 |
if (!SLIST_EMPTY(&sc->sc_ports)) { |
248 | 248 |
SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) |
249 |
EVENTHANDLER_INVOKE(vlan_config, lp->lp_ifp, vtag);
|
|
249 |
EVENTHANDLER_INVOKE(vlan_config, lp->lp_ifp, vid, 0);
|
|
250 | 250 |
} |
251 | 251 |
LAGG_RUNLOCK(sc, &tracker); |
252 | 252 |
} |
... | ... | |
256 | 256 |
* unconfig EVENT |
257 | 257 |
*/ |
258 | 258 |
static void |
259 |
lagg_unregister_vlan(void *arg, struct ifnet *ifp, u_int16_t vtag)
|
|
259 |
lagg_unregister_vlan(void *arg, struct ifnet *ifp) |
|
260 | 260 |
{ |
261 | 261 |
struct lagg_softc *sc = ifp->if_softc; |
262 | 262 |
struct lagg_port *lp; |
... | ... | |
268 | 268 |
LAGG_RLOCK(sc, &tracker); |
269 | 269 |
if (!SLIST_EMPTY(&sc->sc_ports)) { |
270 | 270 |
SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) |
271 |
EVENTHANDLER_INVOKE(vlan_unconfig, lp->lp_ifp, vtag);
|
|
271 |
EVENTHANDLER_INVOKE(vlan_unconfig, lp->lp_ifp); |
|
272 | 272 |
} |
273 | 273 |
LAGG_RUNLOCK(sc, &tracker); |
274 | 274 |
} |
/pfsense/src/sys/net/if_vlan.c 2014-09-12 19:06:25.000000000 +0200 | ||
---|---|---|
117 | 117 |
int ifvm_mintu; /* min transmission unit */ |
118 | 118 |
uint16_t ifvm_proto; /* encapsulation ethertype */ |
119 | 119 |
uint16_t ifvm_tag; /* tag to apply on packets leaving if */ |
120 |
int16_t ifvm_vid; /* VLAN ID */ |
|
120 | 121 |
uint8_t ifvm_pcp; /* Priority Code Point (PCP). */ |
121 | 122 |
} ifv_mib; |
122 | 123 |
SLIST_HEAD(, vlan_mc_entry) vlan_mc_listhead; |
... | ... | |
125 | 126 |
#endif |
126 | 127 |
}; |
127 | 128 |
#define ifv_proto ifv_mib.ifvm_proto |
128 |
#define ifv_vid ifv_mib.ifvm_tag |
|
129 |
#define ifv_tag ifv_mib.ifvm_tag |
|
130 |
#define ifv_vid ifv_mib.ifvm_vid |
|
129 | 131 |
#define ifv_pcp ifv_mib.ifvm_pcp |
130 | 132 |
#define ifv_encaplen ifv_mib.ifvm_encaplen |
131 | 133 |
#define ifv_mtufudge ifv_mib.ifvm_mtufudge |
... | ... | |
214 | 216 |
static int vlan_setmulti(struct ifnet *ifp); |
215 | 217 |
static void vlan_unconfig(struct ifnet *ifp); |
216 | 218 |
static void vlan_unconfig_locked(struct ifnet *ifp, int departing); |
217 |
static int vlan_config(struct ifvlan *ifv, struct ifnet *p, uint16_t tag);
|
|
219 |
static int vlan_config(struct ifvlan *ifv, struct ifnet *p, uint16_t vid, uint16_t pcp);
|
|
218 | 220 |
static void vlan_link_state(struct ifnet *ifp); |
219 | 221 |
static void vlan_capabilities(struct ifvlan *ifv); |
220 | 222 |
static void vlan_trunk_capabilities(struct ifnet *ifp); |
... | ... | |
714 | 716 |
vlan_tag_recalculate(struct ifvlan *ifv) |
715 | 717 |
{ |
716 | 718 | |
717 |
ifv->ifv_mib.ifvm_tag = EVL_MAKETAG(ifv->ifv_vid, ifv->ifv_pcp, 0);
|
|
719 |
ifv->ifv_tag = EVL_MAKETAG(ifv->ifv_vid, ifv->ifv_pcp, 0); |
|
718 | 720 |
} |
719 | 721 | |
720 | 722 |
/* |
... | ... | |
884 | 886 |
int wildcard; |
885 | 887 |
int unit; |
886 | 888 |
int error; |
887 |
int vid; |
|
889 |
int vid, pcp;
|
|
888 | 890 |
int ethertag; |
889 | 891 |
struct ifvlan *ifv; |
890 | 892 |
struct ifnet *ifp; |
... | ... | |
913 | 915 |
p = ifunit(vlr.vlr_parent); |
914 | 916 |
if (p == NULL) |
915 | 917 |
return ENXIO; |
916 |
/* |
|
917 |
* Don't let the caller set up a VLAN VID with |
|
918 |
* anything except VLID bits. |
|
919 |
*/ |
|
920 |
if (vlr.vlr_tag & ~EVL_VLID_MASK) |
|
921 |
return (EINVAL); |
|
918 | ||
922 | 919 |
error = ifc_name2unit(name, &unit); |
923 | 920 |
if (error != 0) |
924 | 921 |
return (error); |
925 | 922 | |
926 | 923 |
ethertag = 1; |
927 |
vid = vlr.vlr_tag; |
|
924 |
vid = vlr.vlr_vid; |
|
925 |
pcp = vlr.vlr_pcp; |
|
928 | 926 |
wildcard = (unit < 0); |
929 | 927 |
} else if ((p = vlan_clone_match_ethervid(ifc, name, &vid)) != NULL) { |
930 | 928 |
ethertag = 1; |
929 |
vid = vlr.vlr_vid; |
|
930 |
pcp = 0; /* Default: Best Effort */ |
|
931 | 931 |
unit = -1; |
932 | 932 |
wildcard = 0; |
933 | 933 | |
... | ... | |
939 | 939 |
return (EINVAL); |
940 | 940 |
} else { |
941 | 941 |
ethertag = 0; |
942 |
vid = -1; |
|
943 |
pcp = -1; |
|
942 | 944 | |
943 | 945 |
error = ifc_name2unit(name, &unit); |
944 | 946 |
if (error != 0) |
... | ... | |
1000 | 1002 |
sdl->sdl_type = IFT_L2VLAN; |
1001 | 1003 | |
1002 | 1004 |
if (ethertag) { |
1003 |
error = vlan_config(ifv, p, vid); |
|
1005 |
error = vlan_config(ifv, p, vid, pcp);
|
|
1004 | 1006 |
if (error != 0) { |
1005 | 1007 |
/* |
1006 | 1008 |
* Since we've partially failed, we need to back |
... | ... | |
1133 | 1135 |
MTAG_8021Q_PCP_OUT, NULL)) != NULL) |
1134 | 1136 |
tag = EVL_MAKETAG(ifv->ifv_vid, *(uint8_t *)(mtag + 1), 0); |
1135 | 1137 |
else |
1136 |
tag = EVL_MAKETAG(ifv->ifv_vid, ifv->ifv_pcp, 0);
|
|
1138 |
tag = ifv->ifv_tag;
|
|
1137 | 1139 |
if (p->if_capenable & IFCAP_VLAN_HWTAGGING) { |
1138 | 1140 |
m->m_pkthdr.ether_vtag = tag; |
1139 | 1141 |
m->m_flags |= M_VLANTAG; |
... | ... | |
1258 | 1260 |
} |
1259 | 1261 | |
1260 | 1262 |
static int |
1261 |
vlan_config(struct ifvlan *ifv, struct ifnet *p, uint16_t vid) |
|
1263 |
vlan_config(struct ifvlan *ifv, struct ifnet *p, uint16_t vid, uint16_t pcp)
|
|
1262 | 1264 |
{ |
1263 | 1265 |
struct ifvlantrunk *trunk; |
1264 | 1266 |
struct ifnet *ifp; |
... | ... | |
1298 | 1300 |
} |
1299 | 1301 | |
1300 | 1302 |
ifv->ifv_vid = vid; /* must set this before vlan_inshash() */ |
1301 |
ifv->ifv_pcp = 0; /* Default: best effort delivery. */
|
|
1303 |
ifv->ifv_pcp = pcp;
|
|
1302 | 1304 |
vlan_tag_recalculate(ifv); |
1303 | 1305 |
error = vlan_inshash(trunk, ifv); |
1304 | 1306 |
if (error) |
... | ... | |
1377 | 1379 |
done: |
1378 | 1380 |
TRUNK_UNLOCK(trunk); |
1379 | 1381 |
if (error == 0) |
1380 |
EVENTHANDLER_INVOKE(vlan_config, p, ifv->ifv_vid); |
|
1382 |
EVENTHANDLER_INVOKE(vlan_config, p, ifv->ifv_vid, ifv->ifv_pcp);
|
|
1381 | 1383 |
VLAN_UNLOCK(); |
1382 | 1384 | |
1383 | 1385 |
return (error); |
... | ... | |
1473 | 1475 |
* to cleanup anyway. |
1474 | 1476 |
*/ |
1475 | 1477 |
if (parent != NULL) |
1476 |
EVENTHANDLER_INVOKE(vlan_unconfig, parent, ifv->ifv_vid);
|
|
1478 |
EVENTHANDLER_INVOKE(vlan_unconfig, parent); |
|
1477 | 1479 |
} |
1478 | 1480 | |
1479 | 1481 |
/* Handle a reference counted flag that should be set on the parent as well */ |
... | ... | |
1736 | 1738 |
error = ENOENT; |
1737 | 1739 |
break; |
1738 | 1740 |
} |
1739 |
/* |
|
1740 |
* Don't let the caller set up a VLAN VID with |
|
1741 |
* anything except VLID bits. |
|
1742 |
*/ |
|
1743 |
if (vlr.vlr_tag & ~EVL_VLID_MASK) { |
|
1744 |
error = EINVAL; |
|
1745 |
break; |
|
1746 |
} |
|
1747 |
error = vlan_config(ifv, p, vlr.vlr_tag); |
|
1741 | ||
1742 |
error = priv_check(curthread, PRIV_NET_SETVLANPCP); |
|
1743 |
if (error) |
|
1744 |
error = vlan_config(ifv, p, vlr.vlr_vid, 0); /* Set default PCP if privilege missing */ |
|
1745 |
else |
|
1746 |
error = vlan_config(ifv, p, vlr.vlr_vid, vlr.vlr_pcp); |
|
1748 | 1747 |
if (error) |
1749 | 1748 |
break; |
1750 | 1749 | |
... | ... | |
1764 | 1763 |
if (TRUNK(ifv) != NULL) { |
1765 | 1764 |
strlcpy(vlr.vlr_parent, PARENT(ifv)->if_xname, |
1766 | 1765 |
sizeof(vlr.vlr_parent)); |
1767 |
vlr.vlr_tag = ifv->ifv_vid; |
|
1766 |
vlr.vlr_vid = ifv->ifv_vid; |
|
1767 |
vlr.vlr_pcp = ifv->ifv_pcp; |
|
1768 | 1768 |
} |
1769 | 1769 |
VLAN_UNLOCK(); |
1770 | 1770 |
error = copyout(&vlr, ifr->ifr_data, sizeof(vlr)); |
... | ... | |
1793 | 1793 |
} |
1794 | 1794 |
break; |
1795 | 1795 | |
1796 |
case SIOCGVLANPCP: |
|
1797 |
#ifdef VIMAGE |
|
1798 |
if (ifp->if_vnet != ifp->if_home_vnet) { |
|
1799 |
error = EPERM; |
|
1800 |
break; |
|
1801 |
} |
|
1802 |
#endif |
|
1803 |
ifr->ifr_vlan_pcp = ifv->ifv_pcp; |
|
1804 |
break; |
|
1805 | ||
1806 |
case SIOCSVLANPCP: |
|
1807 |
#ifdef VIMAGE |
|
1808 |
if (ifp->if_vnet != ifp->if_home_vnet) { |
|
1809 |
error = EPERM; |
|
1810 |
break; |
|
1811 |
} |
|
1812 |
#endif |
|
1813 |
error = priv_check(curthread, PRIV_NET_SETVLANPCP); |
|
1814 |
if (error) |
|
1815 |
break; |
|
1816 |
if (ifr->ifr_vlan_pcp > 7) { |
|
1817 |
error = EINVAL; |
|
1818 |
break; |
|
1819 |
} |
|
1820 |
ifv->ifv_pcp = ifr->ifr_vlan_pcp; |
|
1821 |
vlan_tag_recalculate(ifv); |
|
1822 |
break; |
|
1823 | ||
1824 | 1796 |
default: |
1825 | 1797 |
error = EINVAL; |
1826 | 1798 |
break; |
/pfsense/src/sys/net/if_vlan_var.h 2014-08-23 20:54:01.000000000 +0200 | ||
---|---|---|
84 | 84 |
*/ |
85 | 85 |
struct vlanreq { |
86 | 86 |
char vlr_parent[IFNAMSIZ]; |
87 |
u_short vlr_tag; |
|
87 |
u_short vlr_vid; |
|
88 |
u_short vlr_pcp; |
|
88 | 89 |
}; |
89 | 90 |
#define SIOCSETVLAN SIOCSIFGENERIC |
90 | 91 |
#define SIOCGETVLAN SIOCGIFGENERIC |
/pfsense/src/sys/sys/eventhandler.h 2014-08-23 20:54:01.000000000 +0200 | ||
---|---|---|
205 | 205 | |
206 | 206 |
/* VLAN state change events */ |
207 | 207 |
struct ifnet; |
208 |
typedef void (*vlan_config_fn)(void *, struct ifnet *, uint16_t); |
|
209 |
typedef void (*vlan_unconfig_fn)(void *, struct ifnet *, uint16_t);
|
|
208 |
typedef void (*vlan_config_fn)(void *, struct ifnet *, uint16_t, uint16_t);
|
|
209 |
typedef void (*vlan_unconfig_fn)(void *, struct ifnet *); |
|
210 | 210 |
EVENTHANDLER_DECLARE(vlan_config, vlan_config_fn); |
211 | 211 |
EVENTHANDLER_DECLARE(vlan_unconfig, vlan_unconfig_fn); |
212 | 212 |
/pfsense/src/sbin/ifconfig/ifvlan.c 2014-08-23 20:54:01.000000000 +0200 | ||
---|---|---|
63 | 63 |
"$FreeBSD$"; |
64 | 64 |
#endif |
65 | 65 | |
66 |
#define NOTAG ((u_short) -1)
|
|
66 |
#define NOPARAM ((u_short) -1)
|
|
67 | 67 | |
68 | 68 |
static struct vlanreq params = { |
69 |
.vlr_tag = NOTAG, |
|
69 |
.vlr_vid = NOPARAM, |
|
70 |
.vlr_pcp = NOPARAM, |
|
70 | 71 |
}; |
71 | 72 | |
72 | 73 |
static int |
... | ... | |
85 | 86 | |
86 | 87 |
if (getvlan(s, &ifr, &vreq) == -1) |
87 | 88 |
return; |
88 |
printf("\tvlan: %d", vreq.vlr_tag); |
|
89 |
if (ioctl(s, SIOCGVLANPCP, (caddr_t)&ifr) != -1) |
|
90 |
printf(" vlanpcp: %u", ifr.ifr_vlan_pcp); |
|
89 |
printf("\tvlan: %u", vreq.vlr_vid); |
|
90 |
printf(" pcp: %u", vreq.vlr_pcp); |
|
91 | 91 |
printf(" parent interface: %s", vreq.vlr_parent[0] == '\0' ? |
92 | 92 |
"<none>" : vreq.vlr_parent); |
93 | 93 |
printf("\n"); |
... | ... | |
96 | 96 |
static void |
97 | 97 |
vlan_create(int s, struct ifreq *ifr) |
98 | 98 |
{ |
99 |
if (params.vlr_tag != NOTAG || params.vlr_parent[0] != '\0') {
|
|
99 |
if (params.vlr_vid != NOPARAM || params.vlr_parent[0] != '\0') {
|
|
100 | 100 |
/* |
101 | 101 |
* One or both parameters were specified, make sure both. |
102 | 102 |
*/ |
103 |
if (params.vlr_tag == NOTAG)
|
|
104 |
errx(1, "must specify a tag for vlan create");
|
|
103 |
if (params.vlr_vid == NOPARAM)
|
|
104 |
errx(1, "must specify a vid for vlan create");
|
|
105 | 105 |
if (params.vlr_parent[0] == '\0') |
106 | 106 |
errx(1, "must specify a parent device for vlan create"); |
107 |
|
|
108 |
if (params.vlr_pcp == NOPARAM) |
|
109 |
params.vlr_pcp = 0; /* Best Effort by default */ |
|
110 |
|
|
107 | 111 |
ifr->ifr_data = (caddr_t) ¶ms; |
108 | 112 |
} |
109 | 113 |
if (ioctl(s, SIOCIFCREATE2, ifr) < 0) |
... | ... | |
113 | 117 |
static void |
114 | 118 |
vlan_cb(int s, void *arg) |
115 | 119 |
{ |
116 |
if ((params.vlr_tag != NOTAG) ^ (params.vlr_parent[0] != '\0'))
|
|
120 |
if ((params.vlr_vid != NOPARAM) ^ (params.vlr_parent[0] != '\0'))
|
|
117 | 121 |
errx(1, "both vlan and vlandev must be specified"); |
118 | 122 |
} |
119 | 123 | |
120 | 124 |
static void |
121 | 125 |
vlan_set(int s, struct ifreq *ifr) |
122 | 126 |
{ |
123 |
if (params.vlr_tag != NOTAG && params.vlr_parent[0] != '\0') { |
|
127 |
if (params.vlr_vid != NOPARAM && params.vlr_parent[0] != '\0') { |
|
128 |
if (params.vlr_pcp == NOPARAM) |
|
129 |
params.vlr_pcp = 0; /* Set to Best Effort by default */ |
|
124 | 130 |
ifr->ifr_data = (caddr_t) ¶ms; |
125 | 131 |
if (ioctl(s, SIOCSETVLAN, (caddr_t)ifr) == -1) |
126 | 132 |
err(1, "SIOCSETVLAN"); |
... | ... | |
128 | 134 |
} |
129 | 135 | |
130 | 136 |
static |
131 |
DECL_CMD_FUNC(setvlantag, val, d)
|
|
137 |
DECL_CMD_FUNC(setvlanvid, val, d)
|
|
132 | 138 |
{ |
133 | 139 |
struct vlanreq vreq; |
134 | 140 |
u_long ul; |
... | ... | |
137 | 143 |
ul = strtoul(val, &endp, 0); |
138 | 144 |
if (*endp != '\0') |
139 | 145 |
errx(1, "invalid value for vlan"); |
140 |
params.vlr_tag = ul;
|
|
141 |
/* check if the value can be represented in vlr_tag */
|
|
142 |
if (params.vlr_tag != ul)
|
|
146 |
params.vlr_vid = ul;
|
|
147 |
/* check if the value can be represented in vlr_vid */
|
|
148 |
if (params.vlr_vid != ul)
|
|
143 | 149 |
errx(1, "value for vlan out of range"); |
144 | 150 | |
145 | 151 |
if (getvlan(s, &ifr, &vreq) != -1) |
... | ... | |
160 | 166 |
static |
161 | 167 |
DECL_CMD_FUNC(setvlanpcp, val, d) |
162 | 168 |
{ |
169 |
struct vlanreq vreq; |
|
163 | 170 |
u_long ul; |
164 | 171 |
char *endp; |
165 | 172 | |
... | ... | |
168 | 175 |
errx(1, "invalid value for vlanpcp"); |
169 | 176 |
if (ul > 7) |
170 | 177 |
errx(1, "value for vlanpcp out of range"); |
171 |
ifr.ifr_vlan_pcp = ul; |
|
172 |
if (ioctl(s, SIOCSVLANPCP, (caddr_t)&ifr) == -1) |
|
173 |
err(1, "SIOCSVLANPCP"); |
|
178 |
|
|
179 |
params.vlr_pcp = ul; |
|
180 |
if (getvlan(s, &ifr, &vreq) != -1) |
|
181 |
vlan_set(s, &ifr); |
|
174 | 182 |
} |
175 | 183 | |
176 | 184 |
static |
... | ... | |
185 | 193 |
err(1, "SIOCGETVLAN"); |
186 | 194 | |
187 | 195 |
bzero((char *)&vreq.vlr_parent, sizeof(vreq.vlr_parent)); |
188 |
vreq.vlr_tag = 0; |
|
189 | 196 | |
190 | 197 |
if (ioctl(s, SIOCSETVLAN, (caddr_t)&ifr) == -1) |
191 | 198 |
err(1, "SIOCSETVLAN"); |
192 | 199 |
} |
193 | 200 | |
194 | 201 |
static struct cmd vlan_cmds[] = { |
195 |
DEF_CLONE_CMD_ARG("vlan", setvlantag),
|
|
202 |
DEF_CLONE_CMD_ARG("vlan", setvlanvid),
|
|
196 | 203 |
DEF_CLONE_CMD_ARG("vlandev", setvlandev), |
197 | 204 |
DEF_CMD_ARG("vlanpcp", setvlanpcp), |
198 | 205 |
/* NB: non-clone cmds */ |
199 |
DEF_CMD_ARG("vlan", setvlantag),
|
|
206 |
DEF_CMD_ARG("vlan", setvlanvid),
|
|
200 | 207 |
DEF_CMD_ARG("vlandev", setvlandev), |
201 | 208 |
/* XXX For compatibility. Should become DEF_CMD() some day. */ |
202 | 209 |
DEF_CMD_OPTARG("-vlandev", unsetvlandev), |