Date: Wed, 3 Jul 2013 00:56:10 +0900 From: Takuya ASADA <syuu@dokukino.com> To: Luigi Rizzo <rizzo@iet.unipi.it> Cc: FreeBSD Net <freebsd-net@freebsd.org> Subject: Re: Multiqueue support for bpf Message-ID: <CALG4x-UYBFsMttpZx1-c_wtVf5MST8%2B_t1psY2HQskTiOZDFLA@mail.gmail.com> In-Reply-To: <CA%2BhQ2%2BgwW6FOQS79xmWVLSWWHrZMFnhaUM98Kp6aDVaUePNfTA@mail.gmail.com> References: <CALG4x-V-OLoqMXQarSNy5Lv3kNVu01AiN4A49Nv7t-Ysfr1DBg@mail.gmail.com> <CA%2BhQ2%2BgwW6FOQS79xmWVLSWWHrZMFnhaUM98Kp6aDVaUePNfTA@mail.gmail.com>
next in thread | previous in thread | raw e-mail | index | archive | help
[-- Attachment #1 --] Hi, Do you have an updated URL for the diffs ? The link below from your > original message > seems not working now (NXDOMAIN) > > http://www.dokukino.com/mq_bpf_20110813.diff > Changes with recent head is on my repository: http://svnweb.freebsd.org/base/user/syuu/mq_bpf/ And I attached a diff file on this mail. [-- Attachment #2 --] Index: ifnet.9 =================================================================== --- ifnet.9 (.../head/share/man/man9/ifnet.9) (revision 252509) +++ ifnet.9 (.../user/syuu/mq_bpf/share/man/man9/ifnet.9) (revision 252509) @@ -119,6 +119,14 @@ .Fo \*(lp*if_resolvemulti\*(rp .Fa "struct ifnet *ifp" "struct sockaddr **retsa" "struct sockaddr *addr" .Fc +.Ft int +.Fn \*(lp*if_get_rxqueue_len\*(rp "struct ifnet *ifp" +.Ft int +.Fn \*(lp*if_get_txqueue_len\*(rp "struct ifnet *ifp" +.Ft int +.Fn \*(lp*if_get_rxqueue_affinity\*(rp "struct ifnet *ifp" "int queid" +.Ft int +.Fn \*(lp*if_get_txqueue_affinity\*(rp "struct ifnet *ifp" "int queid" .Ss "struct ifaddr member function" .Ft void .Fo \*(lp*ifa_rtrequest\*(rp @@ -537,6 +545,14 @@ corresponds to that address which is returned in .Fa *retsa . Returns zero on success, or an error code on failure. +.It Fn if_get_rxqueue_len +Get RX queue length, only required for multiqueue supported interfaces. +.It Fn if_get_txqueue_len +Get TX queue length, only required for multiqueue supported interfaces. +.It Fn if_get_rxqueue_affinity +Get RX queue affinity, only required for multiqueue supported interfaces. +.It Fn if_get_txqueue_affinity +Get TX queue affinity, only required for multiqueue supported interfaces. .El .Ss "Interface Flags" Interface flags are used for a number of different purposes. Index: bpf.4 =================================================================== --- bpf.4 (.../head/share/man/man4/bpf.4) (revision 252509) +++ bpf.4 (.../user/syuu/mq_bpf/share/man/man4/bpf.4) (revision 252509) @@ -631,6 +631,46 @@ .Vt bzh_kernel_gen against .Vt bzh_user_gen . +.It Dv BIOCENAQMASK +Enables multiqueue filter on the descriptor. + +.It Dv BIOCDISQMASK +Disables multiqueue filter on the descriptor. + +.It Dv BIOCSTRXQMASK +.Pq Li uint32_t +Set mask bit on specified RX queue. + +.It Dv BIOCCRRXQMASK +.Pq Li uint32_t +Clear mask bit on specified RX queue. + +.It Dv BIOCGTRXQMASK +.Pq Li uint32_t +Get mask bit on specified RX queue. + +.It Dv BIOCSTTXQMASK +.Pq Li uint32_t +Set mask bit on specified TX queue. + +.It Dv BIOCCRTXQMASK +.Pq Li uint32_t +Clear mask bit on specified TX queue. + +.It Dv BIOCGTTXQMASK +.Pq Li uint32_t +Get mask bit on specified TX queue. + +.It Dv BIOCSTOTHERMASK +Set mask bit for the packets which not tied with any queues. + +.It Dv BIOCCROTHERMASK +Clear mask bit for the packets which not tied with any queues. + +.It Dv BIOCGTOTHERMASK +.Pq Li uint32_t +Get mask bit for the packets which not tied with any queues. + .El .Sh BPF HEADER One of the following structures is prepended to each packet returned by @@ -1037,6 +1077,24 @@ BPF_STMT(BPF_RET+BPF_K, 0), }; .Ed +.Sh MULTIQUEUE SUPPORT +Multiqueue network interface support function provides interfaces for +multithreaded packet processing using bpf. + +Normal bpf can receive packets from specified interface, multiqueue support +function can receive packets from specified hardware queue. + +This distributes bpf workload on multiple threads, also reduces lock +contention on bpf. + +To make your program multithreaded, you'll need to open bpf descriptor on each +thread, enable multiqueue support by BIOCENAQMASK ioctl, and set queue mask by +BIOCSTRXQMASK / BIOCSTTXQMASK / BIOCSTOTHERMASK ioctls. + +Queue length and queue affinity information may useful to optimize setting +queue mask on bpf descriptor, see +.Xr netintro 4 . + .Sh SEE ALSO .Xr tcpdump 1 , .Xr ioctl 2 , Index: ifconfig.c =================================================================== --- ifconfig.c (.../head/sbin/ifconfig/ifconfig.c) (revision 252509) +++ ifconfig.c (.../user/syuu/mq_bpf/sbin/ifconfig/ifconfig.c) (revision 252509) @@ -917,7 +917,7 @@ "\020\1RXCSUM\2TXCSUM\3NETCONS\4VLAN_MTU\5VLAN_HWTAGGING\6JUMBO_MTU\7POLLING" \ "\10VLAN_HWCSUM\11TSO4\12TSO6\13LRO\14WOL_UCAST\15WOL_MCAST\16WOL_MAGIC" \ "\17TOE4\20TOE6\21VLAN_HWFILTER\23VLAN_HWTSO\24LINKSTATE\25NETMAP" \ -"\26RXCSUM_IPV6\27TXCSUM_IPV6" +"\26RXCSUM_IPV6\27TXCSUM_IPV6\30MULTIQUEUE" /* * Print the status of the interface. If an address family was @@ -984,6 +984,38 @@ } } + if ((ifr.ifr_reqcap & IFCAP_MULTIQUEUE)) { + int i, rxqlen = 0, txqlen = 0; + + if (ioctl(s, SIOCGIFQLEN, &ifr) == 0) { + rxqlen = ifr.ifr_rxqueue_len; + txqlen = ifr.ifr_txqueue_len; + }else + perror("ioctl"); + + printf("\trxqueue len=%d affinity=[", rxqlen); + for (i = 0; i < rxqlen; i++) { + ifr.ifr_queue_affinity_index = i; + if (ioctl(s, SIOCGIFRXQAFFINITY, &ifr) == 0) + printf(" %d:%d", ifr.ifr_queue_affinity_index, + ifr.ifr_queue_affinity_cpu); + else + perror("ioctl"); + } + printf(" ]\n"); + + printf("\ttxqueue len=%d affinity=[", txqlen); + for (i = 0; i < txqlen; i++) { + ifr.ifr_queue_affinity_index = i; + if (ioctl(s, SIOCGIFTXQAFFINITY, &ifr) == 0) + printf(" %d:%d", ifr.ifr_queue_affinity_index, + ifr.ifr_queue_affinity_cpu); + else + perror("ioctl"); + } + printf(" ]\n"); + } + tunnel_status(s); for (ift = ifa; ift != NULL; ift = ift->ifa_next) { Index: tcpdump.c =================================================================== --- tcpdump.c (.../head/contrib/tcpdump/tcpdump.c) (revision 252509) +++ tcpdump.c (.../user/syuu/mq_bpf/contrib/tcpdump/tcpdump.c) (revision 252509) @@ -702,6 +702,7 @@ #endif int status; FILE *VFile; + uint32_t rxq = (uint32_t)-1, txq = (uint32_t)-1, other = (uint32_t)-1; #ifdef WIN32 if(wsockinit() != 0) return 1; #endif /* WIN32 */ @@ -737,7 +738,7 @@ #endif while ( - (op = getopt(argc, argv, "aAb" B_FLAG "c:C:d" D_FLAG "eE:fF:G:hHi:" I_FLAG j_FLAG J_FLAG "KlLm:M:nNOpqr:Rs:StT:u" U_FLAG "V:vw:W:xXy:Yz:Z:")) != -1) + (op = getopt(argc, argv, "aAb" B_FLAG "c:C:d" D_FLAG "eE:fF:G:hHi:" I_FLAG j_FLAG J_FLAG "KlLm:M:nNOpqr:Rs:StT:u" U_FLAG "V:vw:W:xXy:Yz:Z:Q:g:k")) != -1) switch (op) { case 'a': @@ -815,6 +816,10 @@ infile = optarg; break; + case 'g': + txq = atoi(optarg); + break; + case 'G': Gflag = atoi(optarg); if (Gflag < 0) @@ -919,6 +924,12 @@ #endif /* WIN32 */ break; + case 'k': + other = atoi(optarg); + if (other != 0 || other != 1) + usage(); + break; + case 'K': ++Kflag; break; @@ -965,6 +976,10 @@ ++suppress_default_print; break; + case 'Q': + rxq = atoi(optarg); + break; + case 'r': RFileName = optarg; break; @@ -1274,6 +1289,13 @@ device, pcap_statustostr(status)); } #endif + if (rxq != (uint32_t)-1) + pcap_set_rxq_mask(pd, rxq); + if (txq != (uint32_t)-1) + pcap_set_txq_mask(pd, txq); + if (other != (uint32_t)-1) + pcap_set_other_mask(pd, other); + status = pcap_activate(pd); if (status < 0) { /* @@ -2078,7 +2100,7 @@ #endif /* WIN32 */ #endif /* HAVE_PCAP_LIB_VERSION */ (void)fprintf(stderr, -"Usage: %s [-aAbd" D_FLAG "efhH" I_FLAG J_FLAG "KlLnNOpqRStu" U_FLAG "vxX]" B_FLAG_USAGE " [ -c count ]\n", program_name); +"Usage: %s [-aAbd" D_FLAG "efghH" I_FLAG J_FLAG "kKlLnNOpqQRStu" U_FLAG "vxX]" B_FLAG_USAGE " [ -c count ]\n", program_name); (void)fprintf(stderr, "\t\t[ -C file_size ] [ -E algo:secret ] [ -F file ] [ -G seconds ]\n"); (void)fprintf(stderr, Index: pcap-int.h =================================================================== --- pcap-int.h (.../head/contrib/libpcap/pcap-int.h) (revision 252509) +++ pcap-int.h (.../user/syuu/mq_bpf/contrib/libpcap/pcap-int.h) (revision 252509) @@ -337,6 +337,9 @@ u_int *tstamp_type_list; struct pcap_pkthdr pcap_header; /* This is needed for the pcap_next_ex() to work */ + + uint32_t rxq_num, txq_num; + uint32_t other_mask; }; /* Index: pcap.h =================================================================== --- pcap.h (.../head/contrib/libpcap/pcap/pcap.h) (revision 252509) +++ pcap.h (.../user/syuu/mq_bpf/contrib/libpcap/pcap/pcap.h) (revision 252509) @@ -331,6 +331,10 @@ #define PCAP_TSTAMP_ADAPTER 3 /* device-provided, synced with the system clock */ #define PCAP_TSTAMP_ADAPTER_UNSYNCED 4 /* device-provided, not synced with the system clock */ +int pcap_set_rxq_mask(pcap_t *, uint32_t); +int pcap_set_txq_mask(pcap_t *, uint32_t); +int pcap_set_other_mask(pcap_t *, uint32_t); + pcap_t *pcap_open_live(const char *, int, int, int, char *); pcap_t *pcap_open_dead(int, int); pcap_t *pcap_open_offline(const char *, char *); Index: pcap.c =================================================================== --- pcap.c (.../head/contrib/libpcap/pcap.c) (revision 252509) +++ pcap.c (.../user/syuu/mq_bpf/contrib/libpcap/pcap.c) (revision 252509) @@ -505,6 +505,9 @@ p->opt.promisc = 0; p->opt.buffer_size = 0; p->opt.tstamp_type = -1; /* default to not setting time stamp type */ + p->rxq_num = (uint32_t)-1; + p->txq_num = (uint32_t)-1; + p->other_mask = (uint32_t)-1; return (p); } @@ -637,6 +640,33 @@ return (status); } +int +pcap_set_rxq_mask(pcap_t *p, uint32_t num) +{ + if (pcap_check_activated(p)) + return PCAP_ERROR_ACTIVATED; + p->rxq_num = num; + return 0; +} + +int +pcap_set_txq_mask(pcap_t *p, uint32_t num) +{ + if (pcap_check_activated(p)) + return PCAP_ERROR_ACTIVATED; + p->txq_num = num; + return 0; +} + +int +pcap_set_other_mask(pcap_t *p, uint32_t mask) +{ + if (pcap_check_activated(p)) + return PCAP_ERROR_ACTIVATED; + p->other_mask = mask; + return 0; +} + pcap_t * pcap_open_live(const char *source, int snaplen, int promisc, int to_ms, char *errbuf) { Index: pcap-bpf.c =================================================================== --- pcap-bpf.c (.../head/contrib/libpcap/pcap-bpf.c) (revision 252509) +++ pcap-bpf.c (.../user/syuu/mq_bpf/contrib/libpcap/pcap-bpf.c) (revision 252509) @@ -34,6 +34,7 @@ #include <sys/mman.h> #endif #include <sys/socket.h> +#include <sys/types.h> #include <time.h> /* * <net/bpf.h> defines ioctls, but doesn't include <sys/ioccom.h>. @@ -2187,6 +2188,40 @@ } #endif + if (p->rxq_num != (uint32_t)-1 || p->txq_num != (uint32_t)-1 || + p->other_mask != (uint32_t)-1) { + if (ioctl(fd, BIOCENAQMASK, NULL) < 0) { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCENAQMASK: %s", + pcap_strerror(errno)); + status = PCAP_ERROR; + goto bad; + } + if (p->rxq_num != (uint32_t)-1) { + if (ioctl(fd, BIOCSTRXQMASK, &p->rxq_num) < 0) { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSTRXQMASK: %s", + pcap_strerror(errno)); + status = PCAP_ERROR; + goto bad; + } + } + if (p->txq_num != (uint32_t)-1) { + if (ioctl(fd, BIOCSTTXQMASK, &p->txq_num) < 0) { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSTTXQMASK: %s", + pcap_strerror(errno)); + status = PCAP_ERROR; + goto bad; + } + } + if (p->other_mask != (uint32_t)-1) { + if (ioctl(fd, BIOCSTOTHERMASK, &p->other_mask) < 0) { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSTOTHERQMASK: %s", + pcap_strerror(errno)); + status = PCAP_ERROR; + goto bad; + } + } + } + /* * If there's no filter program installed, there's * no indication to the kernel of what the snapshot Index: ifnet.9 =================================================================== --- ifnet.9 (.../head/share/man/man9/ifnet.9) (revision 252509) +++ ifnet.9 (.../user/syuu/mq_bpf/share/man/man9/ifnet.9) (revision 252509) @@ -119,6 +119,14 @@ .Fo \*(lp*if_resolvemulti\*(rp .Fa "struct ifnet *ifp" "struct sockaddr **retsa" "struct sockaddr *addr" .Fc +.Ft int +.Fn \*(lp*if_get_rxqueue_len\*(rp "struct ifnet *ifp" +.Ft int +.Fn \*(lp*if_get_txqueue_len\*(rp "struct ifnet *ifp" +.Ft int +.Fn \*(lp*if_get_rxqueue_affinity\*(rp "struct ifnet *ifp" "int queid" +.Ft int +.Fn \*(lp*if_get_txqueue_affinity\*(rp "struct ifnet *ifp" "int queid" .Ss "struct ifaddr member function" .Ft void .Fo \*(lp*ifa_rtrequest\*(rp @@ -537,6 +545,14 @@ corresponds to that address which is returned in .Fa *retsa . Returns zero on success, or an error code on failure. +.It Fn if_get_rxqueue_len +Get RX queue length, only required for multiqueue supported interfaces. +.It Fn if_get_txqueue_len +Get TX queue length, only required for multiqueue supported interfaces. +.It Fn if_get_rxqueue_affinity +Get RX queue affinity, only required for multiqueue supported interfaces. +.It Fn if_get_txqueue_affinity +Get TX queue affinity, only required for multiqueue supported interfaces. .El .Ss "Interface Flags" Interface flags are used for a number of different purposes. Index: netintro.4 =================================================================== --- netintro.4 (.../head/share/man/man4/netintro.4) (revision 252509) +++ netintro.4 (.../user/syuu/mq_bpf/share/man/man4/netintro.4) (revision 252509) @@ -213,6 +213,8 @@ int ifru_media; caddr_t ifru_data; int ifru_cap[2]; + int ifru_queue_len[2]; + int ifru_queue_affinity[2]; } ifr_ifru; #define ifr_addr ifr_ifru.ifru_addr /* address */ #define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-to-p link */ @@ -228,6 +230,10 @@ #define ifr_reqcap ifr_ifru.ifru_cap[0] /* requested capabilities */ #define ifr_curcap ifr_ifru.ifru_cap[1] /* current capabilities */ #define ifr_index ifr_ifru.ifru_index /* interface index */ +#define ifr_rxqueue_len ifr_ifru.ifru_queue_len[0] /* rxqueue len */ +#define ifr_txqueue_len ifr_ifru.ifru_queue_len[1] /* txqueue len */ +#define ifr_queue_affinity_index ifr_ifru.ifru_queue_affinity[0] /* queue id */ +#define ifr_queue_affinity_cpu ifr_ifru.ifru_queue_affinity[1] /* cpu id */ }; .Ed .Pp @@ -319,6 +325,12 @@ field will contain the new interface name. .It Dv SIOCIFDESTROY Attempt to destroy the specified interface. +.It Dv SIOCGIFQLEN +Get interface RX/TX queue length. +.It Dv SIOCGIFRXQAFFINITY +Get interface RX queue affinity. +.It Dv SIOCGIFTXQAFFINITY +Get interface TX queue affinity. .El .Pp There are two requests that make use of a new structure: Index: bpf.4 =================================================================== --- bpf.4 (.../head/share/man/man4/bpf.4) (revision 252509) +++ bpf.4 (.../user/syuu/mq_bpf/share/man/man4/bpf.4) (revision 252509) @@ -631,6 +631,46 @@ .Vt bzh_kernel_gen against .Vt bzh_user_gen . +.It Dv BIOCENAQMASK +Enables multiqueue filter on the descriptor. + +.It Dv BIOCDISQMASK +Disables multiqueue filter on the descriptor. + +.It Dv BIOCSTRXQMASK +.Pq Li uint32_t +Set mask bit on specified RX queue. + +.It Dv BIOCCRRXQMASK +.Pq Li uint32_t +Clear mask bit on specified RX queue. + +.It Dv BIOCGTRXQMASK +.Pq Li uint32_t +Get mask bit on specified RX queue. + +.It Dv BIOCSTTXQMASK +.Pq Li uint32_t +Set mask bit on specified TX queue. + +.It Dv BIOCCRTXQMASK +.Pq Li uint32_t +Clear mask bit on specified TX queue. + +.It Dv BIOCGTTXQMASK +.Pq Li uint32_t +Get mask bit on specified TX queue. + +.It Dv BIOCSTOTHERMASK +Set mask bit for the packets which not tied with any queues. + +.It Dv BIOCCROTHERMASK +Clear mask bit for the packets which not tied with any queues. + +.It Dv BIOCGTOTHERMASK +.Pq Li uint32_t +Get mask bit for the packets which not tied with any queues. + .El .Sh BPF HEADER One of the following structures is prepended to each packet returned by @@ -1037,6 +1077,24 @@ BPF_STMT(BPF_RET+BPF_K, 0), }; .Ed +.Sh MULTIQUEUE SUPPORT +Multiqueue network interface support function provides interfaces for +multithreaded packet processing using bpf. + +Normal bpf can receive packets from specified interface, multiqueue support +function can receive packets from specified hardware queue. + +This distributes bpf workload on multiple threads, also reduces lock +contention on bpf. + +To make your program multithreaded, you'll need to open bpf descriptor on each +thread, enable multiqueue support by BIOCENAQMASK ioctl, and set queue mask by +BIOCSTRXQMASK / BIOCSTTXQMASK / BIOCSTOTHERMASK ioctls. + +Queue length and queue affinity information may useful to optimize setting +queue mask on bpf descriptor, see +.Xr netintro 4 . + .Sh SEE ALSO .Xr tcpdump 1 , .Xr ioctl 2 , Index: if_mxge.c =================================================================== --- if_mxge.c (.../head/sys/dev/mxge/if_mxge.c) (revision 252509) +++ if_mxge.c (.../user/syuu/mq_bpf/sys/dev/mxge/if_mxge.c) (revision 252509) @@ -120,6 +120,11 @@ static int mxge_shutdown(device_t dev); static void mxge_intr(void *arg); +static int mxge_get_rxqueue_len(struct ifnet *); +static int mxge_get_txqueue_len(struct ifnet *); +static int mxge_get_rxqueue_affinity(struct ifnet *, int); +static int mxge_get_txqueue_affinity(struct ifnet *, int); + static device_method_t mxge_methods[] = { /* Device interface */ @@ -2272,6 +2277,9 @@ if (m == NULL) { return; } + m->m_pkthdr.rxqueue = (uint32_t)-1; + m->m_pkthdr.txqueue = (ss - sc->ss); + /* let BPF see it */ BPF_MTAP(ifp, m); @@ -2306,6 +2314,9 @@ if (!drbr_needs_enqueue(ifp, tx->br) && ((tx->mask - (tx->req - tx->done)) > tx->max_desc)) { + m->m_pkthdr.rxqueue = (uint32_t)-1; + m->m_pkthdr.txqueue = (ss - sc->ss); + /* let BPF see it */ BPF_MTAP(ifp, m); /* give it to the nic */ @@ -2719,6 +2730,8 @@ if (sc->num_slices > 1) { m->m_pkthdr.flowid = (ss - sc->ss); m->m_flags |= M_FLOWID; + m->m_pkthdr.rxqueue = (ss - sc->ss); + m->m_pkthdr.txqueue = (uint32_t)-1; } /* pass the frame up the stack */ (*ifp->if_input)(ifp, m); @@ -4896,6 +4909,7 @@ #if defined(INET) || defined(INET6) ifp->if_capabilities |= IFCAP_LRO; #endif + ifp->if_capabilities |= IFCAP_MULTIQUEUE; #ifdef MXGE_NEW_VLAN_API ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_HWCSUM; @@ -4929,6 +4943,11 @@ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = mxge_ioctl; ifp->if_start = mxge_start; + ifp->if_get_rxqueue_len = mxge_get_rxqueue_len; + ifp->if_get_txqueue_len = mxge_get_txqueue_len; + ifp->if_get_rxqueue_affinity = mxge_get_rxqueue_affinity; + ifp->if_get_txqueue_affinity = mxge_get_txqueue_affinity; + /* Initialise the ifmedia structure */ ifmedia_init(&sc->media, 0, mxge_media_change, mxge_media_status); @@ -5025,6 +5044,33 @@ return 0; } + +static int +mxge_get_rxqueue_len(struct ifnet *ifp) +{ + mxge_softc_t *sc = ifp->if_softc; + return (sc->num_slices); +} + +static int +mxge_get_txqueue_len(struct ifnet *ifp) +{ + mxge_softc_t *sc = ifp->if_softc; + return (sc->num_slices); +} + +static int +mxge_get_rxqueue_affinity(struct ifnet *ifp, int queid) +{ + return (queid); +} + +static int +mxge_get_txqueue_affinity(struct ifnet *ifp, int queid) +{ + return (queid); +} + /* This file uses Myri10GE driver indentation. Index: ixgbe.c =================================================================== --- ixgbe.c (.../head/sys/dev/ixgbe/ixgbe.c) (revision 252509) +++ ixgbe.c (.../user/syuu/mq_bpf/sys/dev/ixgbe/ixgbe.c) (revision 252509) @@ -210,6 +210,12 @@ /* Missing shared code prototype */ extern void ixgbe_stop_mac_link_on_d3_82599(struct ixgbe_hw *hw); +static int ixgbe_get_rxqueue_len(struct ifnet *); +static int ixgbe_get_txqueue_len(struct ifnet *); +static int ixgbe_get_rxqueue_affinity(struct ifnet *, int); +static int ixgbe_get_txqueue_affinity(struct ifnet *, int); + + /********************************************************************* * FreeBSD Device Interface Entry Points *********************************************************************/ @@ -753,6 +759,10 @@ IFQ_DRV_PREPEND(&ifp->if_snd, m_head); break; } + + m_head->m_pkthdr.rxqueue = (uint32_t)-1; + m_head->m_pkthdr.txqueue = txr->me; + /* Send a copy of the frame to the BPF listener */ ETHER_BPF_MTAP(ifp, m_head); @@ -851,6 +861,10 @@ drbr_advance(ifp, txr->br); #endif enqueued++; + + next->m_pkthdr.rxqueue = (uint32_t)-1; + next->m_pkthdr.txqueue = txr->me; + /* Send a copy of the frame to the BPF listener */ ETHER_BPF_MTAP(ifp, next); if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) @@ -2618,6 +2632,10 @@ ifp->if_softc = adapter; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = ixgbe_ioctl; + ifp->if_get_rxqueue_len = ixgbe_get_rxqueue_len; + ifp->if_get_txqueue_len = ixgbe_get_txqueue_len; + ifp->if_get_rxqueue_affinity = ixgbe_get_rxqueue_affinity; + ifp->if_get_txqueue_affinity = ixgbe_get_txqueue_affinity; #ifndef IXGBE_LEGACY_TX ifp->if_transmit = ixgbe_mq_start; ifp->if_qflush = ixgbe_qflush; @@ -2644,6 +2662,7 @@ ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_HWTSO | IFCAP_VLAN_MTU; + ifp->if_capabilities |= IFCAP_MULTIQUEUE; ifp->if_capenable = ifp->if_capabilities; /* @@ -4547,6 +4566,8 @@ sendmp->m_pkthdr.flowid = que->msix; sendmp->m_flags |= M_FLOWID; #endif + sendmp->m_pkthdr.rxqueue = que->msix; + sendmp->m_pkthdr.txqueue = (uint32_t)-1; } next_desc: bus_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map, @@ -5743,6 +5764,32 @@ return (error); } +static int +ixgbe_get_rxqueue_len(struct ifnet *ifp) +{ + struct adapter *adapter = ifp->if_softc; + return (adapter->num_queues); +} + +static int +ixgbe_get_txqueue_len(struct ifnet *ifp) +{ + struct adapter *adapter = ifp->if_softc; + return (adapter->num_queues); +} + +static int +ixgbe_get_rxqueue_affinity(struct ifnet *ifp, int queid) +{ + return (queid); +} + +static int +ixgbe_get_txqueue_affinity(struct ifnet *ifp, int queid) +{ + return (queid); +} + /* ** Thermal Shutdown Trigger ** - cause a Thermal Overtemp IRQ Index: if_igb.c =================================================================== --- if_igb.c (.../head/sys/dev/e1000/if_igb.c) (revision 252509) +++ if_igb.c (.../user/syuu/mq_bpf/sys/dev/e1000/if_igb.c) (revision 252509) @@ -278,6 +278,11 @@ static int igb_sysctl_dmac(SYSCTL_HANDLER_ARGS); static int igb_sysctl_eee(SYSCTL_HANDLER_ARGS); +static int igb_get_rxqueue_len(struct ifnet *); +static int igb_get_txqueue_len(struct ifnet *); +static int igb_get_rxqueue_affinity(struct ifnet *, int); +static int igb_get_txqueue_affinity(struct ifnet *, int); + #ifdef DEVICE_POLLING static poll_handler_t igb_poll; #endif /* POLLING */ @@ -919,6 +924,9 @@ break; } + m_head->m_pkthdr.rxqueue = (uint32_t)-1; + m_head->m_pkthdr.txqueue = txr->me; + /* Send a copy of the frame to the BPF listener */ ETHER_BPF_MTAP(ifp, m_head); @@ -1012,6 +1020,8 @@ ifp->if_obytes += next->m_pkthdr.len; if (next->m_flags & M_MCAST) ifp->if_omcasts++; + next->m_pkthdr.rxqueue = (uint32_t)-1; + next->m_pkthdr.txqueue = txr->me; ETHER_BPF_MTAP(ifp, next); if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) break; @@ -3112,6 +3122,10 @@ ifp->if_softc = adapter; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = igb_ioctl; + ifp->if_get_rxqueue_len = igb_get_rxqueue_len; + ifp->if_get_txqueue_len = igb_get_txqueue_len; + ifp->if_get_rxqueue_affinity = igb_get_rxqueue_affinity; + ifp->if_get_txqueue_affinity = igb_get_txqueue_affinity; #ifndef IGB_LEGACY_TX ifp->if_transmit = igb_mq_start; ifp->if_qflush = igb_qflush; @@ -3159,6 +3173,7 @@ ** enable this and get full hardware tag filtering. */ ifp->if_capabilities |= IFCAP_VLAN_HWFILTER; + ifp->if_capabilities |= IFCAP_MULTIQUEUE; /* * Specify the media types supported by this adapter and register @@ -4883,6 +4898,9 @@ rxr->fmp->m_pkthdr.flowid = que->msix; rxr->fmp->m_flags |= M_FLOWID; #endif + rxr->fmp->m_pkthdr.rxqueue = que->msix; + rxr->fmp->m_pkthdr.txqueue = (uint32_t)-1; + sendmp = rxr->fmp; /* Make sure to set M_PKTHDR. */ sendmp->m_flags |= M_PKTHDR; @@ -6047,3 +6065,29 @@ IGB_CORE_UNLOCK(adapter); return (0); } + +static int +igb_get_rxqueue_len(struct ifnet *ifp) +{ + struct adapter *adapter = ifp->if_softc; + return (adapter->num_queues); +} + +static int +igb_get_txqueue_len(struct ifnet *ifp) +{ + struct adapter *adapter = ifp->if_softc; + return (adapter->num_queues); +} + +static int +igb_get_rxqueue_affinity(struct ifnet *ifp, int queid) +{ + return (queid); +} + +static int +igb_get_txqueue_affinity(struct ifnet *ifp, int queid) +{ + return (queid); +} Index: bpfdesc.h =================================================================== --- bpfdesc.h (.../head/sys/net/bpfdesc.h) (revision 252509) +++ bpfdesc.h (.../user/syuu/mq_bpf/sys/net/bpfdesc.h) (revision 252509) @@ -45,6 +45,20 @@ #include <sys/conf.h> #include <net/if.h> +struct bpf_qmask { + boolean_t qm_enabled; + boolean_t * qm_rxq_mask; + boolean_t * qm_txq_mask; + boolean_t qm_other_mask; + struct rwlock qm_lock; +}; + +#define BPFQ_LOCK_DESTROY(qm) rw_destroy(&(qm)->qm_lock) +#define BPFQ_RLOCK(qm) rw_rlock(&(qm)->qm_lock) +#define BPFQ_RUNLOCK(qm) rw_runlock(&(qm)->qm_lock) +#define BPFQ_WLOCK(qm) rw_wlock(&(qm)->qm_lock) +#define BPFQ_WUNLOCK(qm) rw_wunlock(&(qm)->qm_lock) + /* * Descriptor associated with each open bpf file. */ @@ -101,6 +115,7 @@ u_int64_t bd_wdcount; /* number of packets dropped during a write */ u_int64_t bd_zcopy; /* number of zero copy operations */ u_char bd_compat32; /* 32-bit stream on LP64 system */ + struct bpf_qmask bd_qmask; }; /* Values for bd_state */ Index: if_var.h =================================================================== --- if_var.h (.../head/sys/net/if_var.h) (revision 252509) +++ if_var.h (.../user/syuu/mq_bpf/sys/net/if_var.h) (revision 252509) @@ -176,6 +176,15 @@ (struct ifnet *, struct mbuf *); void (*if_reassign) /* reassign to vnet routine */ (struct ifnet *, struct vnet *, char *); + int (*if_get_rxqueue_len) + (struct ifnet *); + int (*if_get_txqueue_len) + (struct ifnet *); + int (*if_get_rxqueue_affinity) + (struct ifnet *, int); + int (*if_get_txqueue_affinity) + (struct ifnet *, int); + struct vnet *if_home_vnet; /* where this ifnet originates from */ struct ifaddr *if_addr; /* pointer to link-level address */ void *if_llsoftc; /* link layer softc */ Index: bpf.h =================================================================== --- bpf.h (.../head/sys/net/bpf.h) (revision 252509) +++ bpf.h (.../user/syuu/mq_bpf/sys/net/bpf.h) (revision 252509) @@ -147,6 +147,17 @@ #define BIOCSETFNR _IOW('B', 130, struct bpf_program) #define BIOCGTSTAMP _IOR('B', 131, u_int) #define BIOCSTSTAMP _IOW('B', 132, u_int) +#define BIOCENAQMASK _IO('B', 133) +#define BIOCDISQMASK _IO('B', 134) +#define BIOCSTRXQMASK _IOWR('B', 135, uint32_t) +#define BIOCCRRXQMASK _IOWR('B', 136, uint32_t) +#define BIOCGTRXQMASK _IOR('B', 137, uint32_t) +#define BIOCSTTXQMASK _IOWR('B', 138, uint32_t) +#define BIOCCRTXQMASK _IOWR('B', 139, uint32_t) +#define BIOCGTTXQMASK _IOR('B', 140, uint32_t) +#define BIOCSTOTHERMASK _IO('B', 141) +#define BIOCCROTHERMASK _IO('B', 142) +#define BIOCGTOTHERMASK _IOR('B', 143, uint32_t) /* Obsolete */ #define BIOCGSEESENT BIOCGDIRECTION Index: if.c =================================================================== --- if.c (.../head/sys/net/if.c) (revision 252509) +++ if.c (.../user/syuu/mq_bpf/sys/net/if.c) (revision 252509) @@ -2428,6 +2428,31 @@ break; } + case SIOCGIFQLEN: + if (!(ifp->if_capabilities & IFCAP_MULTIQUEUE)) + return (EOPNOTSUPP); + KASSERT(ifp->if_get_rxqueue_len, ("if_get_rxqueue_len not set")); + KASSERT(ifp->if_get_txqueue_len, ("if_get_txqueue_len not set")); + ifr->ifr_rxqueue_len = ifp->if_get_rxqueue_len(ifp); + ifr->ifr_txqueue_len = ifp->if_get_txqueue_len(ifp); + break; + + case SIOCGIFRXQAFFINITY: + if (!(ifp->if_capabilities & IFCAP_MULTIQUEUE)) + return (EOPNOTSUPP); + KASSERT(ifp->if_get_rxqueue_affinity, ("if_get_rxqueue_affinity not set")); + ifr->ifr_queue_affinity_cpu = + ifp->if_get_rxqueue_affinity(ifp, ifr->ifr_queue_affinity_index); + break; + + case SIOCGIFTXQAFFINITY: + if (!(ifp->if_capabilities & IFCAP_MULTIQUEUE)) + return (EOPNOTSUPP); + KASSERT(ifp->if_get_rxqueue_affinity, ("if_get_rxqueue_affinity not set")); + ifr->ifr_queue_affinity_cpu = + ifp->if_get_rxqueue_affinity(ifp, ifr->ifr_queue_affinity_index); + break; + default: error = ENOIOCTL; break; Index: if.h =================================================================== --- if.h (.../head/sys/net/if.h) (revision 252509) +++ if.h (.../user/syuu/mq_bpf/sys/net/if.h) (revision 252509) @@ -231,6 +231,7 @@ #define IFCAP_NETMAP 0x100000 /* netmap mode supported/enabled */ #define IFCAP_RXCSUM_IPV6 0x200000 /* can offload checksum on IPv6 RX */ #define IFCAP_TXCSUM_IPV6 0x400000 /* can offload checksum on IPv6 TX */ +#define IFCAP_MULTIQUEUE 0x800000 #define IFCAP_HWCSUM_IPV6 (IFCAP_RXCSUM_IPV6 | IFCAP_TXCSUM_IPV6) @@ -385,6 +386,8 @@ caddr_t ifru_data; int ifru_cap[2]; u_int ifru_fib; + int ifru_queue_len[2]; + int ifru_queue_affinity[2]; } ifr_ifru; #define ifr_addr ifr_ifru.ifru_addr /* address */ #define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-to-p link */ @@ -402,6 +405,11 @@ #define ifr_curcap ifr_ifru.ifru_cap[1] /* current capabilities */ #define ifr_index ifr_ifru.ifru_index /* interface index */ #define ifr_fib ifr_ifru.ifru_fib /* interface fib */ +#define ifr_rxqueue_len ifr_ifru.ifru_queue_len[0] /* rxqueue len */ +#define ifr_txqueue_len ifr_ifru.ifru_queue_len[1] /* txqueue len */ +#define ifr_queue_affinity_index ifr_ifru.ifru_queue_affinity[0] /* queue id */ +#define ifr_queue_affinity_cpu ifr_ifru.ifru_queue_affinity[1] /* cpu id */ + }; #define _SIZEOF_ADDR_IFREQ(ifr) \ Index: bpf.c =================================================================== --- bpf.c (.../head/sys/net/bpf.c) (revision 252509) +++ bpf.c (.../user/syuu/mq_bpf/sys/net/bpf.c) (revision 252509) @@ -819,6 +819,12 @@ size = d->bd_bufsize; bpf_buffer_ioctl_sblen(d, &size); + d->bd_qmask.qm_enabled = FALSE; + d->bd_qmask.qm_rxq_mask = NULL; + d->bd_qmask.qm_txq_mask = NULL; + d->bd_qmask.qm_other_mask = FALSE; + rw_init(&d->bd_qmask.qm_lock, "qmask lock"); + return (0); } @@ -1697,6 +1703,266 @@ case BIOCROTZBUF: error = bpf_ioctl_rotzbuf(td, d, (struct bpf_zbuf *)addr); break; + + case BIOCENAQMASK: + { + struct ifnet *ifp; + + if (d->bd_bif == NULL) { + /* + * No interface attached yet. + */ + error = EINVAL; + break; + } + BPFQ_WLOCK(&d->bd_qmask); + if (d->bd_qmask.qm_enabled) { + BPFQ_WUNLOCK(&d->bd_qmask); + error = EINVAL; + break; + } + ifp = d->bd_bif->bif_ifp; + if (!(ifp->if_capabilities & IFCAP_MULTIQUEUE)) { + BPFQ_WUNLOCK(&d->bd_qmask); + error = EINVAL; + break; + } + KASSERT(ifp->if_get_rxqueue_len, ("ifp->if_get_rxqueue_len not set\n")); + KASSERT(ifp->if_get_txqueue_len, ("ifp->if_get_rxqueue_len not set\n")); + d->bd_qmask.qm_enabled = TRUE; + d->bd_qmask.qm_rxq_mask = + malloc(ifp->if_get_rxqueue_len(ifp) * sizeof(boolean_t), M_BPF, + M_WAITOK | M_ZERO); + d->bd_qmask.qm_txq_mask = + malloc(ifp->if_get_txqueue_len(ifp) * sizeof(boolean_t), M_BPF, + M_WAITOK | M_ZERO); + d->bd_qmask.qm_other_mask = FALSE; + BPFQ_WUNLOCK(&d->bd_qmask); + break; + } + + case BIOCDISQMASK: + { + if (d->bd_bif == NULL) { + /* + * No interface attached yet. + */ + error = EINVAL; + break; + } + BPFQ_WLOCK(&d->bd_qmask); + if (!d->bd_qmask.qm_enabled) { + BPFQ_WUNLOCK(&d->bd_qmask); + error = EINVAL; + break; + } + d->bd_qmask.qm_enabled = FALSE; + + free(d->bd_qmask.qm_rxq_mask, M_BPF); + free(d->bd_qmask.qm_txq_mask, M_BPF); + BPFQ_WUNLOCK(&d->bd_qmask); + break; + } + + case BIOCSTRXQMASK: + { + struct ifnet *ifp; + int index; + + if (d->bd_bif == NULL) { + /* + * No interface attached yet. + */ + error = EINVAL; + break; + } + BPFQ_WLOCK(&d->bd_qmask); + if (!d->bd_qmask.qm_enabled) { + BPFQ_WUNLOCK(&d->bd_qmask); + error = EINVAL; + break; + } + ifp = d->bd_bif->bif_ifp; + index = *(uint32_t *)addr; + if (index > ifp->if_get_rxqueue_len(ifp)) { + BPFQ_WUNLOCK(&d->bd_qmask); + error = EINVAL; + break; + } + d->bd_qmask.qm_rxq_mask[index] = TRUE; + BPFQ_WUNLOCK(&d->bd_qmask); + break; + } + + case BIOCCRRXQMASK: + { + int index; + struct ifnet *ifp; + + if (d->bd_bif == NULL) { + /* + * No interface attached yet. + */ + error = EINVAL; + break; + } + BPFQ_WLOCK(&d->bd_qmask); + if (!d->bd_qmask.qm_enabled) { + BPFQ_WUNLOCK(&d->bd_qmask); + error = EINVAL; + break; + } + ifp = d->bd_bif->bif_ifp; + index = *(uint32_t *)addr; + if (index > ifp->if_get_rxqueue_len(ifp)) { + BPFQ_WUNLOCK(&d->bd_qmask); + error = EINVAL; + break; + } + d->bd_qmask.qm_rxq_mask[index] = FALSE; + BPFQ_WUNLOCK(&d->bd_qmask); + break; + } + + case BIOCGTRXQMASK: + { + int index; + struct ifnet *ifp; + + if (d->bd_bif == NULL) { + /* + * No interface attached yet. + */ + error = EINVAL; + break; + } + BPFQ_WLOCK(&d->bd_qmask); + if (!d->bd_qmask.qm_enabled) { + BPFQ_WUNLOCK(&d->bd_qmask); + error = EINVAL; + break; + } + ifp = d->bd_bif->bif_ifp; + index = *(uint32_t *)addr; + if (index > ifp->if_get_rxqueue_len(ifp)) { + BPFQ_WUNLOCK(&d->bd_qmask); + error = EINVAL; + break; + } + *(uint32_t *)addr = d->bd_qmask.qm_rxq_mask[index]; + BPFQ_WUNLOCK(&d->bd_qmask); + break; + } + + case BIOCSTTXQMASK: + { + struct ifnet *ifp; + int index; + + if (d->bd_bif == NULL) { + /* + * No interface attached yet. + */ + error = EINVAL; + break; + } + BPFQ_WLOCK(&d->bd_qmask); + if (!d->bd_qmask.qm_enabled) { + BPFQ_WUNLOCK(&d->bd_qmask); + error = EINVAL; + break; + } + + ifp = d->bd_bif->bif_ifp; + index = *(uint32_t *)addr; + if (index > ifp->if_get_txqueue_len(ifp)) { + BPFQ_WUNLOCK(&d->bd_qmask); + error = EINVAL; + break; + } + d->bd_qmask.qm_txq_mask[index] = TRUE; + BPFQ_WUNLOCK(&d->bd_qmask); + break; + } + + case BIOCCRTXQMASK: + { + struct ifnet *ifp; + int index; + + if (d->bd_bif == NULL) { + /* + * No interface attached yet. + */ + error = EINVAL; + break; + } + BPFQ_WLOCK(&d->bd_qmask); + if (!d->bd_qmask.qm_enabled) { + BPFQ_WUNLOCK(&d->bd_qmask); + error = EINVAL; + break; + } + + ifp = d->bd_bif->bif_ifp; + index = *(uint32_t *)addr; + if (index > ifp->if_get_txqueue_len(ifp)) { + BPFQ_WUNLOCK(&d->bd_qmask); + error = EINVAL; + break; + } + d->bd_qmask.qm_txq_mask[index] = FALSE; + BPFQ_WUNLOCK(&d->bd_qmask); + break; + } + + case BIOCGTTXQMASK: + { + int index; + struct ifnet *ifp; + + if (d->bd_bif == NULL) { + /* + * No interface attached yet. + */ + error = EINVAL; + break; + } + BPFQ_WLOCK(&d->bd_qmask); + if (!d->bd_qmask.qm_enabled) { + BPFQ_WUNLOCK(&d->bd_qmask); + error = EINVAL; + break; + } + ifp = d->bd_bif->bif_ifp; + index = *(uint32_t *)addr; + if (index > ifp->if_get_txqueue_len(ifp)) { + BPFQ_WUNLOCK(&d->bd_qmask); + error = EINVAL; + break; + } + *(uint32_t *)addr = d->bd_qmask.qm_txq_mask[index]; + BPFQ_WUNLOCK(&d->bd_qmask); + break; + } + + case BIOCSTOTHERMASK: + BPFQ_WLOCK(&d->bd_qmask); + d->bd_qmask.qm_other_mask = TRUE; + BPFQ_WUNLOCK(&d->bd_qmask); + break; + + case BIOCCROTHERMASK: + BPFQ_WLOCK(&d->bd_qmask); + d->bd_qmask.qm_other_mask = FALSE; + BPFQ_WUNLOCK(&d->bd_qmask); + break; + + case BIOCGTOTHERMASK: + BPFQ_WLOCK(&d->bd_qmask); + *(uint32_t *)addr = (uint32_t)d->bd_qmask.qm_other_mask; + BPFQ_WUNLOCK(&d->bd_qmask); + break; } CURVNET_RESTORE(); return (error); @@ -2050,6 +2316,14 @@ * 2) destroying/detaching d is protected by interface * write lock, too */ + BPFQ_RLOCK(&d->bd_qmask); + if (d->bd_qmask.qm_enabled) { + if (!d->bd_qmask.qm_other_mask) { + BPFQ_RUNLOCK(&d->bd_qmask); + continue; + } + } + BPFQ_RUNLOCK(&d->bd_qmask); /* XXX: Do not protect counter for the sake of performance. */ ++d->bd_rcount; @@ -2117,6 +2391,42 @@ BPFIF_RLOCK(bp); LIST_FOREACH(d, &bp->bif_dlist, bd_next) { + BPFQ_RLOCK(&d->bd_qmask); + if (d->bd_qmask.qm_enabled) { + M_ASSERTPKTHDR(m); + if (!(m->m_flags & M_FLOWID)) { + if (!d->bd_qmask.qm_other_mask) { + BPFQ_RUNLOCK(&d->bd_qmask); + continue; + } + } else { + struct ifnet *ifp = bp->bif_ifp; + if (m->m_pkthdr.rxqueue != (uint32_t)-1) { + if (m->m_pkthdr.rxqueue >= ifp->if_get_rxqueue_len(ifp)) { + BPFQ_RUNLOCK(&d->bd_qmask); + BPFIF_RUNLOCK(bp); + return; + } + if (!d->bd_qmask.qm_rxq_mask[m->m_pkthdr.rxqueue]) { + BPFQ_RUNLOCK(&d->bd_qmask); + continue; + } + } + if (m->m_pkthdr.txqueue != (uint32_t)-1) { + if (m->m_pkthdr.txqueue >= ifp->if_get_txqueue_len(ifp)) { + BPFQ_RUNLOCK(&d->bd_qmask); + BPFIF_RUNLOCK(bp); + return; + } + if (!d->bd_qmask.qm_txq_mask[m->m_pkthdr.txqueue]) { + BPFQ_RUNLOCK(&d->bd_qmask); + continue; + } + } + } + } + BPFQ_RUNLOCK(&d->bd_qmask); + if (BPF_CHECK_DIRECTION(d, m->m_pkthdr.rcvif, bp->bif_ifp)) continue; ++d->bd_rcount; @@ -2180,6 +2490,42 @@ BPFIF_RLOCK(bp); LIST_FOREACH(d, &bp->bif_dlist, bd_next) { + BPFQ_RLOCK(&d->bd_qmask); + if (d->bd_qmask.qm_enabled) { + M_ASSERTPKTHDR(m); + if (!(m->m_flags & M_FLOWID)) { + if (!d->bd_qmask.qm_other_mask) { + BPFQ_RUNLOCK(&d->bd_qmask); + continue; + } + } else { + struct ifnet *ifp = bp->bif_ifp; + if (m->m_pkthdr.rxqueue != (uint32_t)-1) { + if (m->m_pkthdr.rxqueue >= ifp->if_get_rxqueue_len(ifp)) { + BPFQ_RUNLOCK(&d->bd_qmask); + BPFIF_RUNLOCK(bp); + return; + } + if (!d->bd_qmask.qm_rxq_mask[m->m_pkthdr.rxqueue]) { + BPFQ_RUNLOCK(&d->bd_qmask); + continue; + } + } + if (m->m_pkthdr.txqueue != (uint32_t)-1) { + if (m->m_pkthdr.txqueue >= ifp->if_get_txqueue_len(ifp)) { + BPFQ_RUNLOCK(&d->bd_qmask); + BPFIF_RUNLOCK(bp); + return; + } + if (!d->bd_qmask.qm_txq_mask[m->m_pkthdr.txqueue]) { + BPFQ_RUNLOCK(&d->bd_qmask); + continue; + } + } + } + } + BPFQ_RUNLOCK(&d->bd_qmask); + if (BPF_CHECK_DIRECTION(d, m->m_pkthdr.rcvif, bp->bif_ifp)) continue; ++d->bd_rcount; @@ -2443,6 +2789,12 @@ } if (d->bd_wfilter != NULL) free((caddr_t)d->bd_wfilter, M_BPF); + + if (d->bd_qmask.qm_enabled) { + free(d->bd_qmask.qm_rxq_mask, M_BPF); + free(d->bd_qmask.qm_txq_mask, M_BPF); + } + mtx_destroy(&d->bd_lock); } Index: sockio.h =================================================================== --- sockio.h (.../head/sys/sys/sockio.h) (revision 252509) +++ sockio.h (.../user/syuu/mq_bpf/sys/sys/sockio.h) (revision 252509) @@ -82,6 +82,10 @@ #define SIOCGIFDESCR _IOWR('i', 42, struct ifreq) /* get ifnet descr */ #define SIOCAIFADDR _IOW('i', 43, struct ifaliasreq)/* add/chg IF alias */ +#define SIOCGIFQLEN _IOWR('i', 45, struct ifreq) /* get IF queue len */ +#define SIOCGIFRXQAFFINITY _IOWR('i', 46, struct ifreq) /* get IF rx queue affinity */ +#define SIOCGIFTXQAFFINITY _IOWR('i', 47, struct ifreq) /* get IF tx queue affinity */ + #define SIOCADDMULTI _IOW('i', 49, struct ifreq) /* add m'cast addr */ #define SIOCDELMULTI _IOW('i', 50, struct ifreq) /* del m'cast addr */ #define SIOCGIFMTU _IOWR('i', 51, struct ifreq) /* get IF mtu */ Index: mbuf.h =================================================================== --- mbuf.h (.../head/sys/sys/mbuf.h) (revision 252509) +++ mbuf.h (.../user/syuu/mq_bpf/sys/sys/mbuf.h) (revision 252509) @@ -121,6 +121,8 @@ uint32_t flowid; /* packet's 4-tuple system * flow identifier */ + uint32_t rxqueue; + uint32_t txqueue; /* variables for hardware checksum */ int csum_flags; /* flags regarding checksum */ int csum_data; /* data field used by csum routines */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CALG4x-UYBFsMttpZx1-c_wtVf5MST8%2B_t1psY2HQskTiOZDFLA>
