Skip to content

Commit 1e7fe2f

Browse files
loos-brkprovost
authored andcommitted
bpf: Add an ioctl to set the VLAN Priority on packets sent by bpf
This allows the use of VLAN PCP in dhclient, which is required for certain ISPs (such as Orange.fr). Reviewed by: bcr (man page) MFC after: 1 week Sponsored by: Rubicon Communications, LLC ("Netgate") Differential Revision: https://reviews.freebsd.org/D31263
1 parent 4b765ab commit 1e7fe2f

File tree

10 files changed

+74
-2
lines changed

10 files changed

+74
-2
lines changed

sbin/dhclient/bpf.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,14 @@ if_register_bpf(struct interface_info *info, int flags)
9090
error("Can't attach interface %s to bpf device %s: %m",
9191
info->name, filename);
9292

93+
/* Tag the packets with the proper VLAN PCP setting. */
94+
if (info->client->config->vlan_pcp != 0) {
95+
if (ioctl(sock, BIOCSETVLANPCP,
96+
&info->client->config->vlan_pcp) < 0)
97+
error( "Can't set the VLAN PCP tag on interface %s: %m",
98+
info->name);
99+
}
100+
93101
return (sock);
94102
}
95103

sbin/dhclient/clparse.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ read_client_conf(void)
7676
memset(&top_level_config, 0, sizeof(top_level_config));
7777

7878
/* Set some defaults... */
79+
top_level_config.vlan_pcp = 0;
7980
top_level_config.timeout = 60;
8081
top_level_config.select_interval = 0;
8182
top_level_config.reboot_timeout = 10;
@@ -201,6 +202,7 @@ parse_client_statement(FILE *cfile, struct interface_info *ip,
201202
int token;
202203
char *val;
203204
struct option *option;
205+
time_t tmp;
204206

205207
switch (next_token(&val, cfile)) {
206208
case SEND:
@@ -260,6 +262,10 @@ parse_client_statement(FILE *cfile, struct interface_info *ip,
260262
case REBOOT:
261263
parse_lease_time(cfile, &config->reboot_timeout);
262264
return;
265+
case VLAN_PCP:
266+
parse_lease_time(cfile, &tmp);
267+
config->vlan_pcp = (u_int)tmp;
268+
return;
263269
case BACKOFF_CUTOFF:
264270
parse_lease_time(cfile, &config->backoff_cutoff);
265271
return;

sbin/dhclient/conflex.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,8 @@ intern(char *atom, int dfv)
524524
case 'v':
525525
if (!strcasecmp(atom + 1, "endor-class"))
526526
return (VENDOR_CLASS);
527+
if (!strcasecmp(atom + 1, "lan-pcp"))
528+
return (VLAN_PCP);
527529
break;
528530
case 'y':
529531
if (!strcasecmp(atom + 1, "iaddr"))

sbin/dhclient/dhclient.conf.5

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
.\"
3939
.\" $FreeBSD$
4040
.\"
41-
.Dd May 31, 2018
41+
.Dd July 21, 2021
4242
.Dt DHCLIENT.CONF 5
4343
.Os
4444
.Sh NAME
@@ -484,6 +484,13 @@ lease database and will record the media type used to acquire the address.
484484
Whenever the client tries to renew the lease, it will use that same media type.
485485
The lease must expire before the client will go back to cycling through media
486486
types.
487+
.It Ic vlan-pcp Ar code ;
488+
The
489+
.Ic vlan-pcp
490+
statement sets the PCP (Priority Code Point) value for the VLAN header.
491+
This requires the
492+
.Va net.link.vlan.mtag_pcp
493+
sysctl to be set to 1.
487494
.El
488495
.Sh EXAMPLES
489496
The following configuration file is used on a laptop

sbin/dhclient/dhcpd.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ struct client_config {
159159
u_int8_t required_options[256];
160160
u_int8_t requested_options[256];
161161
int requested_option_count;
162+
u_int vlan_pcp;
162163
time_t timeout;
163164
time_t initial_interval;
164165
time_t retry_interval;

sbin/dhclient/dhctoken.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@
133133
#define AUTHORITATIVE 333
134134
#define TOKEN_NOT 334
135135
#define ALWAYS_REPLY_RFC1048 335
136+
#define VLAN_PCP 336
136137

137138
#define is_identifier(x) ((x) >= FIRST_TOKEN && \
138139
(x) != STRING && \

share/man/man4/bpf.4

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949
.\"
5050
.\" $FreeBSD$
5151
.\"
52-
.Dd October 9, 2020
52+
.Dd July 22, 2021
5353
.Dt BPF 4
5454
.Os
5555
.Sh NAME
@@ -659,6 +659,8 @@ therefore ownership is not assigned, the user process must check
659659
.Vt bzh_kernel_gen
660660
against
661661
.Vt bzh_user_gen .
662+
.It Dv BIOCSETVLANPCP
663+
Set the VLAN PCP bits to the supplied value.
662664
.El
663665
.Sh STANDARD IOCTLS
664666
.Nm

sys/net/bpf.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
11701196
static int
11711197
bpfwrite(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 */
13611391
static 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);

sys/net/bpf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ struct bpf_zbuf {
153153
#define BIOCSETFNR _IOW('B', 130, struct bpf_program)
154154
#define BIOCGTSTAMP _IOR('B', 131, u_int)
155155
#define BIOCSTSTAMP _IOW('B', 132, u_int)
156+
#define BIOCSETVLANPCP _IOW('B', 133, u_int)
156157

157158
/* Obsolete */
158159
#define BIOCGSEESENT BIOCGDIRECTION

sys/net/bpfdesc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ struct bpf_d {
9191
int bd_feedback; /* true to feed back sent packets */
9292
int bd_async; /* non-zero if packet reception should generate signal */
9393
int bd_sig; /* signal to send upon packet reception */
94+
int bd_pcp; /* VLAN pcp tag */
9495
struct sigio * bd_sigio; /* information for async I/O */
9596
struct selinfo bd_sel; /* bsd select info */
9697
struct mtx bd_lock; /* per-descriptor lock */

0 commit comments

Comments
 (0)