* [PATCH 1/2] netfilter: nfnetlink: fix insufficient validation in nfnetlink_bind
From: Pablo Neira Ayuso @ 2014-11-20 12:30 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev
In-Reply-To: <1416486651-12271-1-git-send-email-pablo@netfilter.org>
Make sure the netlink group exists, otherwise you can trigger an out
of bound array memory access from the netlink_bind() path. This splat
can only be triggered only by superuser.
[ 180.203600] UBSan: Undefined behaviour in ../net/netfilter/nfnetlink.c:467:28
[ 180.204249] index 9 is out of range for type 'int [9]'
[ 180.204697] CPU: 0 PID: 1771 Comm: trinity-main Not tainted 3.18.0-rc4-mm1+ #122
[ 180.205365] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.7.5-0-ge51488c-20140602_164612-nilsson.home.kraxel.org
+04/01/2014
[ 180.206498] 0000000000000018 0000000000000000 0000000000000009 ffff88007bdf7da8
[ 180.207220] ffffffff82b0ef5f 0000000000000092 ffffffff845ae2e0 ffff88007bdf7db8
[ 180.207887] ffffffff8199e489 ffff88007bdf7e18 ffffffff8199ea22 0000003900000000
[ 180.208639] Call Trace:
[ 180.208857] dump_stack (lib/dump_stack.c:52)
[ 180.209370] ubsan_epilogue (lib/ubsan.c:174)
[ 180.209849] __ubsan_handle_out_of_bounds (lib/ubsan.c:400)
[ 180.210512] nfnetlink_bind (net/netfilter/nfnetlink.c:467)
[ 180.210986] netlink_bind (net/netlink/af_netlink.c:1483)
[ 180.211495] SYSC_bind (net/socket.c:1541)
Moreover, define the missing nf_tables and nf_acct multicast groups too.
Reported-by: Andrey Ryabinin <a.ryabinin@samsung.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/netfilter/nfnetlink.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c
index 6c5a915..13c2e17 100644
--- a/net/netfilter/nfnetlink.c
+++ b/net/netfilter/nfnetlink.c
@@ -47,6 +47,8 @@ static const int nfnl_group2type[NFNLGRP_MAX+1] = {
[NFNLGRP_CONNTRACK_EXP_NEW] = NFNL_SUBSYS_CTNETLINK_EXP,
[NFNLGRP_CONNTRACK_EXP_UPDATE] = NFNL_SUBSYS_CTNETLINK_EXP,
[NFNLGRP_CONNTRACK_EXP_DESTROY] = NFNL_SUBSYS_CTNETLINK_EXP,
+ [NFNLGRP_NFTABLES] = NFNL_SUBSYS_NFTABLES,
+ [NFNLGRP_ACCT_QUOTA] = NFNL_SUBSYS_ACCT,
};
void nfnl_lock(__u8 subsys_id)
@@ -464,7 +466,12 @@ static void nfnetlink_rcv(struct sk_buff *skb)
static int nfnetlink_bind(int group)
{
const struct nfnetlink_subsystem *ss;
- int type = nfnl_group2type[group];
+ int type;
+
+ if (group <= NFNLGRP_NONE || group > NFNLGRP_MAX)
+ return -EINVAL;
+
+ type = nfnl_group2type[group];
rcu_read_lock();
ss = nfnetlink_get_subsys(type);
@@ -514,6 +521,9 @@ static int __init nfnetlink_init(void)
{
int i;
+ for (i = NFNLGRP_NONE + 1; i <= NFNLGRP_MAX; i++)
+ BUG_ON(nfnl_group2type[i] == NFNL_SUBSYS_NONE);
+
for (i=0; i<NFNL_SUBSYS_COUNT; i++)
mutex_init(&table[i].mutex);
--
1.7.10.4
^ permalink raw reply related
* Question on bulk dequeue support in virtual drivers
From: James Yonan @ 2014-11-20 12:39 UTC (permalink / raw)
To: Linux Netdev List
Consider a tunneling driver that receives packets in ndo_start_xmit,
encapsulates them in UDP, and forwards via ip_local_out. The
ndo_start_xmit implementation can implement bulking by looking at
skb->xmit_more. But then how to efficiently transmit the resulting
bulked list of encapsulated packets via UDP, so that the packets both
enter and leave the driver in bulked form? Is there an ip_local_out
alternative for bulked skb lists?
James
^ permalink raw reply
* Re: [PATCH net V5] virtio-net: validate features during probe
From: Michael S. Tsirkin @ 2014-11-20 12:44 UTC (permalink / raw)
To: Jason Wang; +Cc: netdev, linux-kernel, virtualization, David Miller
In-Reply-To: <1416474185-10981-1-git-send-email-jasowang@redhat.com>
On Thu, Nov 20, 2014 at 05:03:05PM +0800, Jason Wang wrote:
> We currently trigger BUG when VIRTIO_NET_F_CTRL_VQ
> is not set but one of features depending on it is.
> That's not a friendly way to report errors to
> hypervisors.
> Let's check, and fail probe instead.
>
> Cc: Rusty Russell <rusty@rustcorp.com.au>
> Cc: Cornelia Huck <cornelia.huck@de.ibm.com>
> Cc: Wanlong Gao <gaowanlong@cn.fujitsu.com>
> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> Signed-off-by: Jason Wang <jasowang@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Cc DaveM to pick up the patch.
> ---
> Changes from V1:
> - Drop NETIF_F_*_UFO from checklist
> Changes from V2:
> - only check the features for ctrl vq (this fix the real bug)
> - better error message and simplify API
> Changes from V3:
> - pass dbit directly and even better error message
> - typo fix
> Changes from v4:
> - add "device" before "advertise"
> ---
> drivers/net/virtio_net.c | 37 +++++++++++++++++++++++++++++++++++++
> 1 file changed, 37 insertions(+)
>
> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> index ec2a8b4..b0bc8ea 100644
> --- a/drivers/net/virtio_net.c
> +++ b/drivers/net/virtio_net.c
> @@ -1673,6 +1673,40 @@ static const struct attribute_group virtio_net_mrg_rx_group = {
> };
> #endif
>
> +static bool virtnet_fail_on_feature(struct virtio_device *vdev,
> + unsigned int fbit,
> + const char *fname, const char *dname)
> +{
> + if (!virtio_has_feature(vdev, fbit))
> + return false;
> +
> + dev_err(&vdev->dev, "device advertises feature %s but not %s",
> + fname, dname);
> +
> + return true;
> +}
> +
> +#define VIRTNET_FAIL_ON(vdev, fbit, dbit) \
> + virtnet_fail_on_feature(vdev, fbit, #fbit, dbit)
> +
> +static bool virtnet_validate_features(struct virtio_device *vdev)
> +{
> + if (!virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ) &&
> + (VIRTNET_FAIL_ON(vdev, VIRTIO_NET_F_CTRL_RX,
> + "VIRTIO_NET_F_CTRL_VQ") ||
> + VIRTNET_FAIL_ON(vdev, VIRTIO_NET_F_CTRL_VLAN,
> + "VIRTIO_NET_F_CTRL_VQ") ||
> + VIRTNET_FAIL_ON(vdev, VIRTIO_NET_F_GUEST_ANNOUNCE,
> + "VIRTIO_NET_F_CTRL_VQ") ||
> + VIRTNET_FAIL_ON(vdev, VIRTIO_NET_F_MQ, "VIRTIO_NET_F_CTRL_VQ") ||
> + VIRTNET_FAIL_ON(vdev, VIRTIO_NET_F_CTRL_MAC_ADDR,
> + "VIRTIO_NET_F_CTRL_VQ"))) {
> + return false;
> + }
> +
> + return true;
> +}
> +
> static int virtnet_probe(struct virtio_device *vdev)
> {
> int i, err;
> @@ -1680,6 +1714,9 @@ static int virtnet_probe(struct virtio_device *vdev)
> struct virtnet_info *vi;
> u16 max_queue_pairs;
>
> + if (!virtnet_validate_features(vdev))
> + return -EINVAL;
> +
> /* Find if host supports multiqueue virtio_net device */
> err = virtio_cread_feature(vdev, VIRTIO_NET_F_MQ,
> struct virtio_net_config,
> --
> 1.9.1
^ permalink raw reply
* [patch net-next] i40e: remove dead fdb code
From: Jiri Pirko @ 2014-11-20 13:10 UTC (permalink / raw)
To: netdev
Cc: davem, jeffrey.t.kirsher, jesse.brandeburg, bruce.w.allan,
carolyn.wyborny, donald.c.skidmore, gregory.v.rose, matthew.vick,
john.ronciak, mitch.a.williams, linux.nics, e1000-devel
This code is not used now and also it contains some weird ifdefs. So
remove it for now. It can be added when needed.
Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
drivers/net/ethernet/intel/i40e/i40e_main.c | 98 -----------------------------
1 file changed, 98 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index c998d82..3368bf8 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -7521,97 +7521,6 @@ static int i40e_get_phys_port_id(struct net_device *netdev,
return 0;
}
-#ifdef HAVE_FDB_OPS
-#ifdef USE_CONST_DEV_UC_CHAR
-static int i40e_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
- struct net_device *dev,
- const unsigned char *addr,
- u16 flags)
-#else
-static int i40e_ndo_fdb_add(struct ndmsg *ndm,
- struct net_device *dev,
- unsigned char *addr,
- u16 flags)
-#endif
-{
- struct i40e_netdev_priv *np = netdev_priv(dev);
- struct i40e_pf *pf = np->vsi->back;
- int err = 0;
-
- if (!(pf->flags & I40E_FLAG_SRIOV_ENABLED))
- return -EOPNOTSUPP;
-
- /* Hardware does not support aging addresses so if a
- * ndm_state is given only allow permanent addresses
- */
- if (ndm->ndm_state && !(ndm->ndm_state & NUD_PERMANENT)) {
- netdev_info(dev, "FDB only supports static addresses\n");
- return -EINVAL;
- }
-
- if (is_unicast_ether_addr(addr) || is_link_local_ether_addr(addr))
- err = dev_uc_add_excl(dev, addr);
- else if (is_multicast_ether_addr(addr))
- err = dev_mc_add_excl(dev, addr);
- else
- err = -EINVAL;
-
- /* Only return duplicate errors if NLM_F_EXCL is set */
- if (err == -EEXIST && !(flags & NLM_F_EXCL))
- err = 0;
-
- return err;
-}
-
-#ifndef USE_DEFAULT_FDB_DEL_DUMP
-#ifdef USE_CONST_DEV_UC_CHAR
-static int i40e_ndo_fdb_del(struct ndmsg *ndm,
- struct net_device *dev,
- const unsigned char *addr)
-#else
-static int i40e_ndo_fdb_del(struct ndmsg *ndm,
- struct net_device *dev,
- unsigned char *addr)
-#endif
-{
- struct i40e_netdev_priv *np = netdev_priv(dev);
- struct i40e_pf *pf = np->vsi->back;
- int err = -EOPNOTSUPP;
-
- if (ndm->ndm_state & NUD_PERMANENT) {
- netdev_info(dev, "FDB only supports static addresses\n");
- return -EINVAL;
- }
-
- if (pf->flags & I40E_FLAG_SRIOV_ENABLED) {
- if (is_unicast_ether_addr(addr))
- err = dev_uc_del(dev, addr);
- else if (is_multicast_ether_addr(addr))
- err = dev_mc_del(dev, addr);
- else
- err = -EINVAL;
- }
-
- return err;
-}
-
-static int i40e_ndo_fdb_dump(struct sk_buff *skb,
- struct netlink_callback *cb,
- struct net_device *dev,
- struct net_device *filter_dev,
- int idx)
-{
- struct i40e_netdev_priv *np = netdev_priv(dev);
- struct i40e_pf *pf = np->vsi->back;
-
- if (pf->flags & I40E_FLAG_SRIOV_ENABLED)
- idx = ndo_dflt_fdb_dump(skb, cb, dev, filter_dev, idx);
-
- return idx;
-}
-
-#endif /* USE_DEFAULT_FDB_DEL_DUMP */
-#endif /* HAVE_FDB_OPS */
static const struct net_device_ops i40e_netdev_ops = {
.ndo_open = i40e_open,
.ndo_stop = i40e_close,
@@ -7645,13 +7554,6 @@ static const struct net_device_ops i40e_netdev_ops = {
.ndo_del_vxlan_port = i40e_del_vxlan_port,
#endif
.ndo_get_phys_port_id = i40e_get_phys_port_id,
-#ifdef HAVE_FDB_OPS
- .ndo_fdb_add = i40e_ndo_fdb_add,
-#ifndef USE_DEFAULT_FDB_DEL_DUMP
- .ndo_fdb_del = i40e_ndo_fdb_del,
- .ndo_fdb_dump = i40e_ndo_fdb_dump,
-#endif
-#endif
};
/**
--
1.9.3
^ permalink raw reply related
* [PATCH 1/1] IBM-EMAC: Deletion of unnecessary checks before the function call "of_dev_put"
From: SF Markus Elfring @ 2014-11-20 13:28 UTC (permalink / raw)
To: netdev; +Cc: LKML, kernel-janitors, Julia Lawall
In-Reply-To: <5317A59D.4@users.sourceforge.net>
From: Markus Elfring <elfring@users.sourceforge.net>
Date: Thu, 20 Nov 2014 14:22:47 +0100
The of_dev_put() function tests whether its argument is NULL and then
returns immediately. Thus the test around the call is not needed.
This issue was detected by using the Coccinelle software.
Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---
drivers/net/ethernet/ibm/emac/core.c | 24 ++++++++----------------
1 file changed, 8 insertions(+), 16 deletions(-)
diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c
index 87bd953..3f3fba9 100644
--- a/drivers/net/ethernet/ibm/emac/core.c
+++ b/drivers/net/ethernet/ibm/emac/core.c
@@ -2323,16 +2323,11 @@ static int emac_check_deps(struct emac_instance *dev,
static void emac_put_deps(struct emac_instance *dev)
{
- if (dev->mal_dev)
- of_dev_put(dev->mal_dev);
- if (dev->zmii_dev)
- of_dev_put(dev->zmii_dev);
- if (dev->rgmii_dev)
- of_dev_put(dev->rgmii_dev);
- if (dev->mdio_dev)
- of_dev_put(dev->mdio_dev);
- if (dev->tah_dev)
- of_dev_put(dev->tah_dev);
+ of_dev_put(dev->mal_dev);
+ of_dev_put(dev->zmii_dev);
+ of_dev_put(dev->rgmii_dev);
+ of_dev_put(dev->mdio_dev);
+ of_dev_put(dev->tah_dev);
}
static int emac_of_bus_notify(struct notifier_block *nb, unsigned long action,
@@ -2371,8 +2366,7 @@ static int emac_wait_deps(struct emac_instance *dev)
bus_unregister_notifier(&platform_bus_type, &emac_of_bus_notifier);
err = emac_check_deps(dev, deps) ? 0 : -ENODEV;
for (i = 0; i < EMAC_DEP_COUNT; i++) {
- if (deps[i].node)
- of_node_put(deps[i].node);
+ of_node_put(deps[i].node);
if (err && deps[i].ofdev)
of_dev_put(deps[i].ofdev);
}
@@ -2383,8 +2377,7 @@ static int emac_wait_deps(struct emac_instance *dev)
dev->tah_dev = deps[EMAC_DEP_TAH_IDX].ofdev;
dev->mdio_dev = deps[EMAC_DEP_MDIO_IDX].ofdev;
}
- if (deps[EMAC_DEP_PREV_IDX].ofdev)
- of_dev_put(deps[EMAC_DEP_PREV_IDX].ofdev);
+ of_dev_put(deps[EMAC_DEP_PREV_IDX].ofdev);
return err;
}
@@ -3113,8 +3106,7 @@ static void __exit emac_exit(void)
/* Destroy EMAC boot list */
for (i = 0; i < EMAC_BOOT_LIST_SIZE; i++)
- if (emac_boot_list[i])
- of_node_put(emac_boot_list[i]);
+ of_node_put(emac_boot_list[i]);
}
module_init(emac_init);
--
2.1.3
^ permalink raw reply related
* [PATCH 1/1] net: Xilinx: Deletion of unnecessary checks before two function calls
From: SF Markus Elfring @ 2014-11-20 13:50 UTC (permalink / raw)
To: Michal Simek, netdev, linux-arm-kernel
Cc: LKML, kernel-janitors, Julia Lawall
In-Reply-To: <5317A59D.4@users.sourceforge.net>
From: Markus Elfring <elfring@users.sourceforge.net>
Date: Thu, 20 Nov 2014 14:47:12 +0100
The functions kfree() and of_node_put() test whether their argument is NULL
and then return immediately. Thus the test around the call is not needed.
This issue was detected by using the Coccinelle software.
Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---
drivers/net/ethernet/xilinx/ll_temac_main.c | 3 +--
drivers/net/ethernet/xilinx/xilinx_emaclite.c | 3 +--
2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/xilinx/ll_temac_main.c b/drivers/net/ethernet/xilinx/ll_temac_main.c
index fda5891..af60867 100644
--- a/drivers/net/ethernet/xilinx/ll_temac_main.c
+++ b/drivers/net/ethernet/xilinx/ll_temac_main.c
@@ -224,8 +224,7 @@ static void temac_dma_bd_release(struct net_device *ndev)
dma_free_coherent(ndev->dev.parent,
sizeof(*lp->tx_bd_v) * TX_BD_NUM,
lp->tx_bd_v, lp->tx_bd_p);
- if (lp->rx_skb)
- kfree(lp->rx_skb);
+ kfree(lp->rx_skb);
}
/**
diff --git a/drivers/net/ethernet/xilinx/xilinx_emaclite.c b/drivers/net/ethernet/xilinx/xilinx_emaclite.c
index 28dbbdc..2485879 100644
--- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c
+++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c
@@ -1200,8 +1200,7 @@ static int xemaclite_of_remove(struct platform_device *of_dev)
unregister_netdev(ndev);
- if (lp->phy_node)
- of_node_put(lp->phy_node);
+ of_node_put(lp->phy_node);
lp->phy_node = NULL;
xemaclite_remove_ndev(ndev);
--
2.1.3
^ permalink raw reply related
* Re: [PATCH net-next] net: sctp: keep owned chunk in destructor_arg instead of skb->cb
From: Neil Horman @ 2014-11-20 14:06 UTC (permalink / raw)
To: Daniel Borkmann; +Cc: davem, linux-sctp, netdev
In-Reply-To: <1416439266-11396-1-git-send-email-dborkman@redhat.com>
On Thu, Nov 20, 2014 at 12:21:06AM +0100, Daniel Borkmann wrote:
> It's just silly to hold the skb destructor argument around inside
> skb->cb[] as we currently do in SCTP.
>
> Though this has been around forever, I'm inclined to say that prior
> to 4c3a5bdae293 ("sctp: Don't charge for data in sndbuf again when
> transmitting packet") this may well have caused issues as doing so
> violates the cb[] usage accross layers; before 4c3a5bdae293-times,
> we have charged twice for data, and when destructor kicks in, cb[]
> could have been overwritten already by someone else.
>
> Nowadays, we're sort of cheating on data accounting in the sense
> that due to commit 4c3a5bdae293, we orphan the skb already in the
> SCTP output path, and use a different destructor only to make sure
> the sk doesn't vanish on skb destruction time. Thus, cb[] is still
> valid here as we operate within the SCTP layer. It's actually a big
> candidate for future rework, imho.
>
> Anyhow, lets keep the chunk in destructor_arg, as this is the actual
> purpose for it so that in future, we don't run into trouble.
>
> Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
> ---
> net/sctp/socket.c | 12 ++++--------
> 1 file changed, 4 insertions(+), 8 deletions(-)
>
> diff --git a/net/sctp/socket.c b/net/sctp/socket.c
> index 2120292..85e0b65 100644
> --- a/net/sctp/socket.c
> +++ b/net/sctp/socket.c
> @@ -162,7 +162,7 @@ static inline void sctp_set_owner_w(struct sctp_chunk *chunk)
>
> chunk->skb->destructor = sctp_wfree;
> /* Save the chunk pointer in skb for sctp_wfree to use later. */
> - *((struct sctp_chunk **)(chunk->skb->cb)) = chunk;
> + skb_shinfo(chunk->skb)->destructor_arg = chunk;
>
> asoc->sndbuf_used += SCTP_DATA_SNDSIZE(chunk) +
> sizeof(struct sk_buff) +
> @@ -6870,14 +6870,10 @@ static void sctp_wake_up_waiters(struct sock *sk,
> */
> static void sctp_wfree(struct sk_buff *skb)
> {
> - struct sctp_association *asoc;
> - struct sctp_chunk *chunk;
> - struct sock *sk;
> + struct sctp_chunk *chunk = skb_shinfo(skb)->destructor_arg;
> + struct sctp_association *asoc = chunk->asoc;
> + struct sock *sk = asoc->base.sk;
>
> - /* Get the saved chunk pointer. */
> - chunk = *((struct sctp_chunk **)(skb->cb));
> - asoc = chunk->asoc;
> - sk = asoc->base.sk;
> asoc->sndbuf_used -= SCTP_DATA_SNDSIZE(chunk) +
> sizeof(struct sk_buff) +
> sizeof(struct sctp_chunk);
> --
> 1.7.11.7
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
Seems reasonable
Acked-by: Neil Horman <nhorman@tuxdriver.com>
^ permalink raw reply
* Re: [PATCH net-next v2] net: sctp: keep owned chunk in destructor_arg instead of skb->cb
From: Neil Horman @ 2014-11-20 14:07 UTC (permalink / raw)
To: Daniel Borkmann; +Cc: davem, linux-sctp, netdev
In-Reply-To: <1416444888-12778-1-git-send-email-dborkman@redhat.com>
On Thu, Nov 20, 2014 at 01:54:48AM +0100, Daniel Borkmann wrote:
> It's just silly to hold the skb destructor argument around inside
> skb->cb[] as we currently do in SCTP.
>
> Nowadays, we're sort of cheating on data accounting in the sense
> that due to commit 4c3a5bdae293 ("sctp: Don't charge for data in
> sndbuf again when transmitting packet"), we orphan the skb already
> in the SCTP output path, i.e. giving back charged data memory, and
> use a different destructor only to make sure the sk doesn't vanish
> on skb destruction time. Thus, cb[] is still valid here as we
> operate within the SCTP layer. (It's generally actually a big
> candidate for future rework, imho.)
>
> However, storing the destructor in the cb[] can easily cause issues
> should an non sctp_packet_set_owner_w()'ed skb ever escape the SCTP
> layer, since cb[] may get overwritten by lower layers and thus can
> corrupt the chunk pointer. There are no such issues at present,
> but lets keep the chunk in destructor_arg, as this is the actual
> purpose for it.
>
> Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
> ---
> v1->v2:
> - Only reworded commit message to make it more clear
>
> net/sctp/socket.c | 12 ++++--------
> 1 file changed, 4 insertions(+), 8 deletions(-)
>
> diff --git a/net/sctp/socket.c b/net/sctp/socket.c
> index 2120292..85e0b65 100644
> --- a/net/sctp/socket.c
> +++ b/net/sctp/socket.c
> @@ -162,7 +162,7 @@ static inline void sctp_set_owner_w(struct sctp_chunk *chunk)
>
> chunk->skb->destructor = sctp_wfree;
> /* Save the chunk pointer in skb for sctp_wfree to use later. */
> - *((struct sctp_chunk **)(chunk->skb->cb)) = chunk;
> + skb_shinfo(chunk->skb)->destructor_arg = chunk;
>
> asoc->sndbuf_used += SCTP_DATA_SNDSIZE(chunk) +
> sizeof(struct sk_buff) +
> @@ -6870,14 +6870,10 @@ static void sctp_wake_up_waiters(struct sock *sk,
> */
> static void sctp_wfree(struct sk_buff *skb)
> {
> - struct sctp_association *asoc;
> - struct sctp_chunk *chunk;
> - struct sock *sk;
> + struct sctp_chunk *chunk = skb_shinfo(skb)->destructor_arg;
> + struct sctp_association *asoc = chunk->asoc;
> + struct sock *sk = asoc->base.sk;
>
> - /* Get the saved chunk pointer. */
> - chunk = *((struct sctp_chunk **)(skb->cb));
> - asoc = chunk->asoc;
> - sk = asoc->base.sk;
> asoc->sndbuf_used -= SCTP_DATA_SNDSIZE(chunk) +
> sizeof(struct sk_buff) +
> sizeof(struct sctp_chunk);
> --
> 1.7.11.7
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
Acked-by: Neil Horman <nhorman@tuxdriver.com>
^ permalink raw reply
* [PATCH 1/1] net: Hyper-V: Deletion of an unnecessary check before the function call "vfree"
From: SF Markus Elfring @ 2014-11-20 14:25 UTC (permalink / raw)
To: Haiyang Zhang, K. Y. Srinivasan, devel, netdev
Cc: Julia Lawall, kernel-janitors, LKML
In-Reply-To: <5317A59D.4@users.sourceforge.net>
From: Markus Elfring <elfring@users.sourceforge.net>
Date: Thu, 20 Nov 2014 15:15:21 +0100
The vfree() function performs also input parameter validation. Thus the test
around the call is not needed.
This issue was detected by using the Coccinelle software.
Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---
drivers/net/hyperv/netvsc.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index da2d346..ffe7481 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -548,8 +548,7 @@ int netvsc_device_remove(struct hv_device *device)
vmbus_close(device->channel);
/* Release all resources */
- if (net_device->sub_cb_buf)
- vfree(net_device->sub_cb_buf);
+ vfree(net_device->sub_cb_buf);
kfree(net_device);
return 0;
--
2.1.3
^ permalink raw reply related
* [PATCH net-next V1 2/2] net/mlx4_en: Support for configurable RSS hash function
From: Amir Vadai @ 2014-11-20 14:26 UTC (permalink / raw)
To: David S. Miller
Cc: netdev, Ben Hutchings, Or Gerlitz, Yevgeny Petrilin, Eyal Perry,
Amir Vadai
In-Reply-To: <1416493610-8966-1-git-send-email-amirv@mellanox.com>
From: Eyal Perry <eyalpe@mellanox.com>
The ConnectX HW is capable of using one of the following hash functions:
Toeplitz and an XOR hash function. This patch extends the implementation
of the mlx4_en driver set/get_rxfh callbacks to support getting and
setting the RSS hash function used by the device.
Signed-off-by: Eyal Perry <eyalpe@mellanox.com>
Signed-off-by: Amir Vadai <amirv@mellanox.com>
---
drivers/net/ethernet/mellanox/mlx4/en_ethtool.c | 78 ++++++++++++++++++-------
drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 11 ++++
drivers/net/ethernet/mellanox/mlx4/en_rx.c | 13 ++++-
drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 2 +-
4 files changed, 80 insertions(+), 24 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
index c50181a..ae679ca 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
@@ -978,6 +978,27 @@ static u32 mlx4_en_get_rxfh_key_size(struct net_device *netdev)
return MLX4_EN_RSS_KEY_SIZE;
}
+static int mlx4_en_check_rxfh_func(struct net_device *dev, u8 hfunc)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+
+ /* check if requested function is supported by the device */
+ if ((hfunc == ETH_RSS_HASH_TOP &&
+ !(priv->mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_RSS_TOP)) ||
+ (hfunc == ETH_RSS_HASH_XOR &&
+ !(priv->mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_RSS_XOR)))
+ return -EINVAL;
+
+ priv->rss_hash_fn = hfunc;
+ if (hfunc == ETH_RSS_HASH_TOP && !(dev->features & NETIF_F_RXHASH))
+ en_warn(priv,
+ "Toeplitz hash function should be used in conjunction with RX hashing for optimal performance\n");
+ if (hfunc == ETH_RSS_HASH_XOR && (dev->features & NETIF_F_RXHASH))
+ en_warn(priv,
+ "Enabling both XOR Hash function and RX Hashing can limit RPS functionality\n");
+ return 0;
+}
+
static int mlx4_en_get_rxfh(struct net_device *dev, u32 *ring_index, u8 *key,
u8 *hfunc)
{
@@ -987,18 +1008,23 @@ static int mlx4_en_get_rxfh(struct net_device *dev, u32 *ring_index, u8 *key,
size_t n = priv->rx_ring_num;
int err = 0;
- if (!ring_index)
+ if (!ring_index && !hfunc && !key)
return -EOPNOTSUPP;
- rss_rings = priv->prof->rss_rings ?: priv->rx_ring_num;
- rss_rings = 1 << ilog2(rss_rings);
+ if (ring_index) {
+ rss_rings = priv->prof->rss_rings ?: priv->rx_ring_num;
+ rss_rings = 1 << ilog2(rss_rings);
- while (n--) {
- ring_index[n] = rss_map->qps[n % rss_rings].qpn -
- rss_map->base_qpn;
+ while (n--) {
+ ring_index[n] = rss_map->qps[n % rss_rings].qpn -
+ rss_map->base_qpn;
+ }
}
if (key)
netdev_rss_key_fill(key, MLX4_EN_RSS_KEY_SIZE);
+ if (hfunc)
+ *hfunc = priv->rss_hash_fn;
+
return err;
}
@@ -1015,26 +1041,35 @@ static int mlx4_en_set_rxfh(struct net_device *dev, const u32 *ring_index,
/* We require at least one supported parameter to be changed and no
* change in any of the unsupported parameters
*/
- if (!ring_index || (key || hfunc != ETH_RSS_HASH_NO_CHANGE))
+ if ((!ring_index && hfunc == ETH_RSS_HASH_NO_CHANGE) || key)
return -EOPNOTSUPP;
- /* Calculate RSS table size and make sure flows are spread evenly
- * between rings
- */
- for (i = 0; i < priv->rx_ring_num; i++) {
- if (i > 0 && !ring_index[i] && !rss_rings)
- rss_rings = i;
+ if (ring_index) {
+ /* Calculate RSS table size and make sure flows are spread
+ * evenly between rings
+ */
+ for (i = 0; i < priv->rx_ring_num; i++) {
+ if (i > 0 && !ring_index[i] && !rss_rings)
+ rss_rings = i;
+
+ if (ring_index[i] != (i % (rss_rings ?:
+ priv->rx_ring_num)))
+ return -EINVAL;
+ }
- if (ring_index[i] != (i % (rss_rings ?: priv->rx_ring_num)))
+ if (!rss_rings)
+ rss_rings = priv->rx_ring_num;
+
+ /* RSS table size must be an order of 2 */
+ if (!is_power_of_2(rss_rings))
return -EINVAL;
}
- if (!rss_rings)
- rss_rings = priv->rx_ring_num;
-
- /* RSS table size must be an order of 2 */
- if (!is_power_of_2(rss_rings))
- return -EINVAL;
+ if (hfunc != ETH_RSS_HASH_NO_CHANGE) {
+ err = mlx4_en_check_rxfh_func(dev, hfunc);
+ if (err)
+ return err;
+ }
mutex_lock(&mdev->state_lock);
if (priv->port_up) {
@@ -1042,7 +1077,8 @@ static int mlx4_en_set_rxfh(struct net_device *dev, const u32 *ring_index,
mlx4_en_stop_port(dev, 1);
}
- priv->prof->rss_rings = rss_rings;
+ if (ring_index)
+ priv->prof->rss_rings = rss_rings;
if (port_up) {
err = mlx4_en_start_port(dev);
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index f3df9b3..d81bb31 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -2596,6 +2596,17 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
if (mdev->dev->caps.steering_mode != MLX4_STEERING_MODE_A0)
dev->priv_flags |= IFF_UNICAST_FLT;
+ /* Setting a default hash function value */
+ if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_RSS_TOP) {
+ priv->rss_hash_fn = ETH_RSS_HASH_TOP;
+ } else if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_RSS_XOR) {
+ priv->rss_hash_fn = ETH_RSS_HASH_XOR;
+ } else {
+ en_warn(priv,
+ "No RSS hash capabilities exposed, using Toeplitz\n");
+ priv->rss_hash_fn = ETH_RSS_HASH_TOP;
+ }
+
mdev->pndev[port] = dev;
netif_carrier_off(dev);
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
index b7bda89..3b3ffbd 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
@@ -1223,8 +1223,17 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv)
rss_context->flags = rss_mask;
rss_context->hash_fn = MLX4_RSS_HASH_TOP;
- netdev_rss_key_fill(rss_context->rss_key, MLX4_EN_RSS_KEY_SIZE);
-
+ if (priv->rss_hash_fn == ETH_RSS_HASH_XOR) {
+ rss_context->hash_fn = MLX4_RSS_HASH_XOR;
+ } else if (priv->rss_hash_fn == ETH_RSS_HASH_TOP) {
+ rss_context->hash_fn = MLX4_RSS_HASH_TOP;
+ netdev_rss_key_fill(rss_context->rss_key,
+ MLX4_EN_RSS_KEY_SIZE);
+ } else {
+ en_err(priv, "Unknown RSS hash function requested\n");
+ err = -EINVAL;
+ goto indir_err;
+ }
err = mlx4_qp_to_ready(mdev->dev, &priv->res.mtt, &context,
&rss_map->indir_qp, &rss_map->indir_state);
if (err)
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
index de45674..f08c34c 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
@@ -376,7 +376,6 @@ struct mlx4_en_port_profile {
};
struct mlx4_en_profile {
- int rss_xor;
int udp_rss;
u8 rss_mask;
u32 active_ports;
@@ -618,6 +617,7 @@ struct mlx4_en_priv {
__be16 vxlan_port;
u32 pflags;
+ u8 rss_hash_fn;
};
enum mlx4_en_wol {
--
1.8.3.4
^ permalink raw reply related
* [PATCH net-next V1 0/2] ethtool, net/mlx4_en: RSS hash function selection
From: Amir Vadai @ 2014-11-20 14:26 UTC (permalink / raw)
To: David S. Miller
Cc: netdev, Ben Hutchings, Or Gerlitz, Yevgeny Petrilin, Amir Vadai
Hi,
This patchset by Eyal adds support in set/get of RSS hash function. Current
supported functions are Toeplitz and XOR. The API is design to enable adding
new hash functions without breaking backward compatibility.
Userspace patch will be sent after API is available in kernel.
The patchset was applied and tested over commit 7b909bb ("Merge branches
'core', 'cxgb4', 'iser', 'mlx5' and 'ocrdma' into for-next")
Amir
Changes from V0:
- Patch 1/2 - ethtool: Support for configurable RSS hash function:
- Add ETH prefix to RSS_HASH_* definitions
- Moved the strings array to ethtool.c
- Extend {get,set}_rxfh with additional arg instead of adding new
ethtool_option and adopt the change into drivers implementations.
- Moved indir_size and key_size validation into drivers implantation
- Documented hfunc filed in ethtool_rxfh struct
- Patch 2/2 - net/mlx4_en: Support for configurable RSS hash function
- Remove redundant priv->rss_hash_fn_caps
- Use == operator instead & when determining requested hash function.
Eyal Perry (2):
ethtool: Support for configurable RSS hash function
net/mlx4_en: Support for configurable RSS hash function
drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c | 11 ++-
.../net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c | 14 +++-
drivers/net/ethernet/broadcom/tg3.c | 14 +++-
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 14 +++-
drivers/net/ethernet/emulex/benet/be_ethtool.c | 14 +++-
drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c | 14 +++-
drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c | 14 +++-
drivers/net/ethernet/intel/igb/igb_ethtool.c | 14 +++-
drivers/net/ethernet/mellanox/mlx4/en_ethtool.c | 86 +++++++++++++++++-----
drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 11 +++
drivers/net/ethernet/mellanox/mlx4/en_rx.c | 13 +++-
drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 2 +-
drivers/net/ethernet/sfc/ethtool.c | 16 +++-
drivers/net/vmxnet3/vmxnet3_ethtool.c | 13 +++-
include/linux/ethtool.h | 42 ++++++++---
include/uapi/linux/ethtool.h | 10 ++-
net/core/ethtool.c | 69 +++++++++--------
17 files changed, 281 insertions(+), 90 deletions(-)
--
1.8.3.4
^ permalink raw reply
* [PATCH net-next V1 1/2] ethtool: Support for configurable RSS hash function
From: Amir Vadai @ 2014-11-20 14:26 UTC (permalink / raw)
To: David S. Miller
Cc: netdev, Ben Hutchings, Or Gerlitz, Yevgeny Petrilin, Eyal Perry,
Tom Lendacky, Ariel Elior, Prashant Sreedharan, Michael Chan,
Hariprasad S, Sathya Perla, Subbu Seetharaman, Ajit Khaparde,
Jeff Kirsher, Jesse Brandeburg, Bruce Allan, Carolyn Wyborny,
Don Skidmore, Greg Rose, Matthew Vick, John Ronciak,
Mitch Williams
In-Reply-To: <1416493610-8966-1-git-send-email-amirv@mellanox.com>
From: Eyal Perry <eyalpe@mellanox.com>
This patch extends the set/get_rxfh ethtool-options for getting or
setting the RSS hash function and modifies drivers implementation of
set/get_rxfh accordingly. This change also delegate the responsibility
of checking weather a modification to a certain RX flow hash parameter
is supported to the driver implementation of set_rxfh.
User-kernel API is done through the new hfunc bitmask field in the
ethtool_rxfh struct. A bit set in the hfunc field is corresponding to an
index in the new string-set ETH_SS_RSS_HASH_FUNCS.
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Ariel Elior <ariel.elior@qlogic.com>
Cc: Prashant Sreedharan <prashant@broadcom.com>
Cc: Michael Chan <mchan@broadcom.com>
Cc: Hariprasad S <hariprasad@chelsio.com>
Cc: Sathya Perla <sathya.perla@emulex.com>
Cc: Subbu Seetharaman <subbu.seetharaman@emulex.com>
Cc: Ajit Khaparde <ajit.khaparde@emulex.com>
Cc: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Cc: Jesse Brandeburg <jesse.brandeburg@intel.com>
Cc: Bruce Allan <bruce.w.allan@intel.com>
Cc: Carolyn Wyborny <carolyn.wyborny@intel.com>
Cc: Don Skidmore <donald.c.skidmore@intel.com>
Cc: Greg Rose <gregory.v.rose@intel.com>
Cc: Matthew Vick <matthew.vick@intel.com>
Cc: John Ronciak <john.ronciak@intel.com>
Cc: Mitch Williams <mitch.a.williams@intel.com>
Cc: Amir Vadai <amirv@mellanox.com>
Cc: Solarflare linux maintainers <linux-net-drivers@solarflare.com>
Cc: Shradha Shah <sshah@solarflare.com>
Cc: Shreyas Bhatewara <sbhatewara@vmware.com>
Cc: "VMware, Inc." <pv-drivers@vmware.com>
Cc: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Eyal Perry <eyalpe@mellanox.com>
Signed-off-by: Amir Vadai <amirv@mellanox.com>
---
drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c | 11 +++-
.../net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c | 14 ++++-
drivers/net/ethernet/broadcom/tg3.c | 14 ++++-
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 14 ++++-
drivers/net/ethernet/emulex/benet/be_ethtool.c | 14 ++++-
drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c | 14 ++++-
drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c | 14 ++++-
drivers/net/ethernet/intel/igb/igb_ethtool.c | 14 ++++-
drivers/net/ethernet/mellanox/mlx4/en_ethtool.c | 14 ++++-
drivers/net/ethernet/sfc/ethtool.c | 16 ++++-
drivers/net/vmxnet3/vmxnet3_ethtool.c | 13 +++-
include/linux/ethtool.h | 42 +++++++++----
include/uapi/linux/ethtool.h | 10 +++-
net/core/ethtool.c | 69 ++++++++++++----------
14 files changed, 204 insertions(+), 69 deletions(-)
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
index 95d4453..763aec8 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
@@ -511,7 +511,8 @@ static u32 xgbe_get_rxfh_indir_size(struct net_device *netdev)
return ARRAY_SIZE(pdata->rss_table);
}
-static int xgbe_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key)
+static int xgbe_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
+ u8 *hfunc)
{
struct xgbe_prv_data *pdata = netdev_priv(netdev);
unsigned int i;
@@ -529,12 +530,18 @@ static int xgbe_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key)
}
static int xgbe_set_rxfh(struct net_device *netdev, const u32 *indir,
- const u8 *key)
+ const u8 *key, const u8 hfunc)
{
struct xgbe_prv_data *pdata = netdev_priv(netdev);
struct xgbe_hw_if *hw_if = &pdata->hw_if;
unsigned int ret;
+ /* We require at least one supported parameter to be changed and no
+ * change in any of the unsupported parameters
+ */
+ if ((!indir && !key) || hfunc != ETH_RSS_HASH_NO_CHANGE)
+ return -EOPNOTSUPP;
+
if (indir) {
ret = hw_if->set_rss_lookup_table(pdata, indir);
if (ret)
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
index 1edc931..654c29e 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
@@ -3358,12 +3358,16 @@ static u32 bnx2x_get_rxfh_indir_size(struct net_device *dev)
return T_ETH_INDIRECTION_TABLE_SIZE;
}
-static int bnx2x_get_rxfh(struct net_device *dev, u32 *indir, u8 *key)
+static int bnx2x_get_rxfh(struct net_device *dev, u32 *indir, u8 *key,
+ u8 *hfunc)
{
struct bnx2x *bp = netdev_priv(dev);
u8 ind_table[T_ETH_INDIRECTION_TABLE_SIZE] = {0};
size_t i;
+ if (!indir)
+ return -EOPNOTSUPP;
+
/* Get the current configuration of the RSS indirection table */
bnx2x_get_rss_ind_table(&bp->rss_conf_obj, ind_table);
@@ -3383,11 +3387,17 @@ static int bnx2x_get_rxfh(struct net_device *dev, u32 *indir, u8 *key)
}
static int bnx2x_set_rxfh(struct net_device *dev, const u32 *indir,
- const u8 *key)
+ const u8 *key, const u8 hfunc)
{
struct bnx2x *bp = netdev_priv(dev);
size_t i;
+ /* We require at least one supported parameter to be changed and no
+ * change in any of the unsupported parameters
+ */
+ if (!indir || (key || hfunc != ETH_RSS_HASH_NO_CHANGE))
+ return -EOPNOTSUPP;
+
for (i = 0; i < T_ETH_INDIRECTION_TABLE_SIZE; i++) {
/*
* The same as in bnx2x_get_rxfh: we can't use a memcpy()
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index 2dc0015..03d168c 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -12560,22 +12560,32 @@ static u32 tg3_get_rxfh_indir_size(struct net_device *dev)
return size;
}
-static int tg3_get_rxfh(struct net_device *dev, u32 *indir, u8 *key)
+static int tg3_get_rxfh(struct net_device *dev, u32 *indir, u8 *key, u8 *hfunc)
{
struct tg3 *tp = netdev_priv(dev);
int i;
+ if (!indir)
+ return -EOPNOTSUPP;
+
for (i = 0; i < TG3_RSS_INDIR_TBL_SIZE; i++)
indir[i] = tp->rss_ind_tbl[i];
return 0;
}
-static int tg3_set_rxfh(struct net_device *dev, const u32 *indir, const u8 *key)
+static int tg3_set_rxfh(struct net_device *dev, const u32 *indir, const u8 *key,
+ const u8 hfunc)
{
struct tg3 *tp = netdev_priv(dev);
size_t i;
+ /* We require at least one supported parameter to be changed and no
+ * change in any of the unsupported parameters
+ */
+ if (!indir || (key || hfunc != ETH_RSS_HASH_NO_CHANGE))
+ return -EOPNOTSUPP;
+
for (i = 0; i < TG3_RSS_INDIR_TBL_SIZE; i++)
tp->rss_ind_tbl[i] = indir[i];
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 19ffe9b..a0c0cbf 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -3010,21 +3010,31 @@ static u32 get_rss_table_size(struct net_device *dev)
return pi->rss_size;
}
-static int get_rss_table(struct net_device *dev, u32 *p, u8 *key)
+static int get_rss_table(struct net_device *dev, u32 *p, u8 *key, u8 *hfunc)
{
const struct port_info *pi = netdev_priv(dev);
unsigned int n = pi->rss_size;
+ if (!p)
+ return -EOPNOTSUPP;
+
while (n--)
p[n] = pi->rss[n];
return 0;
}
-static int set_rss_table(struct net_device *dev, const u32 *p, const u8 *key)
+static int set_rss_table(struct net_device *dev, const u32 *p, const u8 *key,
+ const u8 hfunc)
{
unsigned int i;
struct port_info *pi = netdev_priv(dev);
+ /* We require at least one supported parameter to be changed and no
+ * change in any of the unsupported parameters
+ */
+ if (!p || (key || hfunc != ETH_RSS_HASH_NO_CHANGE))
+ return -EOPNOTSUPP;
+
for (i = 0; i < pi->rss_size; i++)
pi->rss[i] = p[i];
if (pi->adapter->flags & FULL_INIT_DONE)
diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c
index e42a791..357089f3 100644
--- a/drivers/net/ethernet/emulex/benet/be_ethtool.c
+++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c
@@ -1171,12 +1171,16 @@ static u32 be_get_rxfh_key_size(struct net_device *netdev)
return RSS_HASH_KEY_LEN;
}
-static int be_get_rxfh(struct net_device *netdev, u32 *indir, u8 *hkey)
+static int be_get_rxfh(struct net_device *netdev, u32 *indir, u8 *hkey,
+ u8 *hfunc)
{
struct be_adapter *adapter = netdev_priv(netdev);
int i;
struct rss_info *rss = &adapter->rss_info;
+ if (!indir && !hkey)
+ return -EOPNOTSUPP;
+
if (indir) {
for (i = 0; i < RSS_INDIR_TABLE_LEN; i++)
indir[i] = rss->rss_queue[i];
@@ -1189,12 +1193,18 @@ static int be_get_rxfh(struct net_device *netdev, u32 *indir, u8 *hkey)
}
static int be_set_rxfh(struct net_device *netdev, const u32 *indir,
- const u8 *hkey)
+ const u8 *hkey, const u8 hfunc)
{
int rc = 0, i, j;
struct be_adapter *adapter = netdev_priv(netdev);
u8 rsstable[RSS_INDIR_TABLE_LEN];
+ /* We require at least one supported parameter to be changed and no
+ * change in any of the unsupported parameters
+ */
+ if ((!indir && !hkey) || hfunc != ETH_RSS_HASH_NO_CHANGE)
+ return -EOPNOTSUPP;
+
if (indir) {
struct be_rx_obj *rxo;
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c b/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c
index 2d04464..352bd8c 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c
@@ -916,11 +916,15 @@ static u32 fm10k_get_rssrk_size(struct net_device *netdev)
return FM10K_RSSRK_SIZE * FM10K_RSSRK_ENTRIES_PER_REG;
}
-static int fm10k_get_rssh(struct net_device *netdev, u32 *indir, u8 *key)
+static int fm10k_get_rssh(struct net_device *netdev, u32 *indir, u8 *key,
+ u8 *hfunc)
{
struct fm10k_intfc *interface = netdev_priv(netdev);
int i, err;
+ if (!indir && !key)
+ return -EOPNOTSUPP;
+
err = fm10k_get_reta(netdev, indir);
if (err || !key)
return err;
@@ -932,12 +936,18 @@ static int fm10k_get_rssh(struct net_device *netdev, u32 *indir, u8 *key)
}
static int fm10k_set_rssh(struct net_device *netdev, const u32 *indir,
- const u8 *key)
+ const u8 *key, const u8 hfunc)
{
struct fm10k_intfc *interface = netdev_priv(netdev);
struct fm10k_hw *hw = &interface->hw;
int i, err;
+ /* We require at least one supported parameter to be changed and no
+ * change in any of the unsupported parameters
+ */
+ if ((!indir && !key) || hfunc != ETH_RSS_HASH_NO_CHANGE)
+ return -EOPNOTSUPP;
+
err = fm10k_set_reta(netdev, indir);
if (err || !key)
return err;
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c b/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c
index 876411c..9ee7847 100644
--- a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c
+++ b/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c
@@ -625,13 +625,17 @@ static u32 i40evf_get_rxfh_indir_size(struct net_device *netdev)
*
* Reads the indirection table directly from the hardware. Always returns 0.
**/
-static int i40evf_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key)
+static int i40evf_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
+ u8 *hfunc)
{
struct i40evf_adapter *adapter = netdev_priv(netdev);
struct i40e_hw *hw = &adapter->hw;
u32 hlut_val;
int i, j;
+ if (!indir)
+ return -EOPNOTSUPP;
+
for (i = 0, j = 0; i <= I40E_VFQF_HLUT_MAX_INDEX; i++) {
hlut_val = rd32(hw, I40E_VFQF_HLUT(i));
indir[j++] = hlut_val & 0xff;
@@ -652,13 +656,19 @@ static int i40evf_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key)
* returns 0 after programming the table.
**/
static int i40evf_set_rxfh(struct net_device *netdev, const u32 *indir,
- const u8 *key)
+ const u8 *key, const u8 hfunc)
{
struct i40evf_adapter *adapter = netdev_priv(netdev);
struct i40e_hw *hw = &adapter->hw;
u32 hlut_val;
int i, j;
+ /* We require at least one supported parameter to be changed and no
+ * change in any of the unsupported parameters
+ */
+ if (!indir || (key || hfunc != ETH_RSS_HASH_NO_CHANGE))
+ return -EOPNOTSUPP;
+
for (i = 0, j = 0; i <= I40E_VFQF_HLUT_MAX_INDEX; i++) {
hlut_val = indir[j++];
hlut_val |= indir[j++] << 8;
diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c
index 02cfd3b..6cce65a 100644
--- a/drivers/net/ethernet/intel/igb/igb_ethtool.c
+++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c
@@ -2842,11 +2842,15 @@ static u32 igb_get_rxfh_indir_size(struct net_device *netdev)
return IGB_RETA_SIZE;
}
-static int igb_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key)
+static int igb_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
+ u8 *hfunc)
{
struct igb_adapter *adapter = netdev_priv(netdev);
int i;
+ if (!indir)
+ return -EOPNOTSUPP;
+
for (i = 0; i < IGB_RETA_SIZE; i++)
indir[i] = adapter->rss_indir_tbl[i];
@@ -2889,13 +2893,19 @@ void igb_write_rss_indir_tbl(struct igb_adapter *adapter)
}
static int igb_set_rxfh(struct net_device *netdev, const u32 *indir,
- const u8 *key)
+ const u8 *key, const u8 hfunc)
{
struct igb_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
int i;
u32 num_queues;
+ /* We require at least one supported parameter to be changed and no
+ * change in any of the unsupported parameters
+ */
+ if (!indir || (key || hfunc != ETH_RSS_HASH_NO_CHANGE))
+ return -EOPNOTSUPP;
+
num_queues = adapter->rss_queues;
switch (hw->mac.type) {
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
index 710cf30..c50181a 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
@@ -978,7 +978,8 @@ static u32 mlx4_en_get_rxfh_key_size(struct net_device *netdev)
return MLX4_EN_RSS_KEY_SIZE;
}
-static int mlx4_en_get_rxfh(struct net_device *dev, u32 *ring_index, u8 *key)
+static int mlx4_en_get_rxfh(struct net_device *dev, u32 *ring_index, u8 *key,
+ u8 *hfunc)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
struct mlx4_en_rss_map *rss_map = &priv->rss_map;
@@ -986,6 +987,9 @@ static int mlx4_en_get_rxfh(struct net_device *dev, u32 *ring_index, u8 *key)
size_t n = priv->rx_ring_num;
int err = 0;
+ if (!ring_index)
+ return -EOPNOTSUPP;
+
rss_rings = priv->prof->rss_rings ?: priv->rx_ring_num;
rss_rings = 1 << ilog2(rss_rings);
@@ -999,7 +1003,7 @@ static int mlx4_en_get_rxfh(struct net_device *dev, u32 *ring_index, u8 *key)
}
static int mlx4_en_set_rxfh(struct net_device *dev, const u32 *ring_index,
- const u8 *key)
+ const u8 *key, const u8 hfunc)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
struct mlx4_en_dev *mdev = priv->mdev;
@@ -1008,6 +1012,12 @@ static int mlx4_en_set_rxfh(struct net_device *dev, const u32 *ring_index,
int i;
int rss_rings = 0;
+ /* We require at least one supported parameter to be changed and no
+ * change in any of the unsupported parameters
+ */
+ if (!ring_index || (key || hfunc != ETH_RSS_HASH_NO_CHANGE))
+ return -EOPNOTSUPP;
+
/* Calculate RSS table size and make sure flows are spread evenly
* between rings
*/
diff --git a/drivers/net/ethernet/sfc/ethtool.c b/drivers/net/ethernet/sfc/ethtool.c
index cad258a..f5f953c 100644
--- a/drivers/net/ethernet/sfc/ethtool.c
+++ b/drivers/net/ethernet/sfc/ethtool.c
@@ -1086,19 +1086,29 @@ static u32 efx_ethtool_get_rxfh_indir_size(struct net_device *net_dev)
0 : ARRAY_SIZE(efx->rx_indir_table));
}
-static int efx_ethtool_get_rxfh(struct net_device *net_dev, u32 *indir, u8 *key)
+static int efx_ethtool_get_rxfh(struct net_device *net_dev, u32 *indir, u8 *key,
+ u8 *hfunc)
{
struct efx_nic *efx = netdev_priv(net_dev);
+ if (!indir)
+ return -EOPNOTSUPP;
+
memcpy(indir, efx->rx_indir_table, sizeof(efx->rx_indir_table));
return 0;
}
-static int efx_ethtool_set_rxfh(struct net_device *net_dev,
- const u32 *indir, const u8 *key)
+static int efx_ethtool_set_rxfh(struct net_device *net_dev, const u32 *indir,
+ const u8 *key, const u8 hfunc)
{
struct efx_nic *efx = netdev_priv(net_dev);
+ /* We require at least one supported parameter to be changed and no
+ * change in any of the unsupported parameters
+ */
+ if (!indir || (key || hfunc != ETH_RSS_HASH_NO_CHANGE))
+ return -EOPNOTSUPP;
+
memcpy(efx->rx_indir_table, indir, sizeof(efx->rx_indir_table));
efx->type->rx_push_rss_config(efx);
return 0;
diff --git a/drivers/net/vmxnet3/vmxnet3_ethtool.c b/drivers/net/vmxnet3/vmxnet3_ethtool.c
index b725fd9..5a148cb 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethtool.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c
@@ -583,12 +583,14 @@ vmxnet3_get_rss_indir_size(struct net_device *netdev)
}
static int
-vmxnet3_get_rss(struct net_device *netdev, u32 *p, u8 *key)
+vmxnet3_get_rss(struct net_device *netdev, u32 *p, u8 *key, u8 *hfunc)
{
struct vmxnet3_adapter *adapter = netdev_priv(netdev);
struct UPT1_RSSConf *rssConf = adapter->rss_conf;
unsigned int n = rssConf->indTableSize;
+ if (!p)
+ return -EOPNOTSUPP;
while (n--)
p[n] = rssConf->indTable[n];
return 0;
@@ -596,13 +598,20 @@ vmxnet3_get_rss(struct net_device *netdev, u32 *p, u8 *key)
}
static int
-vmxnet3_set_rss(struct net_device *netdev, const u32 *p, const u8 *key)
+vmxnet3_set_rss(struct net_device *netdev, const u32 *p, const u8 *key,
+ const u8 hfunc)
{
unsigned int i;
unsigned long flags;
struct vmxnet3_adapter *adapter = netdev_priv(netdev);
struct UPT1_RSSConf *rssConf = adapter->rss_conf;
+ /* We require at least one supported parameter to be changed and no
+ * change in any of the unsupported parameters
+ */
+ if (!p || (key || hfunc != ETH_RSS_HASH_NO_CHANGE))
+ return -EOPNOTSUPP;
+
for (i = 0; i < rssConf->indTableSize; i++)
rssConf->indTable[i] = p[i];
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index c1a2d60..653dc9c 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -59,6 +59,26 @@ enum ethtool_phys_id_state {
ETHTOOL_ID_OFF
};
+enum {
+ ETH_RSS_HASH_TOP_BIT, /* Configurable RSS hash function - Toeplitz */
+ ETH_RSS_HASH_XOR_BIT, /* Configurable RSS hash function - Xor */
+
+ /*
+ * Add your fresh new hash function bits above and remember to update
+ * rss_hash_func_strings[] in ethtool.c
+ */
+ ETH_RSS_HASH_FUNCS_COUNT
+};
+
+#define __ETH_RSS_HASH_BIT(bit) ((u32)1 << (bit))
+#define __ETH_RSS_HASH(name) __ETH_RSS_HASH_BIT(ETH_RSS_HASH_##name##_BIT)
+
+#define ETH_RSS_HASH_TOP __ETH_RSS_HASH(TOP)
+#define ETH_RSS_HASH_XOR __ETH_RSS_HASH(XOR)
+
+#define ETH_RSS_HASH_UNKNOWN 0
+#define ETH_RSS_HASH_NO_CHANGE 0
+
struct net_device;
/* Some generic methods drivers may use in their ethtool_ops */
@@ -158,17 +178,14 @@ static inline u32 ethtool_rxfh_indir_default(u32 index, u32 n_rx_rings)
* Returns zero if not supported for this specific device.
* @get_rxfh_indir_size: Get the size of the RX flow hash indirection table.
* Returns zero if not supported for this specific device.
- * @get_rxfh: Get the contents of the RX flow hash indirection table and hash
- * key.
- * Will only be called if one or both of @get_rxfh_indir_size and
- * @get_rxfh_key_size are implemented and return non-zero.
- * Returns a negative error code or zero.
- * @set_rxfh: Set the contents of the RX flow hash indirection table and/or
- * hash key. In case only the indirection table or hash key is to be
- * changed, the other argument will be %NULL.
- * Will only be called if one or both of @get_rxfh_indir_size and
- * @get_rxfh_key_size are implemented and return non-zero.
+ * @get_rxfh: Get the contents of the RX flow hash indirection table, hash key
+ * and/or hash function.
* Returns a negative error code or zero.
+ * @set_rxfh: Set the contents of the RX flow hash indirection table, hash
+ * key, and/or hash function. Arguments which are set to %NULL or zero
+ * will remain unchanged.
+ * Returns a negative error code or zero. An error code must be returned
+ * if at least one unsupported change was requested.
* @get_channels: Get number of channels.
* @set_channels: Set number of channels. Returns a negative error code or
* zero.
@@ -241,9 +258,10 @@ struct ethtool_ops {
int (*reset)(struct net_device *, u32 *);
u32 (*get_rxfh_key_size)(struct net_device *);
u32 (*get_rxfh_indir_size)(struct net_device *);
- int (*get_rxfh)(struct net_device *, u32 *indir, u8 *key);
+ int (*get_rxfh)(struct net_device *, u32 *indir, u8 *key,
+ u8 *hfunc);
int (*set_rxfh)(struct net_device *, const u32 *indir,
- const u8 *key);
+ const u8 *key, const u8 hfunc);
void (*get_channels)(struct net_device *, struct ethtool_channels *);
int (*set_channels)(struct net_device *, struct ethtool_channels *);
int (*get_dump_flag)(struct net_device *, struct ethtool_dump *);
diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h
index eb2095b..5f66d9c 100644
--- a/include/uapi/linux/ethtool.h
+++ b/include/uapi/linux/ethtool.h
@@ -534,6 +534,7 @@ struct ethtool_pauseparam {
* @ETH_SS_NTUPLE_FILTERS: Previously used with %ETHTOOL_GRXNTUPLE;
* now deprecated
* @ETH_SS_FEATURES: Device feature names
+ * @ETH_SS_RSS_HASH_FUNCS: RSS hush function names
*/
enum ethtool_stringset {
ETH_SS_TEST = 0,
@@ -541,6 +542,7 @@ enum ethtool_stringset {
ETH_SS_PRIV_FLAGS,
ETH_SS_NTUPLE_FILTERS,
ETH_SS_FEATURES,
+ ETH_SS_RSS_HASH_FUNCS,
};
/**
@@ -884,6 +886,8 @@ struct ethtool_rxfh_indir {
* @key_size: On entry, the array size of the user buffer for the hash key,
* which may be zero. On return from %ETHTOOL_GRSSH, the size of the
* hardware hash key.
+ * @hfunc: Defines the current RSS hash function used by HW (or to be set to).
+ * Valid values are one of the %ETH_RSS_HASH_*.
* @rsvd: Reserved for future extensions.
* @rss_config: RX ring/queue index for each hash value i.e., indirection table
* of @indir_size __u32 elements, followed by hash key of @key_size
@@ -893,14 +897,16 @@ struct ethtool_rxfh_indir {
* size should be returned. For %ETHTOOL_SRSSH, an @indir_size of
* %ETH_RXFH_INDIR_NO_CHANGE means that indir table setting is not requested
* and a @indir_size of zero means the indir table should be reset to default
- * values.
+ * values. An hfunc of zero means that hash function setting is not requested.
*/
struct ethtool_rxfh {
__u32 cmd;
__u32 rss_context;
__u32 indir_size;
__u32 key_size;
- __u32 rsvd[2];
+ __u8 hfunc;
+ __u8 rsvd8[3];
+ __u32 rsvd32;
__u32 rss_config[0];
};
#define ETH_RXFH_INDIR_NO_CHANGE 0xffffffff
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 715f51f..550892c 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -100,6 +100,12 @@ static const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN]
[NETIF_F_BUSY_POLL_BIT] = "busy-poll",
};
+static const char
+rss_hash_func_strings[ETH_RSS_HASH_FUNCS_COUNT][ETH_GSTRING_LEN] = {
+ [ETH_RSS_HASH_TOP_BIT] = "toeplitz",
+ [ETH_RSS_HASH_XOR_BIT] = "xor",
+};
+
static int ethtool_get_features(struct net_device *dev, void __user *useraddr)
{
struct ethtool_gfeatures cmd = {
@@ -185,6 +191,9 @@ static int __ethtool_get_sset_count(struct net_device *dev, int sset)
if (sset == ETH_SS_FEATURES)
return ARRAY_SIZE(netdev_features_strings);
+ if (sset == ETH_SS_RSS_HASH_FUNCS)
+ return ARRAY_SIZE(rss_hash_func_strings);
+
if (ops->get_sset_count && ops->get_strings)
return ops->get_sset_count(dev, sset);
else
@@ -199,6 +208,9 @@ static void __ethtool_get_strings(struct net_device *dev,
if (stringset == ETH_SS_FEATURES)
memcpy(data, netdev_features_strings,
sizeof(netdev_features_strings));
+ else if (stringset == ETH_SS_RSS_HASH_FUNCS)
+ memcpy(data, rss_hash_func_strings,
+ sizeof(rss_hash_func_strings));
else
/* ops->get_strings is valid because checked earlier */
ops->get_strings(dev, stringset, data);
@@ -618,7 +630,7 @@ static noinline_for_stack int ethtool_get_rxfh_indir(struct net_device *dev,
if (!indir)
return -ENOMEM;
- ret = dev->ethtool_ops->get_rxfh(dev, indir, NULL);
+ ret = dev->ethtool_ops->get_rxfh(dev, indir, NULL, NULL);
if (ret)
goto out;
@@ -679,7 +691,7 @@ static noinline_for_stack int ethtool_set_rxfh_indir(struct net_device *dev,
goto out;
}
- ret = ops->set_rxfh(dev, indir, NULL);
+ ret = ops->set_rxfh(dev, indir, NULL, ETH_RSS_HASH_NO_CHANGE);
out:
kfree(indir);
@@ -697,12 +709,11 @@ static noinline_for_stack int ethtool_get_rxfh(struct net_device *dev,
u32 total_size;
u32 indir_bytes;
u32 *indir = NULL;
+ u8 dev_hfunc = 0;
u8 *hkey = NULL;
u8 *rss_config;
- if (!(dev->ethtool_ops->get_rxfh_indir_size ||
- dev->ethtool_ops->get_rxfh_key_size) ||
- !dev->ethtool_ops->get_rxfh)
+ if (!ops->get_rxfh)
return -EOPNOTSUPP;
if (ops->get_rxfh_indir_size)
@@ -710,16 +721,14 @@ static noinline_for_stack int ethtool_get_rxfh(struct net_device *dev,
if (ops->get_rxfh_key_size)
dev_key_size = ops->get_rxfh_key_size(dev);
- if ((dev_key_size + dev_indir_size) == 0)
- return -EOPNOTSUPP;
-
if (copy_from_user(&rxfh, useraddr, sizeof(rxfh)))
return -EFAULT;
user_indir_size = rxfh.indir_size;
user_key_size = rxfh.key_size;
/* Check that reserved fields are 0 for now */
- if (rxfh.rss_context || rxfh.rsvd[0] || rxfh.rsvd[1])
+ if (rxfh.rss_context || rxfh.rsvd8[0] || rxfh.rsvd8[1] ||
+ rxfh.rsvd8[2] || rxfh.rsvd32)
return -EINVAL;
rxfh.indir_size = dev_indir_size;
@@ -727,13 +736,6 @@ static noinline_for_stack int ethtool_get_rxfh(struct net_device *dev,
if (copy_to_user(useraddr, &rxfh, sizeof(rxfh)))
return -EFAULT;
- /* If the user buffer size is 0, this is just a query for the
- * device table size and key size. Otherwise, if the User size is
- * not equal to device table size or key size it's an error.
- */
- if (!user_indir_size && !user_key_size)
- return 0;
-
if ((user_indir_size && (user_indir_size != dev_indir_size)) ||
(user_key_size && (user_key_size != dev_key_size)))
return -EINVAL;
@@ -750,14 +752,19 @@ static noinline_for_stack int ethtool_get_rxfh(struct net_device *dev,
if (user_key_size)
hkey = rss_config + indir_bytes;
- ret = dev->ethtool_ops->get_rxfh(dev, indir, hkey);
- if (!ret) {
- if (copy_to_user(useraddr +
- offsetof(struct ethtool_rxfh, rss_config[0]),
- rss_config, total_size))
- ret = -EFAULT;
- }
+ ret = dev->ethtool_ops->get_rxfh(dev, indir, hkey, &dev_hfunc);
+ if (ret)
+ goto out;
+ if (copy_to_user(useraddr + offsetof(struct ethtool_rxfh, hfunc),
+ &dev_hfunc, sizeof(rxfh.hfunc))) {
+ ret = -EFAULT;
+ } else if (copy_to_user(useraddr +
+ offsetof(struct ethtool_rxfh, rss_config[0]),
+ rss_config, total_size)) {
+ ret = -EFAULT;
+ }
+out:
kfree(rss_config);
return ret;
@@ -776,33 +783,31 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
u8 *rss_config;
u32 rss_cfg_offset = offsetof(struct ethtool_rxfh, rss_config[0]);
- if (!(ops->get_rxfh_indir_size || ops->get_rxfh_key_size) ||
- !ops->get_rxnfc || !ops->set_rxfh)
+ if (!ops->get_rxnfc || !ops->set_rxfh)
return -EOPNOTSUPP;
if (ops->get_rxfh_indir_size)
dev_indir_size = ops->get_rxfh_indir_size(dev);
if (ops->get_rxfh_key_size)
dev_key_size = dev->ethtool_ops->get_rxfh_key_size(dev);
- if ((dev_key_size + dev_indir_size) == 0)
- return -EOPNOTSUPP;
if (copy_from_user(&rxfh, useraddr, sizeof(rxfh)))
return -EFAULT;
/* Check that reserved fields are 0 for now */
- if (rxfh.rss_context || rxfh.rsvd[0] || rxfh.rsvd[1])
+ if (rxfh.rss_context || rxfh.rsvd8[0] || rxfh.rsvd8[1] ||
+ rxfh.rsvd8[2] || rxfh.rsvd32)
return -EINVAL;
- /* If either indir or hash key is valid, proceed further.
- * It is not valid to request that both be unchanged.
+ /* If either indir, hash key or function is valid, proceed further.
+ * Must request at least one change: indir size, hash key or function.
*/
if ((rxfh.indir_size &&
rxfh.indir_size != ETH_RXFH_INDIR_NO_CHANGE &&
rxfh.indir_size != dev_indir_size) ||
(rxfh.key_size && (rxfh.key_size != dev_key_size)) ||
(rxfh.indir_size == ETH_RXFH_INDIR_NO_CHANGE &&
- rxfh.key_size == 0))
+ rxfh.key_size == 0 && rxfh.hfunc == ETH_RSS_HASH_NO_CHANGE))
return -EINVAL;
if (rxfh.indir_size != ETH_RXFH_INDIR_NO_CHANGE)
@@ -845,7 +850,7 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
}
}
- ret = ops->set_rxfh(dev, indir, hkey);
+ ret = ops->set_rxfh(dev, indir, hkey, rxfh.hfunc);
out:
kfree(rss_config);
--
1.8.3.4
^ permalink raw reply related
* Re: [PATCH net-next V1 0/2] ethtool, net/mlx4_en: RSS hash function selection
From: Amir Vadai @ 2014-11-20 14:34 UTC (permalink / raw)
To: Amir Vadai
Cc: David S. Miller, netdev, Ben Hutchings, Or Gerlitz,
Yevgeny Petrilin
In-Reply-To: <1416493610-8966-1-git-send-email-amirv@mellanox.com>
On Thu, Nov 20, 2014 at 4:26 PM, Amir Vadai <amirv@mellanox.com> wrote:
> Hi,
>
> This patchset by Eyal adds support in set/get of RSS hash function. Current
> supported functions are Toeplitz and XOR. The API is design to enable adding
> new hash functions without breaking backward compatibility.
> Userspace patch will be sent after API is available in kernel.
>
> The patchset was applied and tested over commit 7b909bb ("Merge branches
> 'core', 'cxgb4', 'iser', 'mlx5' and 'ocrdma' into for-next")
Should be commit daaf427 ("bpf: fix arraymap NULL deref and missing
overflow and zero size checks")
>
> Amir
>
[...]
^ permalink raw reply
* [PATCH 1/2] net/am2150: fix nmclan_cs.c shared interrupt handling
From: Arnd Bergmann @ 2014-11-20 15:11 UTC (permalink / raw)
To: netdev; +Cc: Jeff Kirsher, Roger Pao, linux-kernel, linux-pcmcia
A recent patch tried to work around a valid warning for the use of a
deprecated interface by blindly changing from the old
pcmcia_request_exclusive_irq() interface to pcmcia_request_irq().
This driver has an interrupt handler that is not currently aware
of shared interrupts, but can be easily converted to be.
At the moment, the driver reads the interrupt status register
repeatedly until it contains only zeroes in the interesting bits,
and handles each bit individually.
This patch adds the missing part of returning IRQ_NONE in case none
of the bits are set to start with, so we can move on to the next
interrupt source.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Fixes: 5f5316fcd08ef7 ("am2150: Update nmclan_cs.c to use update PCMCIA API")
---
I had this patch in my queue of things to submit and noticed that
the warning had gone away upstream but my patch was still there.
For all I can tell, the driver is broken without this, although it
would rarely be a problem.
diff --git a/drivers/net/ethernet/amd/nmclan_cs.c b/drivers/net/ethernet/amd/nmclan_cs.c
index 5b22764ba88d..27245efe9f50 100644
--- a/drivers/net/ethernet/amd/nmclan_cs.c
+++ b/drivers/net/ethernet/amd/nmclan_cs.c
@@ -952,6 +952,8 @@ static irqreturn_t mace_interrupt(int irq, void *dev_id)
do {
/* WARNING: MACE_IR is a READ/CLEAR port! */
status = inb(ioaddr + AM2150_MACE_BASE + MACE_IR);
+ if (!(status & ~MACE_IMR_DEFAULT) && IntrCnt == MACE_MAX_IR_ITERATIONS)
+ return IRQ_NONE;
pr_debug("mace_interrupt: irq 0x%X status 0x%X.\n", irq, status);
^ permalink raw reply related
* [PATCH 1/1] net: USB: Deletion of unnecessary checks before the function call "kfree"
From: SF Markus Elfring @ 2014-11-20 15:16 UTC (permalink / raw)
To: Jan Dumon, linux-usb, netdev; +Cc: LKML, kernel-janitors, Julia Lawall
In-Reply-To: <5317A59D.4@users.sourceforge.net>
From: Markus Elfring <elfring@users.sourceforge.net>
Date: Thu, 20 Nov 2014 16:11:56 +0100
The kfree() function tests whether its argument is NULL and then
returns immediately. Thus the test around the call is not needed.
This issue was detected by using the Coccinelle software.
Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---
drivers/net/usb/asix_devices.c | 3 +--
drivers/net/usb/hso.c | 3 +--
2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c
index 5d19409..8a7582b 100644
--- a/drivers/net/usb/asix_devices.c
+++ b/drivers/net/usb/asix_devices.c
@@ -499,8 +499,7 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
static void ax88772_unbind(struct usbnet *dev, struct usb_interface *intf)
{
- if (dev->driver_priv)
- kfree(dev->driver_priv);
+ kfree(dev->driver_priv);
}
static const struct ethtool_ops ax88178_ethtool_ops = {
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c
index babda7d..9c5aa92 100644
--- a/drivers/net/usb/hso.c
+++ b/drivers/net/usb/hso.c
@@ -2746,8 +2746,7 @@ exit:
tty_unregister_device(tty_drv, serial->minor);
kfree(serial);
}
- if (hso_dev)
- kfree(hso_dev);
+ kfree(hso_dev);
return NULL;
}
--
2.1.3
^ permalink raw reply related
* [PATCH 2/2] pcmcia: remove pcmcia_request_exclusive_irq
From: Arnd Bergmann @ 2014-11-20 15:21 UTC (permalink / raw)
To: netdev; +Cc: Jeff Kirsher, Roger Pao, linux-kernel, linux-pcmcia
In-Reply-To: <4353896.15JnC91eLO@wuerfel>
The last user of the deprecated pcmcia_request_exclusive_irq function,
was removed in 5f5316fcd08e ("am2150: Update nmclan_cs.c to use update
PCMCIA API"), so we can clean up the core code and remove the interface
and its documentation.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
Documentation/pcmcia/driver-changes.txt | 3 ---
drivers/pcmcia/pcmcia_resource.c | 39 ---------------------------------------
include/pcmcia/ds.h | 10 ----------
3 files changed, 0 insertions(+), 52 deletions(-)
---
The patch that removed the last user was merged in 3.18-rc1, so this
should be safe to apply independently now.
diff --git a/Documentation/pcmcia/driver-changes.txt b/Documentation/pcmcia/driver-changes.txt
index dd04361dd361..78355c4c268a 100644
--- a/Documentation/pcmcia/driver-changes.txt
+++ b/Documentation/pcmcia/driver-changes.txt
@@ -46,9 +46,6 @@ This file details changes in 2.6 which affect PCMCIA card driver authors:
- use pcmcia_request_irq(p_dev, handler_t); the PCMCIA core will
clean up automatically on calls to pcmcia_disable_device() or
device ejection.
- - drivers still not capable of IRQF_SHARED (or not telling us so) may
- use the deprecated pcmcia_request_exclusive_irq() for the time
- being; they might receive a shared IRQ nonetheless.
* no cs_error / CS_CHECK / CONFIG_PCMCIA_DEBUG (as of 2.6.33)
Instead of the cs_error() callback or the CS_CHECK() macro, please use
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c
index e8c19def1b0f..23a123da3dd7 100644
--- a/drivers/pcmcia/pcmcia_resource.c
+++ b/drivers/pcmcia/pcmcia_resource.c
@@ -712,45 +712,6 @@ int __must_check pcmcia_request_irq(struct pcmcia_device *p_dev,
}
EXPORT_SYMBOL(pcmcia_request_irq);
-
-/**
- * pcmcia_request_exclusive_irq() - attempt to request an exclusive IRQ first
- * @p_dev: the associated PCMCIA device
- * @handler: IRQ handler to register
- *
- * pcmcia_request_exclusive_irq() is a wrapper around request_irq() which
- * attempts first to request an exclusive IRQ. If it fails, it also accepts
- * a shared IRQ, but prints out a warning. PCMCIA drivers should allow for
- * IRQ sharing and either use request_irq directly (then they need to call
- * free_irq() themselves, too), or the pcmcia_request_irq() function.
- */
-int __must_check
-__pcmcia_request_exclusive_irq(struct pcmcia_device *p_dev,
- irq_handler_t handler)
-{
- int ret;
-
- if (!p_dev->irq)
- return -EINVAL;
-
- ret = request_irq(p_dev->irq, handler, 0, p_dev->devname, p_dev->priv);
- if (ret) {
- ret = pcmcia_request_irq(p_dev, handler);
- dev_printk(KERN_WARNING, &p_dev->dev, "pcmcia: "
- "request for exclusive IRQ could not be fulfilled.\n");
- dev_printk(KERN_WARNING, &p_dev->dev, "pcmcia: the driver "
- "needs updating to supported shared IRQ lines.\n");
- }
- if (ret)
- dev_printk(KERN_INFO, &p_dev->dev, "request_irq() failed\n");
- else
- p_dev->_irq = 1;
-
- return ret;
-} /* pcmcia_request_exclusive_irq */
-EXPORT_SYMBOL(__pcmcia_request_exclusive_irq);
-
-
#ifdef CONFIG_PCMCIA_PROBE
/* mask of IRQs already reserved by other cards, we should avoid using them */
diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h
index 2d56e428506c..3037157855f0 100644
--- a/include/pcmcia/ds.h
+++ b/include/pcmcia/ds.h
@@ -206,16 +206,6 @@ int pcmcia_write_config_byte(struct pcmcia_device *p_dev, off_t where, u8 val);
/* device configuration */
int pcmcia_request_io(struct pcmcia_device *p_dev);
-int __must_check
-__pcmcia_request_exclusive_irq(struct pcmcia_device *p_dev,
- irq_handler_t handler);
-static inline __must_check __deprecated int
-pcmcia_request_exclusive_irq(struct pcmcia_device *p_dev,
- irq_handler_t handler)
-{
- return __pcmcia_request_exclusive_irq(p_dev, handler);
-}
-
int __must_check pcmcia_request_irq(struct pcmcia_device *p_dev,
irq_handler_t handler);
^ permalink raw reply related
* Re: Question on bulk dequeue support in virtual drivers
From: Eric Dumazet @ 2014-11-20 15:26 UTC (permalink / raw)
To: James Yonan; +Cc: Linux Netdev List
In-Reply-To: <546DE110.8060607@openvpn.net>
On Thu, 2014-11-20 at 05:39 -0700, James Yonan wrote:
> Consider a tunneling driver that receives packets in ndo_start_xmit,
> encapsulates them in UDP, and forwards via ip_local_out. The
> ndo_start_xmit implementation can implement bulking by looking at
> skb->xmit_more. But then how to efficiently transmit the resulting
> bulked list of encapsulated packets via UDP, so that the packets both
> enter and leave the driver in bulked form? Is there an ip_local_out
> alternative for bulked skb lists?
There is no such thing. Quite frankly it wont happen. Consider IP stacks
and netfilter, there is no provision for batches (other than GSO/TSO)
xmit_more addresses a specific hardware problem, it is not an
alternative for batches.
xmit_more will happen in your case in the last step, from qdisc to
ethernet device.
^ permalink raw reply
* Re: [PATCH v2 net-next] tcp: make connect() mem charging friendly
From: Eric Dumazet @ 2014-11-20 15:33 UTC (permalink / raw)
To: David Miller; +Cc: ycheng, nuclearcat, netdev, ncardwell
In-Reply-To: <20141119.145741.1905980604994551607.davem@davemloft.net>
On Wed, 2014-11-19 at 14:57 -0500, David Miller wrote:
> From: Yuchung Cheng <ycheng@google.com>
> >
> > Thanks! this simplifies the code a lot.
>
> Agreed, applied, thanks everyone!
BTW, unless I am mistaken, it seems we can probably replace
memcpy_fromiovecend() by memcpy_fromiovec() and delete from
tcp_sendmsg() the annoying code skipping over the already consumed
bytes.
Something like this untested patch :
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index c239f4740d10b10b67ef4fa44c831851fb9e1dcf..227540eef9d0870721258f9ddbace27b417c619e 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -1089,20 +1089,19 @@ int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
struct tcp_sock *tp = tcp_sk(sk);
struct sk_buff *skb;
int iovlen, flags, err, copied = 0;
- int mss_now = 0, size_goal, copied_syn = 0, offset = 0;
+ int mss_now = 0, size_goal, copied_syn = 0;
bool sg;
long timeo;
lock_sock(sk);
flags = msg->msg_flags;
- if (flags & MSG_FASTOPEN) {
+ if (unlikely(flags & MSG_FASTOPEN)) {
err = tcp_sendmsg_fastopen(sk, msg, &copied_syn, size);
if (err == -EINPROGRESS && copied_syn > 0)
goto out;
else if (err)
goto out_err;
- offset = copied_syn;
}
timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT);
@@ -1151,15 +1150,6 @@ int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
unsigned char __user *from = iov->iov_base;
iov++;
- if (unlikely(offset > 0)) { /* Skip bytes copied in SYN */
- if (offset >= seglen) {
- offset -= seglen;
- continue;
- }
- seglen -= offset;
- from += offset;
- offset = 0;
- }
while (seglen > 0) {
int copy = 0;
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index f5bd4bd3f7e669b3fd48a843d55e7313a30a3409..524e5b657e881a348f11def3f48f29a76f54fbab 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -3049,8 +3049,8 @@ static int tcp_send_syn_data(struct sock *sk, struct sk_buff *syn)
goto fallback;
syn_data->ip_summed = CHECKSUM_PARTIAL;
memcpy(syn_data->cb, syn->cb, sizeof(syn->cb));
- if (unlikely(memcpy_fromiovecend(skb_put(syn_data, space),
- fo->data->msg_iov, 0, space))) {
+ if (unlikely(memcpy_fromiovec(skb_put(syn_data, space),
+ fo->data->msg_iov, space))) {
kfree_skb(syn_data);
goto fallback;
}
^ permalink raw reply related
* [PATCH 1/1] net: brcm80211: Deletion of unnecessary checks before two function calls
From: SF Markus Elfring @ 2014-11-20 15:50 UTC (permalink / raw)
To: Arend van Spriel, Brett Rudley, Franky (Zhenhui) Lin,
Hante Meuleman, John W. Linville, linux-wireless,
brcm80211-dev-list, netdev
Cc: LKML, kernel-janitors, Julia Lawall
In-Reply-To: <5317A59D.4@users.sourceforge.net>
From: Markus Elfring <elfring@users.sourceforge.net>
Date: Thu, 20 Nov 2014 16:42:51 +0100
The functions brcmu_pkt_buf_free_skb() and release_firmware() test whether
their argument is NULL and then return immediately. Thus the test around
the call is not needed.
This issue was detected by using the Coccinelle software.
Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---
drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | 3 +--
drivers/net/wireless/brcm80211/brcmfmac/firmware.c | 3 +--
drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c | 3 +--
drivers/net/wireless/brcm80211/brcmsmac/main.c | 3 +--
4 files changed, 4 insertions(+), 8 deletions(-)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index f55f625..8ff7037 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -2539,8 +2539,7 @@ static void brcmf_sdio_bus_stop(struct device *dev)
brcmu_pktq_flush(&bus->txq, true, NULL, NULL);
/* Clear any held glomming stuff */
- if (bus->glomd)
- brcmu_pkt_buf_free_skb(bus->glomd);
+ brcmu_pkt_buf_free_skb(bus->glomd);
brcmf_sdio_free_glom(bus);
/* Clear rx control and wake any waiters */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
index 8ea9f28..3a2d014 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
@@ -262,8 +262,7 @@ static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx)
fail:
brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev));
- if (fwctx->code)
- release_firmware(fwctx->code);
+ release_firmware(fwctx->code);
device_release_driver(fwctx->dev);
kfree(fwctx);
}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
index 8f8b937..0cb00dc 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
@@ -506,8 +506,7 @@ static int brcmf_msgbuf_query_dcmd(struct brcmf_pub *drvr, int ifidx,
memcpy(buf, skb->data, (len < msgbuf->ioctl_resp_ret_len) ?
len : msgbuf->ioctl_resp_ret_len);
}
- if (skb)
- brcmu_pkt_buf_free_skb(skb);
+ brcmu_pkt_buf_free_skb(skb);
return msgbuf->ioctl_resp_status;
}
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index 1b47482..ce538a1 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
@@ -1009,8 +1009,7 @@ brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs)
if (txh)
trace_brcms_txdesc(&wlc->hw->d11core->dev, txh,
sizeof(*txh));
- if (p)
- brcmu_pkt_buf_free_skb(p);
+ brcmu_pkt_buf_free_skb(p);
}
if (dma && queue < NFIFO) {
--
2.1.3
^ permalink raw reply related
* Re: [patch net-next v2 02/10] net: introduce generic switch devices support
From: Andy Gospodarek @ 2014-11-20 15:55 UTC (permalink / raw)
To: Roopa Prabhu
Cc: Jiri Pirko, netdev, davem, nhorman, andy, tgraf, dborkman,
ogerlitz, jesse, pshelar, azhou, ben, stephen, jeffrey.t.kirsher,
vyasevic, xiyou.wangcong, john.r.fastabend, edumazet, jhs,
sfeldma, f.fainelli, linville, jasowang, ebiederm,
nicolas.dichtel, ryazanov.s.a, buytenh, aviadr, nbd,
alexei.starovoitov, Neil.Jerram, ronye, simon.horman,
alexander.h.duyck, john.ronciak, mleitner, shrijeet, bcrl
In-Reply-To: <546CA237.3010600@cumulusnetworks.com>
On Wed, Nov 19, 2014 at 05:59:19AM -0800, Roopa Prabhu wrote:
> On 11/19/14, 5:46 AM, Jiri Pirko wrote:
> >Wed, Nov 19, 2014 at 02:28:10PM CET, roopa@cumulusnetworks.com wrote:
> >>On 11/9/14, 2:51 AM, Jiri Pirko wrote:
> >>>The goal of this is to provide a possibility to support various switch
> >>>chips. Drivers should implement relevant ndos to do so. Now there is
> >>>only one ndo defined:
> >>>- for getting physical switch id is in place.
> >>>
> >>>Note that user can use random port netdevice to access the switch.
> >>>
> >>>Signed-off-by: Jiri Pirko <jiri@resnulli.us>
> >>>---
> >>> Documentation/networking/switchdev.txt | 59 ++++++++++++++++++++++++++++++++++
> >>> MAINTAINERS | 7 ++++
> >>> include/linux/netdevice.h | 10 ++++++
> >>> include/net/switchdev.h | 30 +++++++++++++++++
> >>> net/Kconfig | 1 +
> >>> net/Makefile | 3 ++
> >>> net/switchdev/Kconfig | 13 ++++++++
> >>> net/switchdev/Makefile | 5 +++
> >>> net/switchdev/switchdev.c | 33 +++++++++++++++++++
> >>> 9 files changed, 161 insertions(+)
> >>> create mode 100644 Documentation/networking/switchdev.txt
> >>> create mode 100644 include/net/switchdev.h
> >>> create mode 100644 net/switchdev/Kconfig
> >>> create mode 100644 net/switchdev/Makefile
> >>> create mode 100644 net/switchdev/switchdev.c
> >>>
> >>>diff --git a/Documentation/networking/switchdev.txt b/Documentation/networking/switchdev.txt
> >>>new file mode 100644
> >>>index 0000000..98be76c
> >>>--- /dev/null
> >>>+++ b/Documentation/networking/switchdev.txt
> >>>@@ -0,0 +1,59 @@
> >>>+Switch (and switch-ish) device drivers HOWTO
> >>>+===========================
> >>>+
> >>>+Please note that the word "switch" is here used in very generic meaning.
> >>>+This include devices supporting L2/L3 but also various flow offloading chips,
> >>>+including switches embedded into SR-IOV NICs.
> >>>+
> >>>+Lets describe a topology a bit. Imagine the following example:
> >>>+
> >>>+ +----------------------------+ +---------------+
> >>>+ | SOME switch chip | | CPU |
> >>>+ +----------------------------+ +---------------+
> >>>+ port1 port2 port3 port4 MNGMNT | PCI-E |
> >>>+ | | | | | +---------------+
> >>>+ PHY PHY | | | | NIC0 NIC1
> >>>+ | | | | | |
> >>>+ | | +- PCI-E -+ | |
> >>>+ | +------- MII -------+ |
> >>>+ +------------- MII ------------+
> >>>+
> >>>+In this example, there are two independent lines between the switch silicon
> >>>+and CPU. NIC0 and NIC1 drivers are not aware of a switch presence. They are
> >>>+separate from the switch driver. SOME switch chip is by managed by a driver
> >>>+via PCI-E device MNGMNT. Note that MNGMNT device, NIC0 and NIC1 may be
> >>>+connected to some other type of bus.
> >>>+
> >>>+Now, for the previous example show the representation in kernel:
> >>>+
> >>>+ +----------------------------+ +---------------+
> >>>+ | SOME switch chip | | CPU |
> >>>+ +----------------------------+ +---------------+
> >>>+ sw0p0 sw0p1 sw0p2 sw0p3 MNGMNT | PCI-E |
> >>>+ | | | | | +---------------+
> >>>+ PHY PHY | | | | eth0 eth1
> >>>+ | | | | | |
> >>>+ | | +- PCI-E -+ | |
> >>>+ | +------- MII -------+ |
> >>>+ +------------- MII ------------+
> >>>+
> >>>+Lets call the example switch driver for SOME switch chip "SOMEswitch". This
> >>>+driver takes care of PCI-E device MNGMNT. There is a netdevice instance sw0pX
> >>>+created for each port of a switch. These netdevices are instances
> >>>+of "SOMEswitch" driver. sw0pX netdevices serve as a "representation"
> >>>+of the switch chip. eth0 and eth1 are instances of some other existing driver.
> >>>+
> >>>+The only difference of the switch-port netdevice from the ordinary netdevice
> >>>+is that is implements couple more NDOs:
> >>>+
> >>>+ ndo_sw_parent_get_id - This returns the same ID for two port netdevices
> >>>+ of the same physical switch chip. This is
> >>>+ mandatory to be implemented by all switch drivers
> >>>+ and serves the caller for recognition of a port
> >>>+ netdevice.
> >>>+ ndo_sw_parent_* - Functions that serve for a manipulation of the switch
> >>>+ chip itself (it can be though of as a "parent" of the
> >>>+ port, therefore the name). They are not port-specific.
> >>>+ Caller might use arbitrary port netdevice of the same
> >>>+ switch and it will make no difference.
> >>>+ ndo_sw_port_* - Functions that serve for a port-specific manipulation.
> >>>diff --git a/MAINTAINERS b/MAINTAINERS
> >>>index 3a41fb0..776e078 100644
> >>>--- a/MAINTAINERS
> >>>+++ b/MAINTAINERS
> >>>@@ -9003,6 +9003,13 @@ F: lib/swiotlb.c
> >>> F: arch/*/kernel/pci-swiotlb.c
> >>> F: include/linux/swiotlb.h
> >>>+SWITCHDEV
> >>>+M: Jiri Pirko <jiri@resnulli.us>
> >>>+L: netdev@vger.kernel.org
> >>>+S: Supported
> >>>+F: net/switchdev/
> >>>+F: include/net/switchdev.h
> >>>+
> >>> SYNOPSYS ARC ARCHITECTURE
> >>> M: Vineet Gupta <vgupta@synopsys.com>
> >>> S: Supported
> >>>diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
> >>>index 71922e0..97eade9 100644
> >>>--- a/include/linux/netdevice.h
> >>>+++ b/include/linux/netdevice.h
> >>>@@ -1017,6 +1017,12 @@ typedef u16 (*select_queue_fallback_t)(struct net_device *dev,
> >>> * performing GSO on a packet. The device returns true if it is
> >>> * able to GSO the packet, false otherwise. If the return value is
> >>> * false the stack will do software GSO.
> >>>+ *
> >>>+ * int (*ndo_sw_parent_id_get)(struct net_device *dev,
> >>>+ * struct netdev_phys_item_id *psid);
> >>>+ * Called to get an ID of the switch chip this port is part of.
> >>>+ * If driver implements this, it indicates that it represents a port
> >>>+ * of a switch chip.
> >>> */
> >>> struct net_device_ops {
> >>> int (*ndo_init)(struct net_device *dev);
> >>>@@ -1168,6 +1174,10 @@ struct net_device_ops {
> >>> int (*ndo_get_lock_subclass)(struct net_device *dev);
> >>> bool (*ndo_gso_check) (struct sk_buff *skb,
> >>> struct net_device *dev);
> >>>+#ifdef CONFIG_NET_SWITCHDEV
> >>>+ int (*ndo_sw_parent_id_get)(struct net_device *dev,
> >>>+ struct netdev_phys_item_id *psid);
> >>Can we keep the name generic and not include "sw" which implies switch here
> >>?.
> >>I understand that it is under CONFIG_NET_SWITCHDEV but we might find use for
> >>them in other offload scenarios in the future.
> >>This particular ndo can be just ndo_parent_id_get().
> >>And the others that do specific offloads can have "offload" in them if
> >>required..?.
> >
> >But this is for getting parent switch id, sw should be there.
>
> Since we have not figured out the details or namespace for switchd ids yet,
> its still some parent id to me.
>
> >If comes a
> >time when this might be reused to something else, we change it then.
> >This is internal api, easily changeable.
> also, "sw" seems more "software" than "switch".
I had voiced this same concern when we met and discussed this in
Dusseldorf. Let's move to another name such as 'hw' (since we really
are talking about hardware abstraction) or 'offload.' Just using 'sw'
is confusing as many will not read it as switch.
I'll be happy to post a fix based on your devel patches.
>
> >
> >>
> >>
> >>>+#endif
> >>> };
> >>> /**
> >>>diff --git a/include/net/switchdev.h b/include/net/switchdev.h
> >>>new file mode 100644
> >>>index 0000000..79bf9bd
> >>>--- /dev/null
> >>>+++ b/include/net/switchdev.h
> >>>@@ -0,0 +1,30 @@
> >>>+/*
> >>>+ * include/net/switchdev.h - Switch device API
> >>>+ * Copyright (c) 2014 Jiri Pirko <jiri@resnulli.us>
> >>>+ *
> >>>+ * This program is free software; you can redistribute it and/or modify
> >>>+ * it under the terms of the GNU General Public License as published by
> >>>+ * the Free Software Foundation; either version 2 of the License, or
> >>>+ * (at your option) any later version.
> >>>+ */
> >>>+#ifndef _LINUX_SWITCHDEV_H_
> >>>+#define _LINUX_SWITCHDEV_H_
> >>>+
> >>>+#include <linux/netdevice.h>
> >>>+
> >>>+#ifdef CONFIG_NET_SWITCHDEV
> >>>+
> >>>+int netdev_sw_parent_id_get(struct net_device *dev,
> >>>+ struct netdev_phys_item_id *psid);
> >>>+
> >>>+#else
> >>>+
> >>>+static inline int netdev_sw_parent_id_get(struct net_device *dev,
> >>>+ struct netdev_phys_item_id *psid)
> >>>+{
> >>>+ return -EOPNOTSUPP;
> >>>+}
> >>>+
> >>>+#endif
> >>>+
> >>>+#endif /* _LINUX_SWITCHDEV_H_ */
> >>>diff --git a/net/Kconfig b/net/Kconfig
> >>>index 99815b5..ff9ffc1 100644
> >>>--- a/net/Kconfig
> >>>+++ b/net/Kconfig
> >>>@@ -228,6 +228,7 @@ source "net/vmw_vsock/Kconfig"
> >>> source "net/netlink/Kconfig"
> >>> source "net/mpls/Kconfig"
> >>> source "net/hsr/Kconfig"
> >>>+source "net/switchdev/Kconfig"
> >>> config RPS
> >>> boolean
> >>>diff --git a/net/Makefile b/net/Makefile
> >>>index 7ed1970..95fc694 100644
> >>>--- a/net/Makefile
> >>>+++ b/net/Makefile
> >>>@@ -73,3 +73,6 @@ obj-$(CONFIG_OPENVSWITCH) += openvswitch/
> >>> obj-$(CONFIG_VSOCKETS) += vmw_vsock/
> >>> obj-$(CONFIG_NET_MPLS_GSO) += mpls/
> >>> obj-$(CONFIG_HSR) += hsr/
> >>>+ifneq ($(CONFIG_NET_SWITCHDEV),)
> >>>+obj-y += switchdev/
> >>>+endif
> >>>diff --git a/net/switchdev/Kconfig b/net/switchdev/Kconfig
> >>>new file mode 100644
> >>>index 0000000..1557545
> >>>--- /dev/null
> >>>+++ b/net/switchdev/Kconfig
> >>>@@ -0,0 +1,13 @@
> >>>+#
> >>>+# Configuration for Switch device support
> >>>+#
> >>>+
> >>>+config NET_SWITCHDEV
> >>>+ boolean "Switch (and switch-ish) device support (EXPERIMENTAL)"
> >>>+ depends on INET
> >>>+ ---help---
> >>>+ This module provides glue between core networking code and device
> >>>+ drivers in order to support hardware switch chips in very generic
> >>>+ meaning of the word "switch". This include devices supporting L2/L3 but
> >>>+ also various flow offloading chips, including switches embedded into
> >>>+ SR-IOV NICs.
> >>>diff --git a/net/switchdev/Makefile b/net/switchdev/Makefile
> >>>new file mode 100644
> >>>index 0000000..5ed63ed
> >>>--- /dev/null
> >>>+++ b/net/switchdev/Makefile
> >>>@@ -0,0 +1,5 @@
> >>>+#
> >>>+# Makefile for the Switch device API
> >>>+#
> >>>+
> >>>+obj-$(CONFIG_NET_SWITCHDEV) += switchdev.o
> >>>diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c
> >>>new file mode 100644
> >>>index 0000000..5010f646
> >>>--- /dev/null
> >>>+++ b/net/switchdev/switchdev.c
> >>>@@ -0,0 +1,33 @@
> >>>+/*
> >>>+ * net/switchdev/switchdev.c - Switch device API
> >>>+ * Copyright (c) 2014 Jiri Pirko <jiri@resnulli.us>
> >>>+ *
> >>>+ * This program is free software; you can redistribute it and/or modify
> >>>+ * it under the terms of the GNU General Public License as published by
> >>>+ * the Free Software Foundation; either version 2 of the License, or
> >>>+ * (at your option) any later version.
> >>>+ */
> >>>+
> >>>+#include <linux/kernel.h>
> >>>+#include <linux/types.h>
> >>>+#include <linux/init.h>
> >>>+#include <linux/netdevice.h>
> >>>+#include <net/switchdev.h>
> >>>+
> >>>+/**
> >>>+ * netdev_sw_parent_id_get - Get ID of a switch
> >>>+ * @dev: port device
> >>>+ * @psid: switch ID
> >>>+ *
> >>>+ * Get ID of a switch this port is part of.
> >>>+ */
> >>>+int netdev_sw_parent_id_get(struct net_device *dev,
> >>>+ struct netdev_phys_item_id *psid)
> >>>+{
> >>>+ const struct net_device_ops *ops = dev->netdev_ops;
> >>>+
> >>>+ if (!ops->ndo_sw_parent_id_get)
> >>>+ return -EOPNOTSUPP;
> >>>+ return ops->ndo_sw_parent_id_get(dev, psid);
> >>>+}
> >>>+EXPORT_SYMBOL(netdev_sw_parent_id_get);
> >--
> >To unsubscribe from this list: send the line "unsubscribe netdev" in
> >the body of a message to majordomo@vger.kernel.org
> >More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply
* Re: [PATCH] net: team: expose sysfs attributes for each team option
From: Thomas Graf @ 2014-11-20 16:05 UTC (permalink / raw)
To: Hamad Kadmany
Cc: Cong Wang, Hamad Kadmany, Jiri Pirko, netdev, Daniel Borkmann
In-Reply-To: <546CECAD.1040402@redhat.com>
On 11/19/14 at 08:17pm, Daniel Borkmann wrote:
> On 11/19/2014 07:45 PM, Cong Wang wrote:
> >On Wed, Nov 19, 2014 at 4:28 AM, Hamad Kadmany <hkadmany@codeaurora.org> wrote:
> >>On Mon, November 17, 2014 1:02 pm, Jiri Pirko wrote:
> >>>
> >>>Nak.
> >>>
> >>>I don't like this patch. The plan for team was keep things simple and to
> >>>have single userspace api using netlink, as that is the correct way to
> >>>deal with things. Sysfs for this use-case is not. Please, use netlink api.
>
> +1
>
> >>Using team driver requires using libnl3. In Android based platforms, libnl3
> >> is not supported, and libnl3 license poses constraints in Android's user-space.
>
> Constraints?! libnl3 is LGPL ...
The behaviour on this particular topic is disappointing. Instead of
working with the community and using an existing library such as
libmnl or libnl Android chose to fork libnl3 and disregard the
community a couple of years ago.
The reasoning in this thread is the next episode of the same story.
Very disappointing.
^ permalink raw reply
* Re: [PATCH 00/10] net: phy: add device-type abstraction
From: Florian Fainelli @ 2014-11-20 16:18 UTC (permalink / raw)
To: Johan Hovold
Cc: David S. Miller, netdev, linux-kernel, Bruno Thomsen,
Sascha Hauer, Mark Rutland
In-Reply-To: <1416398363-32306-1-git-send-email-johan@kernel.org>
On 11/19/2014 03:59 AM, Johan Hovold wrote:
> This series adds device and device-type abstractions to the micrel
> driver, and enables support for RMII-reference clock selection for
> KSZ8081 and KSZ8091 devices.
>
> While adding support for more features for the Micrel PHYs mentioned
> above, it became apparent that the configuration space is much too large
> and that adding type-specific callbacks will simply not scale. Instead I
> added a driver_data field to struct phy_device, which can be used to
> store static device type data that can be parsed and acted on in
> generic driver callbacks. This allows a lot of duplicated code to be
> removed, and should make it much easier to add new features or deal with
> device-type quirks in the future.
>
> The series has been tested on a dual KSZ8081 setup. Further testing on
> other Micrel PHYs would be much appreciated.
>
> The recent commit a95a18afe4c8 ("phy/micrel: KSZ8031RNL RMII clock
> reconfiguration bug") currently prevents KSZ8031 PHYs from using the
> generic config-init. Bruno, who is the author of that patch, has agreed
> to test this series and some follow-up diagnostic patches to determine
> how best to incorporate these devices as well. I intend to send a
> follow-up patch that removes the custom 8031 config-init and documents
> this quirk, but the current series can be applied meanwhile.
>
> These patches are against net-next which contains some already merged
> prerequisite patches to the driver.
LGTM, thanks Johan!
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
>
> Johan
>
>
> Johan Hovold (10):
> net: phy: add static data field to struct phy_driver
> net: phy: micrel: add device-type abstraction
> net: phy: micrel: parse of nodes at probe
> net: phy: micrel: add has-broadcast-disable flag to type data
> net: phy: micrel: add generic clock-mode-select support
> net: phy: micrel: add support for clock-mode select to KSZ8081/KSZ8091
> dt/bindings: reformat micrel eth-phy documentation
> dt/bindings: add clock-select function property to micrel phy binding
> net: phy: micrel: refactor interrupt config
> net: phy: micrel: add copyright entry
>
> Documentation/devicetree/bindings/net/micrel.txt | 37 ++--
> drivers/net/phy/micrel.c | 262 ++++++++++++++---------
> include/linux/micrel_phy.h | 1 -
> include/linux/phy.h | 2 +
> 4 files changed, 184 insertions(+), 118 deletions(-)
>
^ permalink raw reply
* [PATCH net-next] tcp: remove from tcp_sendmsg() some fastopen code
From: Eric Dumazet @ 2014-11-20 16:23 UTC (permalink / raw)
To: David Miller; +Cc: ycheng, nuclearcat, netdev, ncardwell
In-Reply-To: <1416497628.8629.24.camel@edumazet-glaptop2.roam.corp.google.com>
From: Eric Dumazet <edumazet@google.com>
If we consume iovec bytes in tcp_send_syn_data(), we can remove
annoying fastopen code in tcp_sendmsg() skipping over the already
consumed bytes.
Also add an unlikely(flags & MSG_FASTOPEN), as most TCP sendmsg() do not
ask for FASTOPEN.
Tested:
Ran our 125 packetdrill fastopen tests
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
net/ipv4/tcp.c | 14 ++------------
net/ipv4/tcp_output.c | 4 ++--
2 files changed, 4 insertions(+), 14 deletions(-)
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index c239f4740d10b10b67ef4fa44c831851fb9e1dcf..227540eef9d0870721258f9ddbace27b417c619e 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -1089,20 +1089,19 @@ int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
struct tcp_sock *tp = tcp_sk(sk);
struct sk_buff *skb;
int iovlen, flags, err, copied = 0;
- int mss_now = 0, size_goal, copied_syn = 0, offset = 0;
+ int mss_now = 0, size_goal, copied_syn = 0;
bool sg;
long timeo;
lock_sock(sk);
flags = msg->msg_flags;
- if (flags & MSG_FASTOPEN) {
+ if (unlikely(flags & MSG_FASTOPEN)) {
err = tcp_sendmsg_fastopen(sk, msg, &copied_syn, size);
if (err == -EINPROGRESS && copied_syn > 0)
goto out;
else if (err)
goto out_err;
- offset = copied_syn;
}
timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT);
@@ -1151,15 +1150,6 @@ int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
unsigned char __user *from = iov->iov_base;
iov++;
- if (unlikely(offset > 0)) { /* Skip bytes copied in SYN */
- if (offset >= seglen) {
- offset -= seglen;
- continue;
- }
- seglen -= offset;
- from += offset;
- offset = 0;
- }
while (seglen > 0) {
int copy = 0;
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index f5bd4bd3f7e669b3fd48a843d55e7313a30a3409..524e5b657e881a348f11def3f48f29a76f54fbab 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -3049,8 +3049,8 @@ static int tcp_send_syn_data(struct sock *sk, struct sk_buff *syn)
goto fallback;
syn_data->ip_summed = CHECKSUM_PARTIAL;
memcpy(syn_data->cb, syn->cb, sizeof(syn->cb));
- if (unlikely(memcpy_fromiovecend(skb_put(syn_data, space),
- fo->data->msg_iov, 0, space))) {
+ if (unlikely(memcpy_fromiovec(skb_put(syn_data, space),
+ fo->data->msg_iov, space))) {
kfree_skb(syn_data);
goto fallback;
}
^ permalink raw reply related
* Re: [PATCH net-next 1/4] net: allow large number of rx queues
From: Pankaj Gupta @ 2014-11-20 16:31 UTC (permalink / raw)
To: Cong Wang
Cc: linux-kernel, netdev, David Miller, Jason Wang,
Michael S. Tsirkin, dgibson, vfalico, Eric Dumazet,
Vladislav Yasevich, Jerry Chu, wuzhy, Pavel Emelyanov,
Tom Herbert, bhutchings, xii, Stephen Hemminger,
Jiří Pírko, sergei shtylyov
In-Reply-To: <CAHA+R7MnLy=8uL_hSnx=BN2QTs2kvempTxtmSO6hjcS+E0yRwg@mail.gmail.com>
> On Tue, Nov 18, 2014 at 8:22 AM, Pankaj Gupta <pagupta@redhat.com> wrote:
> >
> > As vmalloc() adds overhead on a critical network path,
> > __GFP_REPEAT flag is used with kzalloc() to do this fallback
> > only when really needed.
> >
>
> Are you sure we need __GFP_REPEAT? We have vmalloc() as
> fallback of kmalloc() in many places of networking (grep kvfree),
> none of those I checked has this flag set.
Its there in netif_alloc_netdev_queues() function in same file.
Also, I found it some other places as well.
I think its good to have.
>
^ permalink raw reply
* [PATCH net-next v1 0/8] amd-xgbe: AMD XGBE driver updates 2014-11-20
From: Tom Lendacky @ 2014-11-20 17:03 UTC (permalink / raw)
To: netdev; +Cc: David Miller
The following series of patches includes functional updates to the
driver as well as some trivial changes.
- Add a read memory barrier in the Tx and Rx path after checking the
descriptor ownership bit
- Wait for the Tx engine to stop/suspend before issuing a stop command
- Implement a smatch tool suggestion to simplify an if statement
- Separate out Tx and Rx ring data fields into their own structures
- Add BQL support
- Remove an unused variable
- Change Tx coalescing support to operate on packet basis instead of
a descriptor basis
- Add support for the skb->xmit_more flag
This patch series is based on net-next.
---
Tom Lendacky (8):
amd-xgbe: Add a read memory barrier to Tx/Rx path
amd-xgbe: Tx engine must not be active before stopping it
amd-xgbe: Incorporate Smatch coding suggestion
amd-xgbe: Separate Tx/Rx ring data fields into new structs
amd-xgbe: Add BQL support
amd-xgbe: Remove unused variable
amd-xgbe: Perform Tx coalescing on a packet basis
amd-xgbe: Add support for the skb->xmit_more flag
drivers/net/ethernet/amd/xgbe/xgbe-common.h | 21 ++-
drivers/net/ethernet/amd/xgbe/xgbe-desc.c | 40 +++---
drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 170 +++++++++++++++++++++------
drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 112 ++++++++++++++----
drivers/net/ethernet/amd/xgbe/xgbe.h | 42 ++++++-
5 files changed, 289 insertions(+), 96 deletions(-)
--
Tom Lendacky
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox