* Re: [PATCH net V3] net: reevalulate autoflowlabel setting after sysctl setting
From: David Miller @ 2017-12-21 18:07 UTC (permalink / raw)
To: shli; +Cc: netdev, Kernel-team, shli, kafai, eric.dumazet, tom
In-Reply-To: <321216a522a3b46e77125a5b9df41c2b64821cf3.1513799711.git.shli@fb.com>
From: Shaohua Li <shli@kernel.org>
Date: Wed, 20 Dec 2017 12:10:21 -0800
> From: Shaohua Li <shli@fb.com>
>
> sysctl.ip6.auto_flowlabels is default 1. In our hosts, we set it to 2.
> If sockopt doesn't set autoflowlabel, outcome packets from the hosts are
> supposed to not include flowlabel. This is true for normal packet, but
> not for reset packet.
>
> The reason is ipv6_pinfo.autoflowlabel is set in sock creation. Later if
> we change sysctl.ip6.auto_flowlabels, the ipv6_pinfo.autoflowlabel isn't
> changed, so the sock will keep the old behavior in terms of auto
> flowlabel. Reset packet is suffering from this problem, because reset
> packet is sent from a special control socket, which is created at boot
> time. Since sysctl.ipv6.auto_flowlabels is 1 by default, the control
> socket will always have its ipv6_pinfo.autoflowlabel set, even after
> user set sysctl.ipv6.auto_flowlabels to 1, so reset packset will always
> have flowlabel. Normal sock created before sysctl setting suffers from
> the same issue. We can't even turn off autoflowlabel unless we kill all
> socks in the hosts.
>
> To fix this, if IPV6_AUTOFLOWLABEL sockopt is used, we use the
> autoflowlabel setting from user, otherwise we always call
> ip6_default_np_autolabel() which has the new settings of sysctl.
>
> Note, this changes behavior a little bit. Before commit 42240901f7c4
> (ipv6: Implement different admin modes for automatic flow labels), the
> autoflowlabel behavior of a sock isn't sticky, eg, if sysctl changes,
> existing connection will change autoflowlabel behavior. After that
> commit, autoflowlabel behavior is sticky in the whole life of the sock.
> With this patch, the behavior isn't sticky again.
>
> Cc: Martin KaFai Lau <kafai@fb.com>
> Cc: Eric Dumazet <eric.dumazet@gmail.com>
> Cc: Tom Herbert <tom@quantonium.net>
> Signed-off-by: Shaohua Li <shli@fb.com>
This looks a lot better, applied, thanks.
^ permalink raw reply
* Re: [PATCH v3 next-queue 00/10] ixgbe: Add ipsec offload
From: Shannon Nelson @ 2017-12-21 17:55 UTC (permalink / raw)
To: Yanjun Zhu, intel-wired-lan, jeffrey.t.kirsher
Cc: steffen.klassert, sowmini.varadhan, netdev
In-Reply-To: <e253e271-eda9-8707-af57-3a5cf33cb097@oracle.com>
On 12/20/2017 11:09 PM, Yanjun Zhu wrote:
> On 2017/12/21 14:39, Yanjun Zhu wrote:
>> On 2017/12/20 7:59, Shannon Nelson wrote:
>>> This is an implementation of the ipsec hardware offload feature for
>>> the ixgbe driver and Intel's 10Gbe series NICs: x540, x550, 82599.
>> Hi, Nelson
>>
>> I notice that the ipsec feature is based on x540, x550, 82599. But
>> this ixgbe driver
>> will also work with 82598.
>>
>> Does this ipsec feature also work with 82598?
> Sorry. I mean, after these ipsec patches are applied, whether ipsec
> offload enabled or not,
> can this ixgbe driver still work well with 82598?
Hmm... I don't have one to test on, but I suspect the 82598 might not be
happy with this. I'll send a followup patch to catch this case.
Thanks!
sln
>
> Zhu Yanjun
>>
>> Thanks a lot.
>> Zhu Yanjun
>>> These patches apply to net-next v4.14 as well as Jeff Kirsher's
>>> next-queue
>>> v4.15-rc1-206-ge47375b.
>>>
>>> The ixgbe NICs support ipsec offload for 1024 Rx and 1024 Tx Security
>>> Associations (SAs), using up to 128 inbound IP addresses, and using the
>>> rfc4106(gcm(aes)) encryption. This code does not yet support IPv6,
>>> checksum offload, or TSO in conjunction with the ipsec offload - those
>>> will be added in the future.
>>>
>>> This code shows improvements in both packet throughput and CPU
>>> utilization.
>>> For example, here are some quicky numbers that show the magnitude of the
>>> performance gain on a single run of "iperf -c <dest>" with the ipsec
>>> offload on both ends of a point-to-point connection:
>>>
>>> 9.4 Gbps - normal case
>>> 7.6 Gbps - ipsec with offload
>>> 343 Mbps - ipsec no offload
>>>
>>> To set up a similar test case, you first need to be sure you have a
>>> recent
>>> version of iproute2 that supports the ipsec offload tag, probably
>>> something
>>> from ip 4.12 or newer would be best. I have a shell script that builds
>>> up the appropriate commands for me, but here are the resulting commands
>>> for all tcp traffic between 14.0.0.52 and 14.0.0.70:
>>>
>>> For the left side (14.0.0.52):
>>> ip x p add dir out src 14.0.0.52/24 dst 14.0.0.70/24 proto tcp tmpl \
>>> proto esp src 14.0.0.52 dst 14.0.0.70 spi 0x07 mode transport
>>> reqid 0x07
>>> ip x p add dir in src 14.0.0.70/24 dst 14.0.0.52/24 proto tcp tmpl \
>>> proto esp dst 14.0.0.52 src 14.0.0.70 spi 0x07 mode transport
>>> reqid 0x07
>>> ip x s add proto esp src 14.0.0.52 dst 14.0.0.70 spi 0x07 mode
>>> transport \
>>> reqid 0x07 replay-window 32 \
>>> aead 'rfc4106(gcm(aes))'
>>> 0x44434241343332312423222114131211f4f3f2f1 128 \
>>> sel src 14.0.0.52/24 dst 14.0.0.70/24 proto tcp offload dev
>>> eth4 dir out
>>> ip x s add proto esp dst 14.0.0.52 src 14.0.0.70 spi 0x07 mode
>>> transport \
>>> reqid 0x07 replay-window 32 \
>>> aead 'rfc4106(gcm(aes))'
>>> 0x44434241343332312423222114131211f4f3f2f1 128 \
>>> sel src 14.0.0.70/24 dst 14.0.0.52/24 proto tcp offload dev
>>> eth4 dir in
>>> For the right side (14.0.0.70):
>>> ip x p add dir out src 14.0.0.70/24 dst 14.0.0.52/24 proto tcp tmpl \
>>> proto esp src 14.0.0.70 dst 14.0.0.52 spi 0x07 mode transport
>>> reqid 0x07
>>> ip x p add dir in src 14.0.0.52/24 dst 14.0.0.70/24 proto tcp tmpl \
>>> proto esp dst 14.0.0.70 src 14.0.0.52 spi 0x07 mode transport
>>> reqid 0x07
>>> ip x s add proto esp src 14.0.0.70 dst 14.0.0.52 spi 0x07 mode
>>> transport \
>>> reqid 0x07 replay-window 32 \
>>> aead 'rfc4106(gcm(aes))'
>>> 0x44434241343332312423222114131211f4f3f2f1 128 \
>>> sel src 14.0.0.70/24 dst 14.0.0.52/24 proto tcp offload dev
>>> eth4 dir out
>>> ip x s add proto esp dst 14.0.0.70 src 14.0.0.52 spi 0x07 mode
>>> transport \
>>> reqid 0x07 replay-window 32 \
>>> aead 'rfc4106(gcm(aes))'
>>> 0x44434241343332312423222114131211f4f3f2f1 128 \
>>> sel src 14.0.0.52/24 dst 14.0.0.70/24 proto tcp offload dev
>>> eth4 dir in
>>>
>>> In both cases, the command "ip x s flush ; ip x p flush" will clean
>>> it all out and remove the offloads.
>>>
>>> Lastly, thanks to Alex Duyck for his early comments.
>>>
>>> Please see the individual patches for specific update info.
>>>
>>> v3: fixes after comments from those wonderfully pesky kbuild robots
>>> v2: fixes after comments from Alex
>>>
>>> Shannon Nelson (10):
>>> ixgbe: clean up ipsec defines
>>> ixgbe: add ipsec register access routines
>>> ixgbe: add ipsec engine start and stop routines
>>> ixgbe: add ipsec data structures
>>> ixgbe: add ipsec offload add and remove SA
>>> ixgbe: restore offloaded SAs after a reset
>>> ixgbe: process the Rx ipsec offload
>>> ixgbe: process the Tx ipsec offload
>>> ixgbe: ipsec offload stats
>>> ixgbe: register ipsec offload with the xfrm subsystem
>>>
>>> drivers/net/ethernet/intel/ixgbe/Makefile | 1 +
>>> drivers/net/ethernet/intel/ixgbe/ixgbe.h | 33 +-
>>> drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c | 2 +
>>> drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c | 923
>>> +++++++++++++++++++++++
>>> drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.h | 92 +++
>>> drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c | 4 +-
>>> drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 39 +-
>>> drivers/net/ethernet/intel/ixgbe/ixgbe_type.h | 22 +-
>>> 8 files changed, 1093 insertions(+), 23 deletions(-)
>>> create mode 100644 drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
>>> create mode 100644 drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.h
>>>
>>
>>
>
^ permalink raw reply
* Re: [PATCH v3 1/3] net: ibm: emac: replace custom rgmii_mode_name with phy_modes
From: David Miller @ 2017-12-21 18:10 UTC (permalink / raw)
To: chunkeey; +Cc: netdev, andrew, christophe.jaillet
In-Reply-To: <a9482f4f4037f6eb732de327290a432539648bcd.1513806256.git.chunkeey@gmail.com>
From: Christian Lamparter <chunkeey@gmail.com>
Date: Wed, 20 Dec 2017 23:01:48 +0100
> phy_modes() in the common phy.h already defines the same phy mode
> names in lower case. The deleted rgmii_mode_name() is used only
> in one place and for a "notice-level" printk. Hence, it will not
> be missed.
>
> Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
Applied to net-next.
^ permalink raw reply
* Re: [PATCH v3 2/3] net: ibm: emac: replace custom PHY_MODE_* macros
From: David Miller @ 2017-12-21 18:10 UTC (permalink / raw)
To: chunkeey; +Cc: netdev, andrew, christophe.jaillet
In-Reply-To: <2cb74d50c22d01873d1d976ec384917dc799be08.1513806256.git.chunkeey@gmail.com>
From: Christian Lamparter <chunkeey@gmail.com>
Date: Wed, 20 Dec 2017 23:01:49 +0100
> The ibm_emac driver predates the PHY_INTERFACE_MODE_*
> enums by a few years.
>
> And while the driver has been retrofitted to use the PHYLIB,
> the old definitions have stuck around to this day.
>
> This patch replaces all occurences of PHY_MODE_* with
> the respective equivalent PHY_INTERFACE_MODE_* enum.
> And finally, it purges the old macros for good.
>
> Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
Applied to net-next.
^ permalink raw reply
* Re: [PATCH v3 3/3] net: ibm: emac: support RGMII-[RX|TX]ID phymode
From: David Miller @ 2017-12-21 18:10 UTC (permalink / raw)
To: chunkeey; +Cc: netdev, andrew, christophe.jaillet
In-Reply-To: <de458d66be6e804a45e1bd96e57aa5907bb98e03.1513806256.git.chunkeey@gmail.com>
From: Christian Lamparter <chunkeey@gmail.com>
Date: Wed, 20 Dec 2017 23:01:50 +0100
> The RGMII spec allows compliance for devices that implement an internal
> delay on TXC and/or RXC inside the transmitter. This patch adds the
> necessary RGMII_[RX|TX]ID mode code to handle such PHYs with the
> emac driver.
>
> Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
Applied to net-next.
^ permalink raw reply
* [PATCH next-queue] ixgbe: no ipsec offload for 82598
From: Shannon Nelson @ 2017-12-21 18:21 UTC (permalink / raw)
To: intel-wired-lan, jeffrey.t.kirsher; +Cc: steffen.klassert, netdev
Don't try to set up ipsec offload on the oldest part of
the ixgbe family.
Suggested-by: Yanjun Zhu <yanjun.zhu@oracle.com>
Signed-off-by: Shannon Nelson <shannon.nelson@oracle.com>
---
drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
index 424dbf7..12c7132 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
@@ -863,6 +863,9 @@ void ixgbe_init_ipsec_offload(struct ixgbe_adapter *adapter)
struct ixgbe_ipsec *ipsec;
size_t size;
+ if (adapter->hw.mac.type == ixgbe_mac_82598EB)
+ return;
+
ipsec = kzalloc(sizeof(*ipsec), GFP_KERNEL);
if (!ipsec)
goto err1;
--
2.7.4
^ permalink raw reply related
* [PATCH net-next] tcp: md5: Handle RCU dereference of md5sig_info
From: Mat Martineau @ 2017-12-21 18:29 UTC (permalink / raw)
To: netdev; +Cc: Mat Martineau
In-Reply-To: <20171221182910.4785-1-mathew.j.martineau@linux.intel.com>
Dereference tp->md5sig_info in tcp_v4_destroy_sock() the same way it is
done in the adjacent call to tcp_clear_md5_list().
Resolves this sparse warning:
net/ipv4/tcp_ipv4.c:1914:17: warning: incorrect type in argument 1 (different address spaces)
net/ipv4/tcp_ipv4.c:1914:17: expected struct callback_head *head
net/ipv4/tcp_ipv4.c:1914:17: got struct callback_head [noderef] <asn:4>*<noident>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
---
net/ipv4/tcp_ipv4.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index dd945b114215..5d203248123e 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1911,7 +1911,7 @@ void tcp_v4_destroy_sock(struct sock *sk)
/* Clean up the MD5 key list, if any */
if (tp->md5sig_info) {
tcp_clear_md5_list(sk);
- kfree_rcu(tp->md5sig_info, rcu);
+ kfree_rcu(rcu_dereference_protected(tp->md5sig_info, 1), rcu);
tp->md5sig_info = NULL;
}
#endif
--
2.15.1
^ permalink raw reply related
* [PATCH net] tcp: Avoid preprocessor directives in tracepoint macro args
From: Mat Martineau @ 2017-12-21 18:29 UTC (permalink / raw)
To: netdev; +Cc: Mat Martineau, David Ahern
Using a preprocessor directive to check for CONFIG_IPV6 in the middle of
a DECLARE_EVENT_CLASS macro's arg list causes sparse to report a series
of errors:
./include/trace/events/tcp.h:68:1: error: directive in argument list
./include/trace/events/tcp.h:75:1: error: directive in argument list
./include/trace/events/tcp.h:144:1: error: directive in argument list
./include/trace/events/tcp.h:151:1: error: directive in argument list
./include/trace/events/tcp.h:216:1: error: directive in argument list
./include/trace/events/tcp.h:223:1: error: directive in argument list
./include/trace/events/tcp.h:274:1: error: directive in argument list
./include/trace/events/tcp.h:281:1: error: directive in argument list
Once sparse finds an error, it stops printing warnings for the file it
is checking. This masks any sparse warnings that would normally be
reported for the core TCP code.
Instead, handle the preprocessor conditionals in a couple of auxiliary
macros. This also has the benefit of reducing duplicate code.
Cc: David Ahern <dsahern@gmail.com>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
---
include/trace/events/tcp.h | 97 ++++++++++++++++++----------------------------
1 file changed, 37 insertions(+), 60 deletions(-)
diff --git a/include/trace/events/tcp.h b/include/trace/events/tcp.h
index 07cccca6cbf1..ab34c561f26b 100644
--- a/include/trace/events/tcp.h
+++ b/include/trace/events/tcp.h
@@ -25,6 +25,35 @@
tcp_state_name(TCP_CLOSING), \
tcp_state_name(TCP_NEW_SYN_RECV))
+#define TP_STORE_V4MAPPED(__entry, saddr, daddr) \
+ do { \
+ struct in6_addr *pin6; \
+ \
+ pin6 = (struct in6_addr *)__entry->saddr_v6; \
+ ipv6_addr_set_v4mapped(saddr, pin6); \
+ pin6 = (struct in6_addr *)__entry->daddr_v6; \
+ ipv6_addr_set_v4mapped(daddr, pin6); \
+ } while (0)
+
+#if IS_ENABLED(CONFIG_IPV6)
+#define TP_STORE_ADDRS(__entry, saddr, daddr, saddr6, daddr6) \
+ do { \
+ if (sk->sk_family == AF_INET6) { \
+ struct in6_addr *pin6; \
+ \
+ pin6 = (struct in6_addr *)__entry->saddr_v6; \
+ *pin6 = saddr6; \
+ pin6 = (struct in6_addr *)__entry->daddr_v6; \
+ *pin6 = daddr6; \
+ } else { \
+ TP_STORE_V4MAPPED(__entry, saddr, daddr); \
+ } \
+ } while (0)
+#else
+#define TP_STORE_ADDRS(__entry, saddr, daddr, saddr6, daddr6) \
+ TP_STORE_V4MAPPED(__entry, saddr, daddr)
+#endif
+
/*
* tcp event with arguments sk and skb
*
@@ -50,7 +79,6 @@ DECLARE_EVENT_CLASS(tcp_event_sk_skb,
TP_fast_assign(
struct inet_sock *inet = inet_sk(sk);
- struct in6_addr *pin6;
__be32 *p32;
__entry->skbaddr = skb;
@@ -65,20 +93,8 @@ DECLARE_EVENT_CLASS(tcp_event_sk_skb,
p32 = (__be32 *) __entry->daddr;
*p32 = inet->inet_daddr;
-#if IS_ENABLED(CONFIG_IPV6)
- if (sk->sk_family == AF_INET6) {
- pin6 = (struct in6_addr *)__entry->saddr_v6;
- *pin6 = sk->sk_v6_rcv_saddr;
- pin6 = (struct in6_addr *)__entry->daddr_v6;
- *pin6 = sk->sk_v6_daddr;
- } else
-#endif
- {
- pin6 = (struct in6_addr *)__entry->saddr_v6;
- ipv6_addr_set_v4mapped(inet->inet_saddr, pin6);
- pin6 = (struct in6_addr *)__entry->daddr_v6;
- ipv6_addr_set_v4mapped(inet->inet_daddr, pin6);
- }
+ TP_STORE_ADDRS(__entry, inet->inet_saddr, inet->inet_daddr,
+ sk->sk_v6_rcv_saddr, sk->sk_v6_daddr);
),
TP_printk("sport=%hu dport=%hu saddr=%pI4 daddr=%pI4 saddrv6=%pI6c daddrv6=%pI6c",
@@ -127,7 +143,6 @@ DECLARE_EVENT_CLASS(tcp_event_sk,
TP_fast_assign(
struct inet_sock *inet = inet_sk(sk);
- struct in6_addr *pin6;
__be32 *p32;
__entry->skaddr = sk;
@@ -141,20 +156,8 @@ DECLARE_EVENT_CLASS(tcp_event_sk,
p32 = (__be32 *) __entry->daddr;
*p32 = inet->inet_daddr;
-#if IS_ENABLED(CONFIG_IPV6)
- if (sk->sk_family == AF_INET6) {
- pin6 = (struct in6_addr *)__entry->saddr_v6;
- *pin6 = sk->sk_v6_rcv_saddr;
- pin6 = (struct in6_addr *)__entry->daddr_v6;
- *pin6 = sk->sk_v6_daddr;
- } else
-#endif
- {
- pin6 = (struct in6_addr *)__entry->saddr_v6;
- ipv6_addr_set_v4mapped(inet->inet_saddr, pin6);
- pin6 = (struct in6_addr *)__entry->daddr_v6;
- ipv6_addr_set_v4mapped(inet->inet_daddr, pin6);
- }
+ TP_STORE_ADDRS(__entry, inet->inet_saddr, inet->inet_daddr,
+ sk->sk_v6_rcv_saddr, sk->sk_v6_daddr);
),
TP_printk("sport=%hu dport=%hu saddr=%pI4 daddr=%pI4 saddrv6=%pI6c daddrv6=%pI6c",
@@ -197,7 +200,6 @@ TRACE_EVENT(tcp_set_state,
TP_fast_assign(
struct inet_sock *inet = inet_sk(sk);
- struct in6_addr *pin6;
__be32 *p32;
__entry->skaddr = sk;
@@ -213,20 +215,8 @@ TRACE_EVENT(tcp_set_state,
p32 = (__be32 *) __entry->daddr;
*p32 = inet->inet_daddr;
-#if IS_ENABLED(CONFIG_IPV6)
- if (sk->sk_family == AF_INET6) {
- pin6 = (struct in6_addr *)__entry->saddr_v6;
- *pin6 = sk->sk_v6_rcv_saddr;
- pin6 = (struct in6_addr *)__entry->daddr_v6;
- *pin6 = sk->sk_v6_daddr;
- } else
-#endif
- {
- pin6 = (struct in6_addr *)__entry->saddr_v6;
- ipv6_addr_set_v4mapped(inet->inet_saddr, pin6);
- pin6 = (struct in6_addr *)__entry->daddr_v6;
- ipv6_addr_set_v4mapped(inet->inet_daddr, pin6);
- }
+ TP_STORE_ADDRS(__entry, inet->inet_saddr, inet->inet_daddr,
+ sk->sk_v6_rcv_saddr, sk->sk_v6_daddr);
),
TP_printk("sport=%hu dport=%hu saddr=%pI4 daddr=%pI4 saddrv6=%pI6c daddrv6=%pI6c oldstate=%s newstate=%s",
@@ -256,7 +246,6 @@ TRACE_EVENT(tcp_retransmit_synack,
TP_fast_assign(
struct inet_request_sock *ireq = inet_rsk(req);
- struct in6_addr *pin6;
__be32 *p32;
__entry->skaddr = sk;
@@ -271,20 +260,8 @@ TRACE_EVENT(tcp_retransmit_synack,
p32 = (__be32 *) __entry->daddr;
*p32 = ireq->ir_rmt_addr;
-#if IS_ENABLED(CONFIG_IPV6)
- if (sk->sk_family == AF_INET6) {
- pin6 = (struct in6_addr *)__entry->saddr_v6;
- *pin6 = ireq->ir_v6_loc_addr;
- pin6 = (struct in6_addr *)__entry->daddr_v6;
- *pin6 = ireq->ir_v6_rmt_addr;
- } else
-#endif
- {
- pin6 = (struct in6_addr *)__entry->saddr_v6;
- ipv6_addr_set_v4mapped(ireq->ir_loc_addr, pin6);
- pin6 = (struct in6_addr *)__entry->daddr_v6;
- ipv6_addr_set_v4mapped(ireq->ir_rmt_addr, pin6);
- }
+ TP_STORE_ADDRS(__entry, ireq->ir_loc_addr, ireq->ir_rmt_addr,
+ ireq->ir_v6_loc_addr, ireq->ir_v6_rmt_addr);
),
TP_printk("sport=%hu dport=%hu saddr=%pI4 daddr=%pI4 saddrv6=%pI6c daddrv6=%pI6c",
--
2.15.1
^ permalink raw reply related
* Re: [Patch net] net_sched: fix a missing rcu barrier in mini_qdisc_pair_swap()
From: Cong Wang @ 2017-12-21 19:01 UTC (permalink / raw)
To: Jiri Pirko; +Cc: Linux Kernel Network Developers, Jiri Pirko, John Fastabend
In-Reply-To: <20171221090313.GB1930@nanopsycho>
On Thu, Dec 21, 2017 at 1:03 AM, Jiri Pirko <jiri@resnulli.us> wrote:
> Thu, Dec 21, 2017 at 08:26:24AM CET, xiyou.wangcong@gmail.com wrote:
>>The rcu_barrier_bh() in mini_qdisc_pair_swap() is to wait for
>>flying RCU callback installed by a previous mini_qdisc_pair_swap(),
>>however we miss it on the tp_head==NULL path, which leads to that
>>the RCU callback still uses miniq_old->rcu after it is freed together
>>with qdisc in qdisc_graft(). So just add it on that path too.
>>
>>Fixes: 46209401f8f6 ("net: core: introduce mini_Qdisc and eliminate usage of tp->q for clsact fastpath ")
>
> This fixes:
> 752fbcc33405 ("net_sched: no need to free qdisc in RCU callback")
>
> Before that, the issue was not there as the qdisc struct got removed
> after a grace period.
This is non-sense. You have to read the stack trace from Jakub again
and tell me why you keep believing any RCU reader involved.
I am pretty sure no one reported any crash between commit
752fbcc33405 and 46209401f8f6.
>
>
>>Reported-by: Jakub Kicinski <jakub.kicinski@netronome.com>
>>Tested-by: Jakub Kicinski <jakub.kicinski@netronome.com>
>>Cc: Jiri Pirko <jiri@mellanox.com>
>>Cc: John Fastabend <john.fastabend@gmail.com>
>>Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
>>---
>> net/sched/sch_generic.c | 4 +++-
>> 1 file changed, 3 insertions(+), 1 deletion(-)
>>
>>diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
>>index cd1b200acae7..661c7144b53a 100644
>>--- a/net/sched/sch_generic.c
>>+++ b/net/sched/sch_generic.c
>>@@ -1040,6 +1040,8 @@ void mini_qdisc_pair_swap(struct mini_Qdisc_pair *miniqp,
>>
>> if (!tp_head) {
>> RCU_INIT_POINTER(*miniqp->p_miniq, NULL);
>>+ /* Wait for flying RCU callback before it is freed. */
>>+ rcu_barrier_bh();
>
>
>> return;
>> }
>>
>>@@ -1055,7 +1057,7 @@ void mini_qdisc_pair_swap(struct mini_Qdisc_pair *miniqp,
>> rcu_assign_pointer(*miniqp->p_miniq, miniq);
>>
>> if (miniq_old)
>>- /* This is counterpart of the rcu barrier above. We need to
>>+ /* This is counterpart of the rcu barriers above. We need to
>
> This is incorrect. Here we block in order to not use the same miniq
> again in scenario
>
> miniq1 (X)
> miniq2
> miniq1 (yet there are reader using X)
>
> This call_rcu has 0 relation to the barrier you are adding.
Seriously? It is this call_rcu still flying after we free the qdisc.
Did you seriously look into the stack trace from Jakub?
>
>
> But again, we don't we just free qdisc in call_rcu and avoid the
> barrier?
Non-sense again. Why qdisc code should be adjusted for your
miniq code? It is your own responsibility to take care of this shit.
Don't spread it out of minq.
^ permalink raw reply
* Re: [net-next: PATCH 0/8] Armada 7k/8k PP2 ACPI support
From: Antoine Tenart @ 2017-12-21 19:21 UTC (permalink / raw)
To: Marcin Wojtas
Cc: linux-kernel, linux-arm-kernel, netdev, davem, linux,
rafael.j.wysocki, andrew, f.fainelli, antoine.tenart,
thomas.petazzoni, gregory.clement, ezequiel.garcia, nadavh, neta,
ard.biesheuvel, jaz, tn
In-Reply-To: <1513588684-15647-1-git-send-email-mw@semihalf.com>
Hi Marcin,
On Mon, Dec 18, 2017 at 10:17:56AM +0100, Marcin Wojtas wrote:
>
> Marcin Wojtas (8):
> device property: Introduce fwnode_get_mac_address()
> device property: Introduce fwnode_get_phy_mode()
> mdio_bus: Introduce fwnode MDIO helpers
> net: mvmdio: add ACPI support
> net: mvpp2: simplify maintaining enabled ports' list
> net: mvpp2: use device_*/fwnode_* APIs instead of of_*
> net: mvpp2: handle PHY with its fwnode
> net: mvpp2: enable ACPI support in the driver
I tested your series on a mcbin, using the dt way. It still worked. If
it is relevant, you can add on the mvpp2 related patches:
Tested-by: Antoine Tenart <antoine.tenart@free-electrons.com>
Thanks!
Antoine
--
Antoine Ténart, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
^ permalink raw reply
* [PATCH v5 net-next 0/7] net: ILA notification mechanism and fixes
From: Tom Herbert @ 2017-12-21 19:33 UTC (permalink / raw)
To: davem; +Cc: netdev, roopa, rohit, Tom Herbert
This patch set adds support to get netlink notifications for ILA
routes when a route is used.
This patch set contains:
- General infrastructure for route notifications
- The ILA route notification mechanism
- Add net to ila build_state
- Add flush command to ila_xlat
- Fix use of rhashtable for latest fixes
Route notifications will be used in conjunction with populating
ILA forwarding caches. There are three methods described in
the ILA Mapping Protocol. These are redirects, request/reply,
and push. The ILA route mechanism is relevant to the first two methods.
- ILA router secure redirect mechanism-- This is used on an ILA
router where a notification is sent when an ILA host route is
used. The purpose of this notification is to send an
ILA redirect towards the ILA forwarding node of a source to
inform it of a direct ILA route. When the forwarding node
receives the redirect it can populate its cache so that
subsequent packets take the direct path. This is the
RECOMMENDED method.
- Cache address resolution-- This used to perform request/reply
address resolution on a route. As noted on netdev list, a
request/reply mechanism is susceptible to DOS attacks.
For this reason, this method is not NOT RECOMMENDED as the
primary means to populate an ILA cache.
ILAMP is described in
https://www.ietf.org/internet-drafts/draft-herbert-ila-ilamp-00.txt
Tested:
Ran ILA traffic, set up ILA notify routes and observed correct
routing message via ip monitor.
v5:
- Fix some compiler and sparse warnings
- Generalize route notify with RTM_NOTIFYROUTE,
RTNLGRP_ROUTE_NOTIFY (suggested by Roopa)
v4:
- Remove front end cache per davem feedback
- Eliminate separate LWT type just use ILA LWT already in place
v3:
- Removed rhashtable changes to their own patch set
- Restructure ILA code to be more amenable to changes
- Remove extra call back functions in resolution interface
Changes from initial RFC:
- Added net argument to LWT build_state
- Made resolve timeout an attribute of the LWT encap route
- Changed ILA notifications to be regular routing messages of event
RTM_ADDR_RESOLVE, family RTNL_FAMILY_ILA, and group
RTNLGRP_ILA_NOTIFY
Tom Herbert (7):
lwt: Add net to build_state argument
rtnetlink: Add notify route message types
ila: Fix use of rhashtable walk in ila_xlat.c
ila: Call library function alloc_bucket_locks
ila: Create main ila source file
ila: Flush netlink command to clear xlat table
ila: Route notify
include/net/lwtunnel.h | 6 +-
include/uapi/linux/ila.h | 3 +
include/uapi/linux/rtnetlink.h | 6 +
net/core/lwt_bpf.c | 2 +-
net/core/lwtunnel.c | 4 +-
net/ipv4/fib_semantics.c | 13 +-
net/ipv4/ip_tunnel_core.c | 4 +-
net/ipv6/ila/Makefile | 2 +-
net/ipv6/ila/ila.h | 27 +++-
net/ipv6/ila/ila_common.c | 30 -----
net/ipv6/ila/ila_lwt.c | 275 ++++++++++++++++++++++++++------------
net/ipv6/ila/ila_main.c | 121 +++++++++++++++++
net/ipv6/ila/ila_xlat.c | 290 ++++++++++++++++++++---------------------
net/ipv6/route.c | 2 +-
net/ipv6/seg6_iptunnel.c | 2 +-
net/ipv6/seg6_local.c | 5 +-
net/mpls/mpls_iptunnel.c | 2 +-
17 files changed, 511 insertions(+), 283 deletions(-)
create mode 100644 net/ipv6/ila/ila_main.c
--
2.11.0
^ permalink raw reply
* [PATCH v5 net-next 1/7] lwt: Add net to build_state argument
From: Tom Herbert @ 2017-12-21 19:33 UTC (permalink / raw)
To: davem; +Cc: netdev, roopa, rohit, Tom Herbert
In-Reply-To: <20171221193332.15303-1-tom@quantonium.net>
Users of LWT need to know net if they want to have per net operations
in LWT.
Acked-by: Roopa Prabhu <roopa@cumulusnetworks.com>
Signed-off-by: Tom Herbert <tom@quantonium.net>
---
include/net/lwtunnel.h | 6 +++---
net/core/lwt_bpf.c | 2 +-
net/core/lwtunnel.c | 4 ++--
net/ipv4/fib_semantics.c | 13 ++++++++-----
net/ipv4/ip_tunnel_core.c | 4 ++--
net/ipv6/ila/ila_lwt.c | 2 +-
net/ipv6/route.c | 2 +-
net/ipv6/seg6_iptunnel.c | 2 +-
net/ipv6/seg6_local.c | 5 +++--
net/mpls/mpls_iptunnel.c | 2 +-
10 files changed, 23 insertions(+), 19 deletions(-)
diff --git a/include/net/lwtunnel.h b/include/net/lwtunnel.h
index d747ef975cd8..da5e51e0d122 100644
--- a/include/net/lwtunnel.h
+++ b/include/net/lwtunnel.h
@@ -34,7 +34,7 @@ struct lwtunnel_state {
};
struct lwtunnel_encap_ops {
- int (*build_state)(struct nlattr *encap,
+ int (*build_state)(struct net *net, struct nlattr *encap,
unsigned int family, const void *cfg,
struct lwtunnel_state **ts,
struct netlink_ext_ack *extack);
@@ -113,7 +113,7 @@ int lwtunnel_valid_encap_type(u16 encap_type,
struct netlink_ext_ack *extack);
int lwtunnel_valid_encap_type_attr(struct nlattr *attr, int len,
struct netlink_ext_ack *extack);
-int lwtunnel_build_state(u16 encap_type,
+int lwtunnel_build_state(struct net *net, u16 encap_type,
struct nlattr *encap,
unsigned int family, const void *cfg,
struct lwtunnel_state **lws,
@@ -192,7 +192,7 @@ static inline int lwtunnel_valid_encap_type_attr(struct nlattr *attr, int len,
return 0;
}
-static inline int lwtunnel_build_state(u16 encap_type,
+static inline int lwtunnel_build_state(struct net *net, u16 encap_type,
struct nlattr *encap,
unsigned int family, const void *cfg,
struct lwtunnel_state **lws,
diff --git a/net/core/lwt_bpf.c b/net/core/lwt_bpf.c
index e7e626fb87bb..3a3ac13fcf06 100644
--- a/net/core/lwt_bpf.c
+++ b/net/core/lwt_bpf.c
@@ -238,7 +238,7 @@ static const struct nla_policy bpf_nl_policy[LWT_BPF_MAX + 1] = {
[LWT_BPF_XMIT_HEADROOM] = { .type = NLA_U32 },
};
-static int bpf_build_state(struct nlattr *nla,
+static int bpf_build_state(struct net *net, struct nlattr *nla,
unsigned int family, const void *cfg,
struct lwtunnel_state **ts,
struct netlink_ext_ack *extack)
diff --git a/net/core/lwtunnel.c b/net/core/lwtunnel.c
index 0b171756453c..b3f2f77dfe72 100644
--- a/net/core/lwtunnel.c
+++ b/net/core/lwtunnel.c
@@ -103,7 +103,7 @@ int lwtunnel_encap_del_ops(const struct lwtunnel_encap_ops *ops,
}
EXPORT_SYMBOL_GPL(lwtunnel_encap_del_ops);
-int lwtunnel_build_state(u16 encap_type,
+int lwtunnel_build_state(struct net *net, u16 encap_type,
struct nlattr *encap, unsigned int family,
const void *cfg, struct lwtunnel_state **lws,
struct netlink_ext_ack *extack)
@@ -124,7 +124,7 @@ int lwtunnel_build_state(u16 encap_type,
ops = rcu_dereference(lwtun_encaps[encap_type]);
if (likely(ops && ops->build_state && try_module_get(ops->owner))) {
found = true;
- ret = ops->build_state(encap, family, cfg, lws, extack);
+ ret = ops->build_state(net, encap, family, cfg, lws, extack);
if (ret)
module_put(ops->owner);
}
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index f04d944f8abe..4979e5c6b9b8 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -523,6 +523,7 @@ static int fib_get_nhs(struct fib_info *fi, struct rtnexthop *rtnh,
if (nla) {
struct lwtunnel_state *lwtstate;
struct nlattr *nla_entype;
+ struct net *net = cfg->fc_nlinfo.nl_net;
nla_entype = nla_find(attrs, attrlen,
RTA_ENCAP_TYPE);
@@ -533,7 +534,7 @@ static int fib_get_nhs(struct fib_info *fi, struct rtnexthop *rtnh,
goto err_inval;
}
- ret = lwtunnel_build_state(nla_get_u16(
+ ret = lwtunnel_build_state(net, nla_get_u16(
nla_entype),
nla, AF_INET, cfg,
&lwtstate, extack);
@@ -607,7 +608,7 @@ static void fib_rebalance(struct fib_info *fi)
#endif /* CONFIG_IP_ROUTE_MULTIPATH */
-static int fib_encap_match(u16 encap_type,
+static int fib_encap_match(struct net *net, u16 encap_type,
struct nlattr *encap,
const struct fib_nh *nh,
const struct fib_config *cfg,
@@ -619,7 +620,7 @@ static int fib_encap_match(u16 encap_type,
if (encap_type == LWTUNNEL_ENCAP_NONE)
return 0;
- ret = lwtunnel_build_state(encap_type, encap, AF_INET,
+ ret = lwtunnel_build_state(net, encap_type, encap, AF_INET,
cfg, &lwtstate, extack);
if (!ret) {
result = lwtunnel_cmp_encap(lwtstate, nh->nh_lwtstate);
@@ -632,6 +633,7 @@ static int fib_encap_match(u16 encap_type,
int fib_nh_match(struct fib_config *cfg, struct fib_info *fi,
struct netlink_ext_ack *extack)
{
+ struct net *net = cfg->fc_nlinfo.nl_net;
#ifdef CONFIG_IP_ROUTE_MULTIPATH
struct rtnexthop *rtnh;
int remaining;
@@ -642,7 +644,8 @@ int fib_nh_match(struct fib_config *cfg, struct fib_info *fi,
if (cfg->fc_oif || cfg->fc_gw) {
if (cfg->fc_encap) {
- if (fib_encap_match(cfg->fc_encap_type, cfg->fc_encap,
+ if (fib_encap_match(net, cfg->fc_encap_type,
+ cfg->fc_encap,
fi->fib_nh, cfg, extack))
return 1;
}
@@ -1180,7 +1183,7 @@ struct fib_info *fib_create_info(struct fib_config *cfg,
"LWT encap type not specified");
goto err_inval;
}
- err = lwtunnel_build_state(cfg->fc_encap_type,
+ err = lwtunnel_build_state(net, cfg->fc_encap_type,
cfg->fc_encap, AF_INET, cfg,
&lwtstate, extack);
if (err)
diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c
index 2f39479be92f..32e05aa6117d 100644
--- a/net/ipv4/ip_tunnel_core.c
+++ b/net/ipv4/ip_tunnel_core.c
@@ -228,7 +228,7 @@ static const struct nla_policy ip_tun_policy[LWTUNNEL_IP_MAX + 1] = {
[LWTUNNEL_IP_FLAGS] = { .type = NLA_U16 },
};
-static int ip_tun_build_state(struct nlattr *attr,
+static int ip_tun_build_state(struct net *net, struct nlattr *attr,
unsigned int family, const void *cfg,
struct lwtunnel_state **ts,
struct netlink_ext_ack *extack)
@@ -327,7 +327,7 @@ static const struct nla_policy ip6_tun_policy[LWTUNNEL_IP6_MAX + 1] = {
[LWTUNNEL_IP6_FLAGS] = { .type = NLA_U16 },
};
-static int ip6_tun_build_state(struct nlattr *attr,
+static int ip6_tun_build_state(struct net *net, struct nlattr *attr,
unsigned int family, const void *cfg,
struct lwtunnel_state **ts,
struct netlink_ext_ack *extack)
diff --git a/net/ipv6/ila/ila_lwt.c b/net/ipv6/ila/ila_lwt.c
index 3d56a2fb6f86..9f1e46a1468e 100644
--- a/net/ipv6/ila/ila_lwt.c
+++ b/net/ipv6/ila/ila_lwt.c
@@ -125,7 +125,7 @@ static const struct nla_policy ila_nl_policy[ILA_ATTR_MAX + 1] = {
[ILA_ATTR_HOOK_TYPE] = { .type = NLA_U8, },
};
-static int ila_build_state(struct nlattr *nla,
+static int ila_build_state(struct net *net, struct nlattr *nla,
unsigned int family, const void *cfg,
struct lwtunnel_state **ts,
struct netlink_ext_ack *extack)
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index b3f4d19b3ca5..0e0cc97e8f42 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -2565,7 +2565,7 @@ static struct rt6_info *ip6_route_info_create(struct fib6_config *cfg,
if (cfg->fc_encap) {
struct lwtunnel_state *lwtstate;
- err = lwtunnel_build_state(cfg->fc_encap_type,
+ err = lwtunnel_build_state(net, cfg->fc_encap_type,
cfg->fc_encap, AF_INET6, cfg,
&lwtstate, extack);
if (err)
diff --git a/net/ipv6/seg6_iptunnel.c b/net/ipv6/seg6_iptunnel.c
index bd6cc688bd19..a6cf2fba15f3 100644
--- a/net/ipv6/seg6_iptunnel.c
+++ b/net/ipv6/seg6_iptunnel.c
@@ -359,7 +359,7 @@ static int seg6_output(struct net *net, struct sock *sk, struct sk_buff *skb)
return err;
}
-static int seg6_build_state(struct nlattr *nla,
+static int seg6_build_state(struct net *net, struct nlattr *nla,
unsigned int family, const void *cfg,
struct lwtunnel_state **ts,
struct netlink_ext_ack *extack)
diff --git a/net/ipv6/seg6_local.c b/net/ipv6/seg6_local.c
index 825b8e01f947..45dc670c5a93 100644
--- a/net/ipv6/seg6_local.c
+++ b/net/ipv6/seg6_local.c
@@ -779,8 +779,9 @@ static int parse_nla_action(struct nlattr **attrs, struct seg6_local_lwt *slwt)
return 0;
}
-static int seg6_local_build_state(struct nlattr *nla, unsigned int family,
- const void *cfg, struct lwtunnel_state **ts,
+static int seg6_local_build_state(struct net *net, struct nlattr *nla,
+ unsigned int family, const void *cfg,
+ struct lwtunnel_state **ts,
struct netlink_ext_ack *extack)
{
struct nlattr *tb[SEG6_LOCAL_MAX + 1];
diff --git a/net/mpls/mpls_iptunnel.c b/net/mpls/mpls_iptunnel.c
index 6e558a419f60..c947310cc04f 100644
--- a/net/mpls/mpls_iptunnel.c
+++ b/net/mpls/mpls_iptunnel.c
@@ -157,7 +157,7 @@ static int mpls_xmit(struct sk_buff *skb)
return -EINVAL;
}
-static int mpls_build_state(struct nlattr *nla,
+static int mpls_build_state(struct net *net, struct nlattr *nla,
unsigned int family, const void *cfg,
struct lwtunnel_state **ts,
struct netlink_ext_ack *extack)
--
2.11.0
^ permalink raw reply related
* [PATCH v5 net-next 2/7] rtnetlink: Add notify route message types
From: Tom Herbert @ 2017-12-21 19:33 UTC (permalink / raw)
To: davem; +Cc: netdev, roopa, rohit, Tom Herbert
In-Reply-To: <20171221193332.15303-1-tom@quantonium.net>
Add notify route message and notify rtnl group. This is used to send
a notification about a route. For example, this will be used with ILA
to notify a daemon to send an ILA redirect.
Signed-off-by: Tom Herbert <tom@quantonium.net>
---
include/uapi/linux/rtnetlink.h | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h
index 843e29aa3cac..ee955c7ca48a 100644
--- a/include/uapi/linux/rtnetlink.h
+++ b/include/uapi/linux/rtnetlink.h
@@ -150,6 +150,9 @@ enum {
RTM_NEWCACHEREPORT = 96,
#define RTM_NEWCACHEREPORT RTM_NEWCACHEREPORT
+ RTM_NOTIFYROUTE = 98,
+#define RTM_NOTIFYROUTE RTM_NOTIFYROUTE
+
__RTM_MAX,
#define RTM_MAX (((__RTM_MAX + 3) & ~3) - 1)
};
@@ -677,6 +680,8 @@ enum rtnetlink_groups {
#define RTNLGRP_IPV4_MROUTE_R RTNLGRP_IPV4_MROUTE_R
RTNLGRP_IPV6_MROUTE_R,
#define RTNLGRP_IPV6_MROUTE_R RTNLGRP_IPV6_MROUTE_R
+ RTNLGRP_ROUTE_NOTIFY,
+#define RTNLGRP_ROUTE_NOTIFY RTNLGRP_ROUTE_NOTIFY
__RTNLGRP_MAX
};
#define RTNLGRP_MAX (__RTNLGRP_MAX - 1)
--
2.11.0
^ permalink raw reply related
* [PATCH v5 net-next 3/7] ila: Fix use of rhashtable walk in ila_xlat.c
From: Tom Herbert @ 2017-12-21 19:33 UTC (permalink / raw)
To: davem; +Cc: netdev, roopa, rohit, Tom Herbert
In-Reply-To: <20171221193332.15303-1-tom@quantonium.net>
Perform better EAGAIN handling, handle case where ila_dump_info
fails and we missed objects in the dump, and add a skip index
to skip over ila entires in a list on a rhashtable node that have
already been visited (by a previous call to ila_nl_dump).
Signed-off-by: Tom Herbert <tom@quantonium.net>
---
net/ipv6/ila/ila_xlat.c | 70 ++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 54 insertions(+), 16 deletions(-)
diff --git a/net/ipv6/ila/ila_xlat.c b/net/ipv6/ila/ila_xlat.c
index 44c39c5f0638..887dd5b785b5 100644
--- a/net/ipv6/ila/ila_xlat.c
+++ b/net/ipv6/ila/ila_xlat.c
@@ -474,24 +474,31 @@ static int ila_nl_cmd_get_mapping(struct sk_buff *skb, struct genl_info *info)
struct ila_dump_iter {
struct rhashtable_iter rhiter;
+ int skip;
};
static int ila_nl_dump_start(struct netlink_callback *cb)
{
struct net *net = sock_net(cb->skb->sk);
struct ila_net *ilan = net_generic(net, ila_net_id);
- struct ila_dump_iter *iter = (struct ila_dump_iter *)cb->args[0];
+ struct ila_dump_iter *iter;
+ int ret;
- if (!iter) {
- iter = kmalloc(sizeof(*iter), GFP_KERNEL);
- if (!iter)
- return -ENOMEM;
+ iter = kmalloc(sizeof(*iter), GFP_KERNEL);
+ if (!iter)
+ return -ENOMEM;
- cb->args[0] = (long)iter;
+ ret = rhashtable_walk_init(&ilan->rhash_table, &iter->rhiter,
+ GFP_KERNEL);
+ if (ret) {
+ kfree(iter);
+ return ret;
}
- return rhashtable_walk_init(&ilan->rhash_table, &iter->rhiter,
- GFP_KERNEL);
+ iter->skip = 0;
+ cb->args[0] = (long)iter;
+
+ return ret;
}
static int ila_nl_dump_done(struct netlink_callback *cb)
@@ -509,20 +516,45 @@ static int ila_nl_dump(struct sk_buff *skb, struct netlink_callback *cb)
{
struct ila_dump_iter *iter = (struct ila_dump_iter *)cb->args[0];
struct rhashtable_iter *rhiter = &iter->rhiter;
+ int skip = iter->skip;
struct ila_map *ila;
int ret;
rhashtable_walk_start(rhiter);
- for (;;) {
- ila = rhashtable_walk_next(rhiter);
+ /* Get first entry */
+ ila = rhashtable_walk_peek(rhiter);
+
+ if (ila && !IS_ERR(ila) && skip) {
+ /* Skip over visited entries */
+
+ while (ila && skip) {
+ /* Skip over any ila entries in this list that we
+ * have already dumped.
+ */
+ ila = rcu_access_pointer(ila->next);
+ skip--;
+ }
+ }
+ skip = 0;
+
+ for (;;) {
if (IS_ERR(ila)) {
- if (PTR_ERR(ila) == -EAGAIN)
- continue;
ret = PTR_ERR(ila);
- goto done;
+ if (ret == -EAGAIN) {
+ /* Table has changed and iter has reset. Return
+ * -EAGAIN to the application even if we have
+ * written data to the skb. The application
+ * needs to deal with this.
+ */
+
+ goto out_ret;
+ } else {
+ break;
+ }
} else if (!ila) {
+ ret = 0;
break;
}
@@ -531,15 +563,21 @@ static int ila_nl_dump(struct sk_buff *skb, struct netlink_callback *cb)
cb->nlh->nlmsg_seq, NLM_F_MULTI,
skb, ILA_CMD_GET);
if (ret)
- goto done;
+ goto out;
+ skip++;
ila = rcu_access_pointer(ila->next);
}
+
+ skip = 0;
+ ila = rhashtable_walk_next(rhiter);
}
- ret = skb->len;
+out:
+ iter->skip = skip;
+ ret = (skb->len ? : ret);
-done:
+out_ret:
rhashtable_walk_stop(rhiter);
return ret;
}
--
2.11.0
^ permalink raw reply related
* [PATCH v5 net-next 4/7] ila: Call library function alloc_bucket_locks
From: Tom Herbert @ 2017-12-21 19:33 UTC (permalink / raw)
To: davem; +Cc: netdev, roopa, rohit, Tom Herbert
In-Reply-To: <20171221193332.15303-1-tom@quantonium.net>
To allocate the array of bucket locks for the hash table we now
call library function alloc_bucket_spinlocks.
Signed-off-by: Tom Herbert <tom@quantonium.net>
---
net/ipv6/ila/ila_xlat.c | 22 +++++-----------------
1 file changed, 5 insertions(+), 17 deletions(-)
diff --git a/net/ipv6/ila/ila_xlat.c b/net/ipv6/ila/ila_xlat.c
index 887dd5b785b5..9cc8beedc2ca 100644
--- a/net/ipv6/ila/ila_xlat.c
+++ b/net/ipv6/ila/ila_xlat.c
@@ -31,26 +31,14 @@ struct ila_net {
bool hooks_registered;
};
+#define MAX_LOCKS 1024
#define LOCKS_PER_CPU 10
static int alloc_ila_locks(struct ila_net *ilan)
{
- unsigned int i, size;
- unsigned int nr_pcpus = num_possible_cpus();
-
- nr_pcpus = min_t(unsigned int, nr_pcpus, 32UL);
- size = roundup_pow_of_two(nr_pcpus * LOCKS_PER_CPU);
-
- if (sizeof(spinlock_t) != 0) {
- ilan->locks = kvmalloc(size * sizeof(spinlock_t), GFP_KERNEL);
- if (!ilan->locks)
- return -ENOMEM;
- for (i = 0; i < size; i++)
- spin_lock_init(&ilan->locks[i]);
- }
- ilan->locks_mask = size - 1;
-
- return 0;
+ return alloc_bucket_spinlocks(&ilan->locks, &ilan->locks_mask,
+ MAX_LOCKS, LOCKS_PER_CPU,
+ GFP_KERNEL);
}
static u32 hashrnd __read_mostly;
@@ -639,7 +627,7 @@ static __net_exit void ila_exit_net(struct net *net)
rhashtable_free_and_destroy(&ilan->rhash_table, ila_free_cb, NULL);
- kvfree(ilan->locks);
+ free_bucket_spinlocks(ilan->locks);
if (ilan->hooks_registered)
nf_unregister_net_hooks(net, ila_nf_hook_ops,
--
2.11.0
^ permalink raw reply related
* [PATCH v5 net-next 5/7] ila: Create main ila source file
From: Tom Herbert @ 2017-12-21 19:33 UTC (permalink / raw)
To: davem; +Cc: netdev, roopa, rohit, Tom Herbert
In-Reply-To: <20171221193332.15303-1-tom@quantonium.net>
Create a main ila file that contains the module initialization functions
as well as netlink definitions. Previously these were defined in
ila_xlat and ila_common. This approach allows better extensibility.
Signed-off-by: Tom Herbert <tom@quantonium.net>
---
net/ipv6/ila/Makefile | 2 +-
net/ipv6/ila/ila.h | 26 ++++++++-
net/ipv6/ila/ila_common.c | 30 ----------
net/ipv6/ila/ila_main.c | 115 +++++++++++++++++++++++++++++++++++++
net/ipv6/ila/ila_xlat.c | 142 +++++++++-------------------------------------
5 files changed, 168 insertions(+), 147 deletions(-)
create mode 100644 net/ipv6/ila/ila_main.c
diff --git a/net/ipv6/ila/Makefile b/net/ipv6/ila/Makefile
index 4b32e5921e5c..b7739aba6e68 100644
--- a/net/ipv6/ila/Makefile
+++ b/net/ipv6/ila/Makefile
@@ -4,4 +4,4 @@
obj-$(CONFIG_IPV6_ILA) += ila.o
-ila-objs := ila_common.o ila_lwt.o ila_xlat.o
+ila-objs := ila_main.o ila_common.o ila_lwt.o ila_xlat.o
diff --git a/net/ipv6/ila/ila.h b/net/ipv6/ila/ila.h
index 3c7a11b62334..faba7824ea56 100644
--- a/net/ipv6/ila/ila.h
+++ b/net/ipv6/ila/ila.h
@@ -19,6 +19,7 @@
#include <linux/skbuff.h>
#include <linux/types.h>
#include <net/checksum.h>
+#include <net/genetlink.h>
#include <net/ip.h>
#include <net/protocol.h>
#include <uapi/linux/ila.h>
@@ -104,9 +105,30 @@ void ila_update_ipv6_locator(struct sk_buff *skb, struct ila_params *p,
void ila_init_saved_csum(struct ila_params *p);
+struct ila_net {
+ struct {
+ struct rhashtable rhash_table;
+ spinlock_t *locks; /* Bucket locks for entry manipulation */
+ unsigned int locks_mask;
+ bool hooks_registered;
+ } xlat;
+};
+
int ila_lwt_init(void);
void ila_lwt_fini(void);
-int ila_xlat_init(void);
-void ila_xlat_fini(void);
+
+int ila_xlat_init_net(struct net *net);
+void ila_xlat_exit_net(struct net *net);
+
+int ila_xlat_nl_cmd_add_mapping(struct sk_buff *skb, struct genl_info *info);
+int ila_xlat_nl_cmd_del_mapping(struct sk_buff *skb, struct genl_info *info);
+int ila_xlat_nl_cmd_get_mapping(struct sk_buff *skb, struct genl_info *info);
+int ila_xlat_nl_dump_start(struct netlink_callback *cb);
+int ila_xlat_nl_dump_done(struct netlink_callback *cb);
+int ila_xlat_nl_dump(struct sk_buff *skb, struct netlink_callback *cb);
+
+extern unsigned int ila_net_id;
+
+extern struct genl_family ila_nl_family;
#endif /* __ILA_H */
diff --git a/net/ipv6/ila/ila_common.c b/net/ipv6/ila/ila_common.c
index 8c88ecf29b93..579310466eac 100644
--- a/net/ipv6/ila/ila_common.c
+++ b/net/ipv6/ila/ila_common.c
@@ -154,33 +154,3 @@ void ila_update_ipv6_locator(struct sk_buff *skb, struct ila_params *p,
iaddr->loc = p->locator;
}
-static int __init ila_init(void)
-{
- int ret;
-
- ret = ila_lwt_init();
-
- if (ret)
- goto fail_lwt;
-
- ret = ila_xlat_init();
- if (ret)
- goto fail_xlat;
-
- return 0;
-fail_xlat:
- ila_lwt_fini();
-fail_lwt:
- return ret;
-}
-
-static void __exit ila_fini(void)
-{
- ila_xlat_fini();
- ila_lwt_fini();
-}
-
-module_init(ila_init);
-module_exit(ila_fini);
-MODULE_AUTHOR("Tom Herbert <tom@herbertland.com>");
-MODULE_LICENSE("GPL");
diff --git a/net/ipv6/ila/ila_main.c b/net/ipv6/ila/ila_main.c
new file mode 100644
index 000000000000..f6ac6b14577e
--- /dev/null
+++ b/net/ipv6/ila/ila_main.c
@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <net/genetlink.h>
+#include <net/ila.h>
+#include <net/netns/generic.h>
+#include <uapi/linux/genetlink.h>
+#include "ila.h"
+
+static const struct nla_policy ila_nl_policy[ILA_ATTR_MAX + 1] = {
+ [ILA_ATTR_LOCATOR] = { .type = NLA_U64, },
+ [ILA_ATTR_LOCATOR_MATCH] = { .type = NLA_U64, },
+ [ILA_ATTR_IFINDEX] = { .type = NLA_U32, },
+ [ILA_ATTR_CSUM_MODE] = { .type = NLA_U8, },
+ [ILA_ATTR_IDENT_TYPE] = { .type = NLA_U8, },
+};
+
+static const struct genl_ops ila_nl_ops[] = {
+ {
+ .cmd = ILA_CMD_ADD,
+ .doit = ila_xlat_nl_cmd_add_mapping,
+ .policy = ila_nl_policy,
+ .flags = GENL_ADMIN_PERM,
+ },
+ {
+ .cmd = ILA_CMD_DEL,
+ .doit = ila_xlat_nl_cmd_del_mapping,
+ .policy = ila_nl_policy,
+ .flags = GENL_ADMIN_PERM,
+ },
+ {
+ .cmd = ILA_CMD_GET,
+ .doit = ila_xlat_nl_cmd_get_mapping,
+ .start = ila_xlat_nl_dump_start,
+ .dumpit = ila_xlat_nl_dump,
+ .done = ila_xlat_nl_dump_done,
+ .policy = ila_nl_policy,
+ },
+};
+
+unsigned int ila_net_id;
+
+struct genl_family ila_nl_family __ro_after_init = {
+ .hdrsize = 0,
+ .name = ILA_GENL_NAME,
+ .version = ILA_GENL_VERSION,
+ .maxattr = ILA_ATTR_MAX,
+ .netnsok = true,
+ .parallel_ops = true,
+ .module = THIS_MODULE,
+ .ops = ila_nl_ops,
+ .n_ops = ARRAY_SIZE(ila_nl_ops),
+};
+
+static __net_init int ila_init_net(struct net *net)
+{
+ int err;
+
+ err = ila_xlat_init_net(net);
+ if (err)
+ goto ila_xlat_init_fail;
+
+ return 0;
+
+ila_xlat_init_fail:
+ return err;
+}
+
+static __net_exit void ila_exit_net(struct net *net)
+{
+ ila_xlat_exit_net(net);
+}
+
+static struct pernet_operations ila_net_ops = {
+ .init = ila_init_net,
+ .exit = ila_exit_net,
+ .id = &ila_net_id,
+ .size = sizeof(struct ila_net),
+};
+
+static int __init ila_init(void)
+{
+ int ret;
+
+ ret = register_pernet_device(&ila_net_ops);
+ if (ret)
+ goto register_device_fail;
+
+ ret = genl_register_family(&ila_nl_family);
+ if (ret)
+ goto register_family_fail;
+
+ ret = ila_lwt_init();
+ if (ret)
+ goto fail_lwt;
+
+ return 0;
+
+fail_lwt:
+ genl_unregister_family(&ila_nl_family);
+register_family_fail:
+ unregister_pernet_device(&ila_net_ops);
+register_device_fail:
+ return ret;
+}
+
+static void __exit ila_fini(void)
+{
+ ila_lwt_fini();
+ genl_unregister_family(&ila_nl_family);
+ unregister_pernet_device(&ila_net_ops);
+}
+
+module_init(ila_init);
+module_exit(ila_fini);
+MODULE_AUTHOR("Tom Herbert <tom@herbertland.com>");
+MODULE_LICENSE("GPL");
diff --git a/net/ipv6/ila/ila_xlat.c b/net/ipv6/ila/ila_xlat.c
index 9cc8beedc2ca..d05de891dfb6 100644
--- a/net/ipv6/ila/ila_xlat.c
+++ b/net/ipv6/ila/ila_xlat.c
@@ -22,21 +22,12 @@ struct ila_map {
struct rcu_head rcu;
};
-static unsigned int ila_net_id;
-
-struct ila_net {
- struct rhashtable rhash_table;
- spinlock_t *locks; /* Bucket locks for entry manipulation */
- unsigned int locks_mask;
- bool hooks_registered;
-};
-
#define MAX_LOCKS 1024
#define LOCKS_PER_CPU 10
static int alloc_ila_locks(struct ila_net *ilan)
{
- return alloc_bucket_spinlocks(&ilan->locks, &ilan->locks_mask,
+ return alloc_bucket_spinlocks(&ilan->xlat.locks, &ilan->xlat.locks_mask,
MAX_LOCKS, LOCKS_PER_CPU,
GFP_KERNEL);
}
@@ -58,7 +49,7 @@ static inline u32 ila_locator_hash(struct ila_locator loc)
static inline spinlock_t *ila_get_lock(struct ila_net *ilan,
struct ila_locator loc)
{
- return &ilan->locks[ila_locator_hash(loc) & ilan->locks_mask];
+ return &ilan->xlat.locks[ila_locator_hash(loc) & ilan->xlat.locks_mask];
}
static inline int ila_cmp_wildcards(struct ila_map *ila,
@@ -102,16 +93,6 @@ static const struct rhashtable_params rht_params = {
.obj_cmpfn = ila_cmpfn,
};
-static struct genl_family ila_nl_family;
-
-static const struct nla_policy ila_nl_policy[ILA_ATTR_MAX + 1] = {
- [ILA_ATTR_LOCATOR] = { .type = NLA_U64, },
- [ILA_ATTR_LOCATOR_MATCH] = { .type = NLA_U64, },
- [ILA_ATTR_IFINDEX] = { .type = NLA_U32, },
- [ILA_ATTR_CSUM_MODE] = { .type = NLA_U8, },
- [ILA_ATTR_IDENT_TYPE] = { .type = NLA_U8, },
-};
-
static int parse_nl_config(struct genl_info *info,
struct ila_xlat_params *xp)
{
@@ -149,7 +130,7 @@ static inline struct ila_map *ila_lookup_wildcards(struct ila_addr *iaddr,
{
struct ila_map *ila;
- ila = rhashtable_lookup_fast(&ilan->rhash_table, &iaddr->loc,
+ ila = rhashtable_lookup_fast(&ilan->xlat.rhash_table, &iaddr->loc,
rht_params);
while (ila) {
if (!ila_cmp_wildcards(ila, iaddr, ifindex))
@@ -166,7 +147,7 @@ static inline struct ila_map *ila_lookup_by_params(struct ila_xlat_params *xp,
{
struct ila_map *ila;
- ila = rhashtable_lookup_fast(&ilan->rhash_table,
+ ila = rhashtable_lookup_fast(&ilan->xlat.rhash_table,
&xp->ip.locator_match,
rht_params);
while (ila) {
@@ -222,7 +203,7 @@ static int ila_add_mapping(struct net *net, struct ila_xlat_params *xp)
spinlock_t *lock = ila_get_lock(ilan, xp->ip.locator_match);
int err = 0, order;
- if (!ilan->hooks_registered) {
+ if (!ilan->xlat.hooks_registered) {
/* We defer registering net hooks in the namespace until the
* first mapping is added.
*/
@@ -231,7 +212,7 @@ static int ila_add_mapping(struct net *net, struct ila_xlat_params *xp)
if (err)
return err;
- ilan->hooks_registered = true;
+ ilan->xlat.hooks_registered = true;
}
ila = kzalloc(sizeof(*ila), GFP_KERNEL);
@@ -246,12 +227,12 @@ static int ila_add_mapping(struct net *net, struct ila_xlat_params *xp)
spin_lock(lock);
- head = rhashtable_lookup_fast(&ilan->rhash_table,
+ head = rhashtable_lookup_fast(&ilan->xlat.rhash_table,
&xp->ip.locator_match,
rht_params);
if (!head) {
/* New entry for the rhash_table */
- err = rhashtable_lookup_insert_fast(&ilan->rhash_table,
+ err = rhashtable_lookup_insert_fast(&ilan->xlat.rhash_table,
&ila->node, rht_params);
} else {
struct ila_map *tila = head, *prev = NULL;
@@ -277,7 +258,7 @@ static int ila_add_mapping(struct net *net, struct ila_xlat_params *xp)
} else {
/* Make this ila new head */
RCU_INIT_POINTER(ila->next, head);
- err = rhashtable_replace_fast(&ilan->rhash_table,
+ err = rhashtable_replace_fast(&ilan->xlat.rhash_table,
&head->node,
&ila->node, rht_params);
if (err)
@@ -303,7 +284,7 @@ static int ila_del_mapping(struct net *net, struct ila_xlat_params *xp)
spin_lock(lock);
- head = rhashtable_lookup_fast(&ilan->rhash_table,
+ head = rhashtable_lookup_fast(&ilan->xlat.rhash_table,
&xp->ip.locator_match, rht_params);
ila = head;
@@ -333,15 +314,15 @@ static int ila_del_mapping(struct net *net, struct ila_xlat_params *xp)
* table
*/
err = rhashtable_replace_fast(
- &ilan->rhash_table, &ila->node,
+ &ilan->xlat.rhash_table, &ila->node,
&head->node, rht_params);
if (err)
goto out;
} else {
/* Entry no longer used */
- err = rhashtable_remove_fast(&ilan->rhash_table,
- &ila->node,
- rht_params);
+ err = rhashtable_remove_fast(
+ &ilan->xlat.rhash_table,
+ &ila->node, rht_params);
}
}
@@ -356,7 +337,7 @@ static int ila_del_mapping(struct net *net, struct ila_xlat_params *xp)
return err;
}
-static int ila_nl_cmd_add_mapping(struct sk_buff *skb, struct genl_info *info)
+int ila_xlat_nl_cmd_add_mapping(struct sk_buff *skb, struct genl_info *info)
{
struct net *net = genl_info_net(info);
struct ila_xlat_params p;
@@ -369,7 +350,7 @@ static int ila_nl_cmd_add_mapping(struct sk_buff *skb, struct genl_info *info)
return ila_add_mapping(net, &p);
}
-static int ila_nl_cmd_del_mapping(struct sk_buff *skb, struct genl_info *info)
+int ila_xlat_nl_cmd_del_mapping(struct sk_buff *skb, struct genl_info *info)
{
struct net *net = genl_info_net(info);
struct ila_xlat_params xp;
@@ -421,7 +402,7 @@ static int ila_dump_info(struct ila_map *ila,
return -EMSGSIZE;
}
-static int ila_nl_cmd_get_mapping(struct sk_buff *skb, struct genl_info *info)
+int ila_xlat_nl_cmd_get_mapping(struct sk_buff *skb, struct genl_info *info)
{
struct net *net = genl_info_net(info);
struct ila_net *ilan = net_generic(net, ila_net_id);
@@ -465,7 +446,7 @@ struct ila_dump_iter {
int skip;
};
-static int ila_nl_dump_start(struct netlink_callback *cb)
+int ila_xlat_nl_dump_start(struct netlink_callback *cb)
{
struct net *net = sock_net(cb->skb->sk);
struct ila_net *ilan = net_generic(net, ila_net_id);
@@ -476,7 +457,7 @@ static int ila_nl_dump_start(struct netlink_callback *cb)
if (!iter)
return -ENOMEM;
- ret = rhashtable_walk_init(&ilan->rhash_table, &iter->rhiter,
+ ret = rhashtable_walk_init(&ilan->xlat.rhash_table, &iter->rhiter,
GFP_KERNEL);
if (ret) {
kfree(iter);
@@ -489,7 +470,7 @@ static int ila_nl_dump_start(struct netlink_callback *cb)
return ret;
}
-static int ila_nl_dump_done(struct netlink_callback *cb)
+int ila_xlat_nl_dump_done(struct netlink_callback *cb)
{
struct ila_dump_iter *iter = (struct ila_dump_iter *)cb->args[0];
@@ -500,7 +481,7 @@ static int ila_nl_dump_done(struct netlink_callback *cb)
return 0;
}
-static int ila_nl_dump(struct sk_buff *skb, struct netlink_callback *cb)
+int ila_xlat_nl_dump(struct sk_buff *skb, struct netlink_callback *cb)
{
struct ila_dump_iter *iter = (struct ila_dump_iter *)cb->args[0];
struct rhashtable_iter *rhiter = &iter->rhiter;
@@ -570,77 +551,35 @@ static int ila_nl_dump(struct sk_buff *skb, struct netlink_callback *cb)
return ret;
}
-static const struct genl_ops ila_nl_ops[] = {
- {
- .cmd = ILA_CMD_ADD,
- .doit = ila_nl_cmd_add_mapping,
- .policy = ila_nl_policy,
- .flags = GENL_ADMIN_PERM,
- },
- {
- .cmd = ILA_CMD_DEL,
- .doit = ila_nl_cmd_del_mapping,
- .policy = ila_nl_policy,
- .flags = GENL_ADMIN_PERM,
- },
- {
- .cmd = ILA_CMD_GET,
- .doit = ila_nl_cmd_get_mapping,
- .start = ila_nl_dump_start,
- .dumpit = ila_nl_dump,
- .done = ila_nl_dump_done,
- .policy = ila_nl_policy,
- },
-};
-
-static struct genl_family ila_nl_family __ro_after_init = {
- .hdrsize = 0,
- .name = ILA_GENL_NAME,
- .version = ILA_GENL_VERSION,
- .maxattr = ILA_ATTR_MAX,
- .netnsok = true,
- .parallel_ops = true,
- .module = THIS_MODULE,
- .ops = ila_nl_ops,
- .n_ops = ARRAY_SIZE(ila_nl_ops),
-};
-
#define ILA_HASH_TABLE_SIZE 1024
-static __net_init int ila_init_net(struct net *net)
+int ila_xlat_init_net(struct net *net)
{
- int err;
struct ila_net *ilan = net_generic(net, ila_net_id);
+ int err;
err = alloc_ila_locks(ilan);
if (err)
return err;
- rhashtable_init(&ilan->rhash_table, &rht_params);
+ rhashtable_init(&ilan->xlat.rhash_table, &rht_params);
return 0;
}
-static __net_exit void ila_exit_net(struct net *net)
+void ila_xlat_exit_net(struct net *net)
{
struct ila_net *ilan = net_generic(net, ila_net_id);
- rhashtable_free_and_destroy(&ilan->rhash_table, ila_free_cb, NULL);
+ rhashtable_free_and_destroy(&ilan->xlat.rhash_table, ila_free_cb, NULL);
- free_bucket_spinlocks(ilan->locks);
+ free_bucket_spinlocks(ilan->xlat.locks);
- if (ilan->hooks_registered)
+ if (ilan->xlat.hooks_registered)
nf_unregister_net_hooks(net, ila_nf_hook_ops,
ARRAY_SIZE(ila_nf_hook_ops));
}
-static struct pernet_operations ila_net_ops = {
- .init = ila_init_net,
- .exit = ila_exit_net,
- .id = &ila_net_id,
- .size = sizeof(struct ila_net),
-};
-
static int ila_xlat_addr(struct sk_buff *skb, bool sir2ila)
{
struct ila_map *ila;
@@ -667,28 +606,3 @@ static int ila_xlat_addr(struct sk_buff *skb, bool sir2ila)
return 0;
}
-int __init ila_xlat_init(void)
-{
- int ret;
-
- ret = register_pernet_device(&ila_net_ops);
- if (ret)
- goto exit;
-
- ret = genl_register_family(&ila_nl_family);
- if (ret < 0)
- goto unregister;
-
- return 0;
-
-unregister:
- unregister_pernet_device(&ila_net_ops);
-exit:
- return ret;
-}
-
-void ila_xlat_fini(void)
-{
- genl_unregister_family(&ila_nl_family);
- unregister_pernet_device(&ila_net_ops);
-}
--
2.11.0
^ permalink raw reply related
* [PATCH v5 net-next 6/7] ila: Flush netlink command to clear xlat table
From: Tom Herbert @ 2017-12-21 19:33 UTC (permalink / raw)
To: davem; +Cc: netdev, roopa, rohit, Tom Herbert
In-Reply-To: <20171221193332.15303-1-tom@quantonium.net>
Add ILA_CMD_FLUSH netlink command to clear the ILA translation table.
Signed-off-by: Tom Herbert <tom@quantonium.net>
---
include/uapi/linux/ila.h | 1 +
net/ipv6/ila/ila.h | 1 +
net/ipv6/ila/ila_main.c | 6 +++++
net/ipv6/ila/ila_xlat.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++--
4 files changed, 68 insertions(+), 2 deletions(-)
diff --git a/include/uapi/linux/ila.h b/include/uapi/linux/ila.h
index 483b77af4eb8..db45d3e49a12 100644
--- a/include/uapi/linux/ila.h
+++ b/include/uapi/linux/ila.h
@@ -30,6 +30,7 @@ enum {
ILA_CMD_ADD,
ILA_CMD_DEL,
ILA_CMD_GET,
+ ILA_CMD_FLUSH,
__ILA_CMD_MAX,
};
diff --git a/net/ipv6/ila/ila.h b/net/ipv6/ila/ila.h
index faba7824ea56..1f747bcbec29 100644
--- a/net/ipv6/ila/ila.h
+++ b/net/ipv6/ila/ila.h
@@ -123,6 +123,7 @@ void ila_xlat_exit_net(struct net *net);
int ila_xlat_nl_cmd_add_mapping(struct sk_buff *skb, struct genl_info *info);
int ila_xlat_nl_cmd_del_mapping(struct sk_buff *skb, struct genl_info *info);
int ila_xlat_nl_cmd_get_mapping(struct sk_buff *skb, struct genl_info *info);
+int ila_xlat_nl_cmd_flush(struct sk_buff *skb, struct genl_info *info);
int ila_xlat_nl_dump_start(struct netlink_callback *cb);
int ila_xlat_nl_dump_done(struct netlink_callback *cb);
int ila_xlat_nl_dump(struct sk_buff *skb, struct netlink_callback *cb);
diff --git a/net/ipv6/ila/ila_main.c b/net/ipv6/ila/ila_main.c
index f6ac6b14577e..18fac76b9520 100644
--- a/net/ipv6/ila/ila_main.c
+++ b/net/ipv6/ila/ila_main.c
@@ -27,6 +27,12 @@ static const struct genl_ops ila_nl_ops[] = {
.flags = GENL_ADMIN_PERM,
},
{
+ .cmd = ILA_CMD_FLUSH,
+ .doit = ila_xlat_nl_cmd_flush,
+ .policy = ila_nl_policy,
+ .flags = GENL_ADMIN_PERM,
+ },
+ {
.cmd = ILA_CMD_GET,
.doit = ila_xlat_nl_cmd_get_mapping,
.start = ila_xlat_nl_dump_start,
diff --git a/net/ipv6/ila/ila_xlat.c b/net/ipv6/ila/ila_xlat.c
index d05de891dfb6..51a15ce50a64 100644
--- a/net/ipv6/ila/ila_xlat.c
+++ b/net/ipv6/ila/ila_xlat.c
@@ -164,9 +164,9 @@ static inline void ila_release(struct ila_map *ila)
kfree_rcu(ila, rcu);
}
-static void ila_free_cb(void *ptr, void *arg)
+static void ila_free_node(struct ila_map *ila)
{
- struct ila_map *ila = (struct ila_map *)ptr, *next;
+ struct ila_map *next;
/* Assume rcu_readlock held */
while (ila) {
@@ -176,6 +176,11 @@ static void ila_free_cb(void *ptr, void *arg)
}
}
+static void ila_free_cb(void *ptr, void *arg)
+{
+ ila_free_node((struct ila_map *)ptr);
+}
+
static int ila_xlat_addr(struct sk_buff *skb, bool sir2ila);
static unsigned int
@@ -365,6 +370,59 @@ int ila_xlat_nl_cmd_del_mapping(struct sk_buff *skb, struct genl_info *info)
return 0;
}
+static inline spinlock_t *lock_from_ila_map(struct ila_net *ilan,
+ struct ila_map *ila)
+{
+ return ila_get_lock(ilan, ila->xp.ip.locator_match);
+}
+
+int ila_xlat_nl_cmd_flush(struct sk_buff *skb, struct genl_info *info)
+{
+ struct net *net = genl_info_net(info);
+ struct ila_net *ilan = net_generic(net, ila_net_id);
+ struct rhashtable_iter iter;
+ struct ila_map *ila;
+ spinlock_t *lock;
+ int ret;
+
+ ret = rhashtable_walk_init(&ilan->xlat.rhash_table, &iter, GFP_KERNEL);
+ if (ret)
+ goto done;
+
+ rhashtable_walk_start(&iter);
+
+ for (;;) {
+ ila = rhashtable_walk_next(&iter);
+
+ if (IS_ERR(ila)) {
+ if (PTR_ERR(ila) == -EAGAIN)
+ continue;
+ ret = PTR_ERR(ila);
+ goto done;
+ } else if (!ila) {
+ break;
+ }
+
+ lock = lock_from_ila_map(ilan, ila);
+
+ spin_lock(lock);
+
+ ret = rhashtable_remove_fast(&ilan->xlat.rhash_table,
+ &ila->node, rht_params);
+ if (!ret)
+ ila_free_node(ila);
+
+ spin_unlock(lock);
+
+ if (ret)
+ break;
+ }
+
+done:
+ rhashtable_walk_stop(&iter);
+ return ret;
+}
+
static int ila_fill_info(struct ila_map *ila, struct sk_buff *msg)
{
if (nla_put_u64_64bit(msg, ILA_ATTR_LOCATOR,
--
2.11.0
^ permalink raw reply related
* [PATCH v5 net-next 7/7] ila: Route notify
From: Tom Herbert @ 2017-12-21 19:33 UTC (permalink / raw)
To: davem; +Cc: netdev, roopa, rohit, Tom Herbert
In-Reply-To: <20171221193332.15303-1-tom@quantonium.net>
Implement RTM notifications for ILA routers. This adds support to
ILA LWT to send a netlink RTM message when a router is uses.
The ILA notify mechanism can be used in two contexts:
- On an ILA forwarding cache a route prefix can be configured to
do an ILA notification. This method is used when address
resolution needs to be done on an address.
- One an ILA router an ILA host route entry may include a
noitification. The purpose of this is to get a notification
to a userspace daemon to send and ILA redirect
This patch also adds a routing protocol number for ILA.
Signed-off-by: Tom Herbert <tom@quantonium.net>
---
include/uapi/linux/ila.h | 2 +
include/uapi/linux/rtnetlink.h | 1 +
net/ipv6/ila/ila_lwt.c | 273 ++++++++++++++++++++++++++++-------------
3 files changed, 191 insertions(+), 85 deletions(-)
diff --git a/include/uapi/linux/ila.h b/include/uapi/linux/ila.h
index db45d3e49a12..5675f3e71fac 100644
--- a/include/uapi/linux/ila.h
+++ b/include/uapi/linux/ila.h
@@ -19,6 +19,8 @@ enum {
ILA_ATTR_CSUM_MODE, /* u8 */
ILA_ATTR_IDENT_TYPE, /* u8 */
ILA_ATTR_HOOK_TYPE, /* u8 */
+ ILA_ATTR_NOTIFY_DST, /* flag */
+ ILA_ATTR_NOTIFY_SRC, /* flag */
__ILA_ATTR_MAX,
};
diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h
index ee955c7ca48a..5da035cce640 100644
--- a/include/uapi/linux/rtnetlink.h
+++ b/include/uapi/linux/rtnetlink.h
@@ -256,6 +256,7 @@ enum {
#define RTPROT_NTK 15 /* Netsukuku */
#define RTPROT_DHCP 16 /* DHCP client */
#define RTPROT_MROUTED 17 /* Multicast daemon */
+#define RTPROT_ILA 18 /* ILA route */
#define RTPROT_BABEL 42 /* Babel daemon */
/* rtm_scope
diff --git a/net/ipv6/ila/ila_lwt.c b/net/ipv6/ila/ila_lwt.c
index 9f1e46a1468e..d0ddd6f2714f 100644
--- a/net/ipv6/ila/ila_lwt.c
+++ b/net/ipv6/ila/ila_lwt.c
@@ -19,10 +19,15 @@
struct ila_lwt {
struct ila_params p;
struct dst_cache dst_cache;
+ u8 hook_type;
u32 connected : 1;
- u32 lwt_output : 1;
+ u32 xlat : 1;
+ u32 notify : 2;
};
+#define ILA_NOTIFY_DST 1
+#define ILA_NOTIFY_SRC 2
+
static inline struct ila_lwt *ila_lwt_lwtunnel(
struct lwtunnel_state *lwt)
{
@@ -35,6 +40,69 @@ static inline struct ila_params *ila_params_lwtunnel(
return &ila_lwt_lwtunnel(lwt)->p;
}
+static size_t ila_rslv_msgsize(void)
+{
+ size_t len =
+ NLMSG_ALIGN(sizeof(struct rtmsg))
+ + nla_total_size(16) /* RTA_DST */
+ + nla_total_size(16) /* RTA_SRC */
+ ;
+
+ return len;
+}
+
+static void ila_notify(struct net *net, struct sk_buff *skb,
+ struct ila_lwt *lwt, struct rt6_info *rt)
+{
+ struct ipv6hdr *ip6h = ipv6_hdr(skb);
+ int flags = NLM_F_MULTI;
+ struct sk_buff *nlskb;
+ struct nlmsghdr *nlh;
+ struct rtmsg *rtm;
+ int err = 0;
+
+ /* Send ILA notification to user */
+ nlskb = nlmsg_new(ila_rslv_msgsize(), GFP_KERNEL);
+ if (!nlskb)
+ return;
+
+ nlh = nlmsg_put(nlskb, 0, 0, RTM_NOTIFYROUTE, sizeof(*rtm), flags);
+ if (!nlh) {
+ err = -EMSGSIZE;
+ goto errout;
+ }
+
+ rtm = nlmsg_data(nlh);
+ rtm->rtm_family = AF_INET6;
+ rtm->rtm_dst_len = 128;
+ rtm->rtm_src_len = 0;
+ rtm->rtm_tos = 0;
+ rtm->rtm_table = RT6_TABLE_UNSPEC;
+ rtm->rtm_type = RTN_UNICAST;
+ rtm->rtm_scope = RT_SCOPE_UNIVERSE;
+ rtm->rtm_protocol = rt->rt6i_protocol;
+
+ if (((lwt->notify & ILA_NOTIFY_DST) &&
+ nla_put_in6_addr(nlskb, RTA_DST, &ip6h->daddr)) ||
+ ((lwt->notify & ILA_NOTIFY_SRC) &&
+ nla_put_in6_addr(nlskb, RTA_SRC, &ip6h->saddr))) {
+ nlmsg_cancel(nlskb, nlh);
+ err = -EMSGSIZE;
+ goto errout;
+ }
+
+ nlmsg_end(nlskb, nlh);
+
+ rtnl_notify(nlskb, net, 0, RTNLGRP_ROUTE_NOTIFY, NULL, GFP_ATOMIC);
+
+ return;
+
+errout:
+ kfree_skb(nlskb);
+ WARN_ON(err == -EMSGSIZE);
+ rtnl_set_sk_err(net, RTNLGRP_ROUTE_NOTIFY, err);
+}
+
static int ila_output(struct net *net, struct sock *sk, struct sk_buff *skb)
{
struct dst_entry *orig_dst = skb_dst(skb);
@@ -46,11 +114,14 @@ static int ila_output(struct net *net, struct sock *sk, struct sk_buff *skb)
if (skb->protocol != htons(ETH_P_IPV6))
goto drop;
- if (ilwt->lwt_output)
+ if (ilwt->xlat)
ila_update_ipv6_locator(skb,
ila_params_lwtunnel(orig_dst->lwtstate),
true);
+ if (ilwt->notify)
+ ila_notify(net, skb, ilwt, rt);
+
if (rt->rt6i_flags & (RTF_GATEWAY | RTF_CACHE)) {
/* Already have a next hop address in route, no need for
* dest cache route.
@@ -101,16 +172,20 @@ static int ila_output(struct net *net, struct sock *sk, struct sk_buff *skb)
static int ila_input(struct sk_buff *skb)
{
struct dst_entry *dst = skb_dst(skb);
+ struct rt6_info *rt = (struct rt6_info *)dst;
struct ila_lwt *ilwt = ila_lwt_lwtunnel(dst->lwtstate);
if (skb->protocol != htons(ETH_P_IPV6))
goto drop;
- if (!ilwt->lwt_output)
+ if (ilwt->xlat)
ila_update_ipv6_locator(skb,
ila_params_lwtunnel(dst->lwtstate),
false);
+ if (ilwt->notify)
+ ila_notify(dev_net(dst->dev), skb, ilwt, rt);
+
return dst->lwtstate->orig_input(skb);
drop:
@@ -123,6 +198,8 @@ static const struct nla_policy ila_nl_policy[ILA_ATTR_MAX + 1] = {
[ILA_ATTR_CSUM_MODE] = { .type = NLA_U8, },
[ILA_ATTR_IDENT_TYPE] = { .type = NLA_U8, },
[ILA_ATTR_HOOK_TYPE] = { .type = NLA_U8, },
+ [ILA_ATTR_NOTIFY_DST] = { .type = NLA_FLAG },
+ [ILA_ATTR_NOTIFY_SRC] = { .type = NLA_FLAG },
};
static int ila_build_state(struct net *net, struct nlattr *nla,
@@ -130,64 +207,73 @@ static int ila_build_state(struct net *net, struct nlattr *nla,
struct lwtunnel_state **ts,
struct netlink_ext_ack *extack)
{
- struct ila_lwt *ilwt;
- struct ila_params *p;
- struct nlattr *tb[ILA_ATTR_MAX + 1];
- struct lwtunnel_state *newts;
const struct fib6_config *cfg6 = cfg;
- struct ila_addr *iaddr;
+ struct ila_addr *iaddr = (struct ila_addr *)&cfg6->fc_dst;
u8 ident_type = ILA_ATYPE_USE_FORMAT;
u8 hook_type = ILA_HOOK_ROUTE_OUTPUT;
+ struct nlattr *tb[ILA_ATTR_MAX + 1];
u8 csum_mode = ILA_CSUM_NO_ACTION;
- bool lwt_output = true;
+ struct lwtunnel_state *newts;
+ struct ila_lwt *ilwt;
+ struct ila_params *p;
u8 eff_ident_type;
- int ret;
+ int err;
if (family != AF_INET6)
return -EINVAL;
- ret = nla_parse_nested(tb, ILA_ATTR_MAX, nla, ila_nl_policy, extack);
- if (ret < 0)
- return ret;
+ err = nla_parse_nested(tb, ILA_ATTR_MAX, nla, ila_nl_policy, extack);
+ if (err < 0)
+ return err;
- if (!tb[ILA_ATTR_LOCATOR])
- return -EINVAL;
+ if (tb[ILA_ATTR_LOCATOR]) {
+ /* Doing ILA translation */
- iaddr = (struct ila_addr *)&cfg6->fc_dst;
+ if (tb[ILA_ATTR_IDENT_TYPE])
+ ident_type = nla_get_u8(tb[ILA_ATTR_IDENT_TYPE]);
- if (tb[ILA_ATTR_IDENT_TYPE])
- ident_type = nla_get_u8(tb[ILA_ATTR_IDENT_TYPE]);
+ if (ident_type == ILA_ATYPE_USE_FORMAT) {
+ /* Infer identifier type from type field in formatted
+ * identifier.
+ */
- if (ident_type == ILA_ATYPE_USE_FORMAT) {
- /* Infer identifier type from type field in formatted
- * identifier.
- */
+ if (cfg6->fc_dst_len < 8 *
+ sizeof(struct ila_locator) + 3) {
+ /* Need to have full locator and at least type
+ * field included in destination
+ */
+ return -EINVAL;
+ }
+
+ eff_ident_type = iaddr->ident.type;
+ } else {
+ eff_ident_type = ident_type;
+ }
- if (cfg6->fc_dst_len < 8 * sizeof(struct ila_locator) + 3) {
- /* Need to have full locator and at least type field
- * included in destination
- */
+ switch (eff_ident_type) {
+ case ILA_ATYPE_IID:
+ /* Don't allow ILA for IID type */
+ return -EINVAL;
+ case ILA_ATYPE_LUID:
+ break;
+ case ILA_ATYPE_VIRT_V4:
+ case ILA_ATYPE_VIRT_UNI_V6:
+ case ILA_ATYPE_VIRT_MULTI_V6:
+ case ILA_ATYPE_NONLOCAL_ADDR:
+ /* These ILA formats are not supported yet. */
+ default:
return -EINVAL;
}
- eff_ident_type = iaddr->ident.type;
- } else {
- eff_ident_type = ident_type;
- }
+ csum_mode = nla_get_u8(tb[ILA_ATTR_CSUM_MODE]);
- switch (eff_ident_type) {
- case ILA_ATYPE_IID:
- /* Don't allow ILA for IID type */
- return -EINVAL;
- case ILA_ATYPE_LUID:
- break;
- case ILA_ATYPE_VIRT_V4:
- case ILA_ATYPE_VIRT_UNI_V6:
- case ILA_ATYPE_VIRT_MULTI_V6:
- case ILA_ATYPE_NONLOCAL_ADDR:
- /* These ILA formats are not supported yet. */
- default:
- return -EINVAL;
+ if (csum_mode == ILA_CSUM_NEUTRAL_MAP &&
+ ila_csum_neutral_set(iaddr->ident)) {
+ /* Don't allow translation if checksum neutral bit is
+ * configured and it's set in the SIR address.
+ */
+ return -EINVAL;
+ }
}
if (tb[ILA_ATTR_HOOK_TYPE])
@@ -195,58 +281,62 @@ static int ila_build_state(struct net *net, struct nlattr *nla,
switch (hook_type) {
case ILA_HOOK_ROUTE_OUTPUT:
- lwt_output = true;
- break;
case ILA_HOOK_ROUTE_INPUT:
- lwt_output = false;
break;
default:
return -EINVAL;
}
- if (tb[ILA_ATTR_CSUM_MODE])
- csum_mode = nla_get_u8(tb[ILA_ATTR_CSUM_MODE]);
-
- if (csum_mode == ILA_CSUM_NEUTRAL_MAP &&
- ila_csum_neutral_set(iaddr->ident)) {
- /* Don't allow translation if checksum neutral bit is
- * configured and it's set in the SIR address.
- */
- return -EINVAL;
- }
-
newts = lwtunnel_state_alloc(sizeof(*ilwt));
if (!newts)
return -ENOMEM;
ilwt = ila_lwt_lwtunnel(newts);
- ret = dst_cache_init(&ilwt->dst_cache, GFP_ATOMIC);
- if (ret) {
+
+ err = dst_cache_init(&ilwt->dst_cache, GFP_ATOMIC);
+ if (err) {
kfree(newts);
- return ret;
+ return err;
}
- ilwt->lwt_output = !!lwt_output;
+ newts->type = LWTUNNEL_ENCAP_ILA;
- p = ila_params_lwtunnel(newts);
+ switch (hook_type) {
+ case ILA_HOOK_ROUTE_OUTPUT:
+ newts->flags |= LWTUNNEL_STATE_OUTPUT_REDIRECT;
+ break;
+ case ILA_HOOK_ROUTE_INPUT:
+ newts->flags |= LWTUNNEL_STATE_INPUT_REDIRECT;
+ break;
+ }
- p->csum_mode = csum_mode;
- p->ident_type = ident_type;
- p->locator.v64 = (__force __be64)nla_get_u64(tb[ILA_ATTR_LOCATOR]);
+ ilwt->hook_type = hook_type;
- /* Precompute checksum difference for translation since we
- * know both the old locator and the new one.
- */
- p->locator_match = iaddr->loc;
+ if (tb[ILA_ATTR_NOTIFY_DST])
+ ilwt->notify |= ILA_NOTIFY_DST;
- ila_init_saved_csum(p);
+ if (tb[ILA_ATTR_NOTIFY_SRC])
+ ilwt->notify |= ILA_NOTIFY_SRC;
- newts->type = LWTUNNEL_ENCAP_ILA;
- newts->flags |= LWTUNNEL_STATE_OUTPUT_REDIRECT |
- LWTUNNEL_STATE_INPUT_REDIRECT;
+ p = ila_params_lwtunnel(newts);
+
+ if (tb[ILA_ATTR_LOCATOR]) {
+ ilwt->xlat = true;
+ p->csum_mode = csum_mode;
+ p->ident_type = ident_type;
+ p->locator.v64 = (__force __be64)nla_get_u64(
+ tb[ILA_ATTR_LOCATOR]);
+
+ /* Precompute checksum difference for translation since we
+ * know both the old locator and the new one.
+ */
+ p->locator_match = iaddr->loc;
- if (cfg6->fc_dst_len == 8 * sizeof(struct in6_addr))
- ilwt->connected = 1;
+ ila_init_saved_csum(p);
+
+ if (cfg6->fc_dst_len == 8 * sizeof(struct in6_addr))
+ ilwt->connected = 1;
+ }
*ts = newts;
@@ -264,21 +354,32 @@ static int ila_fill_encap_info(struct sk_buff *skb,
struct ila_params *p = ila_params_lwtunnel(lwtstate);
struct ila_lwt *ilwt = ila_lwt_lwtunnel(lwtstate);
- if (nla_put_u64_64bit(skb, ILA_ATTR_LOCATOR, (__force u64)p->locator.v64,
- ILA_ATTR_PAD))
- goto nla_put_failure;
+ if (ilwt->xlat) {
+ if (nla_put_u64_64bit(skb, ILA_ATTR_LOCATOR,
+ (__force u64)p->locator.v64,
+ ILA_ATTR_PAD))
+ goto nla_put_failure;
- if (nla_put_u8(skb, ILA_ATTR_CSUM_MODE, (__force u8)p->csum_mode))
- goto nla_put_failure;
+ if (nla_put_u8(skb, ILA_ATTR_CSUM_MODE,
+ (__force u8)p->csum_mode))
+ goto nla_put_failure;
- if (nla_put_u8(skb, ILA_ATTR_IDENT_TYPE, (__force u8)p->ident_type))
- goto nla_put_failure;
+ if (nla_put_u8(skb, ILA_ATTR_IDENT_TYPE,
+ (__force u8)p->ident_type))
+ goto nla_put_failure;
+ }
- if (nla_put_u8(skb, ILA_ATTR_HOOK_TYPE,
- ilwt->lwt_output ? ILA_HOOK_ROUTE_OUTPUT :
- ILA_HOOK_ROUTE_INPUT))
+ if (nla_put_u8(skb, ILA_ATTR_HOOK_TYPE, ilwt->hook_type))
goto nla_put_failure;
+ if (ilwt->notify & ILA_NOTIFY_DST)
+ if (nla_put_flag(skb, ILA_ATTR_NOTIFY_DST))
+ goto nla_put_failure;
+
+ if (ilwt->notify & ILA_NOTIFY_SRC)
+ if (nla_put_flag(skb, ILA_ATTR_NOTIFY_SRC))
+ goto nla_put_failure;
+
return 0;
nla_put_failure:
@@ -291,6 +392,8 @@ static int ila_encap_nlsize(struct lwtunnel_state *lwtstate)
nla_total_size(sizeof(u8)) + /* ILA_ATTR_CSUM_MODE */
nla_total_size(sizeof(u8)) + /* ILA_ATTR_IDENT_TYPE */
nla_total_size(sizeof(u8)) + /* ILA_ATTR_HOOK_TYPE */
+ nla_total_size(0) + /* ILA_ATTR_NOTIFY_DST */
+ nla_total_size(0) + /* ILA_ATTR_NOTIFY_SRC */
0;
}
--
2.11.0
^ permalink raw reply related
* Re: [PATCH net 0/2] zerocopy fixes
From: David Miller @ 2017-12-21 20:01 UTC (permalink / raw)
To: willemdebruijn.kernel; +Cc: netdev, willemb
In-Reply-To: <20171220223750.27795-1-willemdebruijn.kernel@gmail.com>
From: Willem de Bruijn <willemdebruijn.kernel@gmail.com>
Date: Wed, 20 Dec 2017 17:37:48 -0500
> From: Willem de Bruijn <willemb@google.com>
>
> The removal of UFO hardware offload support exposed a bug in
> segmentation of zerocopy skbs.
>
> The reference counting mechanism for msg_zerocopy was incorrectly
> applied to vhost_net zerocopy packets.
>
> The other issue observed through analysis. We do not cook skbs
> with skb_zcopy(skb) but no frags, but this is possible in principle.
> Correctly call skb_zcopy_clear on those.
Series applied and queued up for -stable.
^ permalink raw reply
* Re: [PATCH net-next] phylink: avoid attaching more than one PHY
From: David Miller @ 2017-12-21 20:03 UTC (permalink / raw)
To: rmk+kernel; +Cc: andrew, f.fainelli, netdev
In-Reply-To: <E1eRni1-0006jr-Q8@rmk-PC.armlinux.org.uk>
From: Russell King <rmk+kernel@armlinux.org.uk>
Date: Wed, 20 Dec 2017 23:23:33 +0000
> Attaching more than one PHY to phylink is bad news, as we store a
> pointer to the PHY in a single location. Error out if more than one
> PHY is attempted to be attached.
>
> Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
Applied, thank you.
^ permalink raw reply
* Re: [PATCH net-next] net: dwc-xlgmac: Get rid of custom hex_dump_to_buffer()
From: David Miller @ 2017-12-21 20:06 UTC (permalink / raw)
To: Jie.Deng1; +Cc: netdev, Jose.Abreu, andriy.shevchenko
In-Reply-To: <4289b06ad532868c24d92e5ffa5eeb7934cb3d6f.1513833970.git.jiedeng@synopsys.com>
From: Jie Deng <Jie.Deng1@synopsys.com>
Date: Thu, 21 Dec 2017 13:32:00 +0800
> Get rid of custom hex_dump_to_buffer().
>
> The output is slightly changed, i.e. each byte followed by white space.
>
> Note, we don't use print_hex_dump() here since the original code uses
> nedev_dbg().
>
> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> Signed-off-by: Jie Deng <jiedeng@synopsys.com>
Applied, thank you.
^ permalink raw reply
* Re: [PATCH net] l2tp: fix missing print session offset info
From: David Miller @ 2017-12-21 20:08 UTC (permalink / raw)
To: liuhangbin; +Cc: netdev, jchapman
In-Reply-To: <1513838730-14033-1-git-send-email-liuhangbin@gmail.com>
From: Hangbin Liu <liuhangbin@gmail.com>
Date: Thu, 21 Dec 2017 14:45:30 +0800
> + (session->offset &&
> + nla_put_u16(skb, L2TP_ATTR_OFFSET, session->offset) ||
It really discourages people from reviewing your changes when they
don't even compile.
net/l2tp/l2tp_netlink.c: In function ‘l2tp_nl_session_send’:
net/l2tp/l2tp_netlink.c:764:23: warning: suggest parentheses around ‘&&’ within ‘||’ [-Wparentheses]
(session->offset &&
~~~~~~~~~~~~~~~~^~
nla_put_u16(skb, L2TP_ATTR_OFFSET, session->offset) ||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
net/l2tp/l2tp_netlink.c:782:3: error: expected ‘)’ before ‘goto’
goto nla_put_failure;
^~~~
...
^ permalink raw reply
* Re: [PATCH net-next] cxgb4: add new T5 and T6 device id's
From: David Miller @ 2017-12-21 20:13 UTC (permalink / raw)
To: ganeshgr; +Cc: netdev, nirranjan, indranil, venkatesh
In-Reply-To: <1513846796-14910-1-git-send-email-ganeshgr@chelsio.com>
From: Ganesh Goudar <ganeshgr@chelsio.com>
Date: Thu, 21 Dec 2017 14:29:56 +0530
> Add device id's 0x50ac, 0x6087 for T5 and T6 cards
> respectively.
>
> Signed-off-by: Ganesh Goudar <ganeshgr@chelsio.com>
Applied, thanks Ganesh.
^ permalink raw reply
* Re: [PATCH v2 net-next 0/4] sfc: support extra stats on Medford2
From: David Miller @ 2017-12-21 20:15 UTC (permalink / raw)
To: bkenward; +Cc: netdev, linux-net-drivers
In-Reply-To: <2f0a611b-6867-b1c1-0972-94bca9cfcc3b@solarflare.com>
From: Bert Kenward <bkenward@solarflare.com>
Date: Thu, 21 Dec 2017 08:58:38 +0000
> X2000-series NICs add port stats for two new features: FEC (Forward Error
> Correction, used on 25G links) and CTPIO (cut-through programmed I/O).
> This patch series adds support for reporting both of these sets of stats
>
> v2: add additional Signed-off-by
Series applied, thanks.
^ permalink raw reply
* Re: RCU callback crashes
From: Cong Wang @ 2017-12-21 20:17 UTC (permalink / raw)
To: John Fastabend; +Cc: Jakub Kicinski, Jiri Pirko, netdev@vger.kernel.org
In-Reply-To: <97c5063d-fa28-c02f-2ad7-95a08e8d3cee@gmail.com>
On Thu, Dec 21, 2017 at 8:26 AM, John Fastabend
<john.fastabend@gmail.com> wrote:
> On 12/20/2017 11:27 PM, Cong Wang wrote:
>> On Wed, Dec 20, 2017 at 4:50 PM, Jakub Kicinski <kubakici@wp.pl> wrote:
>>> On Wed, 20 Dec 2017 16:41:14 -0800, Jakub Kicinski wrote:
>>>> Just as I hit send... :) but this looks unrelated, "Comm: sshd" -
>>>> so probably from the management interface.
>>>>
>>>> [ 154.604041] ==================================================================
>>>> [ 154.612245] BUG: KASAN: slab-out-of-bounds in pfifo_fast_dequeue+0x140/0x2d0
>>>> [ 154.620219] Read of size 8 at addr ffff88086bb64040 by task sshd/983
>>>> [ 154.627403]
>>>> [ 154.629161] CPU: 10 PID: 983 Comm: sshd Not tainted 4.15.0-rc3-perf-00984-g82d3fc87a4aa-dirty #13
>>>> [ 154.639190] Hardware name: Dell Inc. PowerEdge R730/072T6D, BIOS 2.3.4 11/08/2016
>>>> [ 154.647665] Call Trace:
>>>> [ 154.650494] dump_stack+0xa6/0x118
>>>> [ 154.654387] ? _atomic_dec_and_lock+0xe8/0xe8
>>>> [ 154.659355] ? trace_event_raw_event_rcu_torture_read+0x190/0x190
>>>> [ 154.666263] ? rcu_segcblist_enqueue+0xe9/0x120
>>>> [ 154.671422] ? _raw_spin_unlock_bh+0x91/0xc0
>>>> [ 154.676286] ? pfifo_fast_dequeue+0x140/0x2d0
>>>> [ 154.681251] print_address_description+0x6a/0x270
>>>> [ 154.686601] ? pfifo_fast_dequeue+0x140/0x2d0
>>>> [ 154.691565] kasan_report+0x23f/0x350
>>>> [ 154.695752] pfifo_fast_dequeue+0x140/0x2d0
>>>
>>> If we trust stack decode it's:
>>>
>>> 615 static struct sk_buff *pfifo_fast_dequeue(struct Qdisc *qdisc)
>>> 616 {
>>> 617 struct pfifo_fast_priv *priv = qdisc_priv(qdisc);
>>> 618 struct sk_buff *skb = NULL;
>>> 619 int band;
>>> 620
>>> 621 for (band = 0; band < PFIFO_FAST_BANDS && !skb; band++) {
>>> 622 struct skb_array *q = band2list(priv, band);
>>> 623
>>>>> 624 if (__skb_array_empty(q))
>>> 625 continue;
>>> 626
>>> 627 skb = skb_array_consume_bh(q);
>>> 628 }
>>> 629 if (likely(skb)) {
>>> 630 qdisc_qstats_cpu_backlog_dec(qdisc, skb);
>>> 631 qdisc_bstats_cpu_update(qdisc, skb);
>>> 632 qdisc_qstats_cpu_qlen_dec(qdisc);
>>> 633 }
>>> 634
>>> 635 return skb;
>>> 636 }
>>
>> Yeah, this one is clearly a different one and it is introduced by John's
>> "lockless" patchset.
>>
>> I will take a look tomorrow if John doesn't.
>>
>
> I guess this path
>
> dev_deactivate_many
> dev_deactivate_queue
> qdisc_reset
>
> here we have the qdisc lock but no rcu call or sync before the reset
> does a kfree_skb and cleans up list walks. So possible for xmit path to
> also be pushing skbs onto the array/lists still. I don't think this is
> the issue triggered above but needs to be fixed
No, we already have a synchronize_net() there. It is probably just
a race with BH.
I think you missed the spinlock in dev_qdisc_reset(), at least
the comment right above qdisc_reset() says so.
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 10aaa3b615ce..00ddb5f8f430 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -1097,8 +1097,11 @@ static void dev_qdisc_reset(struct net_device *dev,
{
struct Qdisc *qdisc = dev_queue->qdisc_sleeping;
- if (qdisc)
+ if (qdisc) {
+ spin_lock_bh(qdisc_lock(qdisc));
qdisc_reset(qdisc);
+ spin_unlock_bh(qdisc_lock(qdisc));
+ }
}
/**
^ permalink raw reply related
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