* limitations under the License.
*/
+#include <vnet/ethernet/ethernet.h>
#include <vnet/lisp-cp/lisp_types.h>
static u16 gid_address_put_no_vni (u8 * b, gid_address_t * gid);
size_to_write_fct size_to_write_fcts[GID_ADDR_TYPES] =
{ ip_prefix_size_to_write, lcaf_size_to_write, mac_size_to_write,
- sd_size_to_write, nsh_size_to_write
+ sd_size_to_write, nsh_size_to_write, 0 /* arp */ , no_addr_size_to_write
};
+
serdes_fct write_fcts[GID_ADDR_TYPES] =
- { ip_prefix_write, lcaf_write, mac_write, sd_write, nsh_write };
+ { ip_prefix_write, lcaf_write, mac_write, sd_write, nsh_write, 0 /* arp */ ,
+ no_addr_write
+};
+
cast_fct cast_fcts[GID_ADDR_TYPES] =
- { ip_prefix_cast, lcaf_cast, mac_cast, sd_cast, nsh_cast };
+ { ip_prefix_cast, lcaf_cast, mac_cast, sd_cast, nsh_cast, 0 /* arp */ ,
+ no_addr_cast
+};
+
addr_len_fct addr_len_fcts[GID_ADDR_TYPES] =
- { ip_prefix_length, lcaf_length, mac_length, sd_length, nsh_length };
+ { ip_prefix_length, lcaf_length, mac_length, sd_length, nsh_length,
+ 0 /* arp */ , no_addr_length
+};
+
copy_fct copy_fcts[GID_ADDR_TYPES] =
- { ip_prefix_copy, lcaf_copy, mac_copy, sd_copy, nsh_copy };
+ { ip_prefix_copy, lcaf_copy, mac_copy, sd_copy, nsh_copy, 0 /* arp */ ,
+ no_addr_copy
+};
#define foreach_lcaf_type \
_(1, no_addr) \
_(0, NULL) \
_(0, NULL) \
_(0, NULL) \
- _(1, sd)
+ _(1, sd) \
+ _(0, NULL) \
+ _(0, NULL) \
+ _(0, NULL) \
+ _(0, NULL) \
+ _(1, nsh)
#define _(cond, name) \
u16 name ## _write (u8 * p, void * a); \
#undef _
};
-u8 *
-format_ip_address (u8 * s, va_list * args)
-{
- ip_address_t *a = va_arg (*args, ip_address_t *);
- u8 ver = ip_addr_version (a);
- if (ver == IP4)
- {
- return format (s, "%U", format_ip4_address, &ip_addr_v4 (a));
- }
- else if (ver == IP6)
- {
- return format (s, "%U", format_ip6_address, &ip_addr_v6 (a));
- }
- else
- {
- clib_warning ("Can't format IP version %d!", ver);
- return 0;
- }
-}
-
-uword
-unformat_ip_address (unformat_input_t * input, va_list * args)
-{
- ip_address_t *a = va_arg (*args, ip_address_t *);
-
- memset (a, 0, sizeof (*a));
- if (unformat (input, "%U", unformat_ip4_address, &ip_addr_v4 (a)))
- ip_addr_version (a) = IP4;
- else if (unformat_user (input, unformat_ip6_address, &ip_addr_v6 (a)))
- ip_addr_version (a) = IP6;
- else
- return 0;
- return 1;
-}
-
-u8 *
-format_ip_prefix (u8 * s, va_list * args)
-{
- ip_prefix_t *a = va_arg (*args, ip_prefix_t *);
- return format (s, "%U/%d", format_ip_address, &ip_prefix_addr (a),
- ip_prefix_len (a));
-}
-
-uword
-unformat_ip_prefix (unformat_input_t * input, va_list * args)
-{
- ip_prefix_t *a = va_arg (*args, ip_prefix_t *);
- 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]);
-}
-
uword
unformat_nsh_address (unformat_input_t * input, va_list * args)
{
return format (s, "SPI:%d SI:%d", a->spi, a->si);
}
+u8 *
+format_fid_nsh_address (u8 * s, va_list * args)
+{
+ u32 *a = va_arg (*args, u32 *);
+ return format (s, "SPI:%d SI:%d", *a >> 8, *a & 0xff);
+}
+
u8 *
format_fid_address (u8 * s, va_list * args)
{
case FID_ADDR_MAC:
return format (s, "%U", format_mac_address, &fid_addr_mac (a));
case FID_ADDR_NSH:
- return format (s, "%U", format_nsh_address, &fid_addr_nsh (a));
+ return format (s, "%U", format_fid_nsh_address, &fid_addr_nsh (a));
default:
clib_warning ("Can't format fid address type %d!", fid_addr_type (a));
case GID_ADDR_MAC:
return format (s, "[%d] %U", gid_address_vni (a), format_mac_address,
&gid_address_mac (a));
+ case GID_ADDR_ARP:
+ case GID_ADDR_NDP:
+ return format (s, "[%d, %U]", gid_address_arp_ndp_bd (a),
+ format_ip_address, &gid_address_arp_ndp_ip (a));
case GID_ADDR_NSH:
return format (s, "%U", format_nsh_address, &gid_address_nsh (a));
+
default:
clib_warning ("Can't format gid type %d", type);
return 0;
else if (unformat (i, "%U", unformat_nsh_address, &nsh))
{
fid_addr_type (a) = FID_ADDR_NSH;
- nsh_copy (&fid_addr_nsh (a), mac);
+ nsh_copy (&fid_addr_nsh (a), &nsh);
}
else
return 0;
fid_address_t sim1, sim2;
nsh_t nsh;
- memset (&ippref, 0, sizeof (ippref));
- memset (&sim1, 0, sizeof (sim1));
- memset (&sim2, 0, sizeof (sim2));
+ clib_memset (&ippref, 0, sizeof (ippref));
+ clib_memset (&sim1, 0, sizeof (sim1));
+ clib_memset (&sim2, 0, sizeof (sim2));
if (unformat (input, "%U|%U", unformat_fid_address, &sim1,
unformat_fid_address, &sim2))
return (s);
}
-u16
-ip_address_size (const ip_address_t * a)
-{
- switch (ip_addr_version (a))
- {
- case IP4:
- return sizeof (ip4_address_t);
- break;
- case IP6:
- return sizeof (ip6_address_t);
- break;
- }
- return 0;
-}
-
-u16
-ip_version_to_size (u8 ver)
-{
- switch (ver)
- {
- case IP4:
- return sizeof (ip4_address_t);
- break;
- case IP6:
- return sizeof (ip6_address_t);
- break;
- }
- return 0;
-}
-
u8
-ip_version_to_max_plen (u8 ver)
+ip_prefix_length (void *a)
{
- switch (ver)
- {
- case IP4:
- return 32;
- break;
- case IP6:
- return 128;
- break;
- }
- return 0;
+ return ip_prefix_len ((ip_prefix_t *) a);
}
always_inline lisp_afi_e
{
switch (version)
{
- case IP4:
+ case AF_IP4:
return LISP_AFI_IP;
- case IP6:
+ case AF_IP6:
return LISP_AFI_IP6;
default:
return 0;
switch (afi)
{
case LISP_AFI_IP:
- return IP4;
+ return AF_IP4;
case LISP_AFI_IP6:
- return IP6;
+ return AF_IP6;
default:
return 0;
}
u8
ip_address_max_len (u8 version)
{
- return version == IP4 ? 32 : 128;
+ return version == AF_IP4 ? 32 : 128;
}
u16
u32
ip4_address_put (u8 * b, ip4_address_t * a)
{
- *(u16 *) b = clib_host_to_net_u16 (ip_version_to_iana_afi (IP4));
+ *(u16 *) b = clib_host_to_net_u16 (ip_version_to_iana_afi (AF_IP4));
u8 *p = b + sizeof (u16);
clib_memcpy (p, a, sizeof (*a));
return ip4_address_size_to_put ();
u32
ip6_address_put (u8 * b, ip6_address_t * a)
{
- *(u16 *) b = clib_host_to_net_u16 (ip_version_to_iana_afi (IP6));
+ *(u16 *) b = clib_host_to_net_u16 (ip_version_to_iana_afi (AF_IP6));
u8 *p = b + sizeof (u16);
clib_memcpy (p, a, sizeof (*a));
return ip6_address_size_to_put ();
return ip_address_parse (p, afi, ip_addr);
case FID_ADDR_NSH:
- ASSERT (0);
break;
}
return ~0;
}
+#define INC(dst, exp) \
+do { \
+ u16 _sum = (exp); \
+ if ((u16)~0 == _sum) \
+ return ~0; \
+ dst += _sum; \
+} while (0);
+
+void
+nsh_free (void *a)
+{
+ /* nothing to do */
+}
+
+u16
+nsh_parse (u8 * p, void *a)
+{
+ lcaf_spi_hdr_t *h = (lcaf_spi_hdr_t *) p;
+ gid_address_t *g = a;
+
+ gid_address_type (g) = GID_ADDR_NSH;
+ gid_address_nsh_spi (g) = clib_net_to_host_u32 (LCAF_SPI_SI (h)) >> 8;
+ gid_address_nsh_si (g) = (u8) clib_net_to_host_u32 (LCAF_SPI_SI (h));
+
+ return sizeof (lcaf_spi_hdr_t);
+}
+
+int
+nsh_cmp (void *a1, void *a2)
+{
+ nsh_t *n1 = a1;
+ nsh_t *n2 = a2;
+
+ if (n1->spi != n2->spi)
+ return 1;
+ if (n1->si != n2->si)
+ return 1;
+ return 0;
+}
+
u16
sd_parse (u8 * p, void *a)
{
sd_hdr = (lcaf_src_dst_hdr_t *) (p + size);
size += sizeof (sd_hdr[0]);
- size += fid_addr_parse (p + size, src);
- size += fid_addr_parse (p + size, dst);
+ INC (size, fid_addr_parse (p + size, src));
+ INC (size, fid_addr_parse (p + size, dst));
if (fid_addr_type (src) == FID_ADDR_IP_PREF)
{
if (LCAF_SOURCE_DEST != lcaf_type (&lcaf))
return ~0;
- size += sd_parse (p + size, a);
+ INC (size, sd_parse (p + size, a));
return size;
}
u16 afi = clib_net_to_host_u16 (*((u16 *) (p + size)));
if (LISP_AFI_LCAF == afi)
{
- u16 len = try_parse_src_dst_lcaf (p + size, g);
- if ((u16) ~ 0 == len)
- return ~0;
- size += len;
+ INC (size, try_parse_src_dst_lcaf (p + size, g));
}
else
- size += gid_address_parse (p + size, g);
+ INC (size, gid_address_parse (p + size, g));
return size;
}
clib_warning ("Unsupported LCAF type: %u", type);
return ~0;
}
- size += (*lcaf_parse_fcts[type]) (offset + size, lcaf);
+ INC (size, (*lcaf_parse_fcts[type]) (offset + size, lcaf));
return sizeof (u16) + size;
}
void
gid_address_from_ip (gid_address_t * g, ip_address_t * ip)
{
- memset (g, 0, sizeof (g[0]));
+ clib_memset (g, 0, sizeof (g[0]));
ip_address_set (&gid_address_ip (g), ip, ip_addr_version (ip));
gid_address_ippref_len (g) = 32;
}
-int
-ip_address_cmp (const ip_address_t * ip1, const ip_address_t * ip2)
-{
- int res = 0;
- if (ip_addr_version (ip1) != ip_addr_version (ip2))
- return -1;
- res =
- memcmp (&ip_addr_addr (ip1), &ip_addr_addr (ip2), ip_address_size (ip1));
-
- if (res < 0)
- res = 2;
- else if (res > 0)
- res = 1;
-
- return res;
-}
-
-void
-ip_address_copy (ip_address_t * dst, const ip_address_t * src)
-{
- if (IP4 == ip_addr_version (src))
- {
- /* don't copy any garbe from the union */
- memset (dst, 0, sizeof (*dst));
- dst->ip.v4 = src->ip.v4;
- dst->version = IP4;
- }
- else
- {
- clib_memcpy (dst, src, sizeof (ip_address_t));
- }
-}
-
-void
-ip_address_copy_addr (void *dst, const ip_address_t * src)
-{
- clib_memcpy (dst, src, ip_address_size (src));
-}
-
-void
-ip_address_set (ip_address_t * dst, const void *src, u8 version)
-{
- clib_memcpy (dst, src, ip_version_to_size (version));
- ip_addr_version (dst) = version;
-}
-
-void
-ip_address_to_46 (const ip_address_t * addr,
- ip46_address_t * a, fib_protocol_t * proto)
-{
- *proto = (IP4 == ip_addr_version (addr) ?
- FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6);
- switch (*proto)
- {
- case FIB_PROTOCOL_IP4:
- ip46_address_set_ip4 (a, &addr->ip.v4);
- break;
- case FIB_PROTOCOL_IP6:
- a->ip6 = addr->ip.v6;
- break;
- default:
- ASSERT (0);
- break;
- }
-}
-
-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)
{
switch (ip_prefix_version (a))
{
- case IP4:
+ case AF_IP4:
return ip4_address_put (p, &ip_prefix_v4 (a));
break;
- case IP6:
+ case AF_IP6:
return ip6_address_put (p, &ip_prefix_v6 (a));
break;
}
return 0;
}
-u8
-ip_prefix_length (void *a)
-{
- return ip_prefix_len ((ip_prefix_t *) a);
-}
-
-void
-ip_prefix_copy (void *dst, void *src)
-{
- clib_memcpy (dst, src, sizeof (ip_prefix_t));
-}
-
void
mac_copy (void *dst, void *src)
{
clib_memcpy (dst, src, sizeof (nsh_t));
}
-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)
- {
- if (ip_prefix_len (p1) < ip_prefix_len (p2))
- {
- cmp = 1;
- }
- else
- {
- if (ip_prefix_len (p1) > ip_prefix_len (p2))
- cmp = 2;
- }
- }
- return cmp;
-}
-
void
no_addr_copy (void *dst, void *src)
{
return &gid_address_mac (a);
}
+void *
+no_addr_cast (gid_address_t * a)
+{
+ return (void *) a;
+}
+
void *
sd_cast (gid_address_t * a)
{
*(u16 *) p = clib_host_to_net_u16 (LISP_AFI_LCAF);
size += sizeof (u16);
- memset (h, 0, sizeof (h[0]));
+ clib_memset (h, 0, sizeof (h[0]));
LCAF_TYPE (h) = type;
u16 lcaf_len = (*lcaf_body_length_fcts[type]) (lcaf);
LCAF_LENGTH (h) = clib_host_to_net_u16 (lcaf_len);
*(u16 *) p = clib_host_to_net_u16 (LISP_AFI_LCAF);
size += sizeof (u16);
- memset (h, 0, sizeof (h[0]));
+ clib_memset (h, 0, sizeof (h[0]));
LCAF_TYPE (h) = LCAF_SOURCE_DEST;
u16 lcaf_len = sizeof (lcaf_src_dst_hdr_t)
+ fid_addr_size_to_write (&sd_src (sd))
clib_memcpy (p + size, h, sizeof (h[0]));
size += sizeof (h[0]);
- memset (&sd_hdr, 0, sizeof (sd_hdr));
+ clib_memset (&sd_hdr, 0, sizeof (sd_hdr));
LCAF_SD_SRC_ML (&sd_hdr) = fid_address_length (&sd_src (sd));
LCAF_SD_DST_ML (&sd_hdr) = fid_address_length (&sd_dst (sd));
clib_memcpy (p + size, &sd_hdr, sizeof (sd_hdr));
u16
nsh_write (u8 * p, void *a)
{
- clib_warning ("not done");
- return 0;
+ lcaf_spi_hdr_t spi;
+ lcaf_hdr_t lcaf;
+ gid_address_t *g = a;
+ u16 size = 0;
+
+ ASSERT (gid_address_type (g) == GID_ADDR_NSH);
+
+ clib_memset (&lcaf, 0, sizeof (lcaf));
+ clib_memset (&spi, 0, sizeof (spi));
+
+ LCAF_TYPE (&lcaf) = LCAF_NSH;
+ LCAF_LENGTH (&lcaf) = clib_host_to_net_u16 (sizeof (lcaf_spi_hdr_t));
+
+ u32 s = clib_host_to_net_u32 (gid_address_nsh_spi (g) << 8 |
+ gid_address_nsh_si (g));
+ LCAF_SPI_SI (&spi) = s;
+
+ *(u16 *) p = clib_host_to_net_u16 (LISP_AFI_LCAF);
+ size += sizeof (u16);
+
+ clib_memcpy (p + size, &lcaf, sizeof (lcaf));
+ size += sizeof (lcaf);
+
+ clib_memcpy (p + size, &spi, sizeof (spi));
+ size += sizeof (spi);
+
+ return size;
}
u16
/* put lcaf header */
*(u16 *) p = clib_host_to_net_u16 (LISP_AFI_LCAF);
size += sizeof (u16);
- memset (h, 0, sizeof (h[0]));
+ clib_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);
u16
nsh_size_to_write (void *a)
{
- return sizeof (u16) + 4;
+ return sizeof (u16) + sizeof (lcaf_hdr_t) + sizeof (lcaf_spi_hdr_t);
}
u8
gid_address_parse (u8 * offset, gid_address_t * a)
{
lisp_afi_e afi;
- int len = 0;
+ u16 len = 0;
- if (!a)
- return 0;
+ ASSERT (a);
/* NOTE: since gid_address_parse may be called by vni_parse, we can't 0
* the gid address here */
clib_warning ("LISP AFI %d not supported!", afi);
return ~0;
}
- return len;
+ return (len == (u16) ~ 0) ? ~0 : len;
}
void
case GID_ADDR_SRC_DST:
cmp = sd_cmp (&gid_address_sd (a1), &gid_address_sd (a2));
break;
+ case GID_ADDR_NSH:
+ cmp = nsh_cmp (&gid_address_nsh (a1), &gid_address_nsh (a2));
+ break;
default:
break;
}
loc->state = status;
loc->local = 0;
+ loc->probed = 0;
loc->priority = LOC_PRIORITY (h);
loc->weight = LOC_WEIGHT (h);
loc->mpriority = LOC_MPRIORITY (h);
void
build_src_dst (gid_address_t * sd, gid_address_t * src, gid_address_t * dst)
{
- memset (sd, 0, sizeof (*sd));
+ clib_memset (sd, 0, sizeof (*sd));
gid_address_type (sd) = GID_ADDR_SRC_DST;
gid_address_vni (sd) = gid_address_vni (dst);
gid_address_vni_mask (sd) = gid_address_vni_mask (dst);