#include <vnet/lisp-cp/lisp_types.h>
+static u16 gid_address_put_no_vni (u8 * b, gid_address_t * gid);
+static u16 gid_address_size_to_put_no_vni (gid_address_t * gid);
+
typedef u16 (*size_to_write_fct)(void *);
typedef void * (*cast_fct)(gid_address_t *);
typedef u16 (*serdes_fct)(u8 *, void *);
int no_addr_cmp (void * a1, void * a2);
size_to_write_fct size_to_write_fcts[GID_ADDR_TYPES] =
- { ip_prefix_size_to_write, lcaf_size_to_write };
+ { ip_prefix_size_to_write, lcaf_size_to_write, mac_size_to_write };
serdes_fct write_fcts[GID_ADDR_TYPES] =
- { ip_prefix_write, lcaf_write };
+ { ip_prefix_write, lcaf_write, mac_write };
cast_fct cast_fcts[GID_ADDR_TYPES] =
- { ip_prefix_cast, lcaf_cast };
+ { ip_prefix_cast, lcaf_cast, mac_cast };
addr_len_fct addr_len_fcts[GID_ADDR_TYPES] =
- { ip_prefix_length, lcaf_prefix_length };
+ { ip_prefix_length, lcaf_length, mac_length };
copy_fct copy_fcts[GID_ADDR_TYPES] =
- { ip_prefix_copy, lcaf_copy };
+ { ip_prefix_copy, lcaf_copy, mac_copy };
cmp_fct lcaf_cmp_fcts[LCAF_TYPES] =
{
unformat_ip_prefix (unformat_input_t * input, va_list * args)
{
ip_prefix_t * a = va_arg(*args, ip_prefix_t *);
- return unformat (input, "%U/%d", unformat_ip_address, &ip_prefix_addr(a),
- &ip_prefix_len(a));
+ if (unformat (input, "%U/%d", unformat_ip_address, &ip_prefix_addr(a),
+ &ip_prefix_len(a)))
+ {
+ if ((ip_prefix_version(a) == IP4 && 32 < ip_prefix_len(a)) ||
+ (ip_prefix_version(a) == IP6 && 128 < ip_prefix_length(a)))
+ {
+ clib_warning("Prefix length to big: %d!", ip_prefix_len(a));
+ return 0;
+ }
+ ip_prefix_normalize(a);
+ }
+ else
+ return 0;
+ return 1;
+}
+
+uword
+unformat_mac_address (unformat_input_t * input, va_list * args)
+{
+ u8 * a = va_arg(*args, u8 *);
+ return unformat (input, "%x:%x:%x:%x:%x:%x", &a[0], &a[1], &a[2], &a[3],
+ &a[4], &a[5]);
+}
+
+u8 *
+format_mac_address (u8 * s, va_list * args)
+{
+ u8 * a = va_arg (*args, u8 *);
+ return format (s, "%02x:%02x:%02x:%02x:%02x:%02x",
+ a[0], a[1], a[2], a[3], a[4], a[5]);
}
u8 *
switch (type)
{
case GID_ADDR_IP_PREFIX:
- return format (s, "%U", format_ip_prefix, &gid_address_ippref(a));
+ return format (s, "[%d] %U", gid_address_vni(a), format_ip_prefix,
+ &gid_address_ippref(a));
+ case GID_ADDR_SRC_DST:
+ return format (s, "[%d] %U|%U", gid_address_vni(a),
+ format_ip_prefix, &gid_address_sd_source_pref(a),
+ format_ip_prefix, &gid_address_sd_dest_pref(a));
+ case GID_ADDR_MAC:
+ return format (s, "[%d] %U", gid_address_vni(a), format_mac_address,
+ &gid_address_mac(a));
default:
clib_warning("Can't format gid type %d", type);
return 0;
uword
unformat_gid_address (unformat_input_t * input, va_list * args)
{
+ u32 vni;
gid_address_t * a = va_arg(*args, gid_address_t *);
- if (unformat (input, "%U", unformat_ip_prefix, &gid_address_ippref(a)))
- gid_address_type(a) = GID_ADDR_IP_PREFIX;
+ u8 mac[6] = {0};
+ ip_prefix_t ippref;
+
+ memset (&ippref, 0, sizeof (ippref));
+ memset(a, 0, sizeof(a[0]));
+
+ if (unformat (input, "%U", unformat_ip_prefix, &ippref))
+ {
+ clib_memcpy (&gid_address_ippref(a), &ippref, sizeof(ippref));
+ gid_address_type(a) = GID_ADDR_IP_PREFIX;
+ }
+ else if (unformat (input, "%U", unformat_mac_address, mac))
+ {
+ clib_memcpy (gid_address_mac(a), mac, sizeof(mac));
+ gid_address_type(a) = GID_ADDR_MAC;
+ }
+ else if (unformat (input, "[%d]", &vni))
+ gid_address_vni(a) = vni;
else
return 0;
+
+ return 1;
+}
+
+uword
+unformat_negative_mapping_action (unformat_input_t * input, va_list * args)
+{
+ u32 * action = va_arg(*args, u32 *);
+ u8 * s = 0;
+
+ if (unformat (input, "%s", &s))
+ {
+ int len = vec_len(s);
+ clib_warning ("len = %d", len);
+ if (!strcmp ((char *) s, "no-action"))
+ action[0] = ACTION_NONE;
+ if (!strcmp ((char *) s, "natively-forward"))
+ action[0] = ACTION_NATIVELY_FORWARDED;
+ if (!strcmp ((char *) s, "send-map-request"))
+ action[0] = ACTION_SEND_MAP_REQUEST;
+ else if (!strcmp ((char *) s, "drop"))
+ action[0] = ACTION_DROP;
+ else
+ {
+ clib_warning("invalid action: '%s'", s);
+ action[0] = ACTION_DROP;
+ return 0;
+ }
+ }
+ else
+ return 0;
+
return 1;
}
u16
vni_parse (u8 * p, void * a)
{
- vni_t * v = a;
+ lcaf_t * lcaf = a;
+ gid_address_t * g = a;
u16 size = 0;
- vni_vni (v) = clib_net_to_host_u32 ( *(u32 *) p);
- size += sizeof (u32);
- vni_gid (v) = clib_mem_alloc (sizeof (gid_address_t));
- gid_address_t * gid = vni_gid (v);
- memset (gid, 0, sizeof (gid[0]));
+ gid_address_vni (g) = clib_net_to_host_u32 ( *(u32 *) p);
+ size += sizeof (u32);
+ gid_address_vni_mask (g) = lcaf_vni_len (lcaf);
- size += gid_address_parse (p + size, gid);
+ /* nested LCAFs are not supported - it is expected that nested AFI type is
+ IP address */
+ size += gid_address_parse (p + size, g);
return size;
}
ip_addr_version(dst) = version;
}
+static void
+ip_prefix_normalize_ip4 (ip4_address_t * ip4, u8 preflen)
+{
+ u32 mask = ~0;
+
+ ASSERT (ip4);
+
+ if (32 <= preflen)
+ {
+ return;
+ }
+
+ mask = pow2_mask (preflen) << (32 - preflen);
+ mask = clib_host_to_net_u32 (mask);
+ ip4->data_u32 &= mask;
+}
+
+static void
+ip_prefix_normalize_ip6 (ip6_address_t * ip6, u8 preflen)
+{
+ u8 mask_6[16];
+ u32 * m;
+ u8 j ,i0, i1;
+
+ ASSERT (ip6);
+
+ memset (mask_6, 0, sizeof (mask_6));
+
+ if (128 <= preflen)
+ {
+ return;
+ }
+
+ i1 = preflen % 32;
+ i0 = preflen / 32;
+ m = (u32 * ) &mask_6[0];
+
+ for (j = 0; j < i0; j++)
+ {
+ m[j] = ~0;
+ }
+
+ if (i1)
+ {
+ m[i0] = clib_host_to_net_u32 (pow2_mask(i1) << (32 - i1));
+ }
+
+ for (j = 0; j < sizeof(mask_6); j++)
+ {
+ ip6->as_u8[j] &= mask_6[j];
+ }
+}
+
+void
+ip_prefix_normalize(ip_prefix_t * a)
+{
+ u8 preflen = ip_prefix_len(a);
+
+ switch (ip_prefix_version (a))
+ {
+ case IP4:
+ ip_prefix_normalize_ip4(&ip_prefix_v4(a), preflen);
+ break;
+
+ case IP6:
+ ip_prefix_normalize_ip6(&ip_prefix_v6(a), preflen);
+ break;
+
+ default:
+ ASSERT(0);
+ }
+}
+
void *
ip_prefix_cast (gid_address_t * a)
{
}
u16
-ip_prefix_write (u8 * p, void * pref)
+ip_prefix_write (u8 * p, void * gid)
{
- ip_prefix_t *a = (ip_prefix_t *) pref;
+ gid_address_t * g = gid;
+ ip_prefix_t *a = &gid_address_ippref (g);
+
switch (ip_prefix_version (a))
{
case IP4:
clib_memcpy (dst, src, sizeof (ip_prefix_t));
}
+void
+mac_copy (void * dst , void * src)
+{
+ clib_memcpy (dst, src, 6);
+}
+
int
ip_prefix_cmp(ip_prefix_t * p1, ip_prefix_t * p2)
{
int cmp = 0;
+
+ ip_prefix_normalize (p1);
+ ip_prefix_normalize (p2);
+
cmp = ip_address_cmp (&ip_prefix_addr(p1), &ip_prefix_addr(p2));
if (cmp == 0)
{
}
u8
-lcaf_prefix_length (void *a)
+lcaf_length (void *a)
+{
+ return 0;
+}
+
+u8
+mac_length (void *a)
{
return 0;
}
return &gid_address_lcaf (a);
}
+void *
+mac_cast (gid_address_t * a)
+{
+ return &gid_address_mac (a);
+}
+
u16
no_addr_length (void * a)
{
u16 lcaf_len = (*lcaf_body_length_fcts[type])(lcaf);
LCAF_LENGTH (h) = clib_host_to_net_u16 (lcaf_len);
- if (LCAF_INSTANCE_ID == type)
- LCAF_RES2 (h) = lcaf_vni_len(lcaf);
-
clib_memcpy (p + size, h, sizeof (h[0]));
size += sizeof (h[0]);
len = (*lcaf_write_fcts[type])(p + size, lcaf);
return size + len;
}
+u16
+mac_write (u8 * p, void * a)
+{
+ *(u16 *)p = clib_host_to_net_u16 (LISP_AFI_MAC);
+ clib_memcpy(p + sizeof (u16), a, 6);
+ return mac_size_to_write (a);
+}
+
u16
vni_write (u8 * p, void * a)
{
- vni_t * v = a;
+ lcaf_hdr_t _h, *h = &_h;
+ gid_address_t * g = a;
u16 size = 0, len;
- *(u32 *)p = clib_host_to_net_u32 (vni_vni (v));
+ /* put lcaf header */
+ *(u16 *) p = clib_host_to_net_u16 (LISP_AFI_LCAF);
+ size += sizeof (u16);
+ memset (h, 0, sizeof (h[0]));
+ LCAF_TYPE (h) = LCAF_INSTANCE_ID;
+ u16 lcaf_len = sizeof (u32) /* Instance ID size */
+ + gid_address_size_to_put_no_vni (g);
+ LCAF_LENGTH (h) = clib_host_to_net_u16 (lcaf_len);
+ LCAF_RES2 (h) = gid_address_vni_mask (g);
+
+ /* put vni header */
+ clib_memcpy (p + size, h, sizeof (h[0]));
+ size += sizeof (h[0]);
+
+ u32 * afip = (u32 *)(p + size);
+ afip[0] = clib_host_to_net_u32 (gid_address_vni (g));
size += sizeof (u32);
- len = gid_address_put (p + size, vni_gid (v));
+
+ /* write the actual address */
+ len = gid_address_put_no_vni (p + size, g);
if ((u16)~0 == len)
return ~0;
u16
vni_size_to_write (void * a)
{
- vni_t * v = a;
- u16 size = sizeof (vni_vni (v));
-
- gid_address_t * gid = vni_gid (v);
- return (size + sizeof (lcaf_hdr_t)
- + gid_address_size_to_put (gid));
+ gid_address_t * g = a;
+ return (sizeof (u32) /* vni size */
+ + sizeof (u16) /* LCAF AFI field size */
+ + sizeof (lcaf_hdr_t)
+ + gid_address_size_to_put_no_vni (g));
}
u16
return size + len;
}
+u16
+mac_size_to_write (void * a)
+{
+ return sizeof (u16) + 6;
+}
+
u8
gid_address_len (gid_address_t *a)
{
return (*addr_len_fcts[type])((*cast_fcts[type])(a));
}
-u16
-gid_address_put (u8 * b, gid_address_t * gid)
+static u16
+gid_address_put_no_vni (u8 * b, gid_address_t * gid)
{
gid_address_type_t type = gid_address_type (gid);
return (*write_fcts[type])(b, (*cast_fcts[type])(gid));
}
u16
-gid_address_size_to_put (gid_address_t * gid)
+gid_address_put (u8 * b, gid_address_t * gid)
+{
+ if (0 != gid_address_vni (gid))
+ return vni_write (b, gid);
+
+ return gid_address_put_no_vni (b, gid);
+}
+
+static u16
+gid_address_size_to_put_no_vni (gid_address_t * gid)
{
gid_address_type_t type = gid_address_type (gid);
return (*size_to_write_fcts[type])((*cast_fcts[type])(gid));
}
+u16
+gid_address_size_to_put (gid_address_t * gid)
+{
+ if (0 != gid_address_vni (gid))
+ return vni_size_to_write (gid);
+
+ return gid_address_size_to_put_no_vni (gid);
+}
+
void *
gid_address_cast (gid_address_t * gid, gid_address_type_t type)
{
gid_address_type_t type = gid_address_type(src);
(*copy_fcts[type])((*cast_fcts[type])(dst), (*cast_fcts[type])(src));
gid_address_type(dst) = type;
+ gid_address_vni(dst) = gid_address_vni(src);
+ gid_address_vni_mask(dst) = gid_address_vni_mask(src);
+}
+
+u32
+mac_parse (u8 * offset, gid_address_t * a)
+{
+ /* skip AFI field */
+ offset += sizeof (u16);
+
+ memcpy (gid_address_mac (a), offset, sizeof (gid_address_mac (a)));
+ return (sizeof (u16) + sizeof (gid_address_mac (a)));
}
u32
if (!a)
return 0;
+ /* NOTE: since gid_adress_parse may be called by vni_parse, we can't 0
+ * the gid address here */
afi = clib_net_to_host_u16 (*((u16 *) offset));
switch (afi)
gid_address_ippref_len(a) = 128;
break;
case LISP_AFI_LCAF:
- len = lcaf_parse (offset, a);
gid_address_type(a) = GID_ADDR_LCAF;
+ len = lcaf_parse (offset, a);
+ break;
+ case LISP_AFI_MAC:
+ len = mac_parse (offset, a);
+ gid_address_type(a) = GID_ADDR_MAC;
break;
default:
clib_warning("LISP AFI %d not supported!", afi);
return -1;
if (gid_address_type(a1) != gid_address_type(a2))
return -1;
+ if (gid_address_vni(a1) != gid_address_vni(a2))
+ return -1;
+ if (gid_address_vni_mask(a1) != gid_address_vni_mask(a2))
+ return -1;
switch (gid_address_type(a1))
{
if (lcaf_type (lcaf1) == lcaf_type (lcaf2))
cmp = (*lcaf_cmp_fcts[lcaf_type (lcaf1)])(lcaf1, lcaf2);
break;
+ case GID_ADDR_MAC:
+ cmp = memcmp (gid_address_mac (a1), gid_address_mac (a2),
+ sizeof (gid_address_mac (a1)));
+ break;
default:
break;
}