@@ -78,6 +78,7 @@ __FBSDID("$FreeBSD$");
7878
7979#include <net/if.h>
8080#include <net/if_var.h>
81+ #include <net/if_vlan_var.h>
8182#include <net/if_dl.h>
8283#include <net/bpf.h>
8384#include <net/bpf_buffer.h>
@@ -130,6 +131,7 @@ struct bpf_program_buffer {
130131#if defined(DEV_BPF ) || defined(NETGRAPH_BPF )
131132
132133#define PRINET 26 /* interruptible */
134+ #define BPF_PRIO_MAX 7
133135
134136#define SIZEOF_BPF_HDR (type ) \
135137 (offsetof(type, bh_hdrlen) + sizeof(((type *)0)->bh_hdrlen))
@@ -977,6 +979,9 @@ bpfopen(struct cdev *dev, int flags, int fmt, struct thread *td)
977979 callout_init_mtx (& d -> bd_callout , & d -> bd_lock , 0 );
978980 knlist_init_mtx (& d -> bd_sel .si_note , & d -> bd_lock );
979981
982+ /* Disable VLAN pcp tagging. */
983+ d -> bd_pcp = 0 ;
984+
980985 return (0 );
981986}
982987
@@ -1167,6 +1172,27 @@ bpf_ready(struct bpf_d *d)
11671172 return (0 );
11681173}
11691174
1175+ static int
1176+ bpf_setpcp (struct mbuf * m , u_int8_t prio )
1177+ {
1178+ struct m_tag * mtag ;
1179+
1180+ KASSERT (prio <= BPF_PRIO_MAX ,
1181+ ("%s with invalid pcp" , __func__ ));
1182+
1183+ mtag = m_tag_locate (m , MTAG_8021Q , MTAG_8021Q_PCP_OUT , NULL );
1184+ if (mtag == NULL ) {
1185+ mtag = m_tag_alloc (MTAG_8021Q , MTAG_8021Q_PCP_OUT ,
1186+ sizeof (uint8_t ), M_NOWAIT );
1187+ if (mtag == NULL )
1188+ return (ENOMEM );
1189+ m_tag_prepend (m , mtag );
1190+ }
1191+
1192+ * (uint8_t * )(mtag + 1 ) = prio ;
1193+ return (0 );
1194+ }
1195+
11701196static int
11711197bpfwrite (struct cdev * dev , struct uio * uio , int ioflag )
11721198{
@@ -1267,6 +1293,9 @@ bpfwrite(struct cdev *dev, struct uio *uio, int ioflag)
12671293 ro .ro_flags = RT_HAS_HEADER ;
12681294 }
12691295
1296+ if (d -> bd_pcp != 0 )
1297+ bpf_setpcp (m , d -> bd_pcp );
1298+
12701299 /* Avoid possible recursion on BPFD_LOCK(). */
12711300 NET_EPOCH_ENTER (et );
12721301 BPFD_UNLOCK (d );
@@ -1356,6 +1385,7 @@ reset_d(struct bpf_d *d)
13561385 * BIOCROTZBUF Force rotation of zero-copy buffer
13571386 * BIOCSETBUFMODE Set buffer mode.
13581387 * BIOCGETBUFMODE Get current buffer mode.
1388+ * BIOCSETVLANPCP Set VLAN PCP tag.
13591389 */
13601390/* ARGSUSED */
13611391static int
@@ -1906,6 +1936,19 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
19061936 case BIOCROTZBUF :
19071937 error = bpf_ioctl_rotzbuf (td , d , (struct bpf_zbuf * )addr );
19081938 break ;
1939+
1940+ case BIOCSETVLANPCP :
1941+ {
1942+ u_int pcp ;
1943+
1944+ pcp = * (u_int * )addr ;
1945+ if (pcp > BPF_PRIO_MAX || pcp < 0 ) {
1946+ error = EINVAL ;
1947+ break ;
1948+ }
1949+ d -> bd_pcp = pcp ;
1950+ break ;
1951+ }
19091952 }
19101953 CURVNET_RESTORE ();
19111954 return (error );
0 commit comments