From owner-svn-src-user@FreeBSD.ORG Wed Jun 26 09:21:40 2013 Return-Path: Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) by hub.freebsd.org (Postfix) with ESMTP id 40B5C8CA; Wed, 26 Jun 2013 09:21:40 +0000 (UTC) (envelope-from syuu@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) by mx1.freebsd.org (Postfix) with ESMTP id 235D21958; Wed, 26 Jun 2013 09:21:40 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.7/8.14.7) with ESMTP id r5Q9LdfB065485; Wed, 26 Jun 2013 09:21:39 GMT (envelope-from syuu@svn.freebsd.org) Received: (from syuu@localhost) by svn.freebsd.org (8.14.7/8.14.5/Submit) id r5Q9LbuQ065469; Wed, 26 Jun 2013 09:21:37 GMT (envelope-from syuu@svn.freebsd.org) Message-Id: <201306260921.r5Q9LbuQ065469@svn.freebsd.org> From: Takuya ASADA Date: Wed, 26 Jun 2013 09:21:37 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r252249 - in user/syuu/mq_bpf: contrib/libpcap contrib/libpcap/pcap contrib/tcpdump sbin/ifconfig share/man/man4 share/man/man9 sys/dev/e1000 sys/dev/ixgbe sys/dev/mxge sys/net sys/sys X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 26 Jun 2013 09:21:40 -0000 Author: syuu Date: Wed Jun 26 09:21:36 2013 New Revision: 252249 URL: http://svnweb.freebsd.org/changeset/base/252249 Log: import mq_bpf patch Modified: user/syuu/mq_bpf/contrib/libpcap/pcap-bpf.c user/syuu/mq_bpf/contrib/libpcap/pcap-int.h user/syuu/mq_bpf/contrib/libpcap/pcap.c user/syuu/mq_bpf/contrib/libpcap/pcap/pcap.h user/syuu/mq_bpf/contrib/tcpdump/tcpdump.c user/syuu/mq_bpf/sbin/ifconfig/ifconfig.c user/syuu/mq_bpf/share/man/man4/bpf.4 user/syuu/mq_bpf/share/man/man4/netintro.4 user/syuu/mq_bpf/share/man/man9/ifnet.9 user/syuu/mq_bpf/sys/dev/e1000/if_igb.c user/syuu/mq_bpf/sys/dev/ixgbe/ixgbe.c user/syuu/mq_bpf/sys/dev/mxge/if_mxge.c user/syuu/mq_bpf/sys/net/bpf.c user/syuu/mq_bpf/sys/net/bpf.h user/syuu/mq_bpf/sys/net/bpfdesc.h user/syuu/mq_bpf/sys/net/if.c user/syuu/mq_bpf/sys/net/if.h user/syuu/mq_bpf/sys/net/if_var.h user/syuu/mq_bpf/sys/sys/mbuf.h user/syuu/mq_bpf/sys/sys/sockio.h Modified: user/syuu/mq_bpf/contrib/libpcap/pcap-bpf.c ============================================================================== --- user/syuu/mq_bpf/contrib/libpcap/pcap-bpf.c Wed Jun 26 09:04:26 2013 (r252248) +++ user/syuu/mq_bpf/contrib/libpcap/pcap-bpf.c Wed Jun 26 09:21:36 2013 (r252249) @@ -34,6 +34,7 @@ static const char rcsid[] _U_ = #include #endif #include +#include #include /* * defines ioctls, but doesn't include . @@ -2187,6 +2188,40 @@ pcap_activate_bpf(pcap_t *p) } #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 Modified: user/syuu/mq_bpf/contrib/libpcap/pcap-int.h ============================================================================== --- user/syuu/mq_bpf/contrib/libpcap/pcap-int.h Wed Jun 26 09:04:26 2013 (r252248) +++ user/syuu/mq_bpf/contrib/libpcap/pcap-int.h Wed Jun 26 09:21:36 2013 (r252249) @@ -337,6 +337,9 @@ struct pcap { 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; }; /* Modified: user/syuu/mq_bpf/contrib/libpcap/pcap.c ============================================================================== --- user/syuu/mq_bpf/contrib/libpcap/pcap.c Wed Jun 26 09:04:26 2013 (r252248) +++ user/syuu/mq_bpf/contrib/libpcap/pcap.c Wed Jun 26 09:21:36 2013 (r252249) @@ -505,6 +505,9 @@ pcap_create_common(const char *source, c 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 @@ pcap_activate(pcap_t *p) 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) { Modified: user/syuu/mq_bpf/contrib/libpcap/pcap/pcap.h ============================================================================== --- user/syuu/mq_bpf/contrib/libpcap/pcap/pcap.h Wed Jun 26 09:04:26 2013 (r252248) +++ user/syuu/mq_bpf/contrib/libpcap/pcap/pcap.h Wed Jun 26 09:21:36 2013 (r252249) @@ -331,6 +331,10 @@ const char *pcap_tstamp_type_val_to_desc #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 *); Modified: user/syuu/mq_bpf/contrib/tcpdump/tcpdump.c ============================================================================== --- user/syuu/mq_bpf/contrib/tcpdump/tcpdump.c Wed Jun 26 09:04:26 2013 (r252248) +++ user/syuu/mq_bpf/contrib/tcpdump/tcpdump.c Wed Jun 26 09:21:36 2013 (r252249) @@ -1101,6 +1101,20 @@ main(int argc, char **argv) } break; + case 'Q': + rxq = atoi(optarg); + break; + + case 'g': + txq = atoi(optarg); + break; + + case 'V': + other = atoi(optarg); + if (other != 0 || other != 1) + usage(); + break; + default: usage(); /* NOTREACHED */ @@ -1274,6 +1288,13 @@ main(int argc, char **argv) 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) { /* Modified: user/syuu/mq_bpf/sbin/ifconfig/ifconfig.c ============================================================================== --- user/syuu/mq_bpf/sbin/ifconfig/ifconfig.c Wed Jun 26 09:04:26 2013 (r252248) +++ user/syuu/mq_bpf/sbin/ifconfig/ifconfig.c Wed Jun 26 09:21:36 2013 (r252249) @@ -917,7 +917,7 @@ unsetifdescr(const char *val, int value, "\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 @@ status(const struct afswtch *afp, const } } + 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) { Modified: user/syuu/mq_bpf/share/man/man4/bpf.4 ============================================================================== --- user/syuu/mq_bpf/share/man/man4/bpf.4 Wed Jun 26 09:04:26 2013 (r252248) +++ user/syuu/mq_bpf/share/man/man4/bpf.4 Wed Jun 26 09:21:36 2013 (r252249) @@ -631,6 +631,46 @@ therefore ownership is not assigned, the .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 @@ struct bpf_insn insns[] = { 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 , Modified: user/syuu/mq_bpf/share/man/man4/netintro.4 ============================================================================== --- user/syuu/mq_bpf/share/man/man4/netintro.4 Wed Jun 26 09:04:26 2013 (r252248) +++ user/syuu/mq_bpf/share/man/man4/netintro.4 Wed Jun 26 09:21:36 2013 (r252249) @@ -213,6 +213,8 @@ struct ifreq { 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 @@ struct ifreq { #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 @@ On successful return the 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: Modified: user/syuu/mq_bpf/share/man/man9/ifnet.9 ============================================================================== --- user/syuu/mq_bpf/share/man/man9/ifnet.9 Wed Jun 26 09:04:26 2013 (r252248) +++ user/syuu/mq_bpf/share/man/man9/ifnet.9 Wed Jun 26 09:21:36 2013 (r252249) @@ -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 @@ for validity, and if necessary compute a 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. Modified: user/syuu/mq_bpf/sys/dev/e1000/if_igb.c ============================================================================== --- user/syuu/mq_bpf/sys/dev/e1000/if_igb.c Wed Jun 26 09:04:26 2013 (r252248) +++ user/syuu/mq_bpf/sys/dev/e1000/if_igb.c Wed Jun 26 09:21:36 2013 (r252249) @@ -278,6 +278,11 @@ static int igb_set_flowcntl(SYSCTL_HANDL 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 @@ igb_start_locked(struct tx_ring *txr, st 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 @@ igb_mq_start_locked(struct ifnet *ifp, s 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 @@ igb_setup_interface(device_t dev, struct 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 @@ igb_setup_interface(device_t dev, struct ** 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 @@ igb_rxeof(struct igb_queue *que, int cou 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_sysctl_eee(SYSCTL_HANDLER_ARGS) 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); +} Modified: user/syuu/mq_bpf/sys/dev/ixgbe/ixgbe.c ============================================================================== --- user/syuu/mq_bpf/sys/dev/ixgbe/ixgbe.c Wed Jun 26 09:04:26 2013 (r252248) +++ user/syuu/mq_bpf/sys/dev/ixgbe/ixgbe.c Wed Jun 26 09:21:36 2013 (r252249) @@ -210,6 +210,12 @@ static void ixgbe_reinit_fdir(void *, in /* 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 @@ ixgbe_start_locked(struct tx_ring *txr, 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 @@ ixgbe_mq_start_locked(struct ifnet *ifp, 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 @@ ixgbe_setup_interface(device_t dev, stru 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 @@ ixgbe_setup_interface(device_t dev, stru 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 @@ ixgbe_rxeof(struct ix_queue *que) 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 @@ ixgbe_set_advertise(SYSCTL_HANDLER_ARGS) 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 Modified: user/syuu/mq_bpf/sys/dev/mxge/if_mxge.c ============================================================================== --- user/syuu/mq_bpf/sys/dev/mxge/if_mxge.c Wed Jun 26 09:04:26 2013 (r252248) +++ user/syuu/mq_bpf/sys/dev/mxge/if_mxge.c Wed Jun 26 09:21:36 2013 (r252249) @@ -120,6 +120,11 @@ static int mxge_detach(device_t dev); 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 @@ mxge_start_locked(struct mxge_slice_stat 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 @@ mxge_transmit_locked(struct mxge_slice_s 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 @@ mxge_rx_done_big(struct mxge_slice_state 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 @@ mxge_attach(device_t dev) #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 @@ mxge_attach(device_t dev) 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 @@ mxge_shutdown(device_t dev) 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. Modified: user/syuu/mq_bpf/sys/net/bpf.c ============================================================================== --- user/syuu/mq_bpf/sys/net/bpf.c Wed Jun 26 09:04:26 2013 (r252248) +++ user/syuu/mq_bpf/sys/net/bpf.c Wed Jun 26 09:21:36 2013 (r252249) @@ -819,6 +819,12 @@ bpfopen(struct cdev *dev, int flags, int 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 @@ bpfioctl(struct cdev *dev, u_long cmd, c 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 @@ bpf_tap(struct bpf_if *bp, u_char *pkt, * 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 @@ bpf_mtap(struct bpf_if *bp, struct mbuf 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 @@ bpf_mtap2(struct bpf_if *bp, void *data, 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; *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***