diff --git a/sbin/dhclient/bpf.c b/sbin/dhclient/bpf.c index 4a753fd2759..a50abca62fd 100644 --- a/sbin/dhclient/bpf.c +++ b/sbin/dhclient/bpf.c @@ -90,6 +90,14 @@ if_register_bpf(struct interface_info *info, int flags) error("Can't attach interface %s to bpf device %s: %m", info->name, filename); + /* Tag the packets with the proper VLAN PCP setting. */ + if (info->client->config->vlan_pcp != 0) { + if (ioctl(sock, BIOCSETVLANPCP, + &info->client->config->vlan_pcp) < 0) + error( "Can't set the VLAN PCP tag on interface %s: %m", + info->name); + } + return (sock); } diff --git a/sbin/dhclient/clparse.c b/sbin/dhclient/clparse.c index 66695fd6b8f..58ece525f8d 100644 --- a/sbin/dhclient/clparse.c +++ b/sbin/dhclient/clparse.c @@ -76,6 +76,7 @@ read_client_conf(void) memset(&top_level_config, 0, sizeof(top_level_config)); /* Set some defaults... */ + top_level_config.vlan_pcp = 0; top_level_config.timeout = 60; top_level_config.select_interval = 0; top_level_config.reboot_timeout = 10; @@ -201,6 +202,7 @@ parse_client_statement(FILE *cfile, struct interface_info *ip, int token; char *val; struct option *option; + time_t tmp; switch (next_token(&val, cfile)) { case SEND: @@ -260,6 +262,10 @@ parse_client_statement(FILE *cfile, struct interface_info *ip, case REBOOT: parse_lease_time(cfile, &config->reboot_timeout); return; + case VLAN_PCP: + parse_lease_time(cfile, &tmp); + config->vlan_pcp = (u_int)tmp; + return; case BACKOFF_CUTOFF: parse_lease_time(cfile, &config->backoff_cutoff); return; diff --git a/sbin/dhclient/conflex.c b/sbin/dhclient/conflex.c index 66fc9e39712..c11c9189527 100644 --- a/sbin/dhclient/conflex.c +++ b/sbin/dhclient/conflex.c @@ -524,6 +524,8 @@ intern(char *atom, int dfv) case 'v': if (!strcasecmp(atom + 1, "endor-class")) return (VENDOR_CLASS); + if (!strcasecmp(atom + 1, "lan-pcp")) + return (VLAN_PCP); break; case 'y': if (!strcasecmp(atom + 1, "iaddr")) diff --git a/sbin/dhclient/dhclient.conf.5 b/sbin/dhclient/dhclient.conf.5 index 2f28c572257..14a0de4111d 100644 --- a/sbin/dhclient/dhclient.conf.5 +++ b/sbin/dhclient/dhclient.conf.5 @@ -38,7 +38,7 @@ .\" .\" $FreeBSD$ .\" -.Dd May 31, 2018 +.Dd July 21, 2021 .Dt DHCLIENT.CONF 5 .Os .Sh NAME @@ -484,6 +484,13 @@ lease database and will record the media type used to acquire the address. Whenever the client tries to renew the lease, it will use that same media type. The lease must expire before the client will go back to cycling through media types. +.It Ic vlan-pcp Ar code ; +The +.Ic vlan-pcp +statement sets the PCP (Priority Code Point) value for the VLAN header. +This requires the +.Va net.link.vlan.mtag_pcp +sysctl to be set to 1. .El .Sh EXAMPLES The following configuration file is used on a laptop diff --git a/sbin/dhclient/dhcpd.h b/sbin/dhclient/dhcpd.h index 240a3ae23bd..b151daa90a1 100644 --- a/sbin/dhclient/dhcpd.h +++ b/sbin/dhclient/dhcpd.h @@ -159,6 +159,7 @@ struct client_config { u_int8_t required_options[256]; u_int8_t requested_options[256]; int requested_option_count; + u_int vlan_pcp; time_t timeout; time_t initial_interval; time_t retry_interval; diff --git a/sbin/dhclient/dhctoken.h b/sbin/dhclient/dhctoken.h index 26c81aa734d..c929307c7e0 100644 --- a/sbin/dhclient/dhctoken.h +++ b/sbin/dhclient/dhctoken.h @@ -133,6 +133,7 @@ #define AUTHORITATIVE 333 #define TOKEN_NOT 334 #define ALWAYS_REPLY_RFC1048 335 +#define VLAN_PCP 336 #define is_identifier(x) ((x) >= FIRST_TOKEN && \ (x) != STRING && \ diff --git a/share/man/man4/bpf.4 b/share/man/man4/bpf.4 index 20032889104..66f4ae72918 100644 --- a/share/man/man4/bpf.4 +++ b/share/man/man4/bpf.4 @@ -49,7 +49,7 @@ .\" .\" $FreeBSD$ .\" -.Dd October 9, 2020 +.Dd July 22, 2021 .Dt BPF 4 .Os .Sh NAME @@ -659,6 +659,8 @@ therefore ownership is not assigned, the user process must check .Vt bzh_kernel_gen against .Vt bzh_user_gen . +.It Dv BIOCSETVLANPCP +Set the VLAN PCP bits to the supplied value. .El .Sh STANDARD IOCTLS .Nm diff --git a/sys/net/bpf.c b/sys/net/bpf.c index 605e7aa39fd..0343c8f851b 100644 --- a/sys/net/bpf.c +++ b/sys/net/bpf.c @@ -78,6 +78,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -130,6 +131,7 @@ struct bpf_program_buffer { #if defined(DEV_BPF) || defined(NETGRAPH_BPF) #define PRINET 26 /* interruptible */ +#define BPF_PRIO_MAX 7 #define SIZEOF_BPF_HDR(type) \ (offsetof(type, bh_hdrlen) + sizeof(((type *)0)->bh_hdrlen)) @@ -969,6 +971,9 @@ bpfopen(struct cdev *dev, int flags, int fmt, struct thread *td) callout_init_mtx(&d->bd_callout, &d->bd_lock, 0); knlist_init_mtx(&d->bd_sel.si_note, &d->bd_lock); + /* Disable VLAN pcp tagging. */ + d->bd_pcp = 0; + return (0); } @@ -1159,6 +1164,27 @@ bpf_ready(struct bpf_d *d) return (0); } +static int +bpf_setpcp(struct mbuf *m, u_int8_t prio) +{ + struct m_tag *mtag; + + KASSERT(prio <= BPF_PRIO_MAX, + ("%s with invalid pcp", __func__)); + + mtag = m_tag_locate(m, MTAG_8021Q, MTAG_8021Q_PCP_OUT, NULL); + if (mtag == NULL) { + mtag = m_tag_alloc(MTAG_8021Q, MTAG_8021Q_PCP_OUT, + sizeof(uint8_t), M_NOWAIT); + if (mtag == NULL) + return (ENOMEM); + m_tag_prepend(m, mtag); + } + + *(uint8_t *)(mtag + 1) = prio; + return (0); +} + static int bpfwrite(struct cdev *dev, struct uio *uio, int ioflag) { @@ -1259,6 +1285,9 @@ bpfwrite(struct cdev *dev, struct uio *uio, int ioflag) ro.ro_flags = RT_HAS_HEADER; } + if (d->bd_pcp != 0) + bpf_setpcp(m, d->bd_pcp); + /* Avoid possible recursion on BPFD_LOCK(). */ NET_EPOCH_ENTER(et); BPFD_UNLOCK(d); @@ -1348,6 +1377,7 @@ reset_d(struct bpf_d *d) * BIOCROTZBUF Force rotation of zero-copy buffer * BIOCSETBUFMODE Set buffer mode. * BIOCGETBUFMODE Get current buffer mode. + * BIOCSETVLANPCP Set VLAN PCP tag. */ /* ARGSUSED */ static int @@ -1898,6 +1928,19 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, case BIOCROTZBUF: error = bpf_ioctl_rotzbuf(td, d, (struct bpf_zbuf *)addr); break; + + case BIOCSETVLANPCP: + { + u_int pcp; + + pcp = *(u_int *)addr; + if (pcp > BPF_PRIO_MAX || pcp < 0) { + error = EINVAL; + break; + } + d->bd_pcp = pcp; + break; + } } CURVNET_RESTORE(); return (error); diff --git a/sys/net/bpf.h b/sys/net/bpf.h index 54bbfd23bba..b7cd8036856 100644 --- a/sys/net/bpf.h +++ b/sys/net/bpf.h @@ -153,6 +153,7 @@ struct bpf_zbuf { #define BIOCSETFNR _IOW('B', 130, struct bpf_program) #define BIOCGTSTAMP _IOR('B', 131, u_int) #define BIOCSTSTAMP _IOW('B', 132, u_int) +#define BIOCSETVLANPCP _IOW('B', 133, u_int) /* Obsolete */ #define BIOCGSEESENT BIOCGDIRECTION diff --git a/sys/net/bpfdesc.h b/sys/net/bpfdesc.h index be978280311..52cc5f130eb 100644 --- a/sys/net/bpfdesc.h +++ b/sys/net/bpfdesc.h @@ -91,6 +91,7 @@ struct bpf_d { int bd_feedback; /* true to feed back sent packets */ int bd_async; /* non-zero if packet reception should generate signal */ int bd_sig; /* signal to send upon packet reception */ + int bd_pcp; /* VLAN pcp tag */ struct sigio * bd_sigio; /* information for async I/O */ struct selinfo bd_sel; /* bsd select info */ struct mtx bd_lock; /* per-descriptor lock */