All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ido Schimmel <idosch@idosch.org>
To: David Ahern <dsahern@gmail.com>
Cc: netdev@vger.kernel.org, davem@davemloft.net, kuba@kernel.org,
	petrm@nvidia.com, roopa@nvidia.com, nikolay@nvidia.com,
	ssuryaextr@gmail.com, mlxsw@nvidia.com,
	Ido Schimmel <idosch@nvidia.com>
Subject: Re: [RFC PATCH net-next v2 03/10] ipv4: Add custom multipath hash policy
Date: Tue, 11 May 2021 23:02:52 +0300	[thread overview]
Message-ID: <YJri7JmNKYQED29J@shredder> (raw)
In-Reply-To: <0a199bbf-0ee7-1826-0906-dcfed8c86c7d@gmail.com>

On Tue, May 11, 2021 at 09:46:27AM -0600, David Ahern wrote:
> On 5/9/21 9:16 AM, Ido Schimmel wrote:
> > diff --git a/net/ipv4/route.c b/net/ipv4/route.c
> > index 9d61e969446e..a4c477475f4c 100644
> > --- a/net/ipv4/route.c
> > +++ b/net/ipv4/route.c
> > @@ -1906,6 +1906,121 @@ static void ip_multipath_l3_keys(const struct sk_buff *skb,
> >  	hash_keys->addrs.v4addrs.dst = key_iph->daddr;
> >  }
> >  
> > +static u32 fib_multipath_custom_hash_outer(const struct net *net,
> > +					   const struct sk_buff *skb,
> > +					   bool *p_has_inner)
> > +{
> > +	u32 hash_fields = net->ipv4.sysctl_fib_multipath_hash_fields;
> > +	struct flow_keys keys, hash_keys;
> > +
> > +	if (!(hash_fields & FIB_MULTIPATH_HASH_FIELD_OUTER_MASK))
> > +		return 0;
> > +
> > +	memset(&hash_keys, 0, sizeof(hash_keys));
> > +	skb_flow_dissect_flow_keys(skb, &keys, FLOW_DISSECTOR_F_STOP_AT_ENCAP);
> > +
> > +	hash_keys.control.addr_type = FLOW_DISSECTOR_KEY_IPV4_ADDRS;
> > +	if (hash_fields & FIB_MULTIPATH_HASH_FIELD_SRC_IP)
> > +		hash_keys.addrs.v4addrs.src = keys.addrs.v4addrs.src;
> > +	if (hash_fields & FIB_MULTIPATH_HASH_FIELD_DST_IP)
> > +		hash_keys.addrs.v4addrs.dst = keys.addrs.v4addrs.dst;
> > +	if (hash_fields & FIB_MULTIPATH_HASH_FIELD_IP_PROTO)
> > +		hash_keys.basic.ip_proto = keys.basic.ip_proto;
> > +	if (hash_fields & FIB_MULTIPATH_HASH_FIELD_SRC_PORT)
> > +		hash_keys.ports.src = keys.ports.src;
> > +	if (hash_fields & FIB_MULTIPATH_HASH_FIELD_DST_PORT)
> > +		hash_keys.ports.dst = keys.ports.dst;
> > +
> > +	*p_has_inner = !!(keys.control.flags & FLOW_DIS_ENCAPSULATION);
> > +	return flow_hash_from_keys(&hash_keys);
> > +}
> > +
> > +static u32 fib_multipath_custom_hash_inner(const struct net *net,
> > +					   const struct sk_buff *skb,
> > +					   bool has_inner)
> > +{
> > +	u32 hash_fields = net->ipv4.sysctl_fib_multipath_hash_fields;
> > +	struct flow_keys keys, hash_keys;
> > +
> > +	/* We assume the packet carries an encapsulation, but if none was
> > +	 * encountered during dissection of the outer flow, then there is no
> > +	 * point in calling the flow dissector again.
> > +	 */
> > +	if (!has_inner)
> > +		return 0;
> > +
> > +	if (!(hash_fields & FIB_MULTIPATH_HASH_FIELD_INNER_MASK))
> > +		return 0;
> > +
> > +	memset(&hash_keys, 0, sizeof(hash_keys));
> > +	skb_flow_dissect_flow_keys(skb, &keys, 0);
> > +
> > +	if (!(keys.control.flags & FLOW_DIS_ENCAPSULATION))
> > +		return 0;
> > +
> > +	if (keys.control.addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) {
> > +		hash_keys.control.addr_type = FLOW_DISSECTOR_KEY_IPV4_ADDRS;
> > +		if (hash_fields & FIB_MULTIPATH_HASH_FIELD_INNER_SRC_IP)
> > +			hash_keys.addrs.v4addrs.src = keys.addrs.v4addrs.src;
> > +		if (hash_fields & FIB_MULTIPATH_HASH_FIELD_INNER_DST_IP)
> > +			hash_keys.addrs.v4addrs.dst = keys.addrs.v4addrs.dst;
> > +	} else if (keys.control.addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) {
> > +		hash_keys.control.addr_type = FLOW_DISSECTOR_KEY_IPV6_ADDRS;
> > +		if (hash_fields & FIB_MULTIPATH_HASH_FIELD_INNER_SRC_IP)
> > +			hash_keys.addrs.v6addrs.src = keys.addrs.v6addrs.src;
> > +		if (hash_fields & FIB_MULTIPATH_HASH_FIELD_INNER_DST_IP)
> > +			hash_keys.addrs.v6addrs.dst = keys.addrs.v6addrs.dst;
> > +		if (hash_fields & FIB_MULTIPATH_HASH_FIELD_INNER_FLOWLABEL)
> > +			hash_keys.tags.flow_label = keys.tags.flow_label;
> > +	}
> > +
> > +	if (hash_fields & FIB_MULTIPATH_HASH_FIELD_INNER_IP_PROTO)
> > +		hash_keys.basic.ip_proto = keys.basic.ip_proto;
> > +	if (hash_fields & FIB_MULTIPATH_HASH_FIELD_INNER_SRC_PORT)
> > +		hash_keys.ports.src = keys.ports.src;
> > +	if (hash_fields & FIB_MULTIPATH_HASH_FIELD_INNER_DST_PORT)
> > +		hash_keys.ports.dst = keys.ports.dst;
> > +
> > +	return flow_hash_from_keys(&hash_keys);
> > +}
> > +
> > +static u32 fib_multipath_custom_hash_skb(const struct net *net,
> > +					 const struct sk_buff *skb)
> > +{
> > +	u32 mhash, mhash_inner;
> > +	bool has_inner = true;
> > +
> 
> Is it not possible to do the dissect once here and pass keys to outer
> and inner functions?
> 
> 	memset(&hash_keys, 0, sizeof(hash_keys));
> 	skb_flow_dissect_flow_keys(skb, &keys, flag);

Not that I'm aware. For outer flow we need to pass
'FLOW_DISSECTOR_F_STOP_AT_ENCAP'. For inner flow, we shouldn't pass any
flags, but make sure encapsulation was encountered by checking
'keys.control.flags & FLOW_DIS_ENCAPSULATION'.

Also, 'struct flow_keys' has keys for a single flow.

> 
> 
> > +	mhash = fib_multipath_custom_hash_outer(net, skb, &has_inner);
> > +	mhash_inner = fib_multipath_custom_hash_inner(net, skb, has_inner);
> > +
> > +	return jhash_2words(mhash, mhash_inner, 0);
> > +}
> > +
> > +static u32 fib_multipath_custom_hash_fl4(const struct net *net,
> > +					 const struct flowi4 *fl4)
> > +{
> > +	u32 hash_fields = net->ipv4.sysctl_fib_multipath_hash_fields;
> > +	struct flow_keys hash_keys;
> > +
> > +	if (!(hash_fields & FIB_MULTIPATH_HASH_FIELD_OUTER_MASK))
> > +		return 0;
> > +
> > +	memset(&hash_keys, 0, sizeof(hash_keys));
> > +	hash_keys.control.addr_type = FLOW_DISSECTOR_KEY_IPV4_ADDRS;
> > +	if (hash_fields & FIB_MULTIPATH_HASH_FIELD_SRC_IP)
> > +		hash_keys.addrs.v4addrs.src = fl4->saddr;
> > +	if (hash_fields & FIB_MULTIPATH_HASH_FIELD_DST_IP)
> > +		hash_keys.addrs.v4addrs.dst = fl4->daddr;
> > +	if (hash_fields & FIB_MULTIPATH_HASH_FIELD_IP_PROTO)
> > +		hash_keys.basic.ip_proto = fl4->flowi4_proto;
> > +	if (hash_fields & FIB_MULTIPATH_HASH_FIELD_SRC_PORT)
> > +		hash_keys.ports.src = fl4->fl4_sport;
> > +	if (hash_fields & FIB_MULTIPATH_HASH_FIELD_DST_PORT)
> > +		hash_keys.ports.dst = fl4->fl4_dport;
> > +
> > +	return flow_hash_from_keys(&hash_keys);
> > +}
> > +
> >  /* if skb is set it will be used and fl4 can be NULL */
> >  int fib_multipath_hash(const struct net *net, const struct flowi4 *fl4,
> >  		       const struct sk_buff *skb, struct flow_keys *flkeys)

  reply	other threads:[~2021-05-11 20:02 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-05-09 15:16 [RFC PATCH net-next v2 00/10] Add support for custom multipath hash Ido Schimmel
2021-05-09 15:16 ` [RFC PATCH net-next v2 01/10] ipv4: Calculate multipath hash inside switch statement Ido Schimmel
2021-05-09 15:16 ` [RFC PATCH net-next v2 02/10] ipv4: Add a sysctl to control multipath hash fields Ido Schimmel
2021-05-11 15:10   ` David Ahern
2021-05-11 19:58     ` Ido Schimmel
2021-05-11 15:49   ` David Ahern
2021-05-11 20:05     ` Ido Schimmel
2021-05-17 14:47       ` David Ahern
2021-05-09 15:16 ` [RFC PATCH net-next v2 03/10] ipv4: Add custom multipath hash policy Ido Schimmel
2021-05-11 15:46   ` David Ahern
2021-05-11 20:02     ` Ido Schimmel [this message]
2021-05-09 15:16 ` [RFC PATCH net-next v2 04/10] ipv6: Use a more suitable label name Ido Schimmel
2021-05-09 15:16 ` [RFC PATCH net-next v2 05/10] ipv6: Calculate multipath hash inside switch statement Ido Schimmel
2021-05-09 15:16 ` [RFC PATCH net-next v2 06/10] ipv6: Add a sysctl to control multipath hash fields Ido Schimmel
2021-05-09 15:16 ` [RFC PATCH net-next v2 07/10] ipv6: Add custom multipath hash policy Ido Schimmel
2021-05-09 15:16 ` [RFC PATCH net-next v2 08/10] selftests: forwarding: Add test for custom multipath hash Ido Schimmel
2021-05-09 15:16 ` [RFC PATCH net-next v2 09/10] selftests: forwarding: Add test for custom multipath hash with IPv4 GRE Ido Schimmel
2021-05-09 15:16 ` [RFC PATCH net-next v2 10/10] selftests: forwarding: Add test for custom multipath hash with IPv6 GRE Ido Schimmel

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=YJri7JmNKYQED29J@shredder \
    --to=idosch@idosch.org \
    --cc=davem@davemloft.net \
    --cc=dsahern@gmail.com \
    --cc=idosch@nvidia.com \
    --cc=kuba@kernel.org \
    --cc=mlxsw@nvidia.com \
    --cc=netdev@vger.kernel.org \
    --cc=nikolay@nvidia.com \
    --cc=petrm@nvidia.com \
    --cc=roopa@nvidia.com \
    --cc=ssuryaextr@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.