diff mbox series

[mptcp-next,2/5] mptcp: convert netlink from small_ops to ops

Message ID 047495a2619c04f9edc7c37e74de25957bfccf92.1689932012.git.dcaratti@redhat.com (mailing list archive)
State Superseded, archived
Delegated to: Paolo Abeni
Headers show
Series convert MPTCP to use YAML spec | expand

Checks

Context Check Description
matttbe/build warning Build error with: make C=1 net/mptcp/pm_netlink.o
matttbe/checkpatch fail total: 5 errors, 5 warnings, 1 checks, 344 lines checked
matttbe/KVM_Validation__normal__except_selftest_mptcp_join_ warning Unstable: 1 failed test(s): selftest_simult_flows
matttbe/KVM_Validation__debug__only_selftest_mptcp_join_ success Success! ✅
matttbe/KVM_Validation__debug__except_selftest_mptcp_join_ success Success! ✅
matttbe/KVM_Validation__normal__only_selftest_mptcp_join_ success Success! ✅

Commit Message

Davide Caratti July 21, 2023, 9:53 a.m. UTC
- use a separate attribute set for add/del/get/flush address operation,
  binary compatible with the existing one, to store the endpoint address.
  MPTCP_PM_ENDPOINT_ADDR is added to the uAPI (with the same value as
  MPTCP_PM_ATTR_ADDR) for these operations.
- convert mptcp_pm_ops[] and add policy files accordingly.

this prepares MPTCP control plane to be described as YAML spec.

Link: https://github.com/multipath-tcp/mptcp_net-next/issues/340
Signed-off-by: Davide Caratti <dcaratti@redhat.com>
---
 include/uapi/linux/mptcp.h |   8 ++
 net/mptcp/pm_netlink.c     | 204 ++++++++++++++++++++++++-------------
 net/mptcp/pm_userspace.c   |   2 +-
 net/mptcp/protocol.h       |   4 +-
 4 files changed, 146 insertions(+), 72 deletions(-)

Comments

Paolo Abeni July 21, 2023, 3:34 p.m. UTC | #1
On Fri, 2023-07-21 at 11:53 +0200, Davide Caratti wrote:
> - use a separate attribute set for add/del/get/flush address operation,
>   binary compatible with the existing one, to store the endpoint address.
>   MPTCP_PM_ENDPOINT_ADDR is added to the uAPI (with the same value as
>   MPTCP_PM_ATTR_ADDR) for these operations.

Perhaps describing with more details why the above is safe would help.

e.g. the current code abuses the MPTCP_PM_ATTR_ADDR with multiple
semathic meaning, etc.

Think again about it, such change could be worthy a separate patch.

> - convert mptcp_pm_ops[] and add policy files accordingly.
> 
> this prepares MPTCP control plane to be described as YAML spec.
> 
> Link: https://github.com/multipath-tcp/mptcp_net-next/issues/340
> Signed-off-by: Davide Caratti <dcaratti@redhat.com>
> ---
>  include/uapi/linux/mptcp.h |   8 ++
>  net/mptcp/pm_netlink.c     | 204 ++++++++++++++++++++++++-------------
>  net/mptcp/pm_userspace.c   |   2 +-
>  net/mptcp/protocol.h       |   4 +-
>  4 files changed, 146 insertions(+), 72 deletions(-)
> 
> diff --git a/include/uapi/linux/mptcp.h b/include/uapi/linux/mptcp.h
> index ee9c49f949a2..34082c14c89b 100644
> --- a/include/uapi/linux/mptcp.h
> +++ b/include/uapi/linux/mptcp.h
> @@ -65,6 +65,14 @@ enum {
>  
>  #define MPTCP_PM_ATTR_MAX (__MPTCP_PM_ATTR_MAX - 1)
>  
> +enum {
> +        MPTCP_PM_ENDPOINT_ADDR = 1,
> +
> +        __MPTCP_PM_ENDPOINT_MAX
> +};
> +
> +#define MPTCP_PM_ENDPOINT_MAX (__MPTCP_PM_ENDPOINT_MAX - 1)
> +
>  enum {
>  	MPTCP_PM_ADDR_ATTR_UNSPEC,
>  
> diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c
> index 3be32f134d2a..936382f5f62e 100644
> --- a/net/mptcp/pm_netlink.c
> +++ b/net/mptcp/pm_netlink.c
> @@ -47,6 +47,53 @@ struct pm_nl_pernet {
>  #define MPTCP_PM_ADDR_MAX	8
>  #define ADD_ADDR_RETRANS_MAX	3
>  
> +const struct nla_policy mptcp_pm_add_addr_nl_policy[MPTCP_PM_ADDR_ATTR_IF_IDX + 1] = {

It looks like that renaming this policy 'mptcp_pm_address_nl_policy'
will reduce the delta in later patches, possibly making the series more
readable.

> +	[MPTCP_PM_ADDR_ATTR_FAMILY] = { .type = NLA_U16, },
> +	[MPTCP_PM_ADDR_ATTR_ADDR4] = { .type = NLA_U32, },
> +	[MPTCP_PM_ADDR_ATTR_ADDR6] = { .len = 16, },
> +	[MPTCP_PM_ADDR_ATTR_ID] = { .type = NLA_U8, },
> +	[MPTCP_PM_ADDR_ATTR_PORT] = { .type = NLA_U16, },
> +	[MPTCP_PM_ADDR_ATTR_IF_IDX] = { .type = NLA_S32, },
> +	[MPTCP_PM_ADDR_ATTR_FLAGS] = { .type = NLA_U32, },
> +};
> +
> +/* MPTCP_PM_CMD_ADD_ADDR / DEL / GET / FLUSH - do */
> +static const struct nla_policy mptcp_pm_endpoint_nl_policy[MPTCP_PM_ENDPOINT_ADDR + 1] = {
> +	[MPTCP_PM_ENDPOINT_ADDR] = NLA_POLICY_NESTED(mptcp_pm_add_addr_nl_policy),
> +};
> +
> +/* MPTCP_PM_CMD_SET_LIMITS - do */
> +static const struct nla_policy mptcp_pm_set_limits_nl_policy[MPTCP_PM_ATTR_SUBFLOWS + 1] = {
> +	[MPTCP_PM_ATTR_RCV_ADD_ADDRS] = { .type = NLA_U32, },
> +	[MPTCP_PM_ATTR_SUBFLOWS] = { .type = NLA_U32, },
> +};
> +
> +/* MPTCP_PM_CMD_SET_FLAGS - do */
> +const struct nla_policy mptcp_pm_set_flags_nl_policy[MPTCP_PM_ATTR_ADDR_REMOTE + 1] = {
> +        [MPTCP_PM_ATTR_ADDR] = NLA_POLICY_NESTED(mptcp_pm_add_addr_nl_policy),
> +        [MPTCP_PM_ATTR_ADDR_REMOTE] = NLA_POLICY_NESTED(mptcp_pm_add_addr_nl_policy),
> +        [MPTCP_PM_ATTR_TOKEN] = { .type = NLA_U32, },
> +};
> +
> +/* MPTCP_PM_CMD_ANNOUNCE - do */
> +static const struct nla_policy mptcp_pm_announce_nl_policy[MPTCP_PM_ATTR_TOKEN + 1] = {
> +	[MPTCP_PM_ATTR_TOKEN] = { .type = NLA_U32, },
> +	[MPTCP_PM_ATTR_ADDR] = NLA_POLICY_NESTED(mptcp_pm_add_addr_nl_policy),
> +};
> +
> +/* MPTCP_PM_CMD_REMOVE - do */
> +static const struct nla_policy mptcp_pm_remove_nl_policy[MPTCP_PM_ATTR_LOC_ID + 1] = {
> +	[MPTCP_PM_ATTR_TOKEN] = { .type = NLA_U32, },
> +	[MPTCP_PM_ATTR_LOC_ID] = { .type = NLA_U8, },
> +};
> +
> +/* MPTCP_PM_CMD_SUBFLOW_CREATE / DESTROY - do */
> +static const struct nla_policy mptcp_pm_subflow_create_nl_policy[MPTCP_PM_ATTR_ADDR_REMOTE + 1] = {
> +	[MPTCP_PM_ATTR_ADDR_REMOTE] = NLA_POLICY_NESTED(mptcp_pm_add_addr_nl_policy),
> +	[MPTCP_PM_ATTR_TOKEN] = { .type = NLA_U32, },
> +	[MPTCP_PM_ATTR_ADDR] = NLA_POLICY_NESTED(mptcp_pm_add_addr_nl_policy),
> +};
> +
>  static struct pm_nl_pernet *pm_nl_get_pernet(const struct net *net)
>  {
>  	return net_generic(net, pm_nl_pernet_id);
> @@ -1100,29 +1147,6 @@ static const struct genl_multicast_group mptcp_pm_mcgrps[] = {
>  					  },
>  };
>  
> -static const struct nla_policy
> -mptcp_pm_addr_policy[MPTCP_PM_ADDR_ATTR_MAX + 1] = {
> -	[MPTCP_PM_ADDR_ATTR_FAMILY]	= { .type	= NLA_U16,	},
> -	[MPTCP_PM_ADDR_ATTR_ID]		= { .type	= NLA_U8,	},
> -	[MPTCP_PM_ADDR_ATTR_ADDR4]	= { .type	= NLA_U32,	},
> -	[MPTCP_PM_ADDR_ATTR_ADDR6]	=
> -		NLA_POLICY_EXACT_LEN(sizeof(struct in6_addr)),
> -	[MPTCP_PM_ADDR_ATTR_PORT]	= { .type	= NLA_U16	},
> -	[MPTCP_PM_ADDR_ATTR_FLAGS]	= { .type	= NLA_U32	},
> -	[MPTCP_PM_ADDR_ATTR_IF_IDX]     = { .type	= NLA_S32	},
> -};
> -
> -static const struct nla_policy mptcp_pm_policy[MPTCP_PM_ATTR_MAX + 1] = {
> -	[MPTCP_PM_ATTR_ADDR]		=
> -					NLA_POLICY_NESTED(mptcp_pm_addr_policy),
> -	[MPTCP_PM_ATTR_RCV_ADD_ADDRS]	= { .type	= NLA_U32,	},
> -	[MPTCP_PM_ATTR_SUBFLOWS]	= { .type	= NLA_U32,	},
> -	[MPTCP_PM_ATTR_TOKEN]		= { .type	= NLA_U32,	},
> -	[MPTCP_PM_ATTR_LOC_ID]		= { .type	= NLA_U8,	},
> -	[MPTCP_PM_ATTR_ADDR_REMOTE]	=
> -					NLA_POLICY_NESTED(mptcp_pm_addr_policy),
> -};
> -
>  void mptcp_pm_nl_subflow_chk_stale(const struct mptcp_sock *msk, struct sock *ssk)
>  {
>  	struct mptcp_subflow_context *iter, *subflow = mptcp_subflow_ctx(ssk);
> @@ -1172,6 +1196,7 @@ static int mptcp_pm_family_to_addr(int family)
>  static int mptcp_pm_parse_pm_addr_attr(struct nlattr *tb[],
>  				       const struct nlattr *attr,
>  				       struct genl_info *info,
> +				       const struct nla_policy *nla_policy,
>  				       struct mptcp_addr_info *addr,
>  				       bool require_family)
>  {
> @@ -1184,7 +1209,7 @@ static int mptcp_pm_parse_pm_addr_attr(struct nlattr *tb[],
>  
>  	/* no validation needed - was already done via nested policy */
>  	err = nla_parse_nested_deprecated(tb, MPTCP_PM_ADDR_ATTR_MAX, attr,
> -					  mptcp_pm_addr_policy, info->extack);
> +					  nla_policy, info->extack);
>  	if (err)
>  		return err;
>  
> @@ -1237,19 +1262,20 @@ int mptcp_pm_parse_addr(struct nlattr *attr, struct genl_info *info,
>  
>  	memset(addr, 0, sizeof(*addr));
>  
> -	return mptcp_pm_parse_pm_addr_attr(tb, attr, info, addr, true);
> +	return mptcp_pm_parse_pm_addr_attr(tb, attr, info, mptcp_pm_add_addr_nl_policy, addr, true);
>  }
>  
>  int mptcp_pm_parse_entry(struct nlattr *attr, struct genl_info *info,
> -			 bool require_family,
> -			 struct mptcp_pm_addr_entry *entry)
> +			 const struct nla_policy *nla_policy,
> +			 bool require_family, struct mptcp_pm_addr_entry *entry)

I *think* mptcp_pm_parse_entry() is always invoked with
'mptcp_pm_add_addr_nl_policy' as the policy argument. Can we just
remove such arg?

If so even mptcp_pm_parse_pm_addr_attr() is always invoked with the
same value for the policy arg, and we could remove even that argument.

The whole diff will be smaller and more readable IMHO.

Otherwise LGTM!

Cheers,

Paolo
diff mbox series

Patch

diff --git a/include/uapi/linux/mptcp.h b/include/uapi/linux/mptcp.h
index ee9c49f949a2..34082c14c89b 100644
--- a/include/uapi/linux/mptcp.h
+++ b/include/uapi/linux/mptcp.h
@@ -65,6 +65,14 @@  enum {
 
 #define MPTCP_PM_ATTR_MAX (__MPTCP_PM_ATTR_MAX - 1)
 
+enum {
+        MPTCP_PM_ENDPOINT_ADDR = 1,
+
+        __MPTCP_PM_ENDPOINT_MAX
+};
+
+#define MPTCP_PM_ENDPOINT_MAX (__MPTCP_PM_ENDPOINT_MAX - 1)
+
 enum {
 	MPTCP_PM_ADDR_ATTR_UNSPEC,
 
diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c
index 3be32f134d2a..936382f5f62e 100644
--- a/net/mptcp/pm_netlink.c
+++ b/net/mptcp/pm_netlink.c
@@ -47,6 +47,53 @@  struct pm_nl_pernet {
 #define MPTCP_PM_ADDR_MAX	8
 #define ADD_ADDR_RETRANS_MAX	3
 
+const struct nla_policy mptcp_pm_add_addr_nl_policy[MPTCP_PM_ADDR_ATTR_IF_IDX + 1] = {
+	[MPTCP_PM_ADDR_ATTR_FAMILY] = { .type = NLA_U16, },
+	[MPTCP_PM_ADDR_ATTR_ADDR4] = { .type = NLA_U32, },
+	[MPTCP_PM_ADDR_ATTR_ADDR6] = { .len = 16, },
+	[MPTCP_PM_ADDR_ATTR_ID] = { .type = NLA_U8, },
+	[MPTCP_PM_ADDR_ATTR_PORT] = { .type = NLA_U16, },
+	[MPTCP_PM_ADDR_ATTR_IF_IDX] = { .type = NLA_S32, },
+	[MPTCP_PM_ADDR_ATTR_FLAGS] = { .type = NLA_U32, },
+};
+
+/* MPTCP_PM_CMD_ADD_ADDR / DEL / GET / FLUSH - do */
+static const struct nla_policy mptcp_pm_endpoint_nl_policy[MPTCP_PM_ENDPOINT_ADDR + 1] = {
+	[MPTCP_PM_ENDPOINT_ADDR] = NLA_POLICY_NESTED(mptcp_pm_add_addr_nl_policy),
+};
+
+/* MPTCP_PM_CMD_SET_LIMITS - do */
+static const struct nla_policy mptcp_pm_set_limits_nl_policy[MPTCP_PM_ATTR_SUBFLOWS + 1] = {
+	[MPTCP_PM_ATTR_RCV_ADD_ADDRS] = { .type = NLA_U32, },
+	[MPTCP_PM_ATTR_SUBFLOWS] = { .type = NLA_U32, },
+};
+
+/* MPTCP_PM_CMD_SET_FLAGS - do */
+const struct nla_policy mptcp_pm_set_flags_nl_policy[MPTCP_PM_ATTR_ADDR_REMOTE + 1] = {
+        [MPTCP_PM_ATTR_ADDR] = NLA_POLICY_NESTED(mptcp_pm_add_addr_nl_policy),
+        [MPTCP_PM_ATTR_ADDR_REMOTE] = NLA_POLICY_NESTED(mptcp_pm_add_addr_nl_policy),
+        [MPTCP_PM_ATTR_TOKEN] = { .type = NLA_U32, },
+};
+
+/* MPTCP_PM_CMD_ANNOUNCE - do */
+static const struct nla_policy mptcp_pm_announce_nl_policy[MPTCP_PM_ATTR_TOKEN + 1] = {
+	[MPTCP_PM_ATTR_TOKEN] = { .type = NLA_U32, },
+	[MPTCP_PM_ATTR_ADDR] = NLA_POLICY_NESTED(mptcp_pm_add_addr_nl_policy),
+};
+
+/* MPTCP_PM_CMD_REMOVE - do */
+static const struct nla_policy mptcp_pm_remove_nl_policy[MPTCP_PM_ATTR_LOC_ID + 1] = {
+	[MPTCP_PM_ATTR_TOKEN] = { .type = NLA_U32, },
+	[MPTCP_PM_ATTR_LOC_ID] = { .type = NLA_U8, },
+};
+
+/* MPTCP_PM_CMD_SUBFLOW_CREATE / DESTROY - do */
+static const struct nla_policy mptcp_pm_subflow_create_nl_policy[MPTCP_PM_ATTR_ADDR_REMOTE + 1] = {
+	[MPTCP_PM_ATTR_ADDR_REMOTE] = NLA_POLICY_NESTED(mptcp_pm_add_addr_nl_policy),
+	[MPTCP_PM_ATTR_TOKEN] = { .type = NLA_U32, },
+	[MPTCP_PM_ATTR_ADDR] = NLA_POLICY_NESTED(mptcp_pm_add_addr_nl_policy),
+};
+
 static struct pm_nl_pernet *pm_nl_get_pernet(const struct net *net)
 {
 	return net_generic(net, pm_nl_pernet_id);
@@ -1100,29 +1147,6 @@  static const struct genl_multicast_group mptcp_pm_mcgrps[] = {
 					  },
 };
 
-static const struct nla_policy
-mptcp_pm_addr_policy[MPTCP_PM_ADDR_ATTR_MAX + 1] = {
-	[MPTCP_PM_ADDR_ATTR_FAMILY]	= { .type	= NLA_U16,	},
-	[MPTCP_PM_ADDR_ATTR_ID]		= { .type	= NLA_U8,	},
-	[MPTCP_PM_ADDR_ATTR_ADDR4]	= { .type	= NLA_U32,	},
-	[MPTCP_PM_ADDR_ATTR_ADDR6]	=
-		NLA_POLICY_EXACT_LEN(sizeof(struct in6_addr)),
-	[MPTCP_PM_ADDR_ATTR_PORT]	= { .type	= NLA_U16	},
-	[MPTCP_PM_ADDR_ATTR_FLAGS]	= { .type	= NLA_U32	},
-	[MPTCP_PM_ADDR_ATTR_IF_IDX]     = { .type	= NLA_S32	},
-};
-
-static const struct nla_policy mptcp_pm_policy[MPTCP_PM_ATTR_MAX + 1] = {
-	[MPTCP_PM_ATTR_ADDR]		=
-					NLA_POLICY_NESTED(mptcp_pm_addr_policy),
-	[MPTCP_PM_ATTR_RCV_ADD_ADDRS]	= { .type	= NLA_U32,	},
-	[MPTCP_PM_ATTR_SUBFLOWS]	= { .type	= NLA_U32,	},
-	[MPTCP_PM_ATTR_TOKEN]		= { .type	= NLA_U32,	},
-	[MPTCP_PM_ATTR_LOC_ID]		= { .type	= NLA_U8,	},
-	[MPTCP_PM_ATTR_ADDR_REMOTE]	=
-					NLA_POLICY_NESTED(mptcp_pm_addr_policy),
-};
-
 void mptcp_pm_nl_subflow_chk_stale(const struct mptcp_sock *msk, struct sock *ssk)
 {
 	struct mptcp_subflow_context *iter, *subflow = mptcp_subflow_ctx(ssk);
@@ -1172,6 +1196,7 @@  static int mptcp_pm_family_to_addr(int family)
 static int mptcp_pm_parse_pm_addr_attr(struct nlattr *tb[],
 				       const struct nlattr *attr,
 				       struct genl_info *info,
+				       const struct nla_policy *nla_policy,
 				       struct mptcp_addr_info *addr,
 				       bool require_family)
 {
@@ -1184,7 +1209,7 @@  static int mptcp_pm_parse_pm_addr_attr(struct nlattr *tb[],
 
 	/* no validation needed - was already done via nested policy */
 	err = nla_parse_nested_deprecated(tb, MPTCP_PM_ADDR_ATTR_MAX, attr,
-					  mptcp_pm_addr_policy, info->extack);
+					  nla_policy, info->extack);
 	if (err)
 		return err;
 
@@ -1237,19 +1262,20 @@  int mptcp_pm_parse_addr(struct nlattr *attr, struct genl_info *info,
 
 	memset(addr, 0, sizeof(*addr));
 
-	return mptcp_pm_parse_pm_addr_attr(tb, attr, info, addr, true);
+	return mptcp_pm_parse_pm_addr_attr(tb, attr, info, mptcp_pm_add_addr_nl_policy, addr, true);
 }
 
 int mptcp_pm_parse_entry(struct nlattr *attr, struct genl_info *info,
-			 bool require_family,
-			 struct mptcp_pm_addr_entry *entry)
+			 const struct nla_policy *nla_policy,
+			 bool require_family, struct mptcp_pm_addr_entry *entry)
 {
 	struct nlattr *tb[MPTCP_PM_ADDR_ATTR_MAX + 1];
 	int err;
 
 	memset(entry, 0, sizeof(*entry));
 
-	err = mptcp_pm_parse_pm_addr_attr(tb, attr, info, &entry->addr, require_family);
+	err = mptcp_pm_parse_pm_addr_attr(tb, attr, info, nla_policy,
+					  &entry->addr, require_family);
 	if (err)
 		return err;
 
@@ -1306,7 +1332,7 @@  static int mptcp_nl_cmd_add_addr(struct sk_buff *skb, struct genl_info *info)
 	struct mptcp_pm_addr_entry addr, *entry;
 	int ret;
 
-	ret = mptcp_pm_parse_entry(attr, info, true, &addr);
+	ret = mptcp_pm_parse_entry(attr, info, mptcp_pm_add_addr_nl_policy, true, &addr);
 	if (ret < 0)
 		return ret;
 
@@ -1488,7 +1514,8 @@  static int mptcp_nl_cmd_del_addr(struct sk_buff *skb, struct genl_info *info)
 	unsigned int addr_max;
 	int ret;
 
-	ret = mptcp_pm_parse_entry(attr, info, false, &addr);
+	ret = mptcp_pm_parse_entry(attr, info, mptcp_pm_add_addr_nl_policy,
+				   false, &addr);
 	if (ret < 0)
 		return ret;
 
@@ -1680,7 +1707,8 @@  static int mptcp_nl_cmd_get_addr(struct sk_buff *skb, struct genl_info *info)
 	void *reply;
 	int ret;
 
-	ret = mptcp_pm_parse_entry(attr, info, false, &addr);
+	ret = mptcp_pm_parse_entry(attr, info, mptcp_pm_add_addr_nl_policy,
+				   false, &addr);
 	if (ret < 0)
 		return ret;
 
@@ -1926,12 +1954,15 @@  static int mptcp_nl_cmd_set_flags(struct sk_buff *skb, struct genl_info *info)
 	u8 bkup = 0;
 	int ret;
 
-	ret = mptcp_pm_parse_entry(attr, info, false, &addr);
+	ret = mptcp_pm_parse_entry(attr, info, mptcp_pm_add_addr_nl_policy,
+				   false, &addr);
 	if (ret < 0)
 		return ret;
 
 	if (attr_rem) {
-		ret = mptcp_pm_parse_entry(attr_rem, info, false, &remote);
+		ret = mptcp_pm_parse_entry(attr_rem, info,
+					   mptcp_pm_add_addr_nl_policy, false,
+					   &remote);
 		if (ret < 0)
 			return ret;
 	}
@@ -2279,72 +2310,105 @@  void mptcp_event(enum mptcp_event_type type, const struct mptcp_sock *msk,
 	nlmsg_free(skb);
 }
 
-static const struct genl_small_ops mptcp_pm_ops[] = {
+
+static const struct genl_ops mptcp_pm_ops[] = {
 	{
-		.cmd    = MPTCP_PM_CMD_ADD_ADDR,
-		.doit   = mptcp_nl_cmd_add_addr,
-		.flags  = GENL_UNS_ADMIN_PERM,
+		.cmd		= MPTCP_PM_CMD_ADD_ADDR,
+		.validate	= GENL_DONT_VALIDATE_STRICT,
+		.doit		= mptcp_nl_cmd_add_addr,
+		.policy		= mptcp_pm_endpoint_nl_policy,
+		.maxattr	= MPTCP_PM_ENDPOINT_ADDR,
+		.flags		= GENL_UNS_ADMIN_PERM,
 	},
 	{
-		.cmd    = MPTCP_PM_CMD_DEL_ADDR,
-		.doit   = mptcp_nl_cmd_del_addr,
-		.flags  = GENL_UNS_ADMIN_PERM,
+		.cmd		= MPTCP_PM_CMD_DEL_ADDR,
+		.validate	= GENL_DONT_VALIDATE_STRICT,
+		.doit		= mptcp_nl_cmd_del_addr,
+		.policy		= mptcp_pm_endpoint_nl_policy,
+		.maxattr	= MPTCP_PM_ENDPOINT_ADDR,
+		.flags		= GENL_UNS_ADMIN_PERM,
 	},
 	{
-		.cmd    = MPTCP_PM_CMD_FLUSH_ADDRS,
-		.doit   = mptcp_nl_cmd_flush_addrs,
-		.flags  = GENL_UNS_ADMIN_PERM,
+		.cmd		= MPTCP_PM_CMD_GET_ADDR,
+		.validate	= GENL_DONT_VALIDATE_STRICT,
+		.doit		= mptcp_nl_cmd_get_addr,
+		.dumpit		= mptcp_nl_cmd_dump_addrs,
+		.policy		= mptcp_pm_endpoint_nl_policy,
+		.maxattr	= MPTCP_PM_ENDPOINT_ADDR,
+		.flags		= GENL_UNS_ADMIN_PERM,
 	},
 	{
-		.cmd    = MPTCP_PM_CMD_GET_ADDR,
-		.doit   = mptcp_nl_cmd_get_addr,
-		.dumpit   = mptcp_nl_cmd_dump_addrs,
+		.cmd		= MPTCP_PM_CMD_FLUSH_ADDRS,
+		.validate	= GENL_DONT_VALIDATE_STRICT,
+		.doit		= mptcp_nl_cmd_flush_addrs,
+		.policy		= mptcp_pm_endpoint_nl_policy,
+		.maxattr	= MPTCP_PM_ENDPOINT_ADDR,
+		.flags		= GENL_UNS_ADMIN_PERM,
 	},
 	{
-		.cmd    = MPTCP_PM_CMD_SET_LIMITS,
-		.doit   = mptcp_nl_cmd_set_limits,
-		.flags  = GENL_UNS_ADMIN_PERM,
+		.cmd		= MPTCP_PM_CMD_SET_LIMITS,
+		.validate	= GENL_DONT_VALIDATE_STRICT,
+		.doit		= mptcp_nl_cmd_set_limits,
+		.policy		= mptcp_pm_set_limits_nl_policy,
+		.maxattr	= MPTCP_PM_ATTR_SUBFLOWS,
+		.flags		= GENL_UNS_ADMIN_PERM,
 	},
 	{
-		.cmd    = MPTCP_PM_CMD_GET_LIMITS,
-		.doit   = mptcp_nl_cmd_get_limits,
+		.cmd		= MPTCP_PM_CMD_GET_LIMITS,
+		.validate	= GENL_DONT_VALIDATE_STRICT,
+		.doit		= mptcp_nl_cmd_get_limits,
+		.policy		= mptcp_pm_set_limits_nl_policy,
+		.maxattr	= MPTCP_PM_ATTR_SUBFLOWS,
 	},
 	{
-		.cmd    = MPTCP_PM_CMD_SET_FLAGS,
-		.doit   = mptcp_nl_cmd_set_flags,
-		.flags  = GENL_UNS_ADMIN_PERM,
+		.cmd		= MPTCP_PM_CMD_SET_FLAGS,
+		.validate	= GENL_DONT_VALIDATE_STRICT,
+		.doit		= mptcp_nl_cmd_set_flags,
+		.policy		= mptcp_pm_set_flags_nl_policy,
+		.maxattr	= MPTCP_PM_ATTR_ADDR_REMOTE,
+		.flags		= GENL_UNS_ADMIN_PERM,
 	},
 	{
-		.cmd    = MPTCP_PM_CMD_ANNOUNCE,
-		.doit   = mptcp_nl_cmd_announce,
-		.flags  = GENL_UNS_ADMIN_PERM,
+		.cmd		= MPTCP_PM_CMD_ANNOUNCE,
+		.validate	= GENL_DONT_VALIDATE_STRICT,
+		.doit		= mptcp_nl_cmd_announce,
+		.policy		= mptcp_pm_announce_nl_policy,
+		.maxattr	= MPTCP_PM_ATTR_TOKEN,
+		.flags		= GENL_UNS_ADMIN_PERM,
 	},
 	{
-		.cmd    = MPTCP_PM_CMD_REMOVE,
-		.doit   = mptcp_nl_cmd_remove,
-		.flags  = GENL_UNS_ADMIN_PERM,
+		.cmd		= MPTCP_PM_CMD_REMOVE,
+		.validate	= GENL_DONT_VALIDATE_STRICT,
+		.doit		= mptcp_nl_cmd_remove,
+		.policy		= mptcp_pm_remove_nl_policy,
+		.maxattr	= MPTCP_PM_ATTR_LOC_ID,
+		.flags		= GENL_UNS_ADMIN_PERM,
 	},
 	{
-		.cmd    = MPTCP_PM_CMD_SUBFLOW_CREATE,
-		.doit   = mptcp_nl_cmd_sf_create,
-		.flags  = GENL_UNS_ADMIN_PERM,
+		.cmd		= MPTCP_PM_CMD_SUBFLOW_CREATE,
+		.validate	= GENL_DONT_VALIDATE_STRICT,
+		.doit		= mptcp_nl_cmd_sf_create,
+		.policy		= mptcp_pm_subflow_create_nl_policy,
+		.maxattr	= MPTCP_PM_ATTR_ADDR_REMOTE,
+		.flags		= GENL_UNS_ADMIN_PERM,
 	},
 	{
-		.cmd    = MPTCP_PM_CMD_SUBFLOW_DESTROY,
-		.doit   = mptcp_nl_cmd_sf_destroy,
-		.flags  = GENL_UNS_ADMIN_PERM,
+		.cmd		= MPTCP_PM_CMD_SUBFLOW_DESTROY,
+		.validate	= GENL_DONT_VALIDATE_STRICT,
+		.doit		= mptcp_nl_cmd_sf_destroy,
+		.policy		= mptcp_pm_subflow_create_nl_policy,
+		.maxattr	= MPTCP_PM_ATTR_ADDR_REMOTE,
+		.flags		= GENL_UNS_ADMIN_PERM,
 	},
 };
 
 static struct genl_family mptcp_genl_family __ro_after_init = {
 	.name		= MPTCP_PM_NAME,
 	.version	= MPTCP_PM_VER,
-	.maxattr	= MPTCP_PM_ATTR_MAX,
-	.policy		= mptcp_pm_policy,
 	.netnsok	= true,
 	.module		= THIS_MODULE,
-	.small_ops	= mptcp_pm_ops,
-	.n_small_ops	= ARRAY_SIZE(mptcp_pm_ops),
+	.ops		= mptcp_pm_ops,
+	.n_ops		= ARRAY_SIZE(mptcp_pm_ops),
 	.resv_start_op	= MPTCP_PM_CMD_SUBFLOW_DESTROY + 1,
 	.mcgrps		= mptcp_pm_mcgrps,
 	.n_mcgrps	= ARRAY_SIZE(mptcp_pm_mcgrps),
diff --git a/net/mptcp/pm_userspace.c b/net/mptcp/pm_userspace.c
index b5a8aa4c1ebd..2acef867dbbe 100644
--- a/net/mptcp/pm_userspace.c
+++ b/net/mptcp/pm_userspace.c
@@ -172,7 +172,7 @@  int mptcp_nl_cmd_announce(struct sk_buff *skb, struct genl_info *info)
 		goto announce_err;
 	}
 
-	err = mptcp_pm_parse_entry(addr, info, true, &addr_val);
+	err = mptcp_pm_parse_entry(addr, info, mptcp_pm_add_addr_nl_policy, true, &addr_val);
 	if (err < 0) {
 		GENL_SET_ERR_MSG(info, "error parsing local address");
 		goto announce_err;
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index bb4d50c8c398..ce4ac8c37c62 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -335,6 +335,8 @@  struct mptcp_sock {
 #define mptcp_for_each_subflow_safe(__msk, __subflow, __tmp)			\
 	list_for_each_entry_safe(__subflow, __tmp, &((__msk)->conn_list), node)
 
+extern const struct nla_policy mptcp_pm_add_addr_nl_policy[];
+
 static inline void msk_owned_by_me(const struct mptcp_sock *msk)
 {
 	sock_owned_by_me((const struct sock *)msk);
@@ -802,7 +804,7 @@  void mptcp_pm_data_reset(struct mptcp_sock *msk);
 int mptcp_pm_parse_addr(struct nlattr *attr, struct genl_info *info,
 			struct mptcp_addr_info *addr);
 int mptcp_pm_parse_entry(struct nlattr *attr, struct genl_info *info,
-			 bool require_family,
+			 const struct nla_policy *nlap, bool require_family,
 			 struct mptcp_pm_addr_entry *entry);
 bool mptcp_pm_addr_families_match(const struct sock *sk,
 				  const struct mptcp_addr_info *loc,