Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH v4 iproute2-next 0/7] cm_id, cq, mr, and pd resource tracking
From: Leon Romanovsky @ 2018-04-01 18:29 UTC (permalink / raw)
  To: David Ahern; +Cc: Steve Wise, stephen, netdev, linux-rdma
In-Reply-To: <8cdcb764-da42-e540-90e6-309eda0eb599@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 1744 bytes --]

On Sun, Apr 01, 2018 at 09:22:14AM -0600, David Ahern wrote:
> On 3/29/18 3:38 PM, Steve Wise wrote:
> > This series enhances the iproute2 rdma tool to include dumping of
> > connection manager id (cm_id), completion queue (cq), memory region (mr),
> > and protection domain (pd) rdma resources.  It is the user-space part of
> > the kernel resource tracking series merged into rdma-next for 4.17 [1]
> > and [2].
> >
> > Changes since v3:
> > - replaced rdma_cma.h inclusion with UAPI rdma_user_cm.h
> > - display only device names instead of device/port for cq, mr, and pd
> > since they are not associated with a specific port.
> >
> > Changes since v2:
> > - pull in rdma-core:include/rdma/rdma_cma.h
> > - 80 column reformat
> > - add reviewed-by tags
> >
> > Changes since v1/RFC:
> > - removed RFC tag
> > - initialize rd properly to avoid passing a garbage port number
> > - revert accidental change to qp_valid_filters
> > - removed cm_id dev/network/transport types
> > - cm_id ip addrs now passed up as __kernel_sockaddr_storage
> > - cm_id ip address ports printed as "address:port" strings
> > - only parse/display memory keys and iova if available
> > - filter on "users" for cqs and pds
> > - fixed memory leaks
> > - removed PD_FLAGS attribute
> > - filter on "mrlen" for mrs
> > - filter on "poll-ctx" for cqs
> > - don't require addrs or qp_type for parsing cm_ids
> > - only filter optional attrs if they are present
> > - remove PGSIZE MR attr to match kernel
> >
> > [1] https://www.spinics.net/lists/linux-rdma/msg61720.html
> > [2] https://www.spinics.net/lists/linux-rdma/msg62979.html
> >     https://www.spinics.net/lists/linux-rdma/msg62980.html
> >
> > ---
> >
>
> applied to iproute2-next. Thanks,

Thanks David

>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply

* Proposal
From: Melisa Mehmet @ 2018-04-01 17:42 UTC (permalink / raw)
  To: Recipients

Hello 


   
   Greetings to you today i asked before but i did't get a response please i know this might come to you as a surprise because you do not know me personally so i will give you a video call to explain more but did you get my previous email ? Let me know asap.





Best Regards,

Miss Melisa Mehmet 

Esentepe Mahallesi Büyükdere 

Caddesi Kristal Kule Binasi
No:215
 Sisli - Istanbul, Turkey 

^ permalink raw reply

* Re: [PATCH 0/2] sh_eth: remove SH_ETH_OFFSET_INVALID abuses
From: David Miller @ 2018-04-01 18:10 UTC (permalink / raw)
  To: sergei.shtylyov; +Cc: netdev, linux-renesas-soc, linux-sh
In-Reply-To: <998029b4-9400-ebc3-51c1-623c3f72b6cc@cogentembedded.com>

From: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
Date: Sun, 1 Apr 2018 00:15:04 +0300

> Hello!
> 
> Here's a set of 2 patches against DaveM's 'net-next.git' repo. They get rid of
> the abuse of SH_ETH_OFFSET_INVALID for the register existence checks, so that
> only its necessary uses would remain...
> 
> [1/2] sh_eth: add sh_eth_cpu_data::no_xdfar flag
> [2/2] sh_eth: kill useless check in __sh_eth_get_regs()

Series applied, thank you.

^ permalink raw reply

* Re: [PATCH net-next 0/2] inet: factorize sk_wmem_alloc updates
From: David Miller @ 2018-04-01 18:09 UTC (permalink / raw)
  To: edumazet; +Cc: netdev, eric.dumazet
In-Reply-To: <20180331201626.186789-1-edumazet@google.com>

From: Eric Dumazet <edumazet@google.com>
Date: Sat, 31 Mar 2018 13:16:24 -0700

> While testing my inet defrag changes, I found that senders
> could spend ~20% of cpu cycles in skb_set_owner_w() updating
> sk->sk_wmem_alloc for every fragment they cook, competing
> with TX completion of prior skbs possibly happening on another cpus.
> 
> One solution to this problem is to use alloc_skb() instead
> of sock_wmalloc() and manually perform a single sk_wmem_alloc change.
> 
> This greatly increases speed for applications sending big UDP datagrams.

Looks good, series applied, thanks.

^ permalink raw reply

* Re: [PATCH V2] treewide/net: Rename eth_stp_addr to ether_stp_addr
From: David Miller @ 2018-04-01 18:07 UTC (permalink / raw)
  To: joe; +Cc: andrew, f.fainelli, vivien.didelot, netdev, bridge, linux-kernel
In-Reply-To: <5f5dafaeacbc9e9aa2d969701e510d31ef6e97db.1522521099.git.joe@perches.com>

From: Joe Perches <joe@perches.com>
Date: Sat, 31 Mar 2018 11:34:06 -0700

> eth_stp_addr is not in the same form as the other global ether_<foo>_addr
> addresses like ether_broadcast_addr.
> 
> Convert it treewide.
> 
> Miscellanea:
> 
> o Add comment to the ether_stp_addr define to show it's for spanning-tree
> 
> Signed-off-by: Joe Perches <joe@perches.com>
> ---
> 
> V2: Remove gg from initial comment (bad editing)

Joe this was part of a larger series.

Please repost the entire series when you fix a patch contained
in that series, not just the patch that is changing.

Thank you.

^ permalink raw reply

* Re: [PATCH v2 2/2] net: usb: asix88179_178a: de-duplicate code
From: David Miller @ 2018-04-01 18:05 UTC (permalink / raw)
  To: marc.zyngier; +Cc: akurz, afd, linux-usb, netdev, freddy
In-Reply-To: <739a9ca166523efb9edc0865feefd014@www.loen.fr>

From: Marc Zyngier <marc.zyngier@arm.com>
Date: Sat, 31 Mar 2018 12:16:05 +0000

> I'd suggest that this patch is reverted until we understand what is
> actually going on here.

Yep, makes sense, reverted.

^ permalink raw reply

* Re: [PATCH net] ip6_gre: remove redundant 'tunnel' setting in ip6erspan_tap_init()
From: David Miller @ 2018-04-01 18:04 UTC (permalink / raw)
  To: alexey.kodanev; +Cc: netdev, u9012063
In-Reply-To: <1522431273-15591-1-git-send-email-alexey.kodanev@oracle.com>

From: Alexey Kodanev <alexey.kodanev@oracle.com>
Date: Fri, 30 Mar 2018 20:34:33 +0300

> 'tunnel' was already set at the start of ip6erspan_tap_init().
> 
> Fixes: 5a963eb61b7c ("ip6_gre: Add ERSPAN native tunnel support")
> Signed-off-by: Alexey Kodanev <alexey.kodanev@oracle.com>

Applied to net-next.

^ permalink raw reply

* Re: [PATCH net-next] net: tcp: update mib LISTENOVERFLOWS if syn flood
From: David Miller @ 2018-04-01 17:59 UTC (permalink / raw)
  To: cugyly; +Cc: netdev, Linyu.Yuan
In-Reply-To: <20180329112009.1379-1-cugyly@163.com>

From: yuan linyu <cugyly@163.com>
Date: Thu, 29 Mar 2018 19:20:09 +0800

> From: yuan linyu <Linyu.Yuan@alcatel-sbell.com.cn>
> 
> it's better to update mib LISTENOVERFLOWS even if packet is flood
> 
> Signed-off-by: yuan linyu <Linyu.Yuan@alcatel-sbell.com.cn>

When we drop because of synflood we had no intention of trying to add
to the accept queue.  Therefore bumping the listen overflow counter
makes no sense.

I'm not applying this, sorry.

^ permalink raw reply

* Re: [PATCH net-next] net/mlx4_en: CHECKSUM_COMPLETE support for fragments
From: David Miller @ 2018-04-01 17:57 UTC (permalink / raw)
  To: eric.dumazet; +Cc: tariqt, saeedm, edumazet, netdev, willemb
In-Reply-To: <00838522-3911-b525-8a19-2e0e8e365e57@gmail.com>

From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Sun, 1 Apr 2018 09:39:38 -0700

> On 04/01/2018 01:06 AM, Tariq Toukan wrote:
> 
>> 
>> Acked-by: Tariq Toukan <tariqt@mellanox.com>
> 
> Thanks Tariq and Saeed for the review !

Applied, thanks everyone.

^ permalink raw reply

* [PATCH net 2/2] net: bgmac: Fix endian access in bgmac_dma_tx_ring_free()
From: Florian Fainelli @ 2018-04-01 17:26 UTC (permalink / raw)
  To: netdev
  Cc: Florian Fainelli, David S. Miller, Scott Branden, Andrew Lunn,
	Abhishek Shah, Ray Jui, open list, jon.mason, nbd
In-Reply-To: <20180401172630.12883-1-f.fainelli@gmail.com>

bgmac_dma_tx_ring_free() assigns the ctl1 word which is a litle endian
32-bit word without using proper accessors, fix this, and because a
length cannot be negative, use unsigned int while at it.

Fixes: 9cde94506eac ("bgmac: implement scatter/gather support")
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
 drivers/net/ethernet/broadcom/bgmac.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c
index 8eef9fb6b1fe..ad8195b0d161 100644
--- a/drivers/net/ethernet/broadcom/bgmac.c
+++ b/drivers/net/ethernet/broadcom/bgmac.c
@@ -533,7 +533,8 @@ static void bgmac_dma_tx_ring_free(struct bgmac *bgmac,
 	int i;
 
 	for (i = 0; i < BGMAC_TX_RING_SLOTS; i++) {
-		int len = dma_desc[i].ctl1 & BGMAC_DESC_CTL1_LEN;
+		u32 ctl1 = le32_to_cpu(dma_desc[i].ctl1);
+		unsigned int len = ctl1 & BGMAC_DESC_CTL1_LEN;
 
 		slot = &ring->slots[i];
 		dev_kfree_skb(slot->skb);
-- 
2.14.1

^ permalink raw reply related

* [PATCH net 1/2] net: bgmac: Correctly annotate register space
From: Florian Fainelli @ 2018-04-01 17:26 UTC (permalink / raw)
  To: netdev
  Cc: Florian Fainelli, David S. Miller, Scott Branden, Andrew Lunn,
	Abhishek Shah, Ray Jui, open list, jon.mason, nbd
In-Reply-To: <20180401172630.12883-1-f.fainelli@gmail.com>

All the members: base, idm_base and nicpm_base should be annotated with
__iomem since they are pointers to register space. This fixes a bunch of
sparse reported warnings.

Fixes: f6a95a24957a ("net: ethernet: bgmac: Add platform device support")
Fixes: dd5c5d037f5e ("net: ethernet: bgmac: add NS2 support")
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
 drivers/net/ethernet/broadcom/bgmac.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/bgmac.h b/drivers/net/ethernet/broadcom/bgmac.h
index 4040d846da8e..40d02fec2747 100644
--- a/drivers/net/ethernet/broadcom/bgmac.h
+++ b/drivers/net/ethernet/broadcom/bgmac.h
@@ -479,9 +479,9 @@ struct bgmac_rx_header {
 struct bgmac {
 	union {
 		struct {
-			void *base;
-			void *idm_base;
-			void *nicpm_base;
+			void __iomem *base;
+			void __iomem *idm_base;
+			void __iomem *nicpm_base;
 		} plat;
 		struct {
 			struct bcma_device *core;
-- 
2.14.1

^ permalink raw reply related

* [PATCH net 0/2] net: bgmac: Couple of sparse warnings
From: Florian Fainelli @ 2018-04-01 17:26 UTC (permalink / raw)
  To: netdev
  Cc: Florian Fainelli, David S. Miller, Scott Branden, Andrew Lunn,
	Abhishek Shah, Ray Jui, open list, jon.mason, nbd

Hi all,

This patch series fixes a couple of warnings reported by sparse, should not
cause any functional problems since bgmac is typically used on LE platforms
anyway.

Florian Fainelli (2):
  net: bgmac: Correctly annotate register space
  net: bgmac: Fix endian access in bgmac_dma_tx_ring_free()

 drivers/net/ethernet/broadcom/bgmac.c | 3 ++-
 drivers/net/ethernet/broadcom/bgmac.h | 6 +++---
 2 files changed, 5 insertions(+), 4 deletions(-)

-- 
2.14.1

^ permalink raw reply

* Re: [PATCH net-next] net/mlx4_en: CHECKSUM_COMPLETE support for fragments
From: Eric Dumazet @ 2018-04-01 16:39 UTC (permalink / raw)
  To: Tariq Toukan, Saeed Mahameed, Eric Dumazet
  Cc: David S . Miller, netdev, Eric Dumazet, Willem de Bruijn
In-Reply-To: <8c43b222-f736-412b-e87c-017610fc97df@mellanox.com>



On 04/01/2018 01:06 AM, Tariq Toukan wrote:

> 
> Acked-by: Tariq Toukan <tariqt@mellanox.com>

Thanks Tariq and Saeed for the review !

^ permalink raw reply

* Re: [PATCH net-next] net: ipv6/gre: Add GRO support
From: Eric Dumazet @ 2018-04-01 16:35 UTC (permalink / raw)
  To: Tariq Toukan, David S. Miller; +Cc: netdev, Eran Ben Elisha, Eric Dumazet
In-Reply-To: <1522588651-28800-1-git-send-email-tariqt@mellanox.com>



On 04/01/2018 06:17 AM, Tariq Toukan wrote:
> From: Eran Ben Elisha <eranbe@mellanox.com>
> 
> Add GRO capability for IPv6 GRE tunnel and ip6erspan tap, via gro_cells
> infrastructure.
> 
> Performance testing: 55% higher badwidth.
> Measuring bandwidth of 1 thread IPv4 TCP traffic over IPv6 GRE tunnel
> while GRO on the physical interface is disabled.
> CPU: Intel Xeon E312xx (Sandy Bridge)
> NIC: Mellanox Technologies MT27700 Family [ConnectX-4]
> Before (GRO not working in tunnel) : 2.47 Gbits/sec
> After  (GRO working in tunnel)     : 3.85 Gbits/sec
> 
> Signed-off-by: Eran Ben Elisha <eranbe@mellanox.com>
> Signed-off-by: Tariq Toukan <tariqt@mellanox.com>
> CC: Eric Dumazet <edumazet@google.com>
> ---


Seems good, but why isn't this handled directly in GRO native layer ?

^ permalink raw reply

* Re: [PATCH net-next] net/broadcom: Fixup broken build due to function name change
From: Florian Fainelli @ 2018-04-01 16:33 UTC (permalink / raw)
  To: Tal Gilboa, David S. Miller; +Cc: netdev, Tariq Toukan, Saeed Mahameed
In-Reply-To: <1522565293-12068-1-git-send-email-talgi@mellanox.com>

Le 03/31/18 à 23:48, Tal Gilboa a écrit :
> Fixes: 8c6d6895bebb ("net/dim: Rename *_get_profile() functions to *_get_rx_moderation()")
> Signed-off-by: Tal Gilboa <talgi@mellanox.com>

I think David just backed out your entire patch series adding TX DIM so
you would have to incorporate that change into your series and
re-submit. Thanks!
-- 
Florian

^ permalink raw reply

* Re: [PATCH net] route: check sysctl_fib_multipath_use_neigh earlier than hash
From: David Ahern @ 2018-04-01 16:19 UTC (permalink / raw)
  To: Xin Long, network dev; +Cc: davem, Julian Anastasov
In-Reply-To: <6265ae9495a93efac372d41001c5ebccbb916df7.1522593635.git.lucien.xin@gmail.com>

On 4/1/18 8:40 AM, Xin Long wrote:
> Prior to this patch, when one packet is hashed into path [1]
> (hash <= nh_upper_bound) and it's neigh is dead, it will try
> path [2]. However, if path [2]'s neigh is alive but it's
> hash > nh_upper_bound, it will not return this alive path.
> This packet will never be sent even if path [2] is alive.
> 
>  3.3.3.1/24:
>   nexthop via 1.1.1.254 dev eth1 weight 1 <--[1] (dead neigh)
>   nexthop via 2.2.2.254 dev eth2 weight 1 <--[2]
> 
> With sysctl_fib_multipath_use_neigh set is supposed to find an
> available path respecting to the l3/l4 hash. But if there is
> no available route with this hash, it should at least return
> an alive route even with other hash.
> 
> This patch is to fix it by processing fib_multipath_use_neigh
> earlier than the hash check, so that it will at least return
> an alive route if there is when fib_multipath_use_neigh is
> enabled. It's also compatible with before when there are alive
> routes with the l3/l4 hash.
> 
> Fixes: a6db4494d218 ("net: ipv4: Consider failed nexthops in multipath routes")
> Reported-by: Jianlin Shi <jishi@redhat.com>
> Signed-off-by: Xin Long <lucien.xin@gmail.com>
> ---
>  net/ipv4/fib_semantics.c | 20 +++++++++++---------
>  1 file changed, 11 insertions(+), 9 deletions(-)
> 

Acked-by: David Ahern <dsa@cumulusnetworks.com>

^ permalink raw reply

* Re: [RFC PATCH 2/3] netdev: kernel-only IFF_HIDDEN netdevice
From: David Ahern @ 2018-04-01 16:11 UTC (permalink / raw)
  To: Si-Wei Liu, mst, jiri, stephen, alexander.h.duyck, davem,
	jesse.brandeburg, kubakici, jasowang, sridhar.samudrala, netdev,
	virtualization, virtio-dev
In-Reply-To: <1522573990-5242-3-git-send-email-si-wei.liu@oracle.com>

On 4/1/18 3:13 AM, Si-Wei Liu wrote:
> Hidden netdevice is not visible to userspace such that
> typical network utilites e.g. ip, ifconfig and et al,
> cannot sense its existence or configure it. Internally
> hidden netdev may associate with an upper level netdev
> that userspace has access to. Although userspace cannot
> manipulate the lower netdev directly, user may control
> or configure the underlying hidden device through the
> upper-level netdev. For identification purpose, the
> kobject for hidden netdev still presents in the sysfs
> hierarchy, however, no uevent message will be generated
> when the sysfs entry is created, modified or destroyed.
> 
> For that end, a separate namescope needs to be carved
> out for IFF_HIDDEN netdevs. As of now netdev name that
> starts with colon i.e. ':' is invalid in userspace,
> since socket ioctls such as SIOCGIFCONF use ':' as the
> separator for ifname. The absence of namescope started
> with ':' can rightly be used as the namescope for
> the kernel-only IFF_HIDDEN netdevs.
> 
> Signed-off-by: Si-Wei Liu <si-wei.liu@oracle.com>
> ---
>  include/linux/netdevice.h   |  12 ++
>  include/net/net_namespace.h |   2 +
>  net/core/dev.c              | 281 ++++++++++++++++++++++++++++++++++++++------
>  net/core/net_namespace.c    |   1 +
>  4 files changed, 263 insertions(+), 33 deletions(-)
> 

There are other use cases that want to hide a device from userspace. I
would prefer a better solution than playing games with name prefixes and
one that includes an API for users to list all devices -- even ones
hidden by default.

https://github.com/dsahern/linux/commit/48a80a00eac284e58bae04af10a5a932dd7aee00

https://github.com/dsahern/iproute2/commit/7563f5b26f5539960e99066e34a995d22ea908ed

Also, why are you suggesting that the device should still be visible via
/sysfs? That leads to inconsistent views of networking state - /sys
shows a device but a link dump does not.

^ permalink raw reply

* Investment opportunity
From: Yi tan @ 2018-03-31 17:35 UTC (permalink / raw)


Greetings,

Please find the content of this mail very confidential. my name is Yi Tan,
I work with a Bank here in Hong Kong. I decided to contact you for an
opportunity to invest in any lucrative business in your country.

We also offer a quick loan at low interest rate, if you are interested
please reply me for more information on my private
e-mail: yitanfinancesystemhk@gmail.com

Sincerely: Yi Tan

^ permalink raw reply

* Re: [PATCH iproute2-next 1/1] tc: jsonify sample action
From: David Ahern @ 2018-04-01 15:47 UTC (permalink / raw)
  To: Roman Mashak; +Cc: stephen, netdev, kernel, jhs, xiyou.wangcong, jiri
In-Reply-To: <1522470045-22397-1-git-send-email-mrv@mojatatu.com>

On 3/30/18 10:20 PM, Roman Mashak wrote:
> Signed-off-by: Roman Mashak <mrv@mojatatu.com>
> ---
>  tc/m_sample.c | 22 +++++++++++++---------
>  1 file changed, 13 insertions(+), 9 deletions(-)
> 

applied to iproute2-next

^ permalink raw reply

* Re: [PATCH iproute2-next 1/1] tc: support oneline mode in action generic printer functions
From: David Ahern @ 2018-04-01 15:43 UTC (permalink / raw)
  To: Roman Mashak; +Cc: stephen, netdev, kernel, jhs, xiyou.wangcong, jiri
In-Reply-To: <1522469805-20584-1-git-send-email-mrv@mojatatu.com>

On 3/30/18 10:16 PM, Roman Mashak wrote:
> Signed-off-by: Roman Mashak <mrv@mojatatu.com>
> ---
>  tc/m_action.c | 12 ++++++++----
>  1 file changed, 8 insertions(+), 4 deletions(-)
> 

applied to iproute2-next

^ permalink raw reply

* Re: [PATCH v2 net-next 10/10] mlxsw: spectrum: Don't use resource ID of 0
From: David Ahern @ 2018-04-01 15:26 UTC (permalink / raw)
  To: Ido Schimmel, netdev; +Cc: davem, jiri, petrm, mlxsw
In-Reply-To: <20180401143459.30770-11-idosch@mellanox.com>

On 4/1/18 8:34 AM, Ido Schimmel wrote:
> From: Petr Machata <petrm@mellanox.com>
> 
> In commit 145307460ba9 ("devlink: Remove top_hierarchy arg to
> devlink_resource_register"), the "top_hierarchy" parameter to
> devlink_resource_register() was removed in favor of using the parameter
> "parent_resource_id" exclusively to determine who the parent is. The
> root node's resource ID for this purpose is
> DEVLINK_RESOURCE_ID_PARENT_TOP with the value 0. It is therefore
> problematic that the resource MLXSW_SP_RESOURCE_KVD has also ID of 0.
> 
> Fix this by numbering driver-specific resources from 1.
> 
> Fixes: 145307460ba9 ("devlink: Remove top_hierarchy arg to devlink_resource_register")
> Signed-off-by: Petr Machata <petrm@mellanox.com>
> Signed-off-by: Ido Schimmel <idosch@mellanox.com>
> ---
>  drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 

not sure how I missed this; I booted the switch with the above patch.
Thanks for fixing.

^ permalink raw reply

* include/uapi/linux/ethtool.h problem
From: Madarassy László @ 2018-04-01 14:57 UTC (permalink / raw)
  To: netdev
In-Reply-To: <82efe0c7-c000-fea1-984b-f549de269aac@cjb.hu>

Hi,

I have the following problem:

I included include/uapi/linux/mii.h from my source and when I compiled I
got this error:

ethtool.h:1556:35: error: comparison between signed and unsigned integer
expressions [-Werro
   return speed <= INT_MAX || speed == SPEED_UNKNOWN;

speed declared as unsigned int32, but SPEED_UNKNOWN defined to -1.

Without -Wno-sign-compare I can't compile.

Regards,
Laszlo

^ permalink raw reply

* Re: [PATCH v2 net-next 00/10] mlxsw: Various cleanups
From: David Miller @ 2018-04-01 15:24 UTC (permalink / raw)
  To: idosch; +Cc: netdev, jiri, petrm, dsahern, mlxsw
In-Reply-To: <20180401143459.30770-1-idosch@mellanox.com>

From: Ido Schimmel <idosch@mellanox.com>
Date: Sun,  1 Apr 2018 17:34:49 +0300

> The first nine patches from Jiri perform small and unrelated cleanups.
> The largest being the conversion of the KVD linear partitions from a
> list to an array, which simplifies the code.
> 
> The last patch from Petr is a bug fix for a recent net-next commit that
> prevented the "kvd" resource from being marked as the parent of its
> various child resources (e.g., "/kvd/linear").
> 
> v2: Dropped devlink patch following David's comment. Will be sent
> separately.

Series applied, thank you.

^ permalink raw reply

* Re: [PATCH v4 iproute2-next 0/7] cm_id, cq, mr, and pd resource tracking
From: David Ahern @ 2018-04-01 15:22 UTC (permalink / raw)
  To: Steve Wise; +Cc: leon, stephen, netdev, linux-rdma
In-Reply-To: <cover.1522359537.git.swise@opengridcomputing.com>

On 3/29/18 3:38 PM, Steve Wise wrote:
> This series enhances the iproute2 rdma tool to include dumping of
> connection manager id (cm_id), completion queue (cq), memory region (mr),
> and protection domain (pd) rdma resources.  It is the user-space part of
> the kernel resource tracking series merged into rdma-next for 4.17 [1]
> and [2].
> 
> Changes since v3:
> - replaced rdma_cma.h inclusion with UAPI rdma_user_cm.h
> - display only device names instead of device/port for cq, mr, and pd
> since they are not associated with a specific port.
> 
> Changes since v2:
> - pull in rdma-core:include/rdma/rdma_cma.h
> - 80 column reformat
> - add reviewed-by tags
> 
> Changes since v1/RFC:
> - removed RFC tag
> - initialize rd properly to avoid passing a garbage port number
> - revert accidental change to qp_valid_filters 
> - removed cm_id dev/network/transport types
> - cm_id ip addrs now passed up as __kernel_sockaddr_storage
> - cm_id ip address ports printed as "address:port" strings
> - only parse/display memory keys and iova if available
> - filter on "users" for cqs and pds
> - fixed memory leaks 
> - removed PD_FLAGS attribute
> - filter on "mrlen" for mrs
> - filter on "poll-ctx" for cqs
> - don't require addrs or qp_type for parsing cm_ids
> - only filter optional attrs if they are present
> - remove PGSIZE MR attr to match kernel 
> 
> [1] https://www.spinics.net/lists/linux-rdma/msg61720.html
> [2] https://www.spinics.net/lists/linux-rdma/msg62979.html
>     https://www.spinics.net/lists/linux-rdma/msg62980.html
> 
> ---
> 

applied to iproute2-next. Thanks,

^ permalink raw reply

* [bpf-next PATCH 4/4] bpf: sockmap, add hash map support
From: John Fastabend @ 2018-04-01 15:01 UTC (permalink / raw)
  To: ast, daniel; +Cc: netdev, davem
In-Reply-To: <20180401145728.24727.706.stgit@john-Precision-Tower-5810>

Sockmap is currently backed by an array and enforces keys to be
four bytes. This works well for many use cases and was originally
modeled after devmap which also uses four bytes keys. However,
this has become limiting in larger use cases where a hash would
be more appropriate. For example users may want to use the 5-tuple
of the socket as the lookup key.

To support this add hash support.

Signed-off-by: John Fastabend <john.fastabend@gmail.com>
---
 include/linux/bpf.h                       |    8 
 include/linux/bpf_types.h                 |    1 
 include/uapi/linux/bpf.h                  |    6 
 kernel/bpf/core.c                         |    1 
 kernel/bpf/sockmap.c                      |  512 ++++++++++++++++++++++++++++-
 kernel/bpf/verifier.c                     |   14 +
 net/core/filter.c                         |   54 +++
 tools/bpf/bpftool/map.c                   |    1 
 tools/include/uapi/linux/bpf.h            |    6 
 tools/testing/selftests/bpf/bpf_helpers.h |   13 +
 10 files changed, 598 insertions(+), 18 deletions(-)

diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 95a7abd..d5c77f2 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -645,6 +645,7 @@ static inline void bpf_map_offload_map_free(struct bpf_map *map)
 
 #if defined(CONFIG_STREAM_PARSER) && defined(CONFIG_BPF_SYSCALL) && defined(CONFIG_INET)
 struct sock  *__sock_map_lookup_elem(struct bpf_map *map, u32 key);
+struct sock  *__sock_hash_lookup_elem(struct bpf_map *map, void *key);
 int sock_map_prog(struct bpf_map *map, struct bpf_prog *prog, u32 type);
 #else
 static inline struct sock  *__sock_map_lookup_elem(struct bpf_map *map, u32 key)
@@ -652,6 +653,12 @@ static inline struct sock  *__sock_map_lookup_elem(struct bpf_map *map, u32 key)
 	return NULL;
 }
 
+static inline struct sock  *__sock_hash_lookup_elem(struct bpf_map *map,
+						    void *key)
+{
+	return NULL;
+}
+
 static inline int sock_map_prog(struct bpf_map *map,
 				struct bpf_prog *prog,
 				u32 type)
@@ -677,6 +684,7 @@ static inline int sock_map_prog(struct bpf_map *map,
 extern const struct bpf_func_proto bpf_skb_vlan_pop_proto;
 extern const struct bpf_func_proto bpf_get_stackid_proto;
 extern const struct bpf_func_proto bpf_sock_map_update_proto;
+extern const struct bpf_func_proto bpf_sock_hash_update_proto;
 
 /* Shared helpers among cBPF and eBPF. */
 void bpf_user_rnd_init_once(void);
diff --git a/include/linux/bpf_types.h b/include/linux/bpf_types.h
index 2b28fcf..3101118 100644
--- a/include/linux/bpf_types.h
+++ b/include/linux/bpf_types.h
@@ -47,6 +47,7 @@
 BPF_MAP_TYPE(BPF_MAP_TYPE_DEVMAP, dev_map_ops)
 #if defined(CONFIG_STREAM_PARSER) && defined(CONFIG_INET)
 BPF_MAP_TYPE(BPF_MAP_TYPE_SOCKMAP, sock_map_ops)
+BPF_MAP_TYPE(BPF_MAP_TYPE_SOCKHASH, sock_hash_ops)
 #endif
 BPF_MAP_TYPE(BPF_MAP_TYPE_CPUMAP, cpu_map_ops)
 #endif
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index c5ec897..9886e88 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -115,6 +115,7 @@ enum bpf_map_type {
 	BPF_MAP_TYPE_DEVMAP,
 	BPF_MAP_TYPE_SOCKMAP,
 	BPF_MAP_TYPE_CPUMAP,
+	BPF_MAP_TYPE_SOCKHASH,
 };
 
 enum bpf_prog_type {
@@ -821,7 +822,10 @@ struct bpf_stack_build_id {
 	FN(msg_apply_bytes),		\
 	FN(msg_cork_bytes),		\
 	FN(msg_pull_data),		\
-	FN(bind),
+	FN(bind),			\
+	FN(sock_hash_update),		\
+	FN(msg_redirect_hash),		\
+	FN(sk_redirect_hash),
 
 /* integer value in 'imm' field of BPF_CALL instruction selects which helper
  * function eBPF program intends to call
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index d315b39..dd2c906 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -1769,6 +1769,7 @@ void bpf_user_rnd_init_once(void)
 const struct bpf_func_proto bpf_get_current_uid_gid_proto __weak;
 const struct bpf_func_proto bpf_get_current_comm_proto __weak;
 const struct bpf_func_proto bpf_sock_map_update_proto __weak;
+const struct bpf_func_proto bpf_sock_hash_update_proto __weak;
 
 const struct bpf_func_proto * __weak bpf_get_trace_printk_proto(void)
 {
diff --git a/kernel/bpf/sockmap.c b/kernel/bpf/sockmap.c
index c006e3b..175fcb0 100644
--- a/kernel/bpf/sockmap.c
+++ b/kernel/bpf/sockmap.c
@@ -59,6 +59,28 @@ struct bpf_stab {
 	struct bpf_sock_progs progs;
 };
 
+struct bucket {
+	struct hlist_nulls_head head;
+	raw_spinlock_t lock;
+};
+
+struct bpf_htab {
+	struct bpf_map map;
+	struct bucket *buckets;
+	atomic_t count;
+	u32 n_buckets;
+	u32 elem_size;
+	struct bpf_sock_progs progs;
+};
+
+struct htab_elem {
+	struct rcu_head rcu;
+	struct hlist_nulls_node hash_node;
+	u32 hash;
+	struct sock *sk;
+	char key[0];
+};
+
 enum smap_psock_state {
 	SMAP_TX_RUNNING,
 };
@@ -66,6 +88,8 @@ enum smap_psock_state {
 struct smap_psock_map_entry {
 	struct list_head list;
 	struct sock **entry;
+	struct htab_elem *hash_link;
+	struct bpf_htab *htab;
 };
 
 struct smap_psock {
@@ -194,6 +218,27 @@ static void bpf_tcp_release(struct sock *sk)
 	rcu_read_unlock();
 }
 
+static void htab_elem_free_rcu(struct rcu_head *head)
+{
+	struct htab_elem *l = container_of(head, struct htab_elem, rcu);
+
+	/* must increment bpf_prog_active to avoid kprobe+bpf triggering while
+	 * we're calling kfree, otherwise deadlock is possible if kprobes
+	 * are placed somewhere inside of slub
+	 */
+	preempt_disable();
+	__this_cpu_inc(bpf_prog_active);
+	kfree(l);
+	__this_cpu_dec(bpf_prog_active);
+	preempt_enable();
+}
+
+static void free_htab_elem(struct bpf_htab *htab, struct htab_elem *l)
+{
+	atomic_dec(&htab->count);
+	call_rcu(&l->rcu, htab_elem_free_rcu);
+}
+
 static void bpf_tcp_close(struct sock *sk, long timeout)
 {
 	void (*close_fun)(struct sock *sk, long timeout);
@@ -230,10 +275,16 @@ static void bpf_tcp_close(struct sock *sk, long timeout)
 	}
 
 	list_for_each_entry_safe(e, tmp, &psock->maps, list) {
-		osk = cmpxchg(e->entry, sk, NULL);
-		if (osk == sk) {
-			list_del(&e->list);
-			smap_release_sock(psock, sk);
+		if (e->entry) {
+			osk = cmpxchg(e->entry, sk, NULL);
+			if (osk == sk) {
+				list_del(&e->list);
+				smap_release_sock(psock, sk);
+			}
+		} else {
+			hlist_nulls_del_rcu(&e->hash_link->hash_node);
+			smap_release_sock(psock, e->hash_link->sk);
+			free_htab_elem(e->htab, e->hash_link);
 		}
 	}
 	write_unlock_bh(&sk->sk_callback_lock);
@@ -1483,12 +1534,14 @@ static struct bpf_map *sock_map_alloc(union bpf_attr *attr)
 	return ERR_PTR(err);
 }
 
-static void smap_list_remove(struct smap_psock *psock, struct sock **entry)
+static void smap_list_remove(struct smap_psock *psock,
+			     struct sock **entry,
+			     struct htab_elem *hash_link)
 {
 	struct smap_psock_map_entry *e, *tmp;
 
 	list_for_each_entry_safe(e, tmp, &psock->maps, list) {
-		if (e->entry == entry) {
+		if (e->entry == entry || e->hash_link == hash_link) {
 			list_del(&e->list);
 			break;
 		}
@@ -1526,7 +1579,7 @@ static void sock_map_free(struct bpf_map *map)
 		 * to be null and queued for garbage collection.
 		 */
 		if (likely(psock)) {
-			smap_list_remove(psock, &stab->sock_map[i]);
+			smap_list_remove(psock, &stab->sock_map[i], NULL);
 			smap_release_sock(psock, sock);
 		}
 		write_unlock_bh(&sock->sk_callback_lock);
@@ -1585,7 +1638,7 @@ static int sock_map_delete_elem(struct bpf_map *map, void *key)
 
 	if (psock->bpf_parse)
 		smap_stop_sock(psock, sock);
-	smap_list_remove(psock, &stab->sock_map[k]);
+	smap_list_remove(psock, &stab->sock_map[k], NULL);
 	smap_release_sock(psock, sock);
 out:
 	write_unlock_bh(&sock->sk_callback_lock);
@@ -1625,7 +1678,7 @@ static int __sock_map_ctx_update_elem(struct bpf_map *map,
 				      struct bpf_sock_progs *progs,
 				      struct sock *sock,
 				      struct sock **map_link,
-				      struct sock **hash_link,
+				      struct htab_elem *hash_link,
 				      void *key)
 {
 	struct bpf_prog *verdict, *parse, *tx_msg;
@@ -1737,6 +1790,11 @@ static int __sock_map_ctx_update_elem(struct bpf_map *map,
 		e->entry = map_link;
 		list_add_tail(&e->list, &psock->maps);
 	}
+	if (hash_link) {
+		e->hash_link = hash_link;
+		e->htab = container_of(map, struct bpf_htab, map);
+		list_add_tail(&e->list, &psock->maps);
+	}
 	write_unlock_bh(&sock->sk_callback_lock);
 	return err;
 out_free:
@@ -1786,7 +1844,7 @@ static int sock_map_ctx_update_elem(struct bpf_sock_ops_kern *skops,
 		struct smap_psock *opsock = smap_psock_sk(osock);
 
 		write_lock_bh(&osock->sk_callback_lock);
-		smap_list_remove(opsock, &stab->sock_map[i]);
+		smap_list_remove(opsock, &stab->sock_map[i], NULL);
 		smap_release_sock(opsock, osock);
 		write_unlock_bh(&osock->sk_callback_lock);
 	}
@@ -1803,6 +1861,10 @@ int sock_map_prog(struct bpf_map *map, struct bpf_prog *prog, u32 type)
 		struct bpf_stab *stab = container_of(map, struct bpf_stab, map);
 
 		progs = &stab->progs;
+	} else if (map->map_type == BPF_MAP_TYPE_SOCKHASH) {
+		struct bpf_htab *htab = container_of(map, struct bpf_htab, map);
+
+		progs = &htab->progs;
 	} else {
 		return -EINVAL;
 	}
@@ -1863,11 +1925,19 @@ static int sock_map_update_elem(struct bpf_map *map,
 
 static void sock_map_release(struct bpf_map *map, struct file *map_file)
 {
-	struct bpf_stab *stab = container_of(map, struct bpf_stab, map);
 	struct bpf_sock_progs *progs;
 	struct bpf_prog *orig;
 
-	progs = &stab->progs;
+	if (map->map_type == BPF_MAP_TYPE_SOCKMAP) {
+		struct bpf_stab *stab = container_of(map, struct bpf_stab, map);
+
+		progs = &stab->progs;
+	} else {
+		struct bpf_htab *htab = container_of(map, struct bpf_htab, map);
+
+		progs = &htab->progs;
+	}
+
 	orig = xchg(&progs->bpf_parse, NULL);
 	if (orig)
 		bpf_prog_put(orig);
@@ -1880,6 +1950,396 @@ static void sock_map_release(struct bpf_map *map, struct file *map_file)
 		bpf_prog_put(orig);
 }
 
+static struct bpf_map *sock_hash_alloc(union bpf_attr *attr)
+{
+	struct bpf_htab *htab;
+	int i, err;
+	u64 cost;
+
+	if (!capable(CAP_NET_ADMIN))
+		return ERR_PTR(-EPERM);
+
+	/* check sanity of attributes */
+	if (attr->max_entries == 0 ||
+	    attr->map_flags & ~SOCK_CREATE_FLAG_MASK)
+		return ERR_PTR(-EINVAL);
+
+	if (attr->value_size > KMALLOC_MAX_SIZE)
+		return ERR_PTR(-E2BIG);
+
+	err = bpf_tcp_ulp_register();
+	if (err && err != -EEXIST)
+		return ERR_PTR(err);
+
+	htab = kzalloc(sizeof(*htab), GFP_USER);
+	if (!htab)
+		return ERR_PTR(-ENOMEM);
+
+	bpf_map_init_from_attr(&htab->map, attr);
+
+	htab->n_buckets = roundup_pow_of_two(htab->map.max_entries);
+	htab->elem_size = sizeof(struct htab_elem) +
+			  round_up(htab->map.key_size, 8);
+
+	if (htab->n_buckets == 0 ||
+	    htab->n_buckets > U32_MAX / sizeof(struct bucket))
+		goto free_htab;
+
+	cost = (u64) htab->n_buckets * sizeof(struct bucket) +
+	       (u64) htab->elem_size * htab->map.max_entries;
+
+	if (cost >= U32_MAX - PAGE_SIZE)
+		goto free_htab;
+
+	htab->map.pages = round_up(cost, PAGE_SIZE) >> PAGE_SHIFT;
+	err = bpf_map_precharge_memlock(htab->map.pages);
+	if (err)
+		goto free_htab;
+
+	err = -ENOMEM;
+	htab->buckets = bpf_map_area_alloc(
+				htab->n_buckets * sizeof(struct bucket),
+				htab->map.numa_node);
+	if (!htab->buckets)
+		goto free_htab;
+
+	for (i = 0; i < htab->n_buckets; i++) {
+		INIT_HLIST_NULLS_HEAD(&htab->buckets[i].head, i);
+		raw_spin_lock_init(&htab->buckets[i].lock);
+	}
+
+	return &htab->map;
+free_htab:
+	kfree(htab);
+	return ERR_PTR(err);
+}
+
+static inline struct bucket *__select_bucket(struct bpf_htab *htab, u32 hash)
+{
+	return &htab->buckets[hash & (htab->n_buckets - 1)];
+}
+
+static inline struct hlist_nulls_head *select_bucket(struct bpf_htab *htab,
+						     u32 hash)
+{
+	return &__select_bucket(htab, hash)->head;
+}
+
+static void sock_hash_free(struct bpf_map *map)
+{
+	struct bpf_htab *htab = container_of(map, struct bpf_htab, map);
+	int i;
+
+	synchronize_rcu();
+
+	/* At this point no update, lookup or delete operations can happen.
+	 * However, be aware we can still get a socket state event updates,
+	 * and data ready callabacks that reference the psock from sk_user_data
+	 * Also psock worker threads are still in-flight. So smap_release_sock
+	 * will only free the psock after cancel_sync on the worker threads
+	 * and a grace period expire to ensure psock is really safe to remove.
+	 */
+	rcu_read_lock();
+	for (i = 0; i < htab->n_buckets; i++) {
+		struct hlist_nulls_head *head = select_bucket(htab, i);
+		struct hlist_nulls_node *n;
+		struct htab_elem *l;
+
+		hlist_nulls_for_each_entry_safe(l, n, head, hash_node) {
+			struct sock *sock = l->sk;
+			struct smap_psock *psock;
+
+			hlist_nulls_del_rcu(&l->hash_node);
+			write_lock_bh(&sock->sk_callback_lock);
+			psock = smap_psock_sk(sock);
+			/* This check handles a racing sock event that can get
+			 * the sk_callback_lock before this case but after xchg
+			 * causing the refcnt to hit zero and sock user data
+			 * (psock) to be null and queued for garbage collection.
+			 */
+			if (likely(psock)) {
+				smap_list_remove(psock, NULL, l);
+				smap_release_sock(psock, sock);
+			}
+			write_unlock_bh(&sock->sk_callback_lock);
+			kfree(l);
+		}
+	}
+	rcu_read_unlock();
+	bpf_map_area_free(htab->buckets);
+	kfree(htab);
+}
+
+static struct htab_elem *alloc_sock_hash_elem(struct bpf_htab *htab,
+					      void *key, u32 key_size, u32 hash,
+					      struct sock *sk,
+					      struct htab_elem *old_elem)
+{
+	struct htab_elem *l_new;
+
+	if (atomic_inc_return(&htab->count) > htab->map.max_entries) {
+		if (!old_elem) {
+			atomic_dec(&htab->count);
+			return ERR_PTR(-E2BIG);
+		}
+	}
+	l_new = kmalloc_node(htab->elem_size, GFP_ATOMIC | __GFP_NOWARN,
+			     htab->map.numa_node);
+	if (!l_new)
+		return ERR_PTR(-ENOMEM);
+
+	memcpy(l_new->key, key, key_size);
+	l_new->sk = sk;
+	l_new->hash = hash;
+	return l_new;
+}
+
+static struct htab_elem *lookup_elem_raw(struct hlist_nulls_head *head,
+					 u32 hash, void *key, u32 key_size)
+{
+	struct hlist_nulls_node *n;
+	struct htab_elem *l;
+
+	hlist_nulls_for_each_entry_rcu(l, n, head, hash_node)
+		if (l->hash == hash && !memcmp(&l->key, key, key_size))
+			return l;
+
+	return NULL;
+}
+
+static inline u32 htab_map_hash(const void *key, u32 key_len)
+{
+	return jhash(key, key_len, 0);
+}
+
+static struct htab_elem *lookup_nulls_elem_raw(struct hlist_nulls_head *head,
+					       u32 hash, void *key,
+					       u32 key_size, u32 n_buckets)
+{
+	struct hlist_nulls_node *n;
+	struct htab_elem *l;
+
+again:
+	hlist_nulls_for_each_entry_rcu(l, n, head, hash_node)
+		if (l->hash == hash && !memcmp(&l->key, key, key_size))
+			return l;
+
+	if (unlikely(get_nulls_value(n) != (hash & (n_buckets - 1))))
+		goto again;
+
+	return NULL;
+}
+
+static int sock_hash_get_next_key(struct bpf_map *map,
+				  void *key, void *next_key)
+{
+	struct bpf_htab *htab = container_of(map, struct bpf_htab, map);
+	struct htab_elem *l, *next_l;
+	struct hlist_nulls_head *h;
+	u32 hash, key_size;
+	int i = 0;
+
+	WARN_ON_ONCE(!rcu_read_lock_held());
+
+	key_size = map->key_size;
+	if (!key)
+		goto find_first_elem;
+	hash = htab_map_hash(key, key_size);
+	h = select_bucket(htab, hash);
+
+	l = lookup_nulls_elem_raw(h, hash, key, key_size, htab->n_buckets);
+	if (!l)
+		goto find_first_elem;
+	next_l = hlist_nulls_entry_safe(
+		     rcu_dereference_raw(hlist_nulls_next_rcu(&l->hash_node)),
+		     struct htab_elem, hash_node);
+	if (next_l) {
+		memcpy(next_key, next_l->key, key_size);
+		return 0;
+	}
+
+	/* no more elements in this hash list, go to the next bucket */
+	i = hash & (htab->n_buckets - 1);
+	i++;
+
+find_first_elem:
+	/* iterate over buckets */
+	for (; i < htab->n_buckets; i++) {
+		h = select_bucket(htab, i);
+
+		/* pick first element in the bucket */
+		next_l = hlist_nulls_entry_safe(
+				rcu_dereference_raw(hlist_nulls_first_rcu(h)),
+				struct htab_elem, hash_node);
+		if (next_l) {
+			/* if it's not empty, just return it */
+			memcpy(next_key, next_l->key, key_size);
+			return 0;
+		}
+	}
+
+	/* iterated over all buckets and all elements */
+	return -ENOENT;
+}
+
+static int sock_hash_ctx_update_elem(struct bpf_sock_ops_kern *skops,
+				     struct bpf_map *map,
+				     void *key, u64 map_flags)
+{
+	struct bpf_htab *htab = container_of(map, struct bpf_htab, map);
+	struct bpf_sock_progs *progs = &htab->progs;
+	struct htab_elem *l_new = NULL, *l_old;
+	struct hlist_nulls_head *head;
+	struct smap_psock *psock;
+	u32 key_size, hash;
+	struct sock *sock;
+	struct bucket *b;
+	int err;
+
+	sock = skops->sk;
+
+	if (sock->sk_type != SOCK_STREAM ||
+	    sock->sk_protocol != IPPROTO_TCP)
+		return -EOPNOTSUPP;
+
+	if (unlikely(map_flags > BPF_EXIST))
+		return -EINVAL;
+
+	WARN_ON_ONCE(!rcu_read_lock_held());
+	key_size = map->key_size;
+	hash = htab_map_hash(key, key_size);
+	b = __select_bucket(htab, hash);
+	head = &b->head;
+
+	err = __sock_map_ctx_update_elem(map, progs, sock, NULL, NULL, key);
+	if (err)
+		goto err;
+
+	/* bpf_map_update_elem() can be called in_irq() */
+	raw_spin_lock_bh(&b->lock);
+	l_old = lookup_elem_raw(head, hash, key, key_size);
+	if (l_old && map_flags == BPF_NOEXIST) {
+		err = -EEXIST;
+		goto bucket_err;
+	}
+	if (!l_old && map_flags == BPF_EXIST) {
+		err = -ENOENT;
+		goto bucket_err;
+	}
+
+	l_new = alloc_sock_hash_elem(htab, key, key_size, hash, sock, l_old);
+	if (IS_ERR(l_new)) {
+		err = PTR_ERR(l_new);
+		goto bucket_err;
+	}
+
+	/* add new element to the head of the list, so that
+	 * concurrent search will find it before old elem
+	 */
+	hlist_nulls_add_head_rcu(&l_new->hash_node, head);
+	if (l_old) {
+		psock = smap_psock_sk(l_old->sk);
+
+		hlist_nulls_del_rcu(&l_old->hash_node);
+		smap_list_remove(psock, NULL, l_old);
+		smap_release_sock(psock, l_old->sk);
+		free_htab_elem(htab, l_old);
+	}
+	raw_spin_unlock_bh(&b->lock);
+	return 0;
+bucket_err:
+	raw_spin_unlock_bh(&b->lock);
+err:
+	psock = smap_psock_sk(sock);
+	if (psock)
+		smap_release_sock(psock, sock);
+	return err;
+}
+
+static int sock_hash_update_elem(struct bpf_map *map,
+				void *key, void *value, u64 flags)
+{
+	struct bpf_sock_ops_kern skops;
+	u32 fd = *(u32 *)value;
+	struct socket *socket;
+	int err;
+
+	socket = sockfd_lookup(fd, &err);
+	if (!socket)
+		return err;
+
+	skops.sk = socket->sk;
+	if (!skops.sk) {
+		fput(socket->file);
+		return -EINVAL;
+	}
+
+	err = sock_hash_ctx_update_elem(&skops, map, key, flags);
+	fput(socket->file);
+	return err;
+}
+
+static int sock_hash_delete_elem(struct bpf_map *map, void *key)
+{
+	struct bpf_htab *htab = container_of(map, struct bpf_htab, map);
+	struct hlist_nulls_head *head;
+	struct bucket *b;
+	struct htab_elem *l;
+	u32 hash, key_size;
+	int ret = -ENOENT;
+
+	key_size = map->key_size;
+	hash = htab_map_hash(key, key_size);
+	b = __select_bucket(htab, hash);
+	head = &b->head;
+
+	raw_spin_lock_bh(&b->lock);
+	l = lookup_elem_raw(head, hash, key, key_size);
+	if (l) {
+		struct sock *sock = l->sk;
+		struct smap_psock *psock;
+
+		hlist_nulls_del_rcu(&l->hash_node);
+		write_lock_bh(&sock->sk_callback_lock);
+		psock = smap_psock_sk(sock);
+		/* This check handles a racing sock event that can get the
+		 * sk_callback_lock before this case but after xchg happens
+		 * causing the refcnt to hit zero and sock user data (psock)
+		 * to be null and queued for garbage collection.
+		 */
+		if (likely(psock)) {
+			smap_list_remove(psock, NULL, l);
+			smap_release_sock(psock, sock);
+		}
+		write_unlock_bh(&sock->sk_callback_lock);
+		free_htab_elem(htab, l);
+		ret = 0;
+	}
+	raw_spin_unlock_bh(&b->lock);
+	return ret;
+}
+
+struct sock  *__sock_hash_lookup_elem(struct bpf_map *map, void *key)
+{
+	struct bpf_htab *htab = container_of(map, struct bpf_htab, map);
+	struct hlist_nulls_head *head;
+	struct htab_elem *l;
+	u32 key_size, hash;
+	struct bucket *b;
+	struct sock *sk;
+
+	key_size = map->key_size;
+	hash = htab_map_hash(key, key_size);
+	b = __select_bucket(htab, hash);
+	head = &b->head;
+
+	raw_spin_lock_bh(&b->lock);
+	l = lookup_elem_raw(head, hash, key, key_size);
+	sk = l ? l->sk : NULL;
+	raw_spin_unlock_bh(&b->lock);
+	return sk;
+}
+
 const struct bpf_map_ops sock_map_ops = {
 	.map_alloc = sock_map_alloc,
 	.map_free = sock_map_free,
@@ -1890,6 +2350,16 @@ static void sock_map_release(struct bpf_map *map, struct file *map_file)
 	.map_release = sock_map_release,
 };
 
+const struct bpf_map_ops sock_hash_ops = {
+	.map_alloc = sock_hash_alloc,
+	.map_free = sock_hash_free,
+	.map_lookup_elem = sock_map_lookup,
+	.map_get_next_key = sock_hash_get_next_key,
+	.map_update_elem = sock_hash_update_elem,
+	.map_delete_elem = sock_hash_delete_elem,
+	.map_release = sock_map_release,
+};
+
 BPF_CALL_4(bpf_sock_map_update, struct bpf_sock_ops_kern *, bpf_sock,
 	   struct bpf_map *, map, void *, key, u64, flags)
 {
@@ -1907,3 +2377,21 @@ static void sock_map_release(struct bpf_map *map, struct file *map_file)
 	.arg3_type	= ARG_PTR_TO_MAP_KEY,
 	.arg4_type	= ARG_ANYTHING,
 };
+
+BPF_CALL_4(bpf_sock_hash_update, struct bpf_sock_ops_kern *, bpf_sock,
+	   struct bpf_map *, map, void *, key, u64, flags)
+{
+	WARN_ON_ONCE(!rcu_read_lock_held());
+	return sock_hash_ctx_update_elem(bpf_sock, map, key, flags);
+}
+
+const struct bpf_func_proto bpf_sock_hash_update_proto = {
+	.func		= bpf_sock_hash_update,
+	.gpl_only	= false,
+	.pkt_access	= true,
+	.ret_type	= RET_INTEGER,
+	.arg1_type	= ARG_PTR_TO_CTX,
+	.arg2_type	= ARG_CONST_MAP_PTR,
+	.arg3_type	= ARG_PTR_TO_MAP_KEY,
+	.arg4_type	= ARG_ANYTHING,
+};
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 5dd1dcb..878cca6 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -2088,6 +2088,13 @@ static int check_map_func_compatibility(struct bpf_verifier_env *env,
 		    func_id != BPF_FUNC_msg_redirect_map)
 			goto error;
 		break;
+	case BPF_MAP_TYPE_SOCKHASH:
+		if (func_id != BPF_FUNC_sk_redirect_hash &&
+		    func_id != BPF_FUNC_sock_hash_update &&
+		    func_id != BPF_FUNC_map_delete_elem &&
+		    func_id != BPF_FUNC_msg_redirect_hash)
+			goto error;
+		break;
 	default:
 		break;
 	}
@@ -2124,11 +2131,14 @@ static int check_map_func_compatibility(struct bpf_verifier_env *env,
 		break;
 	case BPF_FUNC_sk_redirect_map:
 	case BPF_FUNC_msg_redirect_map:
+	case BPF_FUNC_sock_map_update:
 		if (map->map_type != BPF_MAP_TYPE_SOCKMAP)
 			goto error;
 		break;
-	case BPF_FUNC_sock_map_update:
-		if (map->map_type != BPF_MAP_TYPE_SOCKMAP)
+	case BPF_FUNC_sk_redirect_hash:
+	case BPF_FUNC_msg_redirect_hash:
+	case BPF_FUNC_sock_hash_update:
+		if (map->map_type != BPF_MAP_TYPE_SOCKHASH)
 			goto error;
 		break;
 	default:
diff --git a/net/core/filter.c b/net/core/filter.c
index 6456e9d..d629479 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -1850,6 +1850,31 @@ int skb_do_redirect(struct sk_buff *skb)
 	.arg2_type      = ARG_ANYTHING,
 };
 
+BPF_CALL_4(bpf_sk_redirect_hash, struct sk_buff *, skb,
+	   struct bpf_map *, map, void *, key, u64, flags)
+{
+	struct tcp_skb_cb *tcb = TCP_SKB_CB(skb);
+
+	/* If user passes invalid input drop the packet. */
+	if (unlikely(flags & ~(BPF_F_INGRESS)))
+		return SK_DROP;
+
+	tcb->bpf.flags = flags;
+	tcb->bpf.sk = __sock_hash_lookup_elem(map, key);
+
+	return SK_PASS;
+}
+
+static const struct bpf_func_proto bpf_sk_redirect_hash_proto = {
+	.func           = bpf_sk_redirect_hash,
+	.gpl_only       = false,
+	.ret_type       = RET_INTEGER,
+	.arg1_type	= ARG_PTR_TO_CTX,
+	.arg2_type      = ARG_CONST_MAP_PTR,
+	.arg3_type      = ARG_PTR_TO_MAP_KEY,
+	.arg4_type      = ARG_ANYTHING,
+};
+
 BPF_CALL_4(bpf_sk_redirect_map, struct sk_buff *, skb,
 	   struct bpf_map *, map, u32, key, u64, flags)
 {
@@ -1882,6 +1907,29 @@ struct sock *do_sk_redirect_map(struct sk_buff *skb)
 	.arg4_type      = ARG_ANYTHING,
 };
 
+BPF_CALL_4(bpf_msg_redirect_hash, struct sk_msg_buff *, msg,
+	   struct bpf_map *, map, void *, key, u64, flags)
+{
+	/* If user passes invalid input drop the packet. */
+	if (unlikely(flags & ~(BPF_F_INGRESS)))
+		return SK_DROP;
+
+	msg->flags = flags;
+	msg->sk = __sock_hash_lookup_elem(map, key);
+
+	return SK_PASS;
+}
+
+static const struct bpf_func_proto bpf_msg_redirect_hash_proto = {
+	.func           = bpf_msg_redirect_hash,
+	.gpl_only       = false,
+	.ret_type       = RET_INTEGER,
+	.arg1_type	= ARG_PTR_TO_CTX,
+	.arg2_type      = ARG_CONST_MAP_PTR,
+	.arg3_type      = ARG_PTR_TO_MAP_KEY,
+	.arg4_type      = ARG_ANYTHING,
+};
+
 BPF_CALL_4(bpf_msg_redirect_map, struct sk_msg_buff *, msg,
 	   struct bpf_map *, map, u32, key, u64, flags)
 {
@@ -3892,6 +3940,8 @@ static unsigned long bpf_xdp_copy(void *dst_buff, const void *src_buff,
 		return &bpf_sock_ops_cb_flags_set_proto;
 	case BPF_FUNC_sock_map_update:
 		return &bpf_sock_map_update_proto;
+	case BPF_FUNC_sock_hash_update:
+		return &bpf_sock_hash_update_proto;
 	default:
 		return bpf_base_func_proto(func_id);
 	}
@@ -3903,6 +3953,8 @@ static unsigned long bpf_xdp_copy(void *dst_buff, const void *src_buff,
 	switch (func_id) {
 	case BPF_FUNC_msg_redirect_map:
 		return &bpf_msg_redirect_map_proto;
+	case BPF_FUNC_msg_redirect_hash:
+		return &bpf_msg_redirect_hash_proto;
 	case BPF_FUNC_msg_apply_bytes:
 		return &bpf_msg_apply_bytes_proto;
 	case BPF_FUNC_msg_cork_bytes:
@@ -3934,6 +3986,8 @@ static unsigned long bpf_xdp_copy(void *dst_buff, const void *src_buff,
 		return &bpf_get_socket_uid_proto;
 	case BPF_FUNC_sk_redirect_map:
 		return &bpf_sk_redirect_map_proto;
+	case BPF_FUNC_sk_redirect_hash:
+		return &bpf_sk_redirect_hash_proto;
 	default:
 		return bpf_base_func_proto(func_id);
 	}
diff --git a/tools/bpf/bpftool/map.c b/tools/bpf/bpftool/map.c
index f95fa67..2fa4cbb 100644
--- a/tools/bpf/bpftool/map.c
+++ b/tools/bpf/bpftool/map.c
@@ -67,6 +67,7 @@
 	[BPF_MAP_TYPE_DEVMAP]		= "devmap",
 	[BPF_MAP_TYPE_SOCKMAP]		= "sockmap",
 	[BPF_MAP_TYPE_CPUMAP]		= "cpumap",
+	[BPF_MAP_TYPE_SOCKHASH]		= "sockhash",
 };
 
 static unsigned int get_possible_cpus(void)
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index 9d07465..1a19450 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -115,6 +115,7 @@ enum bpf_map_type {
 	BPF_MAP_TYPE_DEVMAP,
 	BPF_MAP_TYPE_SOCKMAP,
 	BPF_MAP_TYPE_CPUMAP,
+	BPF_MAP_TYPE_SOCKHASH,
 };
 
 enum bpf_prog_type {
@@ -821,7 +822,10 @@ struct bpf_stack_build_id {
 	FN(msg_apply_bytes),		\
 	FN(msg_cork_bytes),		\
 	FN(msg_pull_data),		\
-	FN(bind),
+	FN(bind),			\
+	FN(sock_hash_update),		\
+	FN(msg_redirect_hash),		\
+	FN(sk_redirect_hash),
 
 /* integer value in 'imm' field of BPF_CALL instruction selects which helper
  * function eBPF program intends to call
diff --git a/tools/testing/selftests/bpf/bpf_helpers.h b/tools/testing/selftests/bpf/bpf_helpers.h
index d8223d9..fc6cf08 100644
--- a/tools/testing/selftests/bpf/bpf_helpers.h
+++ b/tools/testing/selftests/bpf/bpf_helpers.h
@@ -73,7 +73,7 @@ static int (*bpf_getsockopt)(void *ctx, int level, int optname, void *optval,
 	(void *) BPF_FUNC_getsockopt;
 static int (*bpf_sock_ops_cb_flags_set)(void *ctx, int flags) =
 	(void *) BPF_FUNC_sock_ops_cb_flags_set;
-static int (*bpf_sk_redirect_map)(void *ctx, void *map, int key, int flags) =
+static int (*bpf_sk_redirect_map)(void *ctx, void *map, void *key, int flags) =
 	(void *) BPF_FUNC_sk_redirect_map;
 static int (*bpf_sock_map_update)(void *map, void *key, void *value,
 				  unsigned long long flags) =
@@ -86,7 +86,7 @@ static int (*bpf_perf_prog_read_value)(void *ctx, void *buf,
 	(void *) BPF_FUNC_perf_prog_read_value;
 static int (*bpf_override_return)(void *ctx, unsigned long rc) =
 	(void *) BPF_FUNC_override_return;
-static int (*bpf_msg_redirect_map)(void *ctx, void *map, int key, int flags) =
+static int (*bpf_msg_redirect_map)(void *ctx, void *map, void *key, int flags) =
 	(void *) BPF_FUNC_msg_redirect_map;
 static int (*bpf_msg_apply_bytes)(void *ctx, int len) =
 	(void *) BPF_FUNC_msg_apply_bytes;
@@ -96,6 +96,15 @@ static int (*bpf_msg_pull_data)(void *ctx, int start, int end, int flags) =
 	(void *) BPF_FUNC_msg_pull_data;
 static int (*bpf_bind)(void *ctx, void *addr, int addr_len) =
 	(void *) BPF_FUNC_bind;
+static int (*bpf_sock_hash_update)(void *map, void *key, void *value,
+				   unsigned long long flags) =
+	(void *) BPF_FUNC_sock_hash_update;
+static int (*bpf_msg_redirect_hash)(void *map, void *key, void *value,
+				    unsigned long long flags) =
+	(void *) BPF_FUNC_msg_redirect_hash;
+static int (*bpf_sk_redirect_hash)(void *map, void *key, void *value,
+				    unsigned long long flags) =
+	(void *) BPF_FUNC_sk_redirect_hash;
 
 /* llvm builtin functions that eBPF C program may use to
  * emit BPF_LD_ABS and BPF_LD_IND instructions

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox