When sending ARP requests, or when writing to a bpf handle (as when
sending DHCP Discover), we bypass pf(4) so we have no way to define
the priority (m->m_pkthdr.pf.prio) of the outgoing packets.
My ISP runs two vlans to separate the delivery of general-purpose
internet and TV/phone over fiber; on the internet vlan, any frame with
a priority different from 0 is dropped; because we use m_pkthdr.pf.prio
to define this priority, and the default priority IFQ_DEFPRIO == 3,
all of my ARP and DHCP frames are dropped when I use a stock OpenBSD
kernel.
This diff adds
1) an if_llprio field to struct ifnet
2) the "llprio" keyword to ifconfig(8) and its manpage
3) code to init m_pkthdr.pf.prio from ifp->if_llprio when doing arp(4)
and bpf(4)
Don't forget to install the new headers before rebuilding ifconfig(8).
Comments ?
diff --git a/sbin/ifconfig/ifconfig.8 b/sbin/ifconfig/ifconfig.8
index c301a90..1f42e41 100644
--- a/sbin/ifconfig/ifconfig.8
+++ b/sbin/ifconfig/ifconfig.8
@@ -327,6 +327,10 @@ Disable special processing at the link level with the
specified interface.
Change the link layer address (MAC address) of the interface.
This should be specified as six colon-separated hex values, or can
be chosen randomly.
+.It Cm llprio Ar prio
+Set the priority for link layer communications
+.Pf ( Xr arp 4 ,
+.Xr bpf 4 ) .
.It Cm media Op Ar type
Set the media type of the interface to
.Ar type .
diff --git a/sbin/ifconfig/ifconfig.c b/sbin/ifconfig/ifconfig.c
index c30ced5..c1e3594 100644
--- a/sbin/ifconfig/ifconfig.c
+++ b/sbin/ifconfig/ifconfig.c
@@ -135,6 +135,7 @@ char name[IFNAMSIZ];
int flags, xflags, setaddr, setipdst, doalias;
u_long metric, mtu;
int rdomainid;
+int llprio;
int clearaddr, s;
int newaddr = 0;
int af = AF_INET;
@@ -157,6 +158,7 @@ void addaf(const char *, int);
void removeaf(const char *, int);
void setifbroadaddr(const char *, int);
void setifmtu(const char *, int);
+void setifllprio(const char *, int);
void setifnwid(const char *, int);
void setifbssid(const char *, int);
void setifnwkey(const char *, int);
@@ -521,6 +523,7 @@ const struct cmd {
{ "instance", NEXTARG, A_MEDIAINST, setmediainst },
{ "inst", NEXTARG, A_MEDIAINST, setmediainst },
{ "lladdr", NEXTARG, 0, setiflladdr },
+ { "llprio", NEXTARG, 0, setifllprio },
{ NULL, /*src*/ 0, 0, setifaddr },
{ NULL, /*dst*/ 0, 0, setifdstaddr },
{ NULL, /*illegal*/0, 0, NULL },
@@ -854,6 +857,11 @@ getinfo(struct ifreq *ifr, int create)
else
rdomainid = ifr->ifr_rdomainid;
#endif
+ if (ioctl(s, SIOCGIFLLPRIO, (caddr_t)ifr) < 0)
+ llprio = 0;
+ else
+ llprio = ifr->ifr_llprio;
+
return (0);
}
@@ -1411,6 +1419,21 @@ setifmtu(const char *val, int d)
/* ARGSUSED */
void
+setifllprio(const char *val, int d)
+{
+ const char *errmsg = NULL;
+
+ (void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+
+ ifr.ifr_mtu = strtonum(val, 0, UCHAR_MAX, &errmsg);
+ if (errmsg)
+ errx(1, "mtu %s: %s", val, errmsg);
+ if (ioctl(s, SIOCSIFLLPRIO, (caddr_t)&ifr) < 0)
+ warn("SIOCSIFLLPRIO");
+}
+
+/* ARGSUSED */
+void
setifgroup(const char *group_name, int dummy)
{
struct ifgroupreq ifgr;
@@ -2894,6 +2917,7 @@ status(int link, struct sockaddr_dl *sdl, int ls)
printf(" metric %lu", metric);
if (mtu)
printf(" mtu %lu", mtu);
+ printf(" llprio %lu", llprio);
putchar('\n');
#ifndef SMALL
if (showcapsflag)
diff --git a/sys/net/bpf.c b/sys/net/bpf.c
index 31b6ed0..d2f1060 100644
--- a/sys/net/bpf.c
+++ b/sys/net/bpf.c
@@ -561,6 +561,7 @@ bpfwrite(dev_t dev, struct uio *uio, int ioflag)
}
m->m_pkthdr.ph_rtableid = ifp->if_rdomain;
+ m->m_pkthdr.pf.prio = ifp->if_llprio;
if (d->bd_hdrcmplt && dst.ss_family == AF_UNSPEC)
dst.ss_family = pseudo_AF_HDRCMPLT;
diff --git a/sys/net/if.c b/sys/net/if.c
index 9b53bf1..e155b77 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -536,6 +536,7 @@ if_attach_common(struct ifnet *ifp)
M_TEMP, M_WAITOK|M_ZERO);
ifp->if_linkstatetask = malloc(sizeof(*ifp->if_linkstatetask),
M_TEMP, M_WAITOK|M_ZERO);
+ ifp->if_llprio = IFQ_DEFPRIO;
SRPL_INIT(&ifp->if_inputs);
}
@@ -1988,6 +1989,16 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data,
struct proc *p)
ifnewlladdr(ifp);
break;
+ case SIOCGIFLLPRIO:
+ ifr->ifr_llprio = ifp->if_llprio;
+ break;
+
+ case SIOCSIFLLPRIO:
+ if ((error = suser(p, 0)))
+ return (error);
+ ifp->if_llprio = ifr->ifr_llprio;
+ break;
+
default:
if (so->so_proto == 0)
return (EOPNOTSUPP);
diff --git a/sys/net/if.h b/sys/net/if.h
index 3d3569d..a8d17f6 100644
--- a/sys/net/if.h
+++ b/sys/net/if.h
@@ -104,6 +104,7 @@ struct if_data {
u_int32_t ifi_metric; /* routing metric (external
only) */
u_int32_t ifi_rdomain; /* routing instance */
u_int64_t ifi_baudrate; /* linespeed */
+ u_char ifi_llprio; /* link layer data priority */
/* volatile statistics */
u_int64_t ifi_ipackets; /* packets received on
interface */
u_int64_t ifi_ierrors; /* input errors on interface */
@@ -378,6 +379,7 @@ struct ifreq {
#define ifr_ttl ifr_ifru.ifru_metric /* tunnel TTL
(overload) */
#define ifr_data ifr_ifru.ifru_data /* for use by interface
*/
#define ifr_index ifr_ifru.ifru_index /* interface index */
+#define ifr_llprio ifr_ifru.ifru_metric /* link layer priority */
};
struct ifaliasreq {
diff --git a/sys/net/if_var.h b/sys/net/if_var.h
index d0f4e34..b207a08 100644
--- a/sys/net/if_var.h
+++ b/sys/net/if_var.h
@@ -179,6 +179,7 @@ struct ifnet { /* and the
entries */
#define if_lastchange if_data.ifi_lastchange
#define if_capabilities if_data.ifi_capabilities
#define if_rdomain if_data.ifi_rdomain
+#define if_llprio if_data.ifi_llprio
/*
* The ifaddr structure contains information about one address
diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c
index 1992c3a..989287c 100644
--- a/sys/netinet/if_ether.c
+++ b/sys/netinet/if_ether.c
@@ -234,6 +234,7 @@ arprequest(struct ifnet *ifp, u_int32_t *sip, u_int32_t
*tip, u_int8_t *enaddr)
m->m_len = sizeof(*ea);
m->m_pkthdr.len = sizeof(*ea);
m->m_pkthdr.ph_rtableid = ifp->if_rdomain;
+ m->m_pkthdr.pf.prio = ifp->if_llprio;
MH_ALIGN(m, sizeof(*ea));
ea = mtod(m, struct ether_arp *);
eh = (struct ether_header *)sa.sa_data;
@@ -823,6 +824,7 @@ revarprequest(struct ifnet *ifp)
return;
m->m_len = sizeof(*ea);
m->m_pkthdr.len = sizeof(*ea);
+ m->m_pkthdr.pf.prio = ifp->if_llprio;
MH_ALIGN(m, sizeof(*ea));
ea = mtod(m, struct ether_arp *);
eh = (struct ether_header *)sa.sa_data;
diff --git a/sys/sys/sockio.h b/sys/sys/sockio.h
index 1d6d35a..8ec81fd 100644
--- a/sys/sys/sockio.h
+++ b/sys/sys/sockio.h
@@ -202,6 +202,9 @@
#define SIOCGIFPARENT _IOWR('i', 179, struct if_parent) /* get parent if */
#define SIOCDIFPARENT _IOW('i', 180, struct ifreq) /* del parent if */
+#define SIOCSIFLLPRIO _IOW('i', 181, struct ifreq) /* set ifnet
llprio */
+#define SIOCGIFLLPRIO _IOWR('i', 182, struct ifreq) /* get ifnet
llprio */
+
#define SIOCSVH _IOWR('i', 245, struct ifreq) /* set carp
param */
#define SIOCGVH _IOWR('i', 246, struct ifreq) /* get carp
param */