linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jakub Kicinski <kuba@kernel.org>
To: Dmytro Shytyi <dmytro@shytyi.net>
Cc: "kuznet" <kuznet@ms2.inr.ac.ru>,
	"yoshfuji" <yoshfuji@linux-ipv6.org>,
	"liuhangbin" <liuhangbin@gmail.com>,
	"davem" <davem@davemloft.net>, "netdev" <netdev@vger.kernel.org>,
	"linux-kernel" <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH net-next V5] net: Variable SLAAC: SLAAC with prefixes of arbitrary length in PIO
Date: Tue, 17 Nov 2020 12:43:48 -0800	[thread overview]
Message-ID: <20201117124348.132862b1@kicinski-fedora-PC1C0HJN.hsd1.ca.comcast.net> (raw)
In-Reply-To: <175c31c6260.10eef97f6180313.755036504412557273@shytyi.net>

On Fri, 13 Nov 2020 20:36:58 +0100 Dmytro Shytyi wrote:
> Variable SLAAC: SLAAC with prefixes of arbitrary length in PIO (randomly
> generated hostID or stable privacy + privacy extensions).
> The main problem is that SLAAC RA or PD allocates a /64 by the Wireless
> carrier 4G, 5G to a mobile hotspot, however segmentation of the /64 via
> SLAAC is required so that downstream interfaces can be further subnetted.
> Example: uCPE device (4G + WI-FI enabled) receives /64 via Wireless, and
> assigns /72 to VNF-Firewall, /72 to WIFI, /72 to VNF-Router, /72 to
> Load-Balancer and /72 to wired connected devices.
> IETF document that defines problem statement:
> draft-mishra-v6ops-variable-slaac-problem-stmt
> IETF document that specifies variable slaac:
> draft-mishra-6man-variable-slaac
> 
> Signed-off-by: Dmytro Shytyi <dmytro@shytyi.net>
> ---
> diff -rupN net-next-5.10.0-rc2/include/net/if_inet6.h net-next-patch-5.10.0-rc2/include/net/if_inet6.h
> --- net-next-5.10.0-rc2/include/net/if_inet6.h	2020-11-10 08:46:00.195180579 +0100
> +++ net-next-patch-5.10.0-rc2/include/net/if_inet6.h	2020-11-11 18:11:05.627550135 +0100
> @@ -22,6 +22,12 @@
>  #define IF_RS_SENT	0x10
>  #define IF_READY	0x80000000
>  
> +/* Variable SLAAC (Contact: Dmytro Shytyi)
> + * draft-mishra-6man-variable-slaac
> + * draft-mishra-v6ops-variable-slaac-problem-stmt
> + */
> +#define IF_RA_VAR_PLEN	0x08
> +
>  /* prefix flags */
>  #define IF_PREFIX_ONLINK	0x01
>  #define IF_PREFIX_AUTOCONF	0x02
> diff -rupN net-next-5.10.0-rc2/include/uapi/linux/icmpv6.h net-next-patch-5.10.0-rc2/include/uapi/linux/icmpv6.h
> --- net-next-5.10.0-rc2/include/uapi/linux/icmpv6.h	2020-11-10 08:46:00.351849525 +0100
> +++ net-next-patch-5.10.0-rc2/include/uapi/linux/icmpv6.h	2020-11-11 18:11:05.627550135 +0100
> @@ -42,7 +42,9 @@ struct icmp6hdr {
>                  struct icmpv6_nd_ra {
>  			__u8		hop_limit;
>  #if defined(__LITTLE_ENDIAN_BITFIELD)
> -			__u8		reserved:3,
> +			__u8		reserved:1,
> +					slaac_var_plen:1,
> +					proxy:1,

What's the status of your draft? I'm not too familiar with the IETF
process, but I'm not sure we should change uAPI headers before the
draft reaches reasonable consensus.

I'd appreciate extra opinions here.

>  					router_pref:2,
>  					home_agent:1,
>  					other:1,
> @@ -53,7 +55,9 @@ struct icmp6hdr {
>  					other:1,
>  					home_agent:1,
>  					router_pref:2,
> -					reserved:3;
> +					proxy:1,
> +					slaac_var_plen:1,
> +					reserved:1;
>  #else
>  #error	"Please fix <asm/byteorder.h>"
>  #endif
> @@ -78,9 +82,9 @@ struct icmp6hdr {
>  #define icmp6_addrconf_other	icmp6_dataun.u_nd_ra.other
>  #define icmp6_rt_lifetime	icmp6_dataun.u_nd_ra.rt_lifetime
>  #define icmp6_router_pref	icmp6_dataun.u_nd_ra.router_pref
> +#define icmp6_slaac_var_plen	icmp6_dataun.u_nd_ra.slaac_var_plen
>  };
>  
> -
>  #define ICMPV6_ROUTER_PREF_LOW		0x3
>  #define ICMPV6_ROUTER_PREF_MEDIUM	0x0
>  #define ICMPV6_ROUTER_PREF_HIGH		0x1
> diff -rupN net-next-5.10.0-rc2/net/ipv6/addrconf.c net-next-patch-5.10.0-rc2/net/ipv6/addrconf.c
> --- net-next-5.10.0-rc2/net/ipv6/addrconf.c	2020-11-10 08:46:01.075193379 +0100
> +++ net-next-patch-5.10.0-rc2/net/ipv6/addrconf.c	2020-11-13 19:50:04.401227310 +0100
> @@ -11,6 +11,8 @@
>  /*
>   *	Changes:
>   *
> + *	Dmytro Shytyi			:	Variable SLAAC: SLAAC with
> + *	<dmytro@shytyi.net>			prefixes of arbitrary length.

Please don't add your name to those headers. We have git now,
authorship if clearly preserved. 

>   *	Janos Farkas			:	delete timer on ifdown
>   *	<chexum@bankinf.banki.hu>
>   *	Andi Kleen			:	kill double kfree on module
> @@ -142,7 +144,11 @@ static int ipv6_count_addresses(const st
>  static int ipv6_generate_stable_address(struct in6_addr *addr,
>  					u8 dad_count,
>  					const struct inet6_dev *idev);
> -
> +static int ipv6_generate_address_variable_plen(struct in6_addr *address,
> +					       u8 dad_count,
> +					       const struct inet6_dev *idev,
> +					       unsigned int rcvd_prfx_len,
> +					       bool stable_privacy_mode);

Can you reorder the code to avoid the fwd declaration?

Also please try to shorten the name of this function.

>  #define IN6_ADDR_HSIZE_SHIFT	8
>  #define IN6_ADDR_HSIZE		(1 << IN6_ADDR_HSIZE_SHIFT)
>  /*
> @@ -1315,10 +1321,11 @@ static int ipv6_create_tempaddr(struct i
>  	struct ifa6_config cfg;
>  	long max_desync_factor;
>  	struct in6_addr addr;
> -	int ret = 0;
> +	int ret;
> +	struct in6_addr temp;

Please keep the reverse xmas tree ordering of variables.
Lines should be ordered longest to shortest.

>  
>  	write_lock_bh(&idev->lock);
> -
> +	ret = 0;

Why did you decide to move the init from the definition?

>  retry:
>  	in6_dev_hold(idev);
>  	if (idev->cnf.use_tempaddr <= 0) {
> @@ -1340,9 +1347,16 @@ retry:
>  		goto out;
>  	}
>  	in6_ifa_hold(ifp);
> -	memcpy(addr.s6_addr, ifp->addr.s6_addr, 8);
> -	ipv6_gen_rnd_iid(&addr);
>  
> +	if (ifp->prefix_len == 64) {
> +		memcpy(addr.s6_addr, ifp->addr.s6_addr, 8);
> +		ipv6_gen_rnd_iid(&addr);
> +	} else if (ifp->prefix_len > 0 && ifp->prefix_len <= 128) {
> +		memcpy(addr.s6_addr32, ifp->addr.s6_addr, 16);
> +		get_random_bytes(temp.s6_addr32, 16);
> +		ipv6_addr_prefix_copy(&temp, &addr, ifp->prefix_len);
> +		memcpy(addr.s6_addr, temp.s6_addr, 16);
> +	}
>  	age = (now - ifp->tstamp) / HZ;
>  
>  	regen_advance = idev->cnf.regen_max_retry *
> @@ -2576,9 +2590,42 @@ int addrconf_prefix_rcv_add_addr(struct
>  				 u32 addr_flags, bool sllao, bool tokenized,
>  				 __u32 valid_lft, u32 prefered_lft)
>  {
> -	struct inet6_ifaddr *ifp = ipv6_get_ifaddr(net, addr, dev, 1);
> +	struct inet6_ifaddr *ifp = NULL;
>  	int create = 0;
>  
> +	if ((in6_dev->if_flags & IF_RA_VAR_PLEN) == IF_RA_VAR_PLEN &&
> +	    in6_dev->cnf.addr_gen_mode != IN6_ADDR_GEN_MODE_STABLE_PRIVACY) {
> +		struct inet6_ifaddr *result = NULL;
> +		struct inet6_ifaddr *result_base = NULL;
> +		struct in6_addr curr_net_prfx;
> +		struct in6_addr net_prfx;
> +		bool prfxs_equal;
> +
> +		result_base = result;
> +		rcu_read_lock();
> +		list_for_each_entry_rcu(ifp, &in6_dev->addr_list, if_list) {
> +			if (!net_eq(dev_net(ifp->idev->dev), net))
> +				continue;
> +			ipv6_addr_prefix_copy(&net_prfx, &pinfo->prefix, pinfo->prefix_len);
> +			ipv6_addr_prefix_copy(&curr_net_prfx, &ifp->addr, pinfo->prefix_len);
> +			prfxs_equal =
> +				ipv6_prefix_equal(&net_prfx, &curr_net_prfx, pinfo->prefix_len);
> +
> +			if (prfxs_equal && pinfo->prefix_len == ifp->prefix_len) {
> +				result = ifp;
> +				in6_ifa_hold(ifp);
> +				break;
> +			}
> +		}
> +		rcu_read_unlock();
> +		if (result_base != result)
> +			ifp = result;
> +		else
> +			ifp = NULL;

Could this be a helper of its own?

> +	} else {
> +		ifp = ipv6_get_ifaddr(net, addr, dev, 1);
> +	}
> +
>  	if (!ifp && valid_lft) {
>  		int max_addresses = in6_dev->cnf.max_addresses;
>  		struct ifa6_config cfg = {
> @@ -2781,9 +2828,34 @@ void addrconf_prefix_rcv(struct net_devi
>  				dev_addr_generated = true;
>  			}
>  			goto ok;
> +		} else if (((in6_dev->if_flags & IF_RA_VAR_PLEN) == IF_RA_VAR_PLEN) &&
> +			  pinfo->prefix_len > 0 && pinfo->prefix_len <= 128) {
> +			/* SLAAC with prefixes of arbitrary length (Variable SLAAC).
> +			 * draft-mishra-6man-variable-slaac
> +			 * draft-mishra-v6ops-variable-slaac-problem-stmt
> +			 * Contact: Dmytro Shytyi.
> +			 */
> +			memcpy(&addr, &pinfo->prefix, 16);
> +			if (in6_dev->cnf.addr_gen_mode == IN6_ADDR_GEN_MODE_STABLE_PRIVACY) {
> +				if (!ipv6_generate_address_variable_plen(&addr,
> +									 0,
> +									 in6_dev,
> +									 pinfo->prefix_len,
> +									 true)) {
> +					addr_flags |= IFA_F_STABLE_PRIVACY;
> +					goto ok;
> +			}
> +			} else if (!ipv6_generate_address_variable_plen(&addr,
> +									0,
> +									in6_dev,
> +									pinfo->prefix_len,
> +									false)) {
> +				goto ok;
> +			}
> +		} else {
> +			net_dbg_ratelimited("IPv6: Prefix with unexpected length %d\n",
> +					    pinfo->prefix_len);
>  		}
> -		net_dbg_ratelimited("IPv6 addrconf: prefix with wrong length %d\n",
> -				    pinfo->prefix_len);
>  		goto put;
>  
>  ok:
> @@ -3263,6 +3335,77 @@ retry:
>  	*address = temp;
>  	return 0;
>  }
> +
> +static int ipv6_generate_address_variable_plen(struct in6_addr *address,
> +					       u8 dad_count,
> +					       const struct inet6_dev *idev,
> +					       unsigned int rcvd_prfx_len,
> +					       bool stable_privacy_mode)
> +{
> +	static DEFINE_SPINLOCK(lock);
> +	static __u32 digest[SHA1_DIGEST_WORDS];
> +	static __u32 workspace[SHA1_WORKSPACE_WORDS];
> +
> +	static union {
> +		char __data[SHA1_BLOCK_SIZE];
> +		struct {
> +			struct in6_addr secret;
> +			__be32 prefix[2];
> +			unsigned char hwaddr[MAX_ADDR_LEN];
> +			u8 dad_count;
> +		} __packed;
> +	} data;
> +
> +	struct in6_addr secret;
> +	struct in6_addr temp;
> +	struct net *net = dev_net(idev->dev);

Please dont add empty lines between variable declarations.

> +	BUILD_BUG_ON(sizeof(data.__data) != sizeof(data));
> +
> +	if (stable_privacy_mode) {
> +		if (idev->cnf.stable_secret.initialized)
> +			secret = idev->cnf.stable_secret.secret;
> +		else if (net->ipv6.devconf_dflt->stable_secret.initialized)
> +			secret = net->ipv6.devconf_dflt->stable_secret.secret;
> +		else
> +			return -1;
> +	}
> +
> +retry:
> +	spin_lock_bh(&lock);
> +	if (stable_privacy_mode) {
> +		sha1_init(digest);
> +		memset(&data, 0, sizeof(data));
> +		memset(workspace, 0, sizeof(workspace));
> +		memcpy(data.hwaddr, idev->dev->perm_addr, idev->dev->addr_len);
> +		data.prefix[0] = address->s6_addr32[0];
> +		data.prefix[1] = address->s6_addr32[1];
> +		data.secret = secret;
> +		data.dad_count = dad_count;
> +
> +		sha1_transform(digest, data.__data, workspace);
> +
> +		temp = *address;
> +		temp.s6_addr32[0] = (__force __be32)digest[0];
> +		temp.s6_addr32[1] = (__force __be32)digest[1];
> +		temp.s6_addr32[2] = (__force __be32)digest[2];
> +		temp.s6_addr32[3] = (__force __be32)digest[3];
> +	} else {
> +		temp = *address;
> +		get_random_bytes(temp.s6_addr32, 16);
> +	}
> +	spin_unlock_bh(&lock);
> +
> +	if (ipv6_reserved_interfaceid(temp)) {
> +		dad_count++;
> +		if (dad_count > dev_net(idev->dev)->ipv6.sysctl.idgen_retries)
> +			return -1;
> +		goto retry;
> +	}
> +	ipv6_addr_prefix_copy(&temp, address, rcvd_prfx_len);
> +	*address = temp;
> +	return 0;
> +}
>  
>  static void ipv6_gen_mode_random_init(struct inet6_dev *idev)
>  {
> diff -rupN net-next-5.10.0-rc2/net/ipv6/ndisc.c net-next-patch-5.10.0-rc2/net/ipv6/ndisc.c
> --- net-next-5.10.0-rc2/net/ipv6/ndisc.c	2020-11-10 08:46:01.091860289 +0100
> +++ net-next-patch-5.10.0-rc2/net/ipv6/ndisc.c	2020-11-11 18:11:05.630883513 +0100
> @@ -1244,6 +1244,8 @@ static void ndisc_router_discovery(struc
>  		in6_dev->if_flags |= IF_RA_RCVD;
>  	}
>  
> +	in6_dev->if_flags |= ra_msg->icmph.icmp6_slaac_var_plen ?
> +					IF_RA_VAR_PLEN : 0;
>  	/*
>  	 * Remember the managed/otherconf flags from most recently
>  	 * received RA message (RFC 2462) -- yoshfuji


  reply	other threads:[~2020-11-17 20:44 UTC|newest]

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <175b25d0c79.f8ce5734515834.1635475016968827598@shytyi.net>
2020-11-10 17:45 ` [PATCH net-next] net: Variable SLAAC: SLAAC with prefixes of arbitrary length in PIO Dmytro Shytyi
2020-11-11  1:34   ` kernel test robot
2020-11-11 20:37     ` [PATCH net-next V2] " Dmytro Shytyi
2020-11-12 15:44     ` [PATCH net-next V3] " Dmytro Shytyi
2020-11-12 16:55       ` Hideaki Yoshifuji
2020-11-13  1:50         ` Dmytro Shytyi
2020-11-13  0:21       ` Jakub Kicinski
2020-11-13  1:50         ` Dmytro Shytyi
2020-11-13  1:56       ` [PATCH net-next V4] " Dmytro Shytyi
2020-11-13 12:38         ` Hideaki Yoshifuji
2020-11-13 19:09           ` Dmytro Shytyi
2020-11-13 19:36         ` [PATCH net-next V5] " Dmytro Shytyi
2020-11-17 20:43           ` Jakub Kicinski [this message]
2020-11-18 13:41             ` Dmytro Shytyi
2020-11-18 15:50               ` Jakub Kicinski
2020-11-18 15:56                 ` Dmytro Shytyi
2020-11-19 13:37             ` [PATCH net-next V6] " Dmytro Shytyi
2020-11-19 18:44               ` Jakub Kicinski
2020-11-19 19:31                 ` Dmytro Shytyi
2020-11-20  1:20                   ` Jakub Kicinski
2020-11-20  9:26                   ` [PATCH net-next V7] " Dmytro Shytyi
2020-11-23 13:26                     ` Hideaki Yoshifuji
2020-11-27 16:54                       ` Dmytro Shytyi
2020-12-09  3:27                     ` [PATCH net-next V8] " Dmytro Shytyi
2020-12-16  0:00                       ` David Miller
2020-12-16 14:01                         ` Dmytro Shytyi
2020-12-16 17:28                           ` Jakub Kicinski
2020-12-16 21:56                             ` Dmytro Shytyi
2020-12-16 22:01                       ` [PATCH net-next V9] " Dmytro Shytyi
2021-10-13 23:03                         ` [PATCH net-next V10] " Dmytro Shytyi
2021-10-13 23:20                           ` Dmytro Shytyi
2021-10-14 18:26                             ` Erik Kline
2021-10-14 21:36                               ` Dmytro Shytyi
2021-10-14 13:20                           ` kernel test robot
2020-11-13  0:24     ` [PATCH net-next] " Jakub Kicinski
2020-11-13  0:32       ` [kbuild-all] " Li, Philip
2020-11-13  0:51         ` Jakub Kicinski
2020-11-13  1:01           ` Li, Philip
2020-11-13  1:43       ` Dave Hansen
2020-11-13  1:53         ` Jakub Kicinski
2020-11-13  2:01           ` Dave Hansen

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=20201117124348.132862b1@kicinski-fedora-PC1C0HJN.hsd1.ca.comcast.net \
    --to=kuba@kernel.org \
    --cc=davem@davemloft.net \
    --cc=dmytro@shytyi.net \
    --cc=kuznet@ms2.inr.ac.ru \
    --cc=linux-kernel@vger.kernel.org \
    --cc=liuhangbin@gmail.com \
    --cc=netdev@vger.kernel.org \
    --cc=yoshfuji@linux-ipv6.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).