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: Tom Herbert <t...@quantonium.net>
---
 include/uapi/linux/ila.h | 13 ++++++++++++
 net/ipv6/ila/ila.h       | 12 +-----------
 net/ipv6/ila/ila_lwt.c   | 51 +++++++++++++++++++++++++++++++++++++++++-------
 net/ipv6/ila/ila_xlat.c  | 18 ++++++++++++-----
 4 files changed, 71 insertions(+), 23 deletions(-)

diff --git a/include/uapi/linux/ila.h b/include/uapi/linux/ila.h
index 0744881dcef3..8353c78a7781 100644
--- a/include/uapi/linux/ila.h
+++ b/include/uapi/linux/ila.h
@@ -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 */
diff --git a/net/ipv6/ila/ila.h b/net/ipv6/ila/ila.h
index e0170f62bc39..3c7a11b62334 100644
--- a/net/ipv6/ila/ila.h
+++ b/net/ipv6/ila/ila.h
@@ -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)
diff --git a/net/ipv6/ila/ila_lwt.c b/net/ipv6/ila/ila_lwt.c
index 104af07d83a6..4b97d573f223 100644
--- a/net/ipv6/ila/ila_lwt.c
+++ b/net/ipv6/ila/ila_lwt.c
@@ -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,19 +128,14 @@ 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;
 
-       if (cfg6->fc_dst_len < 8 * sizeof(struct ila_locator) + 3) {
-               /* Need to have full locator and at least type field
-                * included in destination
-                */
-               return -EINVAL;
-       }
-
        ret = nla_parse_nested(tb, ILA_ATTR_MAX, nla, ila_nl_policy, extack);
        if (ret < 0)
                return ret;
@@ -149,6 +145,41 @@ static int ila_build_state(struct nlattr *nla,
 
        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
+                        */
+                       return -EINVAL;
+               }
+
+               eff_ident_type = iaddr->ident.type;
+       } else {
+               eff_ident_type = ident_type;
+       }
+
+       switch (eff_ident_type) {
+       case ILA_ATYPE_IID:
+               /* Don't allow ILA for IID type */
+               return -EINVAL;
+       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;
 }
 
diff --git a/net/ipv6/ila/ila_xlat.c b/net/ipv6/ila/ila_xlat.c
index 213259629e66..6eb5e68f112a 100644
--- a/net/ipv6/ila/ila_xlat.c
+++ b/net/ipv6/ila/ila_xlat.c
@@ -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();
 
-- 
2.11.0

Reply via email to