Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 26 Jun 2013 09:21:37 +0000 (UTC)
From:      Takuya ASADA <syuu@FreeBSD.org>
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
Message-ID:  <201306260921.r5Q9LbuQ065469@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201306260921.r5Q9LbuQ065469>