Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 70d5aef4 authored by Tom Herbert's avatar Tom Herbert Committed by David S. Miller
Browse files

ila: allow configuration of identifier type



Allow identifier to be explicitly configured for a mapping.
This can either be one of the identifier types specified in the
ILA draft or a value of ILA_ATYPE_USE_FORMAT which means the
identifier type is inferred from the identifier type field.
If a value other than ILA_ATYPE_USE_FORMAT is set for a
mapping then it is assumed that the identifier type field is
not present in an identifier.

Signed-off-by: default avatarTom Herbert <tom@quantonium.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 84287bb3
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@ enum {
	ILA_ATTR_DIR,				/* u32 */
	ILA_ATTR_PAD,
	ILA_ATTR_CSUM_MODE,			/* u8 */
	ILA_ATTR_IDENT_TYPE,			/* u8 */

	__ILA_ATTR_MAX,
};
@@ -44,4 +45,16 @@ enum {
	ILA_CSUM_NEUTRAL_MAP_AUTO,
};

enum {
	ILA_ATYPE_IID = 0,
	ILA_ATYPE_LUID,
	ILA_ATYPE_VIRT_V4,
	ILA_ATYPE_VIRT_UNI_V6,
	ILA_ATYPE_VIRT_MULTI_V6,
	ILA_ATYPE_NONLOCAL_ADDR,
	ILA_ATYPE_RSVD_1,
	ILA_ATYPE_RSVD_2,

	ILA_ATYPE_USE_FORMAT = 32, /* Get type from type field in identifier */
};
#endif /* _UAPI_LINUX_ILA_H */
+1 −11
Original line number Diff line number Diff line
@@ -55,17 +55,6 @@ struct ila_identifier {
	};
};

enum {
	ILA_ATYPE_IID = 0,
	ILA_ATYPE_LUID,
	ILA_ATYPE_VIRT_V4,
	ILA_ATYPE_VIRT_UNI_V6,
	ILA_ATYPE_VIRT_MULTI_V6,
	ILA_ATYPE_RSVD_1,
	ILA_ATYPE_RSVD_2,
	ILA_ATYPE_RSVD_3,
};

#define CSUM_NEUTRAL_FLAG	htonl(0x10000000)

struct ila_addr {
@@ -93,6 +82,7 @@ struct ila_params {
	struct ila_locator locator_match;
	__wsum csum_diff;
	u8 csum_mode;
	u8 ident_type;
};

static inline __wsum compute_csum_diff8(const __be32 *from, const __be32 *to)
+44 −7
Original line number Diff line number Diff line
@@ -114,6 +114,7 @@ static int ila_input(struct sk_buff *skb)
static const struct nla_policy ila_nl_policy[ILA_ATTR_MAX + 1] = {
	[ILA_ATTR_LOCATOR] = { .type = NLA_U64, },
	[ILA_ATTR_CSUM_MODE] = { .type = NLA_U8, },
	[ILA_ATTR_IDENT_TYPE] = { .type = NLA_U8, },
};

static int ila_build_state(struct nlattr *nla,
@@ -127,12 +128,31 @@ static int ila_build_state(struct nlattr *nla,
	struct lwtunnel_state *newts;
	const struct fib6_config *cfg6 = cfg;
	struct ila_addr *iaddr;
	u8 ident_type = ILA_ATYPE_USE_FORMAT;
	u8 csum_mode = ILA_CSUM_NO_ACTION;
	u8 eff_ident_type;
	int ret;

	if (family != AF_INET6)
		return -EINVAL;

	ret = nla_parse_nested(tb, ILA_ATTR_MAX, nla, ila_nl_policy, extack);
	if (ret < 0)
		return ret;

	if (!tb[ILA_ATTR_LOCATOR])
		return -EINVAL;

	iaddr = (struct ila_addr *)&cfg6->fc_dst;

	if (tb[ILA_ATTR_IDENT_TYPE])
		ident_type = nla_get_u8(tb[ILA_ATTR_IDENT_TYPE]);

	if (ident_type == ILA_ATYPE_USE_FORMAT) {
		/* Infer identifier type from type field in formatted
		 * identifier.
		 */

		if (cfg6->fc_dst_len < 8 * sizeof(struct ila_locator) + 3) {
			/* Need to have full locator and at least type field
			 * included in destination
@@ -140,14 +160,25 @@ static int ila_build_state(struct nlattr *nla,
			return -EINVAL;
		}

	ret = nla_parse_nested(tb, ILA_ATTR_MAX, nla, ila_nl_policy, extack);
	if (ret < 0)
		return ret;
		eff_ident_type = iaddr->ident.type;
	} else {
		eff_ident_type = ident_type;
	}

	if (!tb[ILA_ATTR_LOCATOR])
	switch (eff_ident_type) {
	case ILA_ATYPE_IID:
		/* Don't allow ILA for IID type */
		return -EINVAL;

	iaddr = (struct ila_addr *)&cfg6->fc_dst;
	case ILA_ATYPE_LUID:
		break;
	case ILA_ATYPE_VIRT_V4:
	case ILA_ATYPE_VIRT_UNI_V6:
	case ILA_ATYPE_VIRT_MULTI_V6:
	case ILA_ATYPE_NONLOCAL_ADDR:
		/* These ILA formats are not supported yet. */
	default:
		return -EINVAL;
	}

	if (tb[ILA_ATTR_CSUM_MODE])
		csum_mode = nla_get_u8(tb[ILA_ATTR_CSUM_MODE]);
@@ -174,6 +205,7 @@ static int ila_build_state(struct nlattr *nla,
	p = ila_params_lwtunnel(newts);

	p->csum_mode = csum_mode;
	p->ident_type = ident_type;
	p->locator.v64 = (__force __be64)nla_get_u64(tb[ILA_ATTR_LOCATOR]);

	/* Precompute checksum difference for translation since we
@@ -208,9 +240,13 @@ static int ila_fill_encap_info(struct sk_buff *skb,
	if (nla_put_u64_64bit(skb, ILA_ATTR_LOCATOR, (__force u64)p->locator.v64,
			      ILA_ATTR_PAD))
		goto nla_put_failure;

	if (nla_put_u8(skb, ILA_ATTR_CSUM_MODE, (__force u8)p->csum_mode))
		goto nla_put_failure;

	if (nla_put_u8(skb, ILA_ATTR_IDENT_TYPE, (__force u8)p->ident_type))
		goto nla_put_failure;

	return 0;

nla_put_failure:
@@ -221,6 +257,7 @@ static int ila_encap_nlsize(struct lwtunnel_state *lwtstate)
{
	return nla_total_size_64bit(sizeof(u64)) + /* ILA_ATTR_LOCATOR */
	       nla_total_size(sizeof(u8)) +        /* ILA_ATTR_CSUM_MODE */
	       nla_total_size(sizeof(u8)) +        /* ILA_ATTR_IDENT_TYPE */
	       0;
}

+13 −5
Original line number Diff line number Diff line
@@ -121,6 +121,7 @@ static const struct nla_policy ila_nl_policy[ILA_ATTR_MAX + 1] = {
	[ILA_ATTR_LOCATOR_MATCH] = { .type = NLA_U64, },
	[ILA_ATTR_IFINDEX] = { .type = NLA_U32, },
	[ILA_ATTR_CSUM_MODE] = { .type = NLA_U8, },
	[ILA_ATTR_IDENT_TYPE] = { .type = NLA_U8, },
};

static int parse_nl_config(struct genl_info *info,
@@ -141,6 +142,12 @@ static int parse_nl_config(struct genl_info *info,
	else
		xp->ip.csum_mode = ILA_CSUM_NO_ACTION;

	if (info->attrs[ILA_ATTR_IDENT_TYPE])
		xp->ip.ident_type = nla_get_u8(
				info->attrs[ILA_ATTR_IDENT_TYPE]);
	else
		xp->ip.ident_type = ILA_ATYPE_USE_FORMAT;

	if (info->attrs[ILA_ATTR_IFINDEX])
		xp->ifindex = nla_get_s32(info->attrs[ILA_ATTR_IFINDEX]);

@@ -398,7 +405,8 @@ static int ila_fill_info(struct ila_map *ila, struct sk_buff *msg)
			      (__force u64)ila->xp.ip.locator_match.v64,
			      ILA_ATTR_PAD) ||
	    nla_put_s32(msg, ILA_ATTR_IFINDEX, ila->xp.ifindex) ||
	    nla_put_u8(msg, ILA_ATTR_CSUM_MODE, ila->xp.ip.csum_mode))
	    nla_put_u8(msg, ILA_ATTR_CSUM_MODE, ila->xp.ip.csum_mode) ||
	    nla_put_u8(msg, ILA_ATTR_IDENT_TYPE, ila->xp.ip.ident_type))
		return -1;

	return 0;
@@ -619,10 +627,10 @@ static int ila_xlat_addr(struct sk_buff *skb, bool sir2ila)

	/* Assumes skb contains a valid IPv6 header that is pulled */

	if (!ila_addr_is_ila(iaddr)) {
		/* Type indicates this is not an ILA address */
		return 0;
	}
	/* No check here that ILA type in the mapping matches what is in the
	 * address. We assume that whatever sender gaves us can be translated.
	 * The checksum mode however is relevant.
	 */

	rcu_read_lock();