From owner-freebsd-bugs@FreeBSD.ORG Mon Sep 30 12:10:00 2013 Return-Path: Delivered-To: freebsd-bugs@smarthost.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTP id 631872B0 for ; Mon, 30 Sep 2013 12:10:00 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:1900:2254:206c::16:87]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id 40BE72107 for ; Mon, 30 Sep 2013 12:10:00 +0000 (UTC) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.7/8.14.7) with ESMTP id r8UCA0GH068836 for ; Mon, 30 Sep 2013 12:10:00 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.7/8.14.7/Submit) id r8UCA08g068835; Mon, 30 Sep 2013 12:10:00 GMT (envelope-from gnats) Resent-Date: Mon, 30 Sep 2013 12:10:00 GMT Resent-Message-Id: <201309301210.r8UCA08g068835@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Takuya ASADA Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTP id C169F17F for ; Mon, 30 Sep 2013 12:05:12 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from oldred.freebsd.org (oldred.freebsd.org [8.8.178.121]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id ACB6720BA for ; Mon, 30 Sep 2013 12:05:12 +0000 (UTC) Received: from oldred.freebsd.org ([127.0.1.6]) by oldred.freebsd.org (8.14.5/8.14.7) with ESMTP id r8UC5CbR078357 for ; Mon, 30 Sep 2013 12:05:12 GMT (envelope-from nobody@oldred.freebsd.org) Received: (from nobody@localhost) by oldred.freebsd.org (8.14.5/8.14.5/Submit) id r8UC5C5f078340; Mon, 30 Sep 2013 12:05:12 GMT (envelope-from nobody) Message-Id: <201309301205.r8UC5C5f078340@oldred.freebsd.org> Date: Mon, 30 Sep 2013 12:05:12 GMT From: Takuya ASADA To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-3.1 Subject: kern/182512: ixgbetool: Flow Director configuration tool for ixgbe(4) X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 30 Sep 2013 12:10:00 -0000 >Number: 182512 >Category: kern >Synopsis: ixgbetool: Flow Director configuration tool for ixgbe(4) >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Mon Sep 30 12:10:00 UTC 2013 >Closed-Date: >Last-Modified: >Originator: Takuya ASADA >Release: 10-CURRENT >Organization: >Environment: >Description: This patch provides a configuration tool for "Ethernet Flow Director", which is ixgbe(4) feature which assigns specific flow to specific RX queue. Here're usage of ixgbetool: - add a filter ixgbetool ix0 add_sig_filter tcpv4 10.1.0.1 34763 10.1.0.2 22 3 - show filters ixgbetool ix0 show_sig_filter - del a filter ixgbetool ix0 del_sig_filter 1 Also, character device(/dev/ix*) and ioctls are added on ixgbe(4) to communicate with ixgbetool. >How-To-Repeat: >Fix: Patch attached with submission follows: diff --git a/sys/dev/ixgbe/ixgbe.c b/sys/dev/ixgbe/ixgbe.c index b65df72..adefb14 100644 --- a/sys/dev/ixgbe/ixgbe.c +++ b/sys/dev/ixgbe/ixgbe.c @@ -35,6 +35,7 @@ #include "opt_inet.h" #include "opt_inet6.h" + #include "ixgbe.h" /********************************************************************* @@ -200,7 +201,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 +227,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 +333,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 +344,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 +419,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 +636,14 @@ ixgbe_attach(device_t dev) #ifdef DEV_NETMAP ixgbe_netmap_attach(adapter); #endif /* DEV_NETMAP */ + + error = ixgbe_makedev(adapter); + if (error) + goto err_late; + + mtx_init(&adapter->filter_mtx, "filter_mtx", NULL, MTX_DEF); + TAILQ_INIT(&adapter->filter_list); + INIT_DEBUGOUT("ixgbe_attach: end"); return (0); err_late: @@ -1812,7 +1852,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 +3099,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 +3519,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 +5310,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 +5702,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 +5889,137 @@ 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 struct ix_filter_entry * +ixgbe_find_filter(struct adapter *adapter, unsigned id) +{ + struct ix_filter_entry *entry; + + TAILQ_FOREACH(entry, &adapter->filter_list, link) + if (entry->filter.id == id) + return entry; + return NULL; +} + +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; + int error = 0; + + if (priv_check(td, PRIV_DRIVER)) { + return (EPERM); + } + + mtx_lock(&adapter->filter_mtx); + switch (cmd) { + case IXGBE_ADD_SIGFILTER: { + struct ix_filter *filter = (struct ix_filter *)data; + struct ix_filter_entry *entry; + 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: + error = EINVAL; + goto out; + } + 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; + + entry = malloc(sizeof(*entry), M_DEVBUF, M_NOWAIT | M_ZERO); + if (!entry) { + error = ENOMEM; + goto out; + } + memcpy(&entry->filter, filter, sizeof(entry->filter)); + entry->filter.id = adapter->next_filter_id++; + TAILQ_INSERT_TAIL(&adapter->filter_list, entry, link); + + ixgbe_fdir_add_signature_filter_82599(&adapter->hw, + input, common, filter->que_index); + break; + } + case IXGBE_GET_SIGFILTER: { + struct ix_filter *filter = (struct ix_filter *)data; + struct ix_filter_entry *entry; + + entry = ixgbe_find_filter(adapter, filter->id); + if (entry) + memcpy(filter, &entry->filter, sizeof(*filter)); + else + error = ENOENT; + break; + }; + case IXGBE_CLR_SIGFILTER: { + unsigned *id = (unsigned *)data; + struct ix_filter_entry *entry; + union ixgbe_atr_hash_dword input = {.dword = 0}; + union ixgbe_atr_hash_dword common = {.dword = 0}; + + entry = ixgbe_find_filter(adapter, *id); + if (!entry) { + error = ENOENT; + goto out; + } + + switch (entry->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: + error = EINVAL; + goto out; + } + common.port.src ^= htons(entry->filter.src_port); + common.port.dst ^= htons(entry->filter.dst_port); + common.flex_bytes ^= htons(ETHERTYPE_IP); + common.ip ^= entry->filter.src_ip.s_addr + ^ entry->filter.dst_ip.s_addr; + + ixgbe_fdir_erase_signature_filter_82599(&adapter->hw, + input, common); + + TAILQ_REMOVE(&adapter->filter_list, entry, link); + break; + } + case IXGBE_GET_SIGFILTER_LEN: { + unsigned *id = (unsigned *)data; + + *id = adapter->next_filter_id; + break; + } + default: + error = EOPNOTSUPP; + break; + } + +out: + mtx_unlock(&adapter->filter_mtx); + return (error); +} + diff --git a/sys/dev/ixgbe/ixgbe.h b/sys/dev/ixgbe/ixgbe.h index 77b72ed..064b510 100644 --- a/sys/dev/ixgbe/ixgbe.h +++ b/sys/dev/ixgbe/ixgbe.h @@ -88,8 +88,11 @@ #include #include #include +#include +#include #include "ixgbe_api.h" +#include "ixgbe_ioctl.h" /* Tunables */ @@ -468,8 +471,17 @@ struct adapter { unsigned long link_irq; struct ixgbe_hw_stats stats; + + struct cdev *cdev; + TAILQ_HEAD(, ix_filter_entry) filter_list; + struct mtx filter_mtx; + unsigned next_filter_id; }; +struct ix_filter_entry { + TAILQ_ENTRY(ix_filter_entry) link; + struct ix_filter filter; +}; /* Precision Time Sync (IEEE 1588) defines */ #define ETHERTYPE_IEEE1588 0x88F7 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..12f1522 --- /dev/null +++ b/sys/dev/ixgbe/ixgbe_ioctl.h @@ -0,0 +1,63 @@ +/************************************************************************** + +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_GET_SIGFILTER, + IX_CLR_SIGFILTER, + IX_GET_SIGFILTER_LEN +}; + +enum { + IXGBE_FILTER_PROTO_TCPV4, + IXGBE_FILTER_PROTO_UDPV4 +}; + +struct ix_filter { + unsigned id; + 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_GET_SIGFILTER _IOWR('i', IX_GET_SIGFILTER, struct ix_filter) +#define IXGBE_CLR_SIGFILTER _IOW('i', IX_CLR_SIGFILTER, unsigned) +#define IXGBE_GET_SIGFILTER_LEN _IOR('i', IX_GET_SIGFILTER_LEN, unsigned) + +#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 diff --git a/tools/tools/ixgbetool/ixgbetool.c b/tools/tools/ixgbetool/ixgbetool.c new file mode 100644 index 0000000..11cb2be --- /dev/null +++ b/tools/tools/ixgbetool/ixgbetool.c @@ -0,0 +1,211 @@ +/************************************************************************** + +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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void +usage(void) +{ + fprintf(stderr, "Usage: ixgbetool [operation]\n"); + fprintf(stderr, "\tadd_sig_filter \n"); + fprintf(stderr, "\tshow_sig_filter\n"); + fprintf(stderr, "\tdel_sig_filter \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 inline const char * +filter_proto_str(int proto) +{ + const char *str; + + switch (proto) { + case IXGBE_FILTER_PROTO_TCPV4: + str = "tcpv4"; + break; + case IXGBE_FILTER_PROTO_UDPV4: + str = "udpv4"; + break; + default: + str = "(inval)"; + } + return str; +} + +static int +show_sig_filter(int argc, char *argv[], char *ifname) +{ + unsigned i; + unsigned len; + int error; + + if (argc != 3) + return -1; + + error = doit(ifname, IXGBE_GET_SIGFILTER_LEN, (void *)&len); + if (error) + perror("ioctl"); + + for (i = 0; i < len; i++) { + struct ix_filter filter; + filter.id = i; + error = doit(ifname, IXGBE_GET_SIGFILTER, (void *)&filter); + if (error) + continue; + printf("id: %u\n", filter.id); + printf("proto: %s\n", filter_proto_str(filter.proto)); + printf("src_ip: %s\n", inet_ntoa(filter.src_ip)); + printf("src_port: %d\n", filter.src_port); + printf("dst_ip: %s\n", inet_ntoa(filter.dst_ip)); + printf("dst_port: %d\n", filter.dst_port); + printf("que_index: %d\n", filter.que_index); + printf("\n"); + } + return 0; +} + +static int +del_sig_filter(int argc, char *argv[], char *ifname) +{ + unsigned id; + int error; + + if (argc != 4) + return -1; + + errno = 0; + id = strtoul(argv[3], NULL, 0); + if (errno) + return errno; + + error = doit(ifname, IXGBE_CLR_SIGFILTER, (void *)&id); + 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], "show_sig_filter")) + ret = show_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); +} + >Release-Note: >Audit-Trail: >Unformatted: