Netdev List
 help / color / mirror / Atom feed
* Re: [patch iproute2 v4 2/3] tc: Add -bs option to batch mode
From: Marcelo Ricardo Leitner @ 2018-01-02 20:04 UTC (permalink / raw)
  To: Chris Mi; +Cc: netdev, gerlitz.or, stephen, dsahern
In-Reply-To: <20180102142804.27145-3-chrism@mellanox.com>

On Tue, Jan 02, 2018 at 11:28:03PM +0900, Chris Mi wrote:
> @@ -240,23 +244,49 @@ static int batch(const char *name)
>  	}
>  
>  	cmdlineno = 0;
> -	while (getcmdline(&line, &len, stdin) != -1) {
> +	if (getcmdline(&line, &len, stdin) == -1)
> +		goto Exit;
> +	do {
>  		char *largv[100];
>  		int largc;
>  
> +		if (getcmdline(&line2, &len, stdin) == -1)
> +			lastline = true;
> +
>  		largc = makeargs(line, largv, 100);
>  		if (largc == 0)
>  			continue;	/* blank line */

If it reads a new line, it won't process anything else after it
because line won't get updated.

  Marcelo

>  
> -		if (do_cmd(largc, largv)) {
> -			fprintf(stderr, "Command failed %s:%d\n", name, cmdlineno);
> +		line = line2;
> +		line2 = NULL;
> +		len = 0;
> +
> +		/*
> +		 * In batch mode, if we haven't accumulated enough commands
> +		 * and this is not the last command, don't send the message
> +		 * immediately.
> +		 */
> +		if (batch_size > 1 && msg_iov_index + 1 != batch_size
> +		    && !lastline)
> +			send = false;
> +		else
> +			send = true;
> +
> +		ret = do_cmd(largc, largv, batch_size, msg_iov_index++, send);
> +		if (ret < 0) {
> +			fprintf(stderr, "Command failed %s:%d\n", name,
> +				cmdlineno);
>  			ret = 1;
>  			if (!force)
>  				break;
>  		}
> -	}
> -	if (line)
> -		free(line);
> +		msg_iov_index %= batch_size;
> +	} while (!lastline);
> +
> +	free_filter_reqs();
> +	free_action_reqs();
> +Exit:
> +	free(line);
>  
>  	rtnl_close(&rth);
>  	return ret;

^ permalink raw reply

* Re: [PATCH net-next 0/5] marvell10g updates
From: David Miller @ 2018-01-02 20:01 UTC (permalink / raw)
  To: linux; +Cc: andrew, f.fainelli, netdev
In-Reply-To: <20171229124412.GA10595@n2100.armlinux.org.uk>

From: Russell King - ARM Linux <linux@armlinux.org.uk>
Date: Fri, 29 Dec 2017 12:44:13 +0000

> This series:
> - adds MDI/MDIX reporting
> - adds support for 10/100Mbps half-duplex link modes
> - adds a comment describing the setup on VF610 ZII boards (where
>   the phy interface mode doesn't change.)
> - cleans up the phy interace mode switching

Series applied, thank you.

^ permalink raw reply

* Re: [Intel-wired-lan] [PATCH] i40e: Delete an error message for a failed memory allocation in i40e_init_interrupt_scheme()
From: Jesse Brandeburg @ 2018-01-02 19:56 UTC (permalink / raw)
  To: SF Markus Elfring
  Cc: netdev, intel-wired-lan, Jeff Kirsher, kernel-janitors, LKML,
	jesse.brandeburg
In-Reply-To: <c9c151e5-bd26-5b72-d26b-c153249811ab@users.sourceforge.net>

On Mon, 1 Jan 2018 20:43:35 +0100
SF Markus Elfring <elfring@users.sourceforge.net> wrote:

> From: Markus Elfring <elfring@users.sourceforge.net>
> Date: Mon, 1 Jan 2018 20:38:14 +0100
> 
> Omit an extra message for a memory allocation failure in this function.
> 
> This issue was detected by using the Coccinelle software.
> 
> Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>

Thanks for the patch.

Acked-by: Jesse Brandeburg <jesse.brandeburg@intel.com>

^ permalink raw reply

* Re: [PATCH iproute2 2/3] link_iptnl: Print tunnel mode
From: Stephen Hemminger @ 2018-01-02 19:54 UTC (permalink / raw)
  To: Serhey Popovych; +Cc: netdev
In-Reply-To: <1514906959-9719-3-git-send-email-serhe.popovych@gmail.com>

On Tue,  2 Jan 2018 17:29:18 +0200
Serhey Popovych <serhe.popovych@gmail.com> wrote:

> Tunnel mode does not appear in parameters print for iptnl
> supported tunnels like ipip and sit, while printed for
> ip6tnl.
> 
> Print tunnel mode with "proto" field for JSON and without
> any name when printing to cli to follow ip6tnl behaviour.
> 
> Signed-off-by: Serhey Popovych <serhe.popovych@gmail.com>
> ---
>  ip/link_iptnl.c |   17 +++++++++++++++++
>  1 file changed, 17 insertions(+)
> 
> diff --git a/ip/link_iptnl.c b/ip/link_iptnl.c
> index d4d935b..afd1696 100644
> --- a/ip/link_iptnl.c
> +++ b/ip/link_iptnl.c
> @@ -372,6 +372,23 @@ static void iptunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[
>  	if (tb[IFLA_IPTUN_COLLECT_METADATA])
>  		print_bool(PRINT_ANY, "external", "external ", true);
>  
> +	if (tb[IFLA_IPTUN_PROTO]) {
> +		switch (rta_getattr_u8(tb[IFLA_IPTUN_PROTO])) {
> +		case IPPROTO_IPIP:
> +			print_string(PRINT_ANY, "proto", "%s ", "ip4ip4");
> +			break;
> +		case IPPROTO_IPV6:
> +			print_string(PRINT_ANY, "proto", "%s ", "ip6ip");
> +			break;
> +		case IPPROTO_MPLS:
> +			print_string(PRINT_ANY, "proto", "%s ", "mplsip");
> +			break;
> +		case 0:
> +			print_string(PRINT_ANY, "proto", "%s ", "any");
> +			break;
> +		}
> +	}
> +
>  	if (tb[IFLA_IPTUN_REMOTE]) {
>  		unsigned int addr = rta_getattr_u32(tb[IFLA_IPTUN_REMOTE]);
>  

In iproute2 utilities the output format must match the input format.
I don't see "proto ip4ip4" as a valid option.

^ permalink raw reply

* Re: [PATCH v3 net-next 2/5] net: tracepoint: replace tcp_set_state tracepoint with inet_sock_set_state tracepoint
From: David Miller @ 2018-01-02 19:52 UTC (permalink / raw)
  To: brendan.d.gregg
  Cc: laoar.shao, songliubraving, marcelo.leitner, rostedt, bgregg,
	netdev, linux-kernel
In-Reply-To: <CAE40pddorDmoaGn2og-7u7vxpDY8uiWN8qEbQ05YYnK8f0Q_XQ@mail.gmail.com>

From: Brendan Gregg <brendan.d.gregg@gmail.com>
Date: Tue, 2 Jan 2018 11:46:26 -0800

> If I'm to use sock:inet_sock_set_state for TCP tracing, I'd like
> sk->sk_protocol exposed as a tracepoint argument so I can match on
> IPPROTO_TCP.

Agreed.

^ permalink raw reply

* Re: [PATCH] NET: usb: qmi_wwan: add support for YUGA CLM920-NC5 PID 0x9625
From: David Miller @ 2018-01-02 19:49 UTC (permalink / raw)
  To: sz.lin; +Cc: bjorn, netdev, linux-usb, linux-kernel
In-Reply-To: <20171229090217.6933-1-sz.lin@moxa.com>

From: SZ Lin (林上智) <sz.lin@moxa.com>
Date: Fri, 29 Dec 2017 17:02:17 +0800

> This patch adds support for PID 0x9625 of YUGA CLM920-NC5.
> 
> YUGA CLM920-NC5 needs to enable QMI_WWAN_QUIRK_DTR before QMI operation.
> 
> qmicli -d /dev/cdc-wdm0 -p --dms-get-revision
> [/dev/cdc-wdm0] Device revision retrieved:
>         Revision: 'CLM920_NC5-V1  1  [Oct 23 2016 19:00:00]'
> 
> Signed-off-by: SZ Lin (林上智) <sz.lin@moxa.com>

Applied, thank you.

^ permalink raw reply

* Re: [patch net-next v4 00/10] net: sched: allow qdiscs to share filter block instances
From: Jiri Pirko @ 2018-01-02 19:49 UTC (permalink / raw)
  To: David Ahern
  Cc: netdev, davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
	f.fainelli, michael.chan, ganeshgr, saeedm, matanb, leonro,
	idosch, jakub.kicinski, simon.horman, pieter.jansenvanvuuren,
	john.hurley, alexander.h.duyck, ogerlitz, john.fastabend, daniel
In-Reply-To: <20171225102346.GB1885@nanopsycho>

Mon, Dec 25, 2017 at 11:23:46AM CET, jiri@resnulli.us wrote:
>Sun, Dec 24, 2017 at 05:25:41PM CET, dsahern@gmail.com wrote:
>>On 12/24/17 1:19 AM, Jiri Pirko wrote:
>>> Sun, Dec 24, 2017 at 02:54:47AM CET, dsahern@gmail.com wrote:
>>>> On 12/23/17 9:54 AM, Jiri Pirko wrote:
>>>>> So back to the example. First, we create 2 qdiscs. Both will share
>>>>> block number 22. "22" is just an identification. If we don't pass any
>>>>> block number, a new one will be generated by kernel:
>>>>>
>>>>> $ tc qdisc add dev ens7 ingress block 22
>>>>>                                 ^^^^^^^^
>>>>> $ tc qdisc add dev ens8 ingress block 22
>>>>>                                 ^^^^^^^^
>>>>>
>>>>> Now if we list the qdiscs, we will see the block index in the output:
>>>>>
>>>>> $ tc qdisc
>>>>> qdisc ingress ffff: dev ens7 parent ffff:fff1 block 22
>>>>> qdisc ingress ffff: dev ens8 parent ffff:fff1 block 22
>>>>>
>>>>> To make is more visual, the situation looks like this:
>>>>>
>>>>>    ens7 ingress qdisc                 ens7 ingress qdisc
>>>>>           |                                  |
>>>>>           |                                  |
>>>>>           +---------->  block 22  <----------+
>>>>>
>>>>> Unlimited number of qdiscs may share the same block.
>>>>>
>>>>> Now we can add filter to any of qdiscs sharing the same block:
>>>>>
>>>>> $ tc filter add dev ens7 ingress protocol ip pref 25 flower dst_ip 192.168.0.0/16 action drop
>>>>
>>>>
>>>> Allowing config of a shared block through any qdisc that references it
>>>> is akin to me allowing nexthop objects to be manipulated by any route
>>>> that references it -- sure, it could be done but causes a lot surprises
>>>> to the user.
>>>>
>>>> You are adding a new tc object -- a shared block. Why the resistance to
>>>> creating a proper API for managing it?
>>> 
>>> Again, no resistance, I said many times it would be done as a follow-up.
>>> But as an api already exists, it has to continue to work. Or do you
>>> suggest it should stop working? That, I don't agree with.
>>> 
>>
>>That is exactly what I am saying - principle of least surprise. The new
>>object brings its own API and can only be modified using the new API.
>>The scheme above can and will surprise users. You are thinking like a tc
>>developer, someone intimately familiar with the code, and not like an
>>ordinary user of this new feature.
>
>Breaking exising tools is newer good. Note that not only about filter
>add/del iface but also dump and notifications. I agree to extend the api
>for the "block handle", sure, but the existing api should continue to
>work.

DaveA, please consider following example:

$ tc qdisc add dev ens7 ingress
$ tc qdisc
qdisc ingress ffff: dev ens7 parent ffff:fff1 block 1

Now I have one device with one qdisc attached.

I will add some filters, for example:
$ tc filter add dev ens7 ingress protocol ip pref 25 flower dst_ip 192.168.0.0/16 action drop

No sharing is happening. The user is doing what he is used to do.

Now user decides to share this filters with another device. As you can
see above, the block created for ens7 qdisc instance has id "1".
User can simply do:

tc qdisc add dev ens8 ingress block 1

And the block gets shared among ens7 ingress qdisc instance and ens8
ingress qdisc instance.

What is wrong with this? The approach you suggest would disallow this
forcing user to explicitly create some block entity and then to attach
it to qdisc instances. I don't really see good reason for it. Could you
please clear this up for me?

Thanks!

^ permalink raw reply

* Re: [PATCH v3 net-next 2/5] net: tracepoint: replace tcp_set_state tracepoint with inet_sock_set_state tracepoint
From: Brendan Gregg @ 2018-01-02 19:46 UTC (permalink / raw)
  To: Yafang Shao
  Cc: Song Liu, David S. Miller, Marcelo Ricardo Leitner,
	Steven Rostedt, Brendan Gregg, netdev, LKML
In-Reply-To: <CALOAHbC4V1EsyecfDXGi-b7P08huhY3+soHdpuqTaEn4AcfVww@mail.gmail.com>

On Sat, Dec 30, 2017 at 7:06 PM, Yafang Shao <laoar.shao@gmail.com> wrote:
> On Sun, Dec 31, 2017 at 6:33 AM, Brendan Gregg
> <brendan.d.gregg@gmail.com> wrote:
>> On Tue, Dec 19, 2017 at 7:12 PM, Yafang Shao <laoar.shao@gmail.com> wrote:
>>> As sk_state is a common field for struct sock, so the state
>>> transition tracepoint should not be a TCP specific feature.
>>> Currently it traces all AF_INET state transition, so I rename this
>>> tracepoint to inet_sock_set_state tracepoint with some minor changes and move it
>>> into trace/events/sock.h.
>>
>> The tcp:tcp_set_state probe is tcp_set_state(), so it's only going to
>> fire for TCP sessions. It's not broken, and we could add a
>> sctp:sctp_set_state as well. Replacing tcp:tcp_set_state with
>> inet_sk_set_state is feeling like we might be baking too much
>> implementation detail into the tracepoint API.
>>
>> If we must have inet_sk_set_state, then must we also delete tcp:tcp_set_state?
>>
>
> Hi Brendan,
>
> The reason we have to make this change could be got from this mail
> thread, https://patchwork.kernel.org/patch/10099243/ .
>
> The original tcp:tcp_set_state probe doesn't traced all TCP state transitions.
> There're some state transitions in inet_connection_sock.c and
> inet_hashtables.c are missed.
> So we have to place this probe into these two files to fix the issue.
> But as inet_connection_sock.c and inet_hashtables.c are common files
> for all IPv4 protocols, not only for TCP, so it is not proper to place
> a tcp_ function in these two files.
> That's why we decide to rename tcp:tcp_set_state probe to
> sock:inet_sock_set_state.

It kinda feels like we are fixing one exposing-implementation problem
(the missing state changes, which I'm happy to see fixed), by exposing
another (there's no tcp:tcp_set_state because we don't want to put tcp
functions in inet*.c files). Anyway...

If I'm to use sock:inet_sock_set_state for TCP tracing, I'd like
sk->sk_protocol exposed as a tracepoint argument so I can match on
IPPROTO_TCP. Otherwise I'll have to keep digging it out of (void
*)skaddr. (And if we're adding arguments, maybe consider sk_family as
well, to make it easier to see which address arguments to use).

Brendan

^ permalink raw reply

* [PATCH] RDS: Heap OOB write in rds_message_alloc_sgs()
From: simo.ghannam @ 2018-01-02 19:44 UTC (permalink / raw)
  To: netdev; +Cc: Mohamed Ghannam

From: Mohamed Ghannam <simo.ghannam@gmail.com>

When args->nr_local is 0, nr_pages gets also 0 due some size
calculation via rds_rm_size(), which is later used to allocate
pages for DMA, this bug produces a heap Out-Of-Bound write access
to a specific memory region.

Signed-off-by: Mohamed Ghannam <simo.ghannam@gmail.com>
---
 net/rds/rdma.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/net/rds/rdma.c b/net/rds/rdma.c
index bc2f1e0977d6..40a733566eb7 100644
--- a/net/rds/rdma.c
+++ b/net/rds/rdma.c
@@ -525,6 +525,9 @@ int rds_rdma_extra_size(struct rds_rdma_args *args)
 
 	local_vec = (struct rds_iovec __user *)(unsigned long) args->local_vec_addr;
 
+	if (args->nr_local == 0)
+		return -EINVAL;
+
 	/* figure out the number of pages in the vector */
 	for (i = 0; i < args->nr_local; i++) {
 		if (copy_from_user(&vec, &local_vec[i],
-- 
2.14.1

^ permalink raw reply related

* Re: [PATCH net-next] cxgb4: Check alignment constraint for T6
From: David Miller @ 2018-01-02 19:40 UTC (permalink / raw)
  To: ganeshgr; +Cc: netdev, nirranjan, indranil, venkatesh, arjun
In-Reply-To: <1514531884-25004-1-git-send-email-ganeshgr@chelsio.com>

From: Ganesh Goudar <ganeshgr@chelsio.com>
Date: Fri, 29 Dec 2017 12:48:04 +0530

> Update the check for setting  IPV4 filters and align filter_id
> to multiple of 2, only for IPv6 filters in case of T6.
> 
> Signed-off-by: Arjun Vynipadath <arjun@chelsio.com>
> Signed-off-by: Ganesh Goudar <ganeshgr@chelsio.com>

Applied, thank you.

^ permalink raw reply

* Re: [RFC 11/14] tcp_md5: Move TCP-MD5 code out of TCP itself
From: Mat Martineau @ 2018-01-02 19:39 UTC (permalink / raw)
  To: Christoph Paasch; +Cc: netdev, Eric Dumazet, Alexei Starovoitov
In-Reply-To: <20171218215109.38700-12-cpaasch@apple.com>


Hi Christoph -

On Mon, 18 Dec 2017, Christoph Paasch wrote:

> This is all just copy-pasting the TCP_MD5-code into functions that are
> placed in net/ipv4/tcp_md5.c.
>
> Signed-off-by: Christoph Paasch <cpaasch@apple.com>
> Reviewed-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
> ---
> include/linux/inet_diag.h |    1 +
> include/linux/tcp_md5.h   |  138 ++++++
> include/net/tcp.h         |   77 ----
> net/ipv4/Makefile         |    1 +
> net/ipv4/tcp.c            |  133 +-----
> net/ipv4/tcp_diag.c       |   81 +---
> net/ipv4/tcp_input.c      |   38 --
> net/ipv4/tcp_ipv4.c       |  520 ++-------------------
> net/ipv4/tcp_md5.c        | 1102 +++++++++++++++++++++++++++++++++++++++++++++
> net/ipv4/tcp_minisocks.c  |   27 +-
> net/ipv4/tcp_output.c     |    4 +-
> net/ipv6/tcp_ipv6.c       |  318 +------------
> 12 files changed, 1305 insertions(+), 1135 deletions(-)
> create mode 100644 include/linux/tcp_md5.h
> create mode 100644 net/ipv4/tcp_md5.c

...

> diff --git a/include/linux/tcp_md5.h b/include/linux/tcp_md5.h
> new file mode 100644
> index 000000000000..f6a681cdded4
> --- /dev/null
> +++ b/include/linux/tcp_md5.h
> @@ -0,0 +1,138 @@

There's no license info in this new file. Take a look at the SPDX 
identifiers recently added as the first line of some files (like 
tcp_vegas.h) for one way to do it.


> +#ifndef _LINUX_TCP_MD5_H
> +#define _LINUX_TCP_MD5_H
> +
> +#include <linux/skbuff.h>
> +
> +#ifdef CONFIG_TCP_MD5SIG
> +#include <linux/types.h>
> +
> +#include <net/tcp.h>
> +
> +union tcp_md5_addr {
> +	struct in_addr  a4;
> +#if IS_ENABLED(CONFIG_IPV6)
> +	struct in6_addr	a6;
> +#endif
> +};
> +
> +/* - key database */
> +struct tcp_md5sig_key {
> +	struct hlist_node	node;
> +	u8			keylen;
> +	u8			family; /* AF_INET or AF_INET6 */
> +	union tcp_md5_addr	addr;
> +	u8			prefixlen;
> +	u8			key[TCP_MD5SIG_MAXKEYLEN];
> +	struct rcu_head		rcu;
> +};
> +
> +/* - sock block */
> +struct tcp_md5sig_info {
> +	struct hlist_head	head;
> +	struct rcu_head		rcu;
> +};
> +
> +union tcp_md5sum_block {
> +	struct tcp4_pseudohdr ip4;
> +#if IS_ENABLED(CONFIG_IPV6)
> +	struct tcp6_pseudohdr ip6;
> +#endif
> +};
> +
> +/* - pool: digest algorithm, hash description and scratch buffer */
> +struct tcp_md5sig_pool {
> +	struct ahash_request	*md5_req;
> +	void			*scratch;
> +};
> +
> +extern const struct tcp_sock_af_ops tcp_sock_ipv4_specific;
> +extern const struct tcp_sock_af_ops tcp_sock_ipv6_specific;
> +extern const struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific;
> +
> +/* - functions */
> +int tcp_v4_md5_hash_skb(char *md5_hash, const struct tcp_md5sig_key *key,
> +			const struct sock *sk, const struct sk_buff *skb);
> +
> +struct tcp_md5sig_key *tcp_v4_md5_lookup(const struct sock *sk,
> +					 const struct sock *addr_sk);
> +
> +void tcp_v4_md5_destroy_sock(struct sock *sk);
> +
> +int tcp_v4_md5_send_response_prepare(struct sk_buff *skb, u8 flags,
> +				     unsigned int remaining,
> +				     struct tcp_out_options *opts,
> +				     const struct sock *sk);
> +
> +void tcp_v4_md5_send_response_write(__be32 *topt, struct sk_buff *skb,
> +				    struct tcphdr *t1,
> +				    struct tcp_out_options *opts,
> +				    const struct sock *sk);
> +
> +int tcp_v6_md5_send_response_prepare(struct sk_buff *skb, u8 flags,
> +				     unsigned int remaining,
> +				     struct tcp_out_options *opts,
> +				     const struct sock *sk);
> +
> +void tcp_v6_md5_send_response_write(__be32 *topt, struct sk_buff *skb,
> +				    struct tcphdr *t1,
> +				    struct tcp_out_options *opts,
> +				    const struct sock *sk);
> +
> +bool tcp_v4_inbound_md5_hash(const struct sock *sk,
> +			     const struct sk_buff *skb);
> +
> +void tcp_v4_md5_syn_recv_sock(const struct sock *listener, struct sock *sk);
> +
> +void tcp_v6_md5_syn_recv_sock(const struct sock *listener, struct sock *sk);
> +
> +void tcp_md5_time_wait(struct sock *sk, struct inet_timewait_sock *tw);
> +
> +struct tcp_md5sig_key *tcp_v6_md5_lookup(const struct sock *sk,
> +					 const struct sock *addr_sk);
> +
> +int tcp_v6_md5_hash_skb(char *md5_hash,
> +			const struct tcp_md5sig_key *key,
> +			const struct sock *sk,
> +			const struct sk_buff *skb);
> +
> +bool tcp_v6_inbound_md5_hash(const struct sock *sk,
> +			     const struct sk_buff *skb);
> +
> +static inline void tcp_md5_twsk_destructor(struct sock *sk)
> +{
> +	struct tcp_timewait_sock *twsk = tcp_twsk(sk);
> +
> +	if (twsk->tw_md5_key)
> +		kfree_rcu(twsk->tw_md5_key, rcu);
> +}
> +
> +static inline void tcp_md5_add_header_len(const struct sock *listener,
> +					  struct sock *sk)
> +{
> +	struct tcp_sock *tp = tcp_sk(sk);
> +
> +	if (tp->af_specific->md5_lookup(listener, sk))
> +		tp->tcp_header_len += TCPOLEN_MD5SIG_ALIGNED;
> +}
> +
> +int tcp_md5_diag_get_aux(struct sock *sk, bool net_admin, struct sk_buff *skb);
> +
> +int tcp_md5_diag_get_aux_size(struct sock *sk, bool net_admin);
> +
> +#else
> +
> +static inline bool tcp_v4_inbound_md5_hash(const struct sock *sk,
> +					   const struct sk_buff *skb)
> +{
> +	return false;
> +}
> +
> +static inline bool tcp_v6_inbound_md5_hash(const struct sock *sk,
> +					   const struct sk_buff *skb)
> +{
> +	return false;
> +}
> +
> +#endif
> +
> +#endif /* _LINUX_TCP_MD5_H */

...

> diff --git a/net/ipv4/tcp_md5.c b/net/ipv4/tcp_md5.c
> new file mode 100644
> index 000000000000..a31b404e6dbf
> --- /dev/null
> +++ b/net/ipv4/tcp_md5.c
> @@ -0,0 +1,1102 @@

This new file needs license info too, maybe a SPDX identifier like 
tcp_input.c


Regards,
Mat


> +#include <linux/inet_diag.h>
> +#include <linux/inetdevice.h>
> +#include <linux/tcp.h>
> +#include <linux/tcp_md5.h>
> +
> +#include <crypto/hash.h>
> +
> +#include <net/inet6_hashtables.h>
> +
> +static DEFINE_PER_CPU(struct tcp_md5sig_pool, tcp_md5sig_pool);
> +static DEFINE_MUTEX(tcp_md5sig_mutex);
> +static bool tcp_md5sig_pool_populated;
> +
> +#define tcp_twsk_md5_key(twsk)	((twsk)->tw_md5_key)
> +
> +static void __tcp_alloc_md5sig_pool(void)
> +{
> +	struct crypto_ahash *hash;
> +	int cpu;
> +
> +	hash = crypto_alloc_ahash("md5", 0, CRYPTO_ALG_ASYNC);
> +	if (IS_ERR(hash))
> +		return;
> +
> +	for_each_possible_cpu(cpu) {
> +		void *scratch = per_cpu(tcp_md5sig_pool, cpu).scratch;
> +		struct ahash_request *req;
> +
> +		if (!scratch) {
> +			scratch = kmalloc_node(sizeof(union tcp_md5sum_block) +
> +					       sizeof(struct tcphdr),
> +					       GFP_KERNEL,
> +					       cpu_to_node(cpu));
> +			if (!scratch)
> +				return;
> +			per_cpu(tcp_md5sig_pool, cpu).scratch = scratch;
> +		}
> +		if (per_cpu(tcp_md5sig_pool, cpu).md5_req)
> +			continue;
> +
> +		req = ahash_request_alloc(hash, GFP_KERNEL);
> +		if (!req)
> +			return;
> +
> +		ahash_request_set_callback(req, 0, NULL, NULL);
> +
> +		per_cpu(tcp_md5sig_pool, cpu).md5_req = req;
> +	}
> +	/* before setting tcp_md5sig_pool_populated, we must commit all writes
> +	 * to memory. See smp_rmb() in tcp_get_md5sig_pool()
> +	 */
> +	smp_wmb();
> +	tcp_md5sig_pool_populated = true;
> +}
> +
> +static bool tcp_alloc_md5sig_pool(void)
> +{
> +	if (unlikely(!tcp_md5sig_pool_populated)) {
> +		mutex_lock(&tcp_md5sig_mutex);
> +
> +		if (!tcp_md5sig_pool_populated)
> +			__tcp_alloc_md5sig_pool();
> +
> +		mutex_unlock(&tcp_md5sig_mutex);
> +	}
> +	return tcp_md5sig_pool_populated;
> +}
> +
> +static void tcp_put_md5sig_pool(void)
> +{
> +	local_bh_enable();
> +}
> +
> +/**
> + *	tcp_get_md5sig_pool - get md5sig_pool for this user
> + *
> + *	We use percpu structure, so if we succeed, we exit with preemption
> + *	and BH disabled, to make sure another thread or softirq handling
> + *	wont try to get same context.
> + */
> +static struct tcp_md5sig_pool *tcp_get_md5sig_pool(void)
> +{
> +	local_bh_disable();
> +
> +	if (tcp_md5sig_pool_populated) {
> +		/* coupled with smp_wmb() in __tcp_alloc_md5sig_pool() */
> +		smp_rmb();
> +		return this_cpu_ptr(&tcp_md5sig_pool);
> +	}
> +	local_bh_enable();
> +	return NULL;
> +}
> +
> +static struct tcp_md5sig_key *tcp_md5_do_lookup_exact(const struct sock *sk,
> +						      const union tcp_md5_addr *addr,
> +						      int family, u8 prefixlen)
> +{
> +	const struct tcp_sock *tp = tcp_sk(sk);
> +	struct tcp_md5sig_key *key;
> +	unsigned int size = sizeof(struct in_addr);
> +	const struct tcp_md5sig_info *md5sig;
> +
> +	/* caller either holds rcu_read_lock() or socket lock */
> +	md5sig = rcu_dereference_check(tp->md5sig_info,
> +				       lockdep_sock_is_held(sk));
> +	if (!md5sig)
> +		return NULL;
> +#if IS_ENABLED(CONFIG_IPV6)
> +	if (family == AF_INET6)
> +		size = sizeof(struct in6_addr);
> +#endif
> +	hlist_for_each_entry_rcu(key, &md5sig->head, node) {
> +		if (key->family != family)
> +			continue;
> +		if (!memcmp(&key->addr, addr, size) &&
> +		    key->prefixlen == prefixlen)
> +			return key;
> +	}
> +	return NULL;
> +}
> +
> +/* This can be called on a newly created socket, from other files */
> +static int tcp_md5_do_add(struct sock *sk, const union tcp_md5_addr *addr,
> +			  int family, u8 prefixlen, const u8 *newkey,
> +			  u8 newkeylen, gfp_t gfp)
> +{
> +	/* Add Key to the list */
> +	struct tcp_md5sig_key *key;
> +	struct tcp_sock *tp = tcp_sk(sk);
> +	struct tcp_md5sig_info *md5sig;
> +
> +	key = tcp_md5_do_lookup_exact(sk, addr, family, prefixlen);
> +	if (key) {
> +		/* Pre-existing entry - just update that one. */
> +		memcpy(key->key, newkey, newkeylen);
> +		key->keylen = newkeylen;
> +		return 0;
> +	}
> +
> +	md5sig = rcu_dereference_protected(tp->md5sig_info,
> +					   lockdep_sock_is_held(sk));
> +	if (!md5sig) {
> +		md5sig = kmalloc(sizeof(*md5sig), gfp);
> +		if (!md5sig)
> +			return -ENOMEM;
> +
> +		sk_nocaps_add(sk, NETIF_F_GSO_MASK);
> +		INIT_HLIST_HEAD(&md5sig->head);
> +		rcu_assign_pointer(tp->md5sig_info, md5sig);
> +	}
> +
> +	key = sock_kmalloc(sk, sizeof(*key), gfp);
> +	if (!key)
> +		return -ENOMEM;
> +	if (!tcp_alloc_md5sig_pool()) {
> +		sock_kfree_s(sk, key, sizeof(*key));
> +		return -ENOMEM;
> +	}
> +
> +	memcpy(key->key, newkey, newkeylen);
> +	key->keylen = newkeylen;
> +	key->family = family;
> +	key->prefixlen = prefixlen;
> +	memcpy(&key->addr, addr,
> +	       (family == AF_INET6) ? sizeof(struct in6_addr) :
> +				      sizeof(struct in_addr));
> +	hlist_add_head_rcu(&key->node, &md5sig->head);
> +	return 0;
> +}
> +
> +static void tcp_clear_md5_list(struct sock *sk)
> +{
> +	struct tcp_sock *tp = tcp_sk(sk);
> +	struct tcp_md5sig_key *key;
> +	struct hlist_node *n;
> +	struct tcp_md5sig_info *md5sig;
> +
> +	md5sig = rcu_dereference_protected(tp->md5sig_info, 1);
> +
> +	hlist_for_each_entry_safe(key, n, &md5sig->head, node) {
> +		hlist_del_rcu(&key->node);
> +		atomic_sub(sizeof(*key), &sk->sk_omem_alloc);
> +		kfree_rcu(key, rcu);
> +	}
> +}
> +
> +static int tcp_md5_do_del(struct sock *sk, const union tcp_md5_addr *addr,
> +			  int family, u8 prefixlen)
> +{
> +	struct tcp_md5sig_key *key;
> +
> +	key = tcp_md5_do_lookup_exact(sk, addr, family, prefixlen);
> +	if (!key)
> +		return -ENOENT;
> +	hlist_del_rcu(&key->node);
> +	atomic_sub(sizeof(*key), &sk->sk_omem_alloc);
> +	kfree_rcu(key, rcu);
> +	return 0;
> +}
> +
> +static int tcp_md5_hash_key(struct tcp_md5sig_pool *hp,
> +			    const struct tcp_md5sig_key *key)
> +{
> +	struct scatterlist sg;
> +
> +	sg_init_one(&sg, key->key, key->keylen);
> +	ahash_request_set_crypt(hp->md5_req, &sg, NULL, key->keylen);
> +	return crypto_ahash_update(hp->md5_req);
> +}
> +
> +static int tcp_v4_parse_md5_keys(struct sock *sk, int optname,
> +				 char __user *optval, int optlen)
> +{
> +	struct tcp_md5sig cmd;
> +	struct sockaddr_in *sin = (struct sockaddr_in *)&cmd.tcpm_addr;
> +	u8 prefixlen = 32;
> +
> +	if (optlen < sizeof(cmd))
> +		return -EINVAL;
> +
> +	if (copy_from_user(&cmd, optval, sizeof(cmd)))
> +		return -EFAULT;
> +
> +	if (sin->sin_family != AF_INET)
> +		return -EINVAL;
> +
> +	if (optname == TCP_MD5SIG_EXT &&
> +	    cmd.tcpm_flags & TCP_MD5SIG_FLAG_PREFIX) {
> +		prefixlen = cmd.tcpm_prefixlen;
> +		if (prefixlen > 32)
> +			return -EINVAL;
> +	}
> +
> +	if (!cmd.tcpm_keylen)
> +		return tcp_md5_do_del(sk, (union tcp_md5_addr *)&sin->sin_addr.s_addr,
> +				      AF_INET, prefixlen);
> +
> +	if (cmd.tcpm_keylen > TCP_MD5SIG_MAXKEYLEN)
> +		return -EINVAL;
> +
> +	return tcp_md5_do_add(sk, (union tcp_md5_addr *)&sin->sin_addr.s_addr,
> +			      AF_INET, prefixlen, cmd.tcpm_key, cmd.tcpm_keylen,
> +			      GFP_KERNEL);
> +}
> +
> +#if IS_ENABLED(CONFIG_IPV6)
> +static int tcp_v6_parse_md5_keys(struct sock *sk, int optname,
> +				 char __user *optval, int optlen)
> +{
> +	struct tcp_md5sig cmd;
> +	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&cmd.tcpm_addr;
> +	u8 prefixlen;
> +
> +	if (optlen < sizeof(cmd))
> +		return -EINVAL;
> +
> +	if (copy_from_user(&cmd, optval, sizeof(cmd)))
> +		return -EFAULT;
> +
> +	if (sin6->sin6_family != AF_INET6)
> +		return -EINVAL;
> +
> +	if (optname == TCP_MD5SIG_EXT &&
> +	    cmd.tcpm_flags & TCP_MD5SIG_FLAG_PREFIX) {
> +		prefixlen = cmd.tcpm_prefixlen;
> +		if (prefixlen > 128 || (ipv6_addr_v4mapped(&sin6->sin6_addr) &&
> +					prefixlen > 32))
> +			return -EINVAL;
> +	} else {
> +		prefixlen = ipv6_addr_v4mapped(&sin6->sin6_addr) ? 32 : 128;
> +	}
> +
> +	if (!cmd.tcpm_keylen) {
> +		if (ipv6_addr_v4mapped(&sin6->sin6_addr))
> +			return tcp_md5_do_del(sk, (union tcp_md5_addr *)&sin6->sin6_addr.s6_addr32[3],
> +					      AF_INET, prefixlen);
> +		return tcp_md5_do_del(sk, (union tcp_md5_addr *)&sin6->sin6_addr,
> +				      AF_INET6, prefixlen);
> +	}
> +
> +	if (cmd.tcpm_keylen > TCP_MD5SIG_MAXKEYLEN)
> +		return -EINVAL;
> +
> +	if (ipv6_addr_v4mapped(&sin6->sin6_addr))
> +		return tcp_md5_do_add(sk, (union tcp_md5_addr *)&sin6->sin6_addr.s6_addr32[3],
> +				      AF_INET, prefixlen, cmd.tcpm_key,
> +				      cmd.tcpm_keylen, GFP_KERNEL);
> +
> +	return tcp_md5_do_add(sk, (union tcp_md5_addr *)&sin6->sin6_addr,
> +			      AF_INET6, prefixlen, cmd.tcpm_key,
> +			      cmd.tcpm_keylen, GFP_KERNEL);
> +}
> +#endif
> +
> +static int tcp_v4_md5_hash_headers(struct tcp_md5sig_pool *hp,
> +				   __be32 daddr, __be32 saddr,
> +				   const struct tcphdr *th, int nbytes)
> +{
> +	struct tcp4_pseudohdr *bp;
> +	struct scatterlist sg;
> +	struct tcphdr *_th;
> +
> +	bp = hp->scratch;
> +	bp->saddr = saddr;
> +	bp->daddr = daddr;
> +	bp->pad = 0;
> +	bp->protocol = IPPROTO_TCP;
> +	bp->len = cpu_to_be16(nbytes);
> +
> +	_th = (struct tcphdr *)(bp + 1);
> +	memcpy(_th, th, sizeof(*th));
> +	_th->check = 0;
> +
> +	sg_init_one(&sg, bp, sizeof(*bp) + sizeof(*th));
> +	ahash_request_set_crypt(hp->md5_req, &sg, NULL,
> +				sizeof(*bp) + sizeof(*th));
> +	return crypto_ahash_update(hp->md5_req);
> +}
> +
> +#if IS_ENABLED(CONFIG_IPV6)
> +static int tcp_v6_md5_hash_headers(struct tcp_md5sig_pool *hp,
> +				   const struct in6_addr *daddr,
> +				   const struct in6_addr *saddr,
> +				   const struct tcphdr *th, int nbytes)
> +{
> +	struct tcp6_pseudohdr *bp;
> +	struct scatterlist sg;
> +	struct tcphdr *_th;
> +
> +	bp = hp->scratch;
> +	/* 1. TCP pseudo-header (RFC2460) */
> +	bp->saddr = *saddr;
> +	bp->daddr = *daddr;
> +	bp->protocol = cpu_to_be32(IPPROTO_TCP);
> +	bp->len = cpu_to_be32(nbytes);
> +
> +	_th = (struct tcphdr *)(bp + 1);
> +	memcpy(_th, th, sizeof(*th));
> +	_th->check = 0;
> +
> +	sg_init_one(&sg, bp, sizeof(*bp) + sizeof(*th));
> +	ahash_request_set_crypt(hp->md5_req, &sg, NULL,
> +				sizeof(*bp) + sizeof(*th));
> +	return crypto_ahash_update(hp->md5_req);
> +}
> +#endif
> +
> +static int tcp_v4_md5_hash_hdr(char *md5_hash, const struct tcp_md5sig_key *key,
> +			       __be32 daddr, __be32 saddr,
> +			       const struct tcphdr *th)
> +{
> +	struct tcp_md5sig_pool *hp;
> +	struct ahash_request *req;
> +
> +	hp = tcp_get_md5sig_pool();
> +	if (!hp)
> +		goto clear_hash_noput;
> +	req = hp->md5_req;
> +
> +	if (crypto_ahash_init(req))
> +		goto clear_hash;
> +	if (tcp_v4_md5_hash_headers(hp, daddr, saddr, th, th->doff << 2))
> +		goto clear_hash;
> +	if (tcp_md5_hash_key(hp, key))
> +		goto clear_hash;
> +	ahash_request_set_crypt(req, NULL, md5_hash, 0);
> +	if (crypto_ahash_final(req))
> +		goto clear_hash;
> +
> +	tcp_put_md5sig_pool();
> +	return 0;
> +
> +clear_hash:
> +	tcp_put_md5sig_pool();
> +clear_hash_noput:
> +	memset(md5_hash, 0, 16);
> +	return 1;
> +}
> +
> +#if IS_ENABLED(CONFIG_IPV6)
> +static int tcp_v6_md5_hash_hdr(char *md5_hash, const struct tcp_md5sig_key *key,
> +			       const struct in6_addr *daddr,
> +			       struct in6_addr *saddr, const struct tcphdr *th)
> +{
> +	struct tcp_md5sig_pool *hp;
> +	struct ahash_request *req;
> +
> +	hp = tcp_get_md5sig_pool();
> +	if (!hp)
> +		goto clear_hash_noput;
> +	req = hp->md5_req;
> +
> +	if (crypto_ahash_init(req))
> +		goto clear_hash;
> +	if (tcp_v6_md5_hash_headers(hp, daddr, saddr, th, th->doff << 2))
> +		goto clear_hash;
> +	if (tcp_md5_hash_key(hp, key))
> +		goto clear_hash;
> +	ahash_request_set_crypt(req, NULL, md5_hash, 0);
> +	if (crypto_ahash_final(req))
> +		goto clear_hash;
> +
> +	tcp_put_md5sig_pool();
> +	return 0;
> +
> +clear_hash:
> +	tcp_put_md5sig_pool();
> +clear_hash_noput:
> +	memset(md5_hash, 0, 16);
> +	return 1;
> +}
> +#endif
> +
> +/* RFC2385 MD5 checksumming requires a mapping of
> + * IP address->MD5 Key.
> + * We need to maintain these in the sk structure.
> + */
> +
> +/* Find the Key structure for an address.  */
> +static struct tcp_md5sig_key *tcp_md5_do_lookup(const struct sock *sk,
> +						const union tcp_md5_addr *addr,
> +						int family)
> +{
> +	const struct tcp_sock *tp = tcp_sk(sk);
> +	struct tcp_md5sig_key *key;
> +	const struct tcp_md5sig_info *md5sig;
> +	__be32 mask;
> +	struct tcp_md5sig_key *best_match = NULL;
> +	bool match;
> +
> +	/* caller either holds rcu_read_lock() or socket lock */
> +	md5sig = rcu_dereference_check(tp->md5sig_info,
> +				       lockdep_sock_is_held(sk));
> +	if (!md5sig)
> +		return NULL;
> +
> +	hlist_for_each_entry_rcu(key, &md5sig->head, node) {
> +		if (key->family != family)
> +			continue;
> +
> +		if (family == AF_INET) {
> +			mask = inet_make_mask(key->prefixlen);
> +			match = (key->addr.a4.s_addr & mask) ==
> +				(addr->a4.s_addr & mask);
> +#if IS_ENABLED(CONFIG_IPV6)
> +		} else if (family == AF_INET6) {
> +			match = ipv6_prefix_equal(&key->addr.a6, &addr->a6,
> +						  key->prefixlen);
> +#endif
> +		} else {
> +			match = false;
> +		}
> +
> +		if (match && (!best_match ||
> +			      key->prefixlen > best_match->prefixlen))
> +			best_match = key;
> +	}
> +	return best_match;
> +}
> +
> +/* Parse MD5 Signature option */
> +static const u8 *tcp_parse_md5sig_option(const struct tcphdr *th)
> +{
> +	int length = (th->doff << 2) - sizeof(*th);
> +	const u8 *ptr = (const u8 *)(th + 1);
> +
> +	/* If the TCP option is too short, we can short cut */
> +	if (length < TCPOLEN_MD5SIG)
> +		return NULL;
> +
> +	while (length > 0) {
> +		int opcode = *ptr++;
> +		int opsize;
> +
> +		switch (opcode) {
> +		case TCPOPT_EOL:
> +			return NULL;
> +		case TCPOPT_NOP:
> +			length--;
> +			continue;
> +		default:
> +			opsize = *ptr++;
> +			if (opsize < 2 || opsize > length)
> +				return NULL;
> +			if (opcode == TCPOPT_MD5SIG)
> +				return opsize == TCPOLEN_MD5SIG ? ptr : NULL;
> +		}
> +		ptr += opsize - 2;
> +		length -= opsize;
> +	}
> +	return NULL;
> +}
> +
> +#if IS_ENABLED(CONFIG_IPV6)
> +static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(const struct sock *sk,
> +						   const struct in6_addr *addr)
> +{
> +	return tcp_md5_do_lookup(sk, (union tcp_md5_addr *)addr, AF_INET6);
> +}
> +#endif
> +
> +static int tcp_md5_hash_skb_data(struct tcp_md5sig_pool *hp,
> +				 const struct sk_buff *skb,
> +				 unsigned int header_len)
> +{
> +	struct scatterlist sg;
> +	const struct tcphdr *tp = tcp_hdr(skb);
> +	struct ahash_request *req = hp->md5_req;
> +	unsigned int i;
> +	const unsigned int head_data_len = skb_headlen(skb) > header_len ?
> +					   skb_headlen(skb) - header_len : 0;
> +	const struct skb_shared_info *shi = skb_shinfo(skb);
> +	struct sk_buff *frag_iter;
> +
> +	sg_init_table(&sg, 1);
> +
> +	sg_set_buf(&sg, ((u8 *)tp) + header_len, head_data_len);
> +	ahash_request_set_crypt(req, &sg, NULL, head_data_len);
> +	if (crypto_ahash_update(req))
> +		return 1;
> +
> +	for (i = 0; i < shi->nr_frags; ++i) {
> +		const struct skb_frag_struct *f = &shi->frags[i];
> +		unsigned int offset = f->page_offset;
> +		struct page *page = skb_frag_page(f) + (offset >> PAGE_SHIFT);
> +
> +		sg_set_page(&sg, page, skb_frag_size(f),
> +			    offset_in_page(offset));
> +		ahash_request_set_crypt(req, &sg, NULL, skb_frag_size(f));
> +		if (crypto_ahash_update(req))
> +			return 1;
> +	}
> +
> +	skb_walk_frags(skb, frag_iter)
> +		if (tcp_md5_hash_skb_data(hp, frag_iter, 0))
> +			return 1;
> +
> +	return 0;
> +}
> +
> +int tcp_v4_md5_send_response_prepare(struct sk_buff *skb, u8 flags,
> +				     unsigned int remaining,
> +				     struct tcp_out_options *opts,
> +				     const struct sock *sk)
> +{
> +	const struct tcphdr *th = tcp_hdr(skb);
> +	const struct iphdr *iph = ip_hdr(skb);
> +	const __u8 *hash_location = NULL;
> +
> +	rcu_read_lock();
> +	hash_location = tcp_parse_md5sig_option(th);
> +	if (sk && sk_fullsock(sk)) {
> +		opts->md5 = tcp_md5_do_lookup(sk,
> +					      (union tcp_md5_addr *)&iph->saddr,
> +					      AF_INET);
> +	} else if (sk && sk->sk_state == TCP_TIME_WAIT) {
> +		struct tcp_timewait_sock *tcptw = tcp_twsk(sk);
> +
> +		opts->md5 = tcp_twsk_md5_key(tcptw);
> +	} else if (sk && sk->sk_state == TCP_NEW_SYN_RECV) {
> +		opts->md5 = tcp_md5_do_lookup(sk,
> +					      (union tcp_md5_addr *)&iph->saddr,
> +					      AF_INET);
> +	} else if (hash_location) {
> +		unsigned char newhash[16];
> +		struct sock *sk1;
> +		int genhash;
> +
> +		/* active side is lost. Try to find listening socket through
> +		 * source port, and then find md5 key through listening socket.
> +		 * we are not loose security here:
> +		 * Incoming packet is checked with md5 hash with finding key,
> +		 * no RST generated if md5 hash doesn't match.
> +		 */
> +		sk1 = __inet_lookup_listener(dev_net(skb_dst(skb)->dev),
> +					     &tcp_hashinfo, NULL, 0,
> +					     iph->saddr,
> +					     th->source, iph->daddr,
> +					     ntohs(th->source), inet_iif(skb),
> +					     tcp_v4_sdif(skb));
> +		/* don't send rst if it can't find key */
> +		if (!sk1)
> +			goto out_err;
> +
> +		opts->md5 = tcp_md5_do_lookup(sk1, (union tcp_md5_addr *)
> +					      &iph->saddr, AF_INET);
> +		if (!opts->md5)
> +			goto out_err;
> +
> +		genhash = tcp_v4_md5_hash_skb(newhash, opts->md5, NULL, skb);
> +		if (genhash || memcmp(hash_location, newhash, 16) != 0)
> +			goto out_err;
> +	}
> +
> +	if (opts->md5)
> +		return TCPOLEN_MD5SIG_ALIGNED;
> +
> +	rcu_read_unlock();
> +	return 0;
> +
> +out_err:
> +	rcu_read_unlock();
> +	return -1;
> +}
> +
> +void tcp_v4_md5_send_response_write(__be32 *topt, struct sk_buff *skb,
> +				    struct tcphdr *t1,
> +				    struct tcp_out_options *opts,
> +				    const struct sock *sk)
> +{
> +	if (opts->md5) {
> +		*topt++ = htonl((TCPOPT_NOP << 24) |
> +				(TCPOPT_NOP << 16) |
> +				(TCPOPT_MD5SIG << 8) |
> +				TCPOLEN_MD5SIG);
> +
> +		tcp_v4_md5_hash_hdr((__u8 *)topt, opts->md5,
> +				    ip_hdr(skb)->saddr,
> +				    ip_hdr(skb)->daddr, t1);
> +		rcu_read_unlock();
> +	}
> +}
> +
> +#if IS_ENABLED(CONFIG_IPV6)
> +int tcp_v6_md5_send_response_prepare(struct sk_buff *skb, u8 flags,
> +				     unsigned int remaining,
> +				     struct tcp_out_options *opts,
> +				     const struct sock *sk)
> +{
> +	const struct tcphdr *th = tcp_hdr(skb);
> +	struct ipv6hdr *ipv6h = ipv6_hdr(skb);
> +	const __u8 *hash_location = NULL;
> +
> +	rcu_read_lock();
> +	hash_location = tcp_parse_md5sig_option(th);
> +	if (sk && sk_fullsock(sk)) {
> +		opts->md5 = tcp_v6_md5_do_lookup(sk, &ipv6h->saddr);
> +	} else if (sk && sk->sk_state == TCP_TIME_WAIT) {
> +		struct tcp_timewait_sock *tcptw = tcp_twsk(sk);
> +
> +		opts->md5 = tcp_twsk_md5_key(tcptw);
> +	} else if (sk && sk->sk_state == TCP_NEW_SYN_RECV) {
> +		opts->md5 = tcp_v6_md5_do_lookup(sk, &ipv6h->saddr);
> +	} else if (hash_location) {
> +		unsigned char newhash[16];
> +		struct sock *sk1;
> +		int genhash;
> +
> +		/* active side is lost. Try to find listening socket through
> +		 * source port, and then find md5 key through listening socket.
> +		 * we are not loose security here:
> +		 * Incoming packet is checked with md5 hash with finding key,
> +		 * no RST generated if md5 hash doesn't match.
> +		 */
> +		sk1 = inet6_lookup_listener(dev_net(skb_dst(skb)->dev),
> +					    &tcp_hashinfo, NULL, 0,
> +					    &ipv6h->saddr,
> +					    th->source, &ipv6h->daddr,
> +					    ntohs(th->source), tcp_v6_iif(skb),
> +					    tcp_v6_sdif(skb));
> +		if (!sk1)
> +			goto out_err;
> +
> +		opts->md5 = tcp_v6_md5_do_lookup(sk1, &ipv6h->saddr);
> +		if (!opts->md5)
> +			goto out_err;
> +
> +		genhash = tcp_v6_md5_hash_skb(newhash, opts->md5, NULL, skb);
> +		if (genhash || memcmp(hash_location, newhash, 16) != 0)
> +			goto out_err;
> +	}
> +
> +	if (opts->md5)
> +		return TCPOLEN_MD5SIG_ALIGNED;
> +
> +	rcu_read_unlock();
> +	return 0;
> +
> +out_err:
> +	rcu_read_unlock();
> +	return -1;
> +}
> +EXPORT_SYMBOL_GPL(tcp_v6_md5_send_response_prepare);
> +
> +void tcp_v6_md5_send_response_write(__be32 *topt, struct sk_buff *skb,
> +				    struct tcphdr *t1,
> +				    struct tcp_out_options *opts,
> +				    const struct sock *sk)
> +{
> +	if (opts->md5) {
> +		*topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
> +				(TCPOPT_MD5SIG << 8) | TCPOLEN_MD5SIG);
> +		tcp_v6_md5_hash_hdr((__u8 *)topt, opts->md5,
> +				    &ipv6_hdr(skb)->saddr,
> +				    &ipv6_hdr(skb)->daddr, t1);
> +
> +		rcu_read_unlock();
> +	}
> +}
> +EXPORT_SYMBOL_GPL(tcp_v6_md5_send_response_write);
> +#endif
> +
> +struct tcp_md5sig_key *tcp_v4_md5_lookup(const struct sock *sk,
> +					 const struct sock *addr_sk)
> +{
> +	const union tcp_md5_addr *addr;
> +
> +	addr = (const union tcp_md5_addr *)&addr_sk->sk_daddr;
> +	return tcp_md5_do_lookup(sk, addr, AF_INET);
> +}
> +EXPORT_SYMBOL(tcp_v4_md5_lookup);
> +
> +int tcp_v4_md5_hash_skb(char *md5_hash, const struct tcp_md5sig_key *key,
> +			const struct sock *sk,
> +			const struct sk_buff *skb)
> +{
> +	struct tcp_md5sig_pool *hp;
> +	struct ahash_request *req;
> +	const struct tcphdr *th = tcp_hdr(skb);
> +	__be32 saddr, daddr;
> +
> +	if (sk) { /* valid for establish/request sockets */
> +		saddr = sk->sk_rcv_saddr;
> +		daddr = sk->sk_daddr;
> +	} else {
> +		const struct iphdr *iph = ip_hdr(skb);
> +
> +		saddr = iph->saddr;
> +		daddr = iph->daddr;
> +	}
> +
> +	hp = tcp_get_md5sig_pool();
> +	if (!hp)
> +		goto clear_hash_noput;
> +	req = hp->md5_req;
> +
> +	if (crypto_ahash_init(req))
> +		goto clear_hash;
> +
> +	if (tcp_v4_md5_hash_headers(hp, daddr, saddr, th, skb->len))
> +		goto clear_hash;
> +	if (tcp_md5_hash_skb_data(hp, skb, th->doff << 2))
> +		goto clear_hash;
> +	if (tcp_md5_hash_key(hp, key))
> +		goto clear_hash;
> +	ahash_request_set_crypt(req, NULL, md5_hash, 0);
> +	if (crypto_ahash_final(req))
> +		goto clear_hash;
> +
> +	tcp_put_md5sig_pool();
> +	return 0;
> +
> +clear_hash:
> +	tcp_put_md5sig_pool();
> +clear_hash_noput:
> +	memset(md5_hash, 0, 16);
> +	return 1;
> +}
> +EXPORT_SYMBOL(tcp_v4_md5_hash_skb);
> +
> +#if IS_ENABLED(CONFIG_IPV6)
> +int tcp_v6_md5_hash_skb(char *md5_hash,
> +			const struct tcp_md5sig_key *key,
> +			const struct sock *sk,
> +			const struct sk_buff *skb)
> +{
> +	const struct in6_addr *saddr, *daddr;
> +	struct tcp_md5sig_pool *hp;
> +	struct ahash_request *req;
> +	const struct tcphdr *th = tcp_hdr(skb);
> +
> +	if (sk) { /* valid for establish/request sockets */
> +		saddr = &sk->sk_v6_rcv_saddr;
> +		daddr = &sk->sk_v6_daddr;
> +	} else {
> +		const struct ipv6hdr *ip6h = ipv6_hdr(skb);
> +
> +		saddr = &ip6h->saddr;
> +		daddr = &ip6h->daddr;
> +	}
> +
> +	hp = tcp_get_md5sig_pool();
> +	if (!hp)
> +		goto clear_hash_noput;
> +	req = hp->md5_req;
> +
> +	if (crypto_ahash_init(req))
> +		goto clear_hash;
> +
> +	if (tcp_v6_md5_hash_headers(hp, daddr, saddr, th, skb->len))
> +		goto clear_hash;
> +	if (tcp_md5_hash_skb_data(hp, skb, th->doff << 2))
> +		goto clear_hash;
> +	if (tcp_md5_hash_key(hp, key))
> +		goto clear_hash;
> +	ahash_request_set_crypt(req, NULL, md5_hash, 0);
> +	if (crypto_ahash_final(req))
> +		goto clear_hash;
> +
> +	tcp_put_md5sig_pool();
> +	return 0;
> +
> +clear_hash:
> +	tcp_put_md5sig_pool();
> +clear_hash_noput:
> +	memset(md5_hash, 0, 16);
> +	return 1;
> +}
> +EXPORT_SYMBOL_GPL(tcp_v6_md5_hash_skb);
> +#endif
> +
> +/* Called with rcu_read_lock() */
> +bool tcp_v4_inbound_md5_hash(const struct sock *sk,
> +			     const struct sk_buff *skb)
> +{
> +	/* This gets called for each TCP segment that arrives
> +	 * so we want to be efficient.
> +	 * We have 3 drop cases:
> +	 * o No MD5 hash and one expected.
> +	 * o MD5 hash and we're not expecting one.
> +	 * o MD5 hash and its wrong.
> +	 */
> +	const __u8 *hash_location = NULL;
> +	struct tcp_md5sig_key *hash_expected;
> +	const struct iphdr *iph = ip_hdr(skb);
> +	const struct tcphdr *th = tcp_hdr(skb);
> +	int genhash;
> +	unsigned char newhash[16];
> +
> +	hash_expected = tcp_md5_do_lookup(sk, (union tcp_md5_addr *)&iph->saddr,
> +					  AF_INET);
> +	hash_location = tcp_parse_md5sig_option(th);
> +
> +	/* We've parsed the options - do we have a hash? */
> +	if (!hash_expected && !hash_location)
> +		return false;
> +
> +	if (hash_expected && !hash_location) {
> +		NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMD5NOTFOUND);
> +		return true;
> +	}
> +
> +	if (!hash_expected && hash_location) {
> +		NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMD5UNEXPECTED);
> +		return true;
> +	}
> +
> +	/* Okay, so this is hash_expected and hash_location -
> +	 * so we need to calculate the checksum.
> +	 */
> +	genhash = tcp_v4_md5_hash_skb(newhash,
> +				      hash_expected,
> +				      NULL, skb);
> +
> +	if (genhash || memcmp(hash_location, newhash, 16) != 0) {
> +		NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMD5FAILURE);
> +		net_info_ratelimited("MD5 Hash failed for (%pI4, %d)->(%pI4, %d)%s\n",
> +				     &iph->saddr, ntohs(th->source),
> +				     &iph->daddr, ntohs(th->dest),
> +				     genhash ? " tcp_v4_calc_md5_hash failed"
> +				     : "");
> +		return true;
> +	}
> +	return false;
> +}
> +
> +#if IS_ENABLED(CONFIG_IPV6)
> +bool tcp_v6_inbound_md5_hash(const struct sock *sk,
> +			     const struct sk_buff *skb)
> +{
> +	const __u8 *hash_location = NULL;
> +	struct tcp_md5sig_key *hash_expected;
> +	const struct ipv6hdr *ip6h = ipv6_hdr(skb);
> +	const struct tcphdr *th = tcp_hdr(skb);
> +	int genhash;
> +	u8 newhash[16];
> +
> +	hash_expected = tcp_v6_md5_do_lookup(sk, &ip6h->saddr);
> +	hash_location = tcp_parse_md5sig_option(th);
> +
> +	/* We've parsed the options - do we have a hash? */
> +	if (!hash_expected && !hash_location)
> +		return false;
> +
> +	if (hash_expected && !hash_location) {
> +		NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMD5NOTFOUND);
> +		return true;
> +	}
> +
> +	if (!hash_expected && hash_location) {
> +		NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMD5UNEXPECTED);
> +		return true;
> +	}
> +
> +	/* check the signature */
> +	genhash = tcp_v6_md5_hash_skb(newhash,
> +				      hash_expected,
> +				      NULL, skb);
> +
> +	if (genhash || memcmp(hash_location, newhash, 16) != 0) {
> +		NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMD5FAILURE);
> +		net_info_ratelimited("MD5 Hash %s for [%pI6c]:%u->[%pI6c]:%u\n",
> +				     genhash ? "failed" : "mismatch",
> +				     &ip6h->saddr, ntohs(th->source),
> +				     &ip6h->daddr, ntohs(th->dest));
> +		return true;
> +	}
> +
> +	return false;
> +}
> +EXPORT_SYMBOL_GPL(tcp_v6_inbound_md5_hash);
> +#endif
> +
> +void tcp_v4_md5_destroy_sock(struct sock *sk)
> +{
> +	struct tcp_sock *tp = tcp_sk(sk);
> +
> +	/* Clean up the MD5 key list, if any */
> +	if (tp->md5sig_info) {
> +		tcp_clear_md5_list(sk);
> +		kfree_rcu(tp->md5sig_info, rcu);
> +		tp->md5sig_info = NULL;
> +	}
> +}
> +
> +void tcp_v4_md5_syn_recv_sock(const struct sock *listener, struct sock *sk)
> +{
> +	struct inet_sock *inet = inet_sk(sk);
> +	struct tcp_md5sig_key *key;
> +
> +	/* Copy over the MD5 key from the original socket */
> +	key = tcp_md5_do_lookup(listener, (union tcp_md5_addr *)&inet->inet_daddr,
> +				AF_INET);
> +	if (key) {
> +		/* We're using one, so create a matching key
> +		 * on the sk structure. If we fail to get
> +		 * memory, then we end up not copying the key
> +		 * across. Shucks.
> +		 */
> +		tcp_md5_do_add(sk, (union tcp_md5_addr *)&inet->inet_daddr,
> +			       AF_INET, 32, key->key, key->keylen, GFP_ATOMIC);
> +		sk_nocaps_add(sk, NETIF_F_GSO_MASK);
> +	}
> +}
> +
> +#if IS_ENABLED(CONFIG_IPV6)
> +void tcp_v6_md5_syn_recv_sock(const struct sock *listener, struct sock *sk)
> +{
> +	struct tcp_md5sig_key *key;
> +
> +	/* Copy over the MD5 key from the original socket */
> +	key = tcp_v6_md5_do_lookup(listener, &sk->sk_v6_daddr);
> +	if (key) {
> +		/* We're using one, so create a matching key
> +		 * on the newsk structure. If we fail to get
> +		 * memory, then we end up not copying the key
> +		 * across. Shucks.
> +		 */
> +		tcp_md5_do_add(sk, (union tcp_md5_addr *)&sk->sk_v6_daddr,
> +			       AF_INET6, 128, key->key, key->keylen,
> +			       sk_gfp_mask(sk, GFP_ATOMIC));
> +	}
> +}
> +EXPORT_SYMBOL_GPL(tcp_v6_md5_syn_recv_sock);
> +
> +struct tcp_md5sig_key *tcp_v6_md5_lookup(const struct sock *sk,
> +					 const struct sock *addr_sk)
> +{
> +	return tcp_v6_md5_do_lookup(sk, &addr_sk->sk_v6_daddr);
> +}
> +EXPORT_SYMBOL_GPL(tcp_v6_md5_lookup);
> +#endif
> +
> +void tcp_md5_time_wait(struct sock *sk, struct inet_timewait_sock *tw)
> +{
> +	struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw);
> +	struct tcp_sock *tp = tcp_sk(sk);
> +	struct tcp_md5sig_key *key;
> +
> +	/* The timewait bucket does not have the key DB from the
> +	 * sock structure. We just make a quick copy of the
> +	 * md5 key being used (if indeed we are using one)
> +	 * so the timewait ack generating code has the key.
> +	 */
> +	tcptw->tw_md5_key = NULL;
> +	key = tp->af_specific->md5_lookup(sk, sk);
> +	if (key) {
> +		tcptw->tw_md5_key = kmemdup(key, sizeof(*key), GFP_ATOMIC);
> +		BUG_ON(tcptw->tw_md5_key && !tcp_alloc_md5sig_pool());
> +	}
> +}
> +
> +static void tcp_diag_md5sig_fill(struct tcp_diag_md5sig *info,
> +				 const struct tcp_md5sig_key *key)
> +{
> +	info->tcpm_family = key->family;
> +	info->tcpm_prefixlen = key->prefixlen;
> +	info->tcpm_keylen = key->keylen;
> +	memcpy(info->tcpm_key, key->key, key->keylen);
> +
> +	if (key->family == AF_INET)
> +		info->tcpm_addr[0] = key->addr.a4.s_addr;
> +	#if IS_ENABLED(CONFIG_IPV6)
> +	else if (key->family == AF_INET6)
> +		memcpy(&info->tcpm_addr, &key->addr.a6,
> +		       sizeof(info->tcpm_addr));
> +	#endif
> +}
> +
> +static int tcp_diag_put_md5sig(struct sk_buff *skb,
> +			       const struct tcp_md5sig_info *md5sig)
> +{
> +	const struct tcp_md5sig_key *key;
> +	struct tcp_diag_md5sig *info;
> +	struct nlattr *attr;
> +	int md5sig_count = 0;
> +
> +	hlist_for_each_entry_rcu(key, &md5sig->head, node)
> +		md5sig_count++;
> +	if (md5sig_count == 0)
> +		return 0;
> +
> +	attr = nla_reserve(skb, INET_DIAG_MD5SIG,
> +			   md5sig_count * sizeof(struct tcp_diag_md5sig));
> +	if (!attr)
> +		return -EMSGSIZE;
> +
> +	info = nla_data(attr);
> +	memset(info, 0, md5sig_count * sizeof(struct tcp_diag_md5sig));
> +	hlist_for_each_entry_rcu(key, &md5sig->head, node) {
> +		tcp_diag_md5sig_fill(info++, key);
> +		if (--md5sig_count == 0)
> +			break;
> +	}
> +
> +	return 0;
> +}
> +
> +int tcp_md5_diag_get_aux(struct sock *sk, bool net_admin, struct sk_buff *skb)
> +{
> +	if (net_admin) {
> +		struct tcp_md5sig_info *md5sig;
> +		int err = 0;
> +
> +		rcu_read_lock();
> +		md5sig = rcu_dereference(tcp_sk(sk)->md5sig_info);
> +		if (md5sig)
> +			err = tcp_diag_put_md5sig(skb, md5sig);
> +		rcu_read_unlock();
> +		if (err < 0)
> +			return err;
> +	}
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(tcp_md5_diag_get_aux);
> +
> +int tcp_md5_diag_get_aux_size(struct sock *sk, bool net_admin)
> +{
> +	int size = 0;
> +
> +	if (net_admin && sk_fullsock(sk)) {
> +		const struct tcp_md5sig_info *md5sig;
> +		const struct tcp_md5sig_key *key;
> +		size_t md5sig_count = 0;
> +
> +		rcu_read_lock();
> +		md5sig = rcu_dereference(tcp_sk(sk)->md5sig_info);
> +		if (md5sig) {
> +			hlist_for_each_entry_rcu(key, &md5sig->head, node)
> +				md5sig_count++;
> +		}
> +		rcu_read_unlock();
> +		size += nla_total_size(md5sig_count *
> +				       sizeof(struct tcp_diag_md5sig));
> +	}
> +
> +	return size;
> +}
> +EXPORT_SYMBOL_GPL(tcp_md5_diag_get_aux_size);
> +
> +const struct tcp_sock_af_ops tcp_sock_ipv4_specific = {
> +	.md5_lookup	= tcp_v4_md5_lookup,
> +	.calc_md5_hash	= tcp_v4_md5_hash_skb,
> +	.md5_parse	= tcp_v4_parse_md5_keys,
> +};
> +
> +#if IS_ENABLED(CONFIG_IPV6)
> +const struct tcp_sock_af_ops tcp_sock_ipv6_specific = {
> +	.md5_lookup	=	tcp_v6_md5_lookup,
> +	.calc_md5_hash	=	tcp_v6_md5_hash_skb,
> +	.md5_parse	=	tcp_v6_parse_md5_keys,
> +};
> +EXPORT_SYMBOL_GPL(tcp_sock_ipv6_specific);
> +
> +const struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific = {
> +	.md5_lookup	=	tcp_v4_md5_lookup,
> +	.calc_md5_hash	=	tcp_v4_md5_hash_skb,
> +	.md5_parse	=	tcp_v6_parse_md5_keys,
> +};
> +EXPORT_SYMBOL_GPL(tcp_sock_ipv6_mapped_specific);
> +#endif

^ permalink raw reply

* Re: [patch net-next v5 00/10] net: sched: allow qdiscs to share filter block instances
From: David Miller @ 2018-01-02 19:37 UTC (permalink / raw)
  To: jiri; +Cc: netdev
In-Reply-To: <20180102193612.GF2051@nanopsycho.orion>

From: Jiri Pirko <jiri@resnulli.us>
Date: Tue, 2 Jan 2018 20:36:12 +0100

> Okay. Should I repost v5 so we can continue on that?

I don't think reposting the patch series is necessary for that.

A simple email to restart the discussion on the specific issue of
the API will suffice.

Once you two resolve your discussion, then you can think about
reposting the series.

Thank you.

^ permalink raw reply

* Re: [patch net-next v5 00/10] net: sched: allow qdiscs to share filter block instances
From: Jiri Pirko @ 2018-01-02 19:36 UTC (permalink / raw)
  To: David Miller; +Cc: netdev
In-Reply-To: <20180102.142459.615655443719244387.davem@davemloft.net>

Tue, Jan 02, 2018 at 08:24:59PM CET, davem@davemloft.net wrote:
>From: Jiri Pirko <jiri@resnulli.us>
>Date: Tue, 2 Jan 2018 20:22:59 +0100
>
>> Dave, I see that in pw you flipped this to "Changes Requested". Why?
>
>I think your API discussion with David Ahern needs to continue and is
>not fully resolved.

Okay. Should I repost v5 so we can continue on that?

^ permalink raw reply

* Re: Pravin Shelar
From: David Miller @ 2018-01-02 19:36 UTC (permalink / raw)
  To: pshelar-LZ6Gd1LRuIk
  Cc: joe-6d6DIl74uiNBDgjK7y7TUQ, julia.lawall-L2FTfq7BK8M,
	dev-yBygre7rU0TnMu66kgdUjQ, netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <CAOrHB_ARxdEQ-aYogFCwJgw34Skke1V4SXLO6dGL41Q17xK=_A@mail.gmail.com>

From: Pravin Shelar <pshelar-LZ6Gd1LRuIk@public.gmane.org>
Date: Thu, 28 Dec 2017 15:47:39 -0800

> Thanks Joe for the patch. But it is corrupted. I will send updated patch soon.

I'm still waiting for this, just FYI :)

^ permalink raw reply

* Re: [PATCH net-next 1/2] update ENA driver to version 1.5.0
From: David Miller @ 2018-01-02 19:35 UTC (permalink / raw)
  To: netanel
  Cc: netdev, dwmw, zorik, matua, saeedb, msw, aliguori, nafea, evgenys,
	gtzalik
In-Reply-To: <1514496691-70940-1-git-send-email-netanel@amazon.com>

From: <netanel@amazon.com>
Date: Thu, 28 Dec 2017 21:31:29 +0000

> From: Netanel Belgazal <netanel@amazon.com>
> 
> This patchset contains two changes:
> * Add a robust mechanism for detection of stuck Rx/Tx rings due to
>   missed or misrouted MSI-X
> * Increase the driver version to 1.5.0

I think you meant "[PATCH net-next 0/2]" for this email :-)

Series applied, thanks.

^ permalink raw reply

* Re: [PATCH iproute2] man: fix small formatting errors
From: Stephen Hemminger @ 2018-01-02 19:30 UTC (permalink / raw)
  To: Luca Boccassi; +Cc: netdev
In-Reply-To: <20180102174216.21031-1-bluca@debian.org>

On Tue,  2 Jan 2018 18:42:16 +0100
Luca Boccassi <bluca@debian.org> wrote:

> Lintian detected the following formatting errors:
> 
>  man/man8/devlink-sb.8.gz 230: warning: macro `b' not defined
>  man/man8/ip-link.8.gz 1243: warning: macro `in-8' not defined
>   (possibly missing space after `in')
>  man/man8/tc-u32.8.gz `R' is a string (producing the registered sign),
>   not a macro.
> 
> Signed-off-by: Luca Boccassi <bluca@debian.org>

Applied, thanks.

^ permalink raw reply

* Re: [PATCH net-next v7 0/6] net: tcp: sctp: dccp: Replace jprobe usage with trace events
From: David Miller @ 2018-01-02 19:28 UTC (permalink / raw)
  To: mhiramat
  Cc: mingo, ian.mcdonald, vyasevich, stephen, rostedt, peterz, tglx,
	linux-kernel, hpa, gerrit, nhorman, dccp, netdev, linux-sctp, sfr
In-Reply-To: <151451552014.17912.11834170408829155608.stgit@devbox>

From: Masami Hiramatsu <mhiramat@kernel.org>
Date: Fri, 29 Dec 2017 11:45:20 +0900

> This series is v7 of the replacement of jprobe usage with trace
> events. This version fixes net/dccp/trace.h to avoid sparse
> warning. Since the TP_STORE_ADDR_PORTS macro can be shared
> with trace/events/tcp.h, it also introduce a new common header
> file and move the definition of that macro.
> 
> Previous version is here;
>  https://lkml.org/lkml/2017/12/28/7
> 
> Changes from v6:
>   [5/6]: Avoid preprocessor directives in tracepoint macro args

Series applied, thank you.

^ permalink raw reply

* Re: [PATCH net-next 2/2] l2tp: add peer_offset parameter
From: Lorenzo Bianconi @ 2018-01-02 19:28 UTC (permalink / raw)
  To: Guillaume Nault; +Cc: James Chapman, David S. Miller, netdev, Hangbin Liu
In-Reply-To: <20180102180557.GB1402@alphalink.fr>

>> > Lorenzo, is this being added to fix interoperability with another L2TPv3
>> > implementation? If so, can you share more details?
>> >
>>
>> Hi James,
>>
>> I introduced peer_offset parameter to fix a specific setup where
>> tunnel endpoints
>> running L2TPv3 would use different values for tx offset (since in
>> iproute2 there is no
>> restriction on it), not to fix a given an interoperability issue.
>>
> Yes, but was it just to test iproute2's peer_offset option? Or is there
> a plan to use it for real?
>
>> I introduced this feature since:
>>  - offset has been added for long time to L2TPv3 implementation
>>    (commit f7faffa3ff8ef6ae712ef16312b8a2aa7a1c95fe and
>>    commit 309795f4bec2d69cd507a631f82065c2198a0825) and I wanted to
>> preserve UABI
>>  - have the same degree of freedom for offset parameter we have in
>> L2TPv2 and fix the issue
>>    described above
>>
> AFAIU, the current L2TPv2 implementation never sets the offset field
> and nobody ever realised.
>

Perhaps I am little bit polarized on UABI issue, but I was rethinking
about it and maybe removing offset parameter would lead to an
interoperability issue for device running L2TPv3 since offset
parameter is there and it is not a nope.
Please consider this setup:
- 2 endpoint running L2TPv3, the first running net-next and the second
running 4.14
- both endpoint are configured using iproute2 in this way:

  - ip l2tp add tunnel local <ip0> remote <ip1> tunnel_id <id0>
peer_tunnel_id <id1> udp_sport <p0> udp_dport <p1>
  - ip l2tp add tunnel local <ip1> remote <ip0> tunnel_id <id1>
peer_tunnel_id <id0> udp_sport <p1> udp_dport <p0>
  - ip l2tp add session name l2tp0 tunnel_id <id0> session_id <s0>
peer_session_id <s1> offset 8
  - ip l2tp add session name l2tp0 tunnel_id <id1> session_id <s1>
peer_session_id <s0> offset 8

Can we assume offset is never used for L2TPv3?

Regards,
Lorenzo

>> Now what we can do I guess is:
>> - as suggested by Guillaume drop completely the offset support without removing
>>   netlink attribute in order to not break UABI
>> - fix offset support initializing properly padding bits
>>
> I'd go for the first one. I just wonder if that looks acceptable to
> David an James.

^ permalink raw reply

* Re: [patch net-next v5 00/10] net: sched: allow qdiscs to share filter block instances
From: David Miller @ 2018-01-02 19:24 UTC (permalink / raw)
  To: jiri; +Cc: netdev
In-Reply-To: <20180102192259.GE2051@nanopsycho.orion>

From: Jiri Pirko <jiri@resnulli.us>
Date: Tue, 2 Jan 2018 20:22:59 +0100

> Dave, I see that in pw you flipped this to "Changes Requested". Why?

I think your API discussion with David Ahern needs to continue and is
not fully resolved.

^ permalink raw reply

* Re: [PATCH v2 0/6] wl1251: Fix MAC address for Nokia N900
From: Pali Rohár @ 2018-01-02 19:23 UTC (permalink / raw)
  To: Luis R. Rodriguez, Greg Kroah-Hartman, Kalle Valo, David Gnedt,
	Daniel Wagner, Tony Lindgren, Sebastian Reichel, Pavel Machek,
	Ivaylo Dimitrov, Aaro Koskinen, Grazvydas Ignotas
  Cc: linux-kernel, linux-wireless, netdev
In-Reply-To: <1510270708-14377-1-git-send-email-pali.rohar@gmail.com>

On Friday 10 November 2017 00:38:22 Pali Rohár wrote:
> This patch series fix processing MAC address for wl1251 chip found in Nokia N900.
> 
> Changes since v1:
> * Added Acked-by for Pavel Machek
> * Fixed grammar
> * Magic numbers for NVS offsets are replaced by defines
> * Check for validity of mac address NVS data is moved into function
> * Changed order of patches as Pavel requested
> 
> Pali Rohár (6):
>   wl1251: Update wl->nvs_len after wl->nvs is valid
>   wl1251: Generate random MAC address only if driver does not have
>     valid
>   wl1251: Parse and use MAC address from supplied NVS data
>   wl1251: Set generated MAC address back to NVS data
>   firmware: Add request_firmware_prefer_user() function
>   wl1251: Use request_firmware_prefer_user() for loading NVS
>     calibration data
> 
>  drivers/base/firmware_class.c          |   45 +++++++++++++-
>  drivers/net/wireless/ti/wl1251/Kconfig |    1 +
>  drivers/net/wireless/ti/wl1251/main.c  |  104 ++++++++++++++++++++++++++------
>  include/linux/firmware.h               |    9 +++
>  4 files changed, 138 insertions(+), 21 deletions(-)

Hi! Are there any comments for first 4 patches? If not, could they be
accepted and merged?

-- 
Pali Rohár
pali.rohar@gmail.com

^ permalink raw reply

* Re: [patch net-next v5 00/10] net: sched: allow qdiscs to share filter block instances
From: Jiri Pirko @ 2018-01-02 19:22 UTC (permalink / raw)
  To: davem; +Cc: netdev
In-Reply-To: <20171226141604.1605-1-jiri@resnulli.us>

Dave, I see that in pw you flipped this to "Changes Requested". Why?

Thanks!

Jiri

^ permalink raw reply

* Re: thunderx sgmii interface hang
From: Tim Harvey @ 2018-01-02 19:18 UTC (permalink / raw)
  To: David Daney; +Cc: Andrew Lunn, Sunil Goutham, netdev
In-Reply-To: <40429428-0612-094c-59ec-0fcee1a71d6f@caviumnetworks.com>

On Fri, Dec 22, 2017 at 4:30 PM, David Daney <ddaney@caviumnetworks.com> wrote:
> On 12/22/2017 04:22 PM, Tim Harvey wrote:
<snip>
>>
>> BGXX_GMP_GMI_TXX_INT[UNDFLW] is getting set when the issue is
>> triggered. From CN80XX-HM-1.2P this is caused by:
>>
>> "In the unlikely event that P2X data cannot keep the GMP TX FIFO full,
>> the SGMII/1000BASE-X/ QSGMII packet transfer will underflow. This
>> should be detected by the receiving device as an FCS error.
>> Internally, the packet is drained and lost"
>>
>
> Yikes!
>
>> Perhaps this needs to be caught and handled in some way. There's some
>> interrupt handlers in nicvf_main.c yet I'm not clear where to hook up
>> this one.
>
>
> This would be an interrupt generated by the BGX device, not the NIC device
> It will have an MSI-X index of (6 + LMAC * 7).  See BGX_INT_VEC_E in the
> HRM.
>
> Note that I am telling you which interrupt it is, but not recommending that
> catching it and doing something is necessarily the best thing to do.
>

David,

The following patch registers the BGX_GMP_GMI_TXX interrupt, enables
the UNDFLW interrupt, and toggles the MAC/PCS enable and does indeed
catch/resolve the issue which never occurs again.

I would agree this isn't a 'fix' but works around whatever the issue
is. Any ideas what could cause an UNDFLW like this?

I suspect it might have something to do with the fact we have a 100MHz
external ref clock for the DLM which is configured for
GSERx_LANE_MODE[LMODE] of 0x6 (R_125G_REFCLK15625_SGMII 1.25Gbd
156.25MHz ref clock SGMII) which seems just wrong (100MHz clock yet we
tell CN80XX 165MHz) but according to the reference manual and BDK code
this is an allowed configuration.

Do you have access to a CN80XX reference board that has an SGMII PHY
on it to test for this issue? I've been trying to get hold of one but
have not been successful.

diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.h
b/drivers/net/ethernet/cavium/thunder/thunder_bgx.h
index 2bba9d1..be9148f9 100644
--- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.h
+++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.h
@@ -179,6 +179,15 @@
 #define BGX_GMP_GMI_TXX_BURST          0x38228
 #define BGX_GMP_GMI_TXX_MIN_PKT                0x38240
 #define BGX_GMP_GMI_TXX_SGMII_CTL      0x38300
+#define BGX_GMP_GMI_TXX_INT            0x38500
+#define BGX_GMP_GMI_TXX_INT_W1S                0x38508
+#define BGX_GMP_GMI_TXX_INT_ENA_W1C    0x38510
+#define BGX_GMP_GMI_TXX_INT_ENA_W1S    0x38518
+#define  GMI_TXX_INT_PTP_LOST                  BIT_ULL(4)
+#define  GMI_TXX_INT_LATE_COL                  BIT_ULL(3)
+#define  GMI_TXX_INT_XSDEF                     BIT_ULL(2)
+#define  GMI_TXX_INT_XSCOL                     BIT_ULL(1)
+#define  GMI_TXX_INT_UNDFLW                    BIT_ULL(0)

 #define BGX_MSIX_VEC_0_29_ADDR         0x400000 /* +(0..29) << 4 */
 #define BGX_MSIX_VEC_0_29_CTL          0x400008

diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
index 805c02a..0690966 100644
--- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
+++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
@@ -1344,6 +1344,54 @@ static int bgx_init_phy(struct bgx *bgx)
        return bgx_init_of_phy(bgx);
 }

+static irqreturn_t bgx_intr_handler(int irq, void *data)
+{
+       struct bgx *bgx = (struct bgx *)data;
+       struct device *dev = &bgx->pdev->dev;
+       u64 status, val;
+       int lmac;
+
+       for (lmac = 0; lmac < bgx->lmac_count; lmac++) {
+               status = bgx_reg_read(bgx, lmac, BGX_GMP_GMI_TXX_INT);
+               if (status & GMI_TXX_INT_UNDFLW) {
+                       dev_err(dev, "BGX%d lmac%d UNDFLW\n", bgx->bgx_id,
+                               lmac);
+                       val = bgx_reg_read(bgx, lmac, BGX_CMRX_CFG);
+                       val &= ~CMR_EN;
+                       bgx_reg_write(bgx, lmac, BGX_CMRX_CFG, val);
+                       val |= CMR_EN;
+                       bgx_reg_write(bgx, lmac, BGX_CMRX_CFG, val);
+               }
+               /* clear interrupts */
+               bgx_reg_write(bgx, lmac, BGX_GMP_GMI_TXX_INT, status);
+       }
+
+       return IRQ_HANDLED;
+}
+
+static int bgx_register_intr(struct pci_dev *pdev)
+{
+       struct bgx *bgx = pci_get_drvdata(pdev);
+       struct device *dev = &pdev->dev;
+       int num_vec, ret;
+       char irq_name[32];
+
+       /* Enable MSI-X */
+       num_vec = pci_msix_vec_count(pdev);
+       ret = pci_alloc_irq_vectors(pdev, num_vec, num_vec, PCI_IRQ_MSIX);
+       if (ret < 0) {
+               dev_err(dev, "Req for #%d msix vectors failed\n", num_vec);
+               return 1;
+       }
+       sprintf(irq_name, "BGX%d", bgx->bgx_id);
+       ret = request_irq(pci_irq_vector(pdev, GMPX_GMI_TX_INT),
+               bgx_intr_handler, 0, irq_name, bgx);
+       if (ret)
+               return 1;
+
+       return 0;
+}
+
 static int bgx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        int err;
@@ -1414,6 +1462,8 @@ static int bgx_probe(struct pci_dev *pdev, const
struct pci_device_id *ent)
                xcv_init_hw(bgx->phy_mode);
        bgx_init_hw(bgx);

+       bgx_register_intr(pdev);
+
        /* Enable all LMACs */
        for (lmac = 0; lmac < bgx->lmac_count; lmac++) {
                err = bgx_lmac_enable(bgx, lmac);
@@ -1424,6 +1474,10 @@ static int bgx_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
                                bgx_lmac_disable(bgx, --lmac);
                        goto err_enable;
                }
+
+               /* enable TX FIFO Underflow interrupt */
+               bgx_reg_modify(bgx, lmac, BGX_GMP_GMI_TXX_INT_ENA_W1S,
+                              GMI_TXX_INT_UNDFLW);
        }

        return 0;

Regards,

Tim

^ permalink raw reply related

* Re: [PATCH iproute2] man: fix small formatting errors
From: Jiri Pirko @ 2018-01-02 19:10 UTC (permalink / raw)
  To: Luca Boccassi; +Cc: netdev
In-Reply-To: <20180102174216.21031-1-bluca@debian.org>

Tue, Jan 02, 2018 at 06:42:16PM CET, bluca@debian.org wrote:
>Lintian detected the following formatting errors:
>
> man/man8/devlink-sb.8.gz 230: warning: macro `b' not defined
> man/man8/ip-link.8.gz 1243: warning: macro `in-8' not defined
>  (possibly missing space after `in')
> man/man8/tc-u32.8.gz `R' is a string (producing the registered sign),
>  not a macro.
>
>Signed-off-by: Luca Boccassi <bluca@debian.org>

Acked-by: Jiri Pirko <jiri@mellanox.com>

Thanks!

^ permalink raw reply

* Re: [PATCH net 3/3] eet: ena: invoke netif_carrier_off() only after netdev registered
From: David Miller @ 2018-01-02 19:08 UTC (permalink / raw)
  To: netanel
  Cc: netdev, dwmw, zorik, matua, saeedb, msw, aliguori, nafea, evgenys,
	gtzalik
In-Reply-To: <1514496620-69953-4-git-send-email-netanel@amazon.com>

From: <netanel@amazon.com>
Date: Thu, 28 Dec 2017 21:30:20 +0000

> From: Netanel Belgazal <netanel@amazon.com>
> 
> netif_carrier_off() should be called only after register netdev.
> Move the function's call after the registration.
> 
> Signed-off-by: Netanel Belgazal <netanel@amazon.com>
> ---
>  drivers/net/ethernet/amazon/ena/ena_netdev.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c
> index fbe21a817bd8..ee50c56765a4 100644
> --- a/drivers/net/ethernet/amazon/ena/ena_netdev.c
> +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c
> @@ -3276,14 +3276,14 @@ static int ena_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
>  
>  	memcpy(adapter->netdev->perm_addr, adapter->mac_addr, netdev->addr_len);
>  
> -	netif_carrier_off(netdev);
> -
>  	rc = register_netdev(netdev);
>  	if (rc) {
>  		dev_err(&pdev->dev, "Cannot register net device\n");
>  		goto err_rss;
>  	}
>  
> +	netif_carrier_off(netdev);
> +

You cannot invoke this after register_netdev(), asynchronous activity can cause this
call to lose information and lose a link up event.

^ permalink raw reply

* Re: [PATCH v4 net-next 0/4] qed*: Advance to FW 8.33.1.0
From: David Miller @ 2018-01-02 18:58 UTC (permalink / raw)
  To: Tomer.Tayar; +Cc: netdev, linux-rdma, linux-scsi
In-Reply-To: <1514395808-16916-1-git-send-email-Tomer.Tayar@cavium.com>

From: Tomer Tayar <Tomer.Tayar@cavium.com>
Date: Wed, 27 Dec 2017 19:30:04 +0200

> This series advances all qed* drivers to use firmware 8.33.1.0 which brings
> new capabilities and initial support of new HW. The changes are mostly in
> qed, and include changes in the FW interface files, as well as updating the
> FW initialization and debug collection code. The protocol drivers have
> minor functional changes for this firmware.
> 
> Patch 1 Rearranges and refactors the FW interface files in preparation of
> the new FW (no functional change).
> Patch 2 Prepares the code for support of new HW (no functional change).
> Patch 3 Actual utilization of the new FW.
> Patch 4 Advances drivers' version.
> 
> v3->v4:
> Fix a compilation issue which was reported by krobot (dependency on CRC8).
> 
> v2->v3:
> Resend the series with a fixed title in the cover letter.
> 
> v1->v2:
> - Break the previous single patch into several patches.
> - Fix compilation issues which were reported by krobot.

I'm going to apply this, however....

These firmware update changes are rediculously invasive.

Backporting patches through these updates will be a giant task if not
impossible for anyone who tries to do something like this.

Who reviewed these changes outside of Cavium to look for clerical
and typographical errors?  I be nobody did.  I personally scanned
them for about 20 minutes.

Therefore, it is my judgment that the way firmware support updates are
done in the QED driver is detrimental to it's long term
maintainability.

Thank you.

^ permalink raw reply


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