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
Takuya ASADA
syuu at FreeBSD.org
Wed Jun 26 09:21:40 UTC 2013
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 <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 @@ 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 ***
More information about the svn-src-user
mailing list