Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 30 Sep 2013 06:43:02 +0900
From:      Takuya ASADA <syuu@dokukino.com>
To:        hiren panchasara <hiren.panchasara@gmail.com>
Cc:        "freebsd-net@freebsd.org" <freebsd-net@freebsd.org>, Adrian Chadd <adrian@freebsd.org>
Subject:   Re: Adding Flow Director sysctls to ixgbe(4) (was: netmap: traffic distribution)
Message-ID:  <CALG4x-Xf27oEOA9K5j%2BRRndFe1VbDowpTti8a8qwu1mRaB4BkQ@mail.gmail.com>
In-Reply-To: <CALCpEUHoVJgmYptMp6Q%2BY%2BDgbxgujN8e7TcANUi1De_fnkOZ_w@mail.gmail.com>
References:  <CALCpEUHcpoJoo_gqjyDzosE1bJ_J=o3uqUuyYJA8dWZdjMrNTA@mail.gmail.com> <CAJ-VmompkSY-tU2SysaEf6p1uJPmcMeXKJ6_EZ_DJiYTQXbUzw@mail.gmail.com> <CALG4x-XowXNze82jvFX84X0=d7MRucpJbUeExug9y7XsaZXkSw@mail.gmail.com> <CALCpEUHoVJgmYptMp6Q%2BY%2BDgbxgujN8e7TcANUi1De_fnkOZ_w@mail.gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help

[-- Attachment #1 --]
Hi,

I just implemented device specific ioctl with device specific configuration
tool.
It still doesn't support some important features such as:
 - FDIR enable / disable via sysctl or tunable params
 - ATR enable / disable via sysctl or tunable params
 - IPv6 support on signature filter
 - signature filter list
 - support perfect filter
But, at least it can configure signature filter manually.

Usage is as follows:
Usage: ixgbetool <ifname> [operation]
add_sig_filter <proto> <src_ip> <src_port> <dst_ip> <dst_port> <que_index>
 del_sig_filter <proto> <src_ip> <src_port> <dst_ip> <dst_port>


2013/9/28 hiren panchasara <hiren.panchasara@gmail.com>

>
>
>
> On Fri, Sep 27, 2013 at 1:58 AM, Takuya ASADA <syuu@dokukino.com> wrote:
>
>> 2013/9/27 Adrian Chadd <adrian@freebsd.org>
>>
>>> On 27 September 2013 00:43, hiren panchasara <hiren.panchasara@gmail.com
>>> > wrote:
>>>
>>>
>>>> Takuya,
>>>>
>>>> I see a lot of responses/comments on proposed changes. Was anything
>>>> decided
>>>> at the end of it? As far as I can tell, its still not committed to the
>>>> tree.
>>>>
>>>
>>> I'd rather see an ioctl API for that chipset and then have a separate
>>> tool program it for now.
>>>
>>
>> Ah, like cxgbetool and cxgbe? (it has device specific tool and ioctls)
>> http://svnweb.freebsd.org/base/head/tools/tools/cxgbetool/
>>
>
> Something like this for ixgbe would be nice to start with, imo.
>
> Cheers,
> Hiren
>
>> http://svnweb.freebsd.org/base/head/sys/dev/cxgb/
>>
>>
>>> So, how bout we hack that up? :)
>>>
>>
>>  Sound's interesting ;-)
>> Could you tell me more detail about your idea?
>>
>>
>

[-- Attachment #2 --]
diff --git a/sys/dev/ixgbe/ixgbe.c b/sys/dev/ixgbe/ixgbe.c
index b65df72..beb3366 100644
--- a/sys/dev/ixgbe/ixgbe.c
+++ b/sys/dev/ixgbe/ixgbe.c
@@ -35,7 +35,9 @@
 
 #include "opt_inet.h"
 #include "opt_inet6.h"
+ 
 #include "ixgbe.h"
+#include "ixgbe_ioctl.h"
 
 /*********************************************************************
  *  Set this to one to display debug statistics
@@ -200,7 +202,9 @@ static void	ixgbe_handle_msf(void *, int);
 static void	ixgbe_handle_mod(void *, int);
 
 #ifdef IXGBE_FDIR
+#ifdef IXGBE_FDIR_ATR
 static void	ixgbe_atr(struct tx_ring *, struct mbuf *);
+#endif
 static void	ixgbe_reinit_fdir(void *, int);
 #endif
 
@@ -224,6 +228,19 @@ static driver_t ixgbe_driver = {
 	"ix", ixgbe_methods, sizeof(struct adapter),
 };
 
+static d_ioctl_t ixgbe_extension_ioctl;
+static d_open_t ixgbe_extension_open;
+static d_close_t ixgbe_extension_close;
+
+static struct cdevsw ixgbe_cdevsw = {
+       .d_version =    D_VERSION,
+       .d_flags =      0,
+       .d_open =       ixgbe_extension_open,
+       .d_close =      ixgbe_extension_close,
+       .d_ioctl =      ixgbe_extension_ioctl,
+       .d_name =       "ixgbe",
+};
+
 devclass_t ixgbe_devclass;
 DRIVER_MODULE(ixgbe, pci, ixgbe_driver, ixgbe_devclass, 0, 0);
 
@@ -317,6 +334,7 @@ static bool ixgbe_rsc_enable = FALSE;
 static int ixgbe_total_ports;
 
 #ifdef IXGBE_FDIR
+#ifdef IXGBE_FDIR_ATR
 /*
 ** For Flow Director: this is the
 ** number of TX packets we sample
@@ -327,6 +345,7 @@ static int ixgbe_total_ports;
 ** setting this to 0.
 */
 static int atr_sample_rate = 20;
+#endif
 /* 
 ** Flow Director actually 'steals'
 ** part of the packet buffer as its
@@ -401,6 +420,20 @@ ixgbe_probe(device_t dev)
 	return (ENXIO);
 }
 
+static int
+ixgbe_makedev(struct adapter *adapter)
+{
+	adapter->cdev = make_dev(&ixgbe_cdevsw, adapter->ifp->if_dunit,
+	    UID_ROOT, GID_WHEEL, 0600, "%s", if_name(adapter->ifp));
+	
+	if (adapter->cdev == NULL)
+		return (ENOMEM);
+
+	adapter->cdev->si_drv1 = (void *)adapter;
+	
+	return (0);
+}
+
 /*********************************************************************
  *  Device initialization routine
  *
@@ -604,6 +637,11 @@ ixgbe_attach(device_t dev)
 #ifdef DEV_NETMAP
 	ixgbe_netmap_attach(adapter);
 #endif /* DEV_NETMAP */
+
+	error = ixgbe_makedev(adapter);
+	if (error)
+		goto err_late;
+
 	INIT_DEBUGOUT("ixgbe_attach: end");
 	return (0);
 err_late:
@@ -1812,7 +1850,7 @@ retry:
 		return (error);
 	}
 
-#ifdef IXGBE_FDIR
+#ifdef IXGBE_FDIR_ATR
 	/* Do the flow director magic */
 	if ((txr->atr_sample) && (!adapter->fdir_reinit)) {
 		++txr->atr_count;
@@ -3059,7 +3097,7 @@ ixgbe_setup_transmit_ring(struct tx_ring *txr)
 		txbuf->eop = NULL;
         }
 
-#ifdef IXGBE_FDIR
+#ifdef IXGBE_FDIR_ATR
 	/* Set the rate at which we sample packets */
 	if (adapter->hw.mac.type != ixgbe_mac_82598EB)
 		txr->atr_sample = atr_sample_rate;
@@ -3479,7 +3517,7 @@ ixgbe_tso_setup(struct tx_ring *txr, struct mbuf *mp,
 	return (0);
 }
 
-#ifdef IXGBE_FDIR
+#ifdef IXGBE_FDIR_ATR
 /*
 ** This routine parses packet headers so that Flow
 ** Director can make a hashed filter table entry 
@@ -5270,13 +5308,33 @@ ixgbe_update_stats_counters(struct adapter *adapter)
 	adapter->stats.xec += IXGBE_READ_REG(hw, IXGBE_XEC);
 	adapter->stats.fccrc += IXGBE_READ_REG(hw, IXGBE_FCCRC);
 	adapter->stats.fclast += IXGBE_READ_REG(hw, IXGBE_FCLAST);
-	/* Only read FCOE on 82599 */
+	/* Only read FCOE/FDIR on 82599 */
 	if (hw->mac.type != ixgbe_mac_82598EB) {
 		adapter->stats.fcoerpdc += IXGBE_READ_REG(hw, IXGBE_FCOERPDC);
 		adapter->stats.fcoeprc += IXGBE_READ_REG(hw, IXGBE_FCOEPRC);
 		adapter->stats.fcoeptc += IXGBE_READ_REG(hw, IXGBE_FCOEPTC);
 		adapter->stats.fcoedwrc += IXGBE_READ_REG(hw, IXGBE_FCOEDWRC);
 		adapter->stats.fcoedwtc += IXGBE_READ_REG(hw, IXGBE_FCOEDWTC);
+		adapter->stats.fdirfree_free =
+			(IXGBE_READ_REG(hw, IXGBE_FDIRFREE) & IXGBE_FDIRFREE_FREE_MASK)
+			>> IXGBE_FDIRFREE_FREE_SHIFT;
+		adapter->stats.fdirfree_coll =
+			(IXGBE_READ_REG(hw, IXGBE_FDIRFREE) & IXGBE_FDIRFREE_COLL_MASK)
+			>> IXGBE_FDIRFREE_COLL_SHIFT;
+		adapter->stats.fdirustat_add +=
+			(IXGBE_READ_REG(hw, IXGBE_FDIRUSTAT) & IXGBE_FDIRUSTAT_ADD_MASK)
+			>> IXGBE_FDIRUSTAT_ADD_SHIFT;
+		adapter->stats.fdirustat_remove +=
+			(IXGBE_READ_REG(hw, IXGBE_FDIRUSTAT) & IXGBE_FDIRUSTAT_REMOVE_MASK)
+			>> IXGBE_FDIRUSTAT_REMOVE_SHIFT;
+		adapter->stats.fdirfstat_fadd +=
+			(IXGBE_READ_REG(hw, IXGBE_FDIRFSTAT) & IXGBE_FDIRFSTAT_FADD_MASK)
+			>> IXGBE_FDIRFSTAT_FADD_SHIFT;
+		adapter->stats.fdirfstat_fremove +=
+			(IXGBE_READ_REG(hw, IXGBE_FDIRFSTAT) & IXGBE_FDIRFSTAT_FREMOVE_MASK)
+			>> IXGBE_FDIRFSTAT_FREMOVE_SHIFT;
+		adapter->stats.fdirmatch += IXGBE_READ_REG(hw, IXGBE_FDIRMATCH);
+		adapter->stats.fdirmiss += IXGBE_READ_REG(hw, IXGBE_FDIRMISS);
 	}
 
 	/* Fill out the OS statistics structure */
@@ -5642,6 +5700,32 @@ ixgbe_add_hw_stats(struct adapter *adapter)
 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_frames_1024_1522",
 			CTLFLAG_RD, &stats->ptc1522,
 			"1024-1522 byte frames transmitted");
+
+	/* fdir stats */
+	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "fdirfree_free",
+		CTLFLAG_RD, &stats->fdirfree_free,
+		"");
+	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "fdirfree_coll",
+		CTLFLAG_RD, &stats->fdirfree_coll,
+		"");
+	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "fdirustat_add",
+		CTLFLAG_RD, &stats->fdirustat_add,
+		"");
+	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "fdirustat_remove",
+		CTLFLAG_RD, &stats->fdirustat_remove,
+		"");
+	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "fdirfstat_fadd",
+		CTLFLAG_RD, &stats->fdirfstat_fadd,
+		"");
+	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "fdirfstat_fremove",
+		CTLFLAG_RD, &stats->fdirfstat_fremove,
+		"");
+	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "fdirmatch",
+		CTLFLAG_RD, &stats->fdirmatch,
+		"");
+	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "fdirmiss",
+		CTLFLAG_RD, &stats->fdirmiss,
+		"");
 }
 
 /*
@@ -5803,3 +5887,83 @@ ixgbe_disable_rx_drop(struct adapter *adapter)
         	IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(i), srrctl);
 	}
 }
+
+static int
+ixgbe_extension_open(struct cdev *dev, int flags, int fmp, struct thread *td)
+{
+       return (0);
+}
+
+static int
+ixgbe_extension_close(struct cdev *dev, int flags, int fmt, struct thread *td)
+{
+       return (0);
+}
+
+static int
+ixgbe_extension_ioctl(struct cdev *dev, unsigned long cmd, caddr_t data,
+    int fflag, struct thread *td)
+{
+	struct adapter *adapter = (struct adapter *)dev->si_drv1;
+
+	if (priv_check(td, PRIV_DRIVER)) {
+		return (EPERM);
+	}
+	
+	switch (cmd) {
+	case IXGBE_ADD_SIGFILTER: {
+		struct ix_filter *filter = (struct ix_filter *)data;
+		union ixgbe_atr_hash_dword input = {.dword = 0};
+		union ixgbe_atr_hash_dword common = {.dword = 0};
+
+		switch (filter->proto) {
+		case IXGBE_FILTER_PROTO_TCPV4:
+			input.formatted.flow_type ^= IXGBE_ATR_FLOW_TYPE_TCPV4;
+			break;
+		case IXGBE_FILTER_PROTO_UDPV4:
+			input.formatted.flow_type ^= IXGBE_ATR_FLOW_TYPE_UDPV4;
+			break;
+		default:
+			return (EINVAL);
+		}
+		common.port.src ^= htons(filter->src_port);
+		common.port.dst ^= htons(filter->dst_port);
+		common.flex_bytes ^= htons(ETHERTYPE_IP);
+		common.ip ^= filter->src_ip.s_addr ^ filter->dst_ip.s_addr;
+
+		ixgbe_fdir_add_signature_filter_82599(&adapter->hw,
+			input, common, filter->que_index);
+		break;
+	}
+	case IXGBE_CLR_SIGFILTER: {
+		struct ix_filter *filter = (struct ix_filter *)data;
+		union ixgbe_atr_hash_dword input = {.dword = 0};
+		union ixgbe_atr_hash_dword common = {.dword = 0};
+
+		switch (filter->proto) {
+		case IXGBE_FILTER_PROTO_TCPV4:
+			input.formatted.flow_type ^= IXGBE_ATR_FLOW_TYPE_TCPV4;
+			break;
+		case IXGBE_FILTER_PROTO_UDPV4:
+			input.formatted.flow_type ^= IXGBE_ATR_FLOW_TYPE_UDPV4;
+			break;
+		default:
+			return (EINVAL);
+		}
+		common.port.src ^= htons(filter->src_port);
+		common.port.dst ^= htons(filter->dst_port);
+		common.flex_bytes ^= htons(ETHERTYPE_IP);
+		common.ip ^= filter->src_ip.s_addr ^ filter->dst_ip.s_addr;
+
+		ixgbe_fdir_erase_signature_filter_82599(&adapter->hw,
+			input, common);
+		break;
+	}
+	default:
+		return (EOPNOTSUPP);
+		break;
+	}
+
+	return (0);
+}
+
diff --git a/sys/dev/ixgbe/ixgbe.h b/sys/dev/ixgbe/ixgbe.h
index 77b72ed..49c41f2 100644
--- a/sys/dev/ixgbe/ixgbe.h
+++ b/sys/dev/ixgbe/ixgbe.h
@@ -88,6 +88,8 @@
 #include <sys/pcpu.h>
 #include <sys/smp.h>
 #include <machine/smp.h>
+#include <sys/conf.h>
+#include <sys/priv.h>
 
 #include "ixgbe_api.h"
 
@@ -468,6 +470,8 @@ struct adapter {
 	unsigned long		link_irq;
 
 	struct ixgbe_hw_stats 	stats;
+
+	struct cdev		*cdev;
 };
 
 
diff --git a/sys/dev/ixgbe/ixgbe_82599.c b/sys/dev/ixgbe/ixgbe_82599.c
index 3cc8cd7..72ea5ea 100644
--- a/sys/dev/ixgbe/ixgbe_82599.c
+++ b/sys/dev/ixgbe/ixgbe_82599.c
@@ -1482,7 +1482,8 @@ s32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 fdirctrl)
 	 *  Set the maximum length per hash bucket to 0xA filters
 	 *  Send interrupt when 64 filters are left
 	 */
-	fdirctrl |= (0x6 << IXGBE_FDIRCTRL_FLEX_SHIFT) |
+	fdirctrl |= IXGBE_FDIRCTRL_REPORT_STATUS |
+ 		    (0x6 << IXGBE_FDIRCTRL_FLEX_SHIFT) |
 		    (0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT) |
 		    (4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT);
 
@@ -1667,6 +1668,56 @@ s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
 	return IXGBE_SUCCESS;
 }
 
+/**
+ *  ixgbe_fdir_erase_signature_filter_82599 - Adds a signature hash filter
+ *  @hw: pointer to hardware structure
+ *  @stream: input bitstream
+ *  @queue: queue index to direct traffic to
+ **/
+s32 ixgbe_fdir_erase_signature_filter_82599(struct ixgbe_hw *hw,
+                                          union ixgbe_atr_hash_dword input,
+                                          union ixgbe_atr_hash_dword common)
+{
+	u64  fdirhashcmd;
+	u32  fdircmd;
+
+	DEBUGFUNC("ixgbe_fdir_clear_signature_filter_82599");
+
+	/*
+	 * Get the flow_type in order to program FDIRCMD properly
+	 * lowest 2 bits are FDIRCMD.L4TYPE, third lowest bit is FDIRCMD.IPV6
+	 */
+	switch (input.formatted.flow_type) {
+	case IXGBE_ATR_FLOW_TYPE_TCPV4:
+	case IXGBE_ATR_FLOW_TYPE_UDPV4:
+	case IXGBE_ATR_FLOW_TYPE_SCTPV4:
+	case IXGBE_ATR_FLOW_TYPE_TCPV6:
+	case IXGBE_ATR_FLOW_TYPE_UDPV6:
+	case IXGBE_ATR_FLOW_TYPE_SCTPV6:
+		break;
+	default:
+		DEBUGOUT(" Error on flow type input\n");
+		return IXGBE_ERR_CONFIG;
+	}
+
+	/* configure FDIRCMD register */
+	fdircmd = IXGBE_FDIRCMD_CMD_REMOVE_FLOW | 
+	          IXGBE_FDIRCMD_LAST | IXGBE_FDIRCMD_QUEUE_EN;
+	fdircmd |= input.formatted.flow_type << IXGBE_FDIRCMD_FLOW_TYPE_SHIFT;
+
+	/*
+	 * The lower 32-bits of fdirhashcmd is for FDIRHASH, the upper 32-bits
+	 * is for FDIRCMD.  Then do a 64-bit register write from FDIRHASH.
+	 */
+	fdirhashcmd = (u64)fdircmd << 32;
+	fdirhashcmd |= ixgbe_atr_compute_sig_hash_82599(input, common);
+	IXGBE_WRITE_REG64(hw, IXGBE_FDIRHASH, fdirhashcmd);
+
+	DEBUGOUT1("Tx hash=%x\n", (u32)fdirhashcmd);
+
+	return IXGBE_SUCCESS;
+}
+
 #define IXGBE_COMPUTE_BKT_HASH_ITERATION(_n) \
 do { \
 	u32 n = (_n); \
diff --git a/sys/dev/ixgbe/ixgbe_api.h b/sys/dev/ixgbe/ixgbe_api.h
index 91023ae..77c6427 100644
--- a/sys/dev/ixgbe/ixgbe_api.h
+++ b/sys/dev/ixgbe/ixgbe_api.h
@@ -144,6 +144,9 @@ s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
 					  union ixgbe_atr_hash_dword input,
 					  union ixgbe_atr_hash_dword common,
 					  u8 queue);
+s32 ixgbe_fdir_erase_signature_filter_82599(struct ixgbe_hw *hw,
+                                          union ixgbe_atr_hash_dword input,
+                                          union ixgbe_atr_hash_dword common);
 s32 ixgbe_fdir_set_input_mask_82599(struct ixgbe_hw *hw,
 				    union ixgbe_atr_input *input_mask);
 s32 ixgbe_fdir_write_perfect_filter_82599(struct ixgbe_hw *hw,
diff --git a/sys/dev/ixgbe/ixgbe_ioctl.h b/sys/dev/ixgbe/ixgbe_ioctl.h
new file mode 100644
index 0000000..f7113d3
--- /dev/null
+++ b/sys/dev/ixgbe/ixgbe_ioctl.h
@@ -0,0 +1,58 @@
+/**************************************************************************
+
+Copyright (c) 2013 Takuya ASADA
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions and the following disclaimer.
+
+ 2. Neither the name of the Chelsio Corporation nor the names of its
+    contributors may be used to endorse or promote products derived from
+    this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+$FreeBSD$
+
+***************************************************************************/
+
+#ifndef __IXGBEIOCTL_H__
+#define __IXGBEIOCTL_H__
+
+enum {
+	IX_ADD_SIGFILTER = 0x0,
+	IX_CLR_SIGFILTER
+};
+
+enum {
+	IXGBE_FILTER_PROTO_TCPV4,
+	IXGBE_FILTER_PROTO_UDPV4
+};
+
+struct ix_filter {
+	int proto;
+	struct in_addr src_ip;
+	int src_port;
+	struct in_addr dst_ip;
+	int dst_port;
+	int que_index;
+};
+
+#define IXGBE_ADD_SIGFILTER	_IOW('i', IX_ADD_SIGFILTER, struct ix_filter)
+#define IXGBE_CLR_SIGFILTER	_IOW('i', IX_CLR_SIGFILTER, struct ix_filter)
+
+#endif
+
diff --git a/sys/dev/ixgbe/ixgbe_type.h b/sys/dev/ixgbe/ixgbe_type.h
index 49f5bc0..c5f29bb 100644
--- a/sys/dev/ixgbe/ixgbe_type.h
+++ b/sys/dev/ixgbe/ixgbe_type.h
@@ -2997,6 +2997,8 @@ struct ixgbe_hw_stats {
 	u64 qbtc[16];
 	u64 qprdc[16];
 	u64 pxon2offc[8];
+	u64 fdirfree_free;
+	u64 fdirfree_coll;
 	u64 fdirustat_add;
 	u64 fdirustat_remove;
 	u64 fdirfstat_fadd;
diff --git a/tools/tools/ixgbetool/Makefile b/tools/tools/ixgbetool/Makefile
new file mode 100644
index 0000000..0695e93
--- /dev/null
+++ b/tools/tools/ixgbetool/Makefile
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+PROG=	ixgbetool
+SRCS=	ixgbetool.c
+NO_MAN=
+CFLAGS+= -I${.CURDIR}/../../../sys/dev/ixgbe -I.
+BINDIR?= /usr/sbin
+
+.include <bsd.prog.mk>
diff --git a/tools/tools/ixgbetool/ixgbetool.c b/tools/tools/ixgbetool/ixgbetool.c
new file mode 100644
index 0000000..d1911a5
--- /dev/null
+++ b/tools/tools/ixgbetool/ixgbetool.c
@@ -0,0 +1,174 @@
+/**************************************************************************
+
+Copyright (c) 2013, Takuya ASADA.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of the Chelsio Corporation nor the names of its
+    contributors may be used to endorse or promote products derived from
+    this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+
+***************************************************************************/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/ioctl.h>
+#include <ixgbe_ioctl.h>
+
+static void
+usage(void)
+{
+	fprintf(stderr, "Usage: ixgbetool <ifname> [operation]\n");
+	fprintf(stderr, "\tadd_sig_filter <proto> <src_ip> <src_port> <dst_ip> <dst_port> <que_index>\n");
+	fprintf(stderr, "\tdel_sig_filter <proto> <src_ip> <src_port> <dst_ip> <dst_port>\n");
+}
+
+static int
+doit(const char *iff_name, unsigned long cmd, void *data)
+{
+	int fd = 0;
+	int err;
+	char buf[64];
+
+	snprintf(buf, 64, "/dev/%s", iff_name);
+	if ((fd = open(buf, O_RDWR)) < 0)
+		return -1;
+	
+	err = ioctl(fd, cmd, data) < 0 ? -1 : 0;
+	close(fd);
+	return err;
+}
+
+static int 
+add_sig_filter(int argc, char *argv[], char *ifname)
+{
+	struct ix_filter filter;
+	int error;
+
+	if (argc != 9) 
+		return -1;
+
+	if (!strcmp(argv[3], "tcpv4"))
+		filter.proto = IXGBE_FILTER_PROTO_TCPV4;
+	else if (!strcmp(argv[3], "udpv4"))
+		filter.proto = IXGBE_FILTER_PROTO_UDPV4;
+	else
+		return -1;
+	error = inet_aton(argv[4], &filter.src_ip);
+	if (error != 1)
+		return error;
+	errno = 0;
+	filter.src_port = strtol(argv[5], NULL, 0);
+	if (errno)
+		return errno;
+	error = inet_aton(argv[6], &filter.dst_ip);
+	if (error != 1)
+		return error;
+	errno = 0;
+	filter.dst_port = strtol(argv[7], NULL, 0);
+	if (errno)
+		return errno;
+	errno = 0;
+	filter.que_index = strtol(argv[8], NULL, 0);
+	if (errno)
+		return errno;
+
+	error = doit(ifname, IXGBE_ADD_SIGFILTER, (void *)&filter);
+	if (error)
+		perror("ioctl");
+	return 0;
+}
+
+static int 
+del_sig_filter(int argc, char *argv[], char *ifname)
+{
+	struct ix_filter filter;
+	int error;
+
+	if (argc != 8) 
+		return -1;
+
+	if (!strcmp(argv[3], "tcpv4"))
+		filter.proto = IXGBE_FILTER_PROTO_TCPV4;
+	else if (!strcmp(argv[3], "udpv4"))
+		filter.proto = IXGBE_FILTER_PROTO_UDPV4;
+	else
+		return -1;
+	error = inet_aton(argv[4], &filter.src_ip);
+	if (error != 1)
+		return error;
+	errno = 0;
+	filter.src_port = strtol(argv[5], NULL, 0);
+	if (errno)
+		return errno;
+	error = inet_aton(argv[6], &filter.dst_ip);
+	if (error != 1)
+		return error;
+	errno = 0;
+	filter.dst_port = strtol(argv[7], NULL, 0);
+	if (errno)
+		return errno;
+
+	error = doit(ifname, IXGBE_CLR_SIGFILTER, (void *)&filter);
+	if (error)
+		perror("ioctl");
+	return 0;
+}
+
+int 
+main(int argc, char *argv[])
+{
+	int ret;
+	char *ifname;
+
+	if (argc < 3) {
+		usage();
+		exit(1);
+	}
+	ifname = argv[1];
+	if (!strcmp(argv[2], "add_sig_filter"))
+		ret = add_sig_filter(argc, argv, ifname);
+	else if (!strcmp(argv[2], "del_sig_filter"))
+		ret = del_sig_filter(argc, argv, ifname);
+	else 
+		ret = -1;
+
+	if (ret)
+		usage();
+
+	return (ret);
+}
+

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CALG4x-Xf27oEOA9K5j%2BRRndFe1VbDowpTti8a8qwu1mRaB4BkQ>