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 */
 

Reply via email to