fib: fix crash while adding intf-rx routes
[vpp.git] / src / vnet / ip / ip_types.c
index cd08c54..ec80a96 100644 (file)
@@ -41,14 +41,16 @@ uword
 unformat_ip_address (unformat_input_t * input, va_list * args)
 {
   ip_address_t *a = va_arg (*args, ip_address_t *);
+  ip_address_t tmp, *p_tmp = &tmp;
 
-  clib_memset (a, 0, sizeof (*a));
-  if (unformat (input, "%U", unformat_ip4_address, &ip_addr_v4 (a)))
-    ip_addr_version (a) = AF_IP4;
-  else if (unformat_user (input, unformat_ip6_address, &ip_addr_v6 (a)))
-    ip_addr_version (a) = AF_IP6;
+  clib_memset (p_tmp, 0, sizeof (*p_tmp));
+  if (unformat (input, "%U", unformat_ip4_address, &ip_addr_v4 (p_tmp)))
+    ip_addr_version (p_tmp) = AF_IP4;
+  else if (unformat_user (input, unformat_ip6_address, &ip_addr_v6 (p_tmp)))
+    ip_addr_version (p_tmp) = AF_IP6;
   else
     return 0;
+  *a = *p_tmp;
   return 1;
 }
 
@@ -64,9 +66,12 @@ uword
 unformat_ip_prefix (unformat_input_t * input, va_list * args)
 {
   ip_prefix_t *a = va_arg (*args, ip_prefix_t *);
+  /* %d writes more than a u8 */
+  int plen;
   if (unformat (input, "%U/%d", unformat_ip_address, &ip_prefix_addr (a),
-               &ip_prefix_len (a)))
+               &plen))
     {
+      ip_prefix_len (a) = plen;
       if ((ip_prefix_version (a) == AF_IP4 && 32 < ip_prefix_len (a)) ||
          (ip_prefix_version (a) == AF_IP6 && 128 < ip_prefix_len (a)))
        {
@@ -200,13 +205,12 @@ ip_address_family_to_link_type (ip_address_family_t af)
   return (VNET_LINK_IP4);
 }
 
-
 void
-ip_address_set (ip_address_t * dst, const void *src, u8 version)
+ip_address_set (ip_address_t *dst, const void *src, ip_address_family_t af)
 {
-  ip_addr_version (dst) = version;
+  ip_addr_version (dst) = af;
 
-  switch (version)
+  switch (af)
     {
     case AF_IP4:
       ip_addr_v4 (dst) = *(ip4_address_t *) src;
@@ -261,6 +265,50 @@ ip_address_from_46 (const ip46_address_t * nh,
   ip_addr_version (ip) = ip_address_family_from_fib_proto (fproto);
 }
 
+/**
+ * convert from a IP address to a FIB prefix
+ */
+void
+ip_address_to_fib_prefix (const ip_address_t * addr, fib_prefix_t * prefix)
+{
+  if (addr->version == AF_IP4)
+    {
+      prefix->fp_len = 32;
+      prefix->fp_proto = FIB_PROTOCOL_IP4;
+      clib_memset (&prefix->fp_addr.pad, 0, sizeof (prefix->fp_addr.pad));
+      memcpy (&prefix->fp_addr.ip4, &addr->ip.ip4,
+             sizeof (prefix->fp_addr.ip4));
+    }
+  else
+    {
+      prefix->fp_len = 128;
+      prefix->fp_proto = FIB_PROTOCOL_IP6;
+      memcpy (&prefix->fp_addr.ip6, &addr->ip.ip6,
+             sizeof (prefix->fp_addr.ip6));
+    }
+  prefix->___fp___pad = 0;
+}
+
+void
+ip_address_to_prefix (const ip_address_t *addr, ip_prefix_t *prefix)
+{
+  prefix->len = (addr->version == AF_IP4 ? 32 : 128);
+  clib_memcpy (&prefix->addr, addr, sizeof (prefix->addr));
+}
+
+void
+ip_address_increment (ip_address_t * ip)
+{
+  ip46_address_increment ((ip_addr_version (ip) == AF_IP4 ?
+                          IP46_TYPE_IP4 : IP46_TYPE_IP6), &ip_addr_46 (ip));
+}
+
+void
+ip_address_reset (ip_address_t * ip)
+{
+  clib_memset (ip, 0, sizeof (*ip));
+}
+
 static void
 ip_prefix_normalize_ip4 (ip4_address_t * ip4, u8 preflen)
 {
@@ -341,29 +389,41 @@ ip_prefix_copy (void *dst, void *src)
 }
 
 int
-ip_prefix_cmp (ip_prefix_t * p1, ip_prefix_t * p2)
+ip_prefix_cmp (const ip_prefix_t *ipp1, const ip_prefix_t *ipp2)
 {
+  ip_prefix_t p1 = *ipp1, p2 = *ipp2;
   int cmp = 0;
 
-  ip_prefix_normalize (p1);
-  ip_prefix_normalize (p2);
+  ip_prefix_normalize (&p1);
+  ip_prefix_normalize (&p2);
 
-  cmp = ip_address_cmp (&ip_prefix_addr (p1), &ip_prefix_addr (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))
+      if (ip_prefix_len (&p1) < ip_prefix_len (&p2))
        {
          cmp = 1;
        }
       else
        {
-         if (ip_prefix_len (p1) > ip_prefix_len (p2))
+         if (ip_prefix_len (&p1) > ip_prefix_len (&p2))
            cmp = 2;
        }
     }
   return cmp;
 }
 
+/**
+ * convert from a LISP to a FIB prefix
+ */
+void
+ip_prefix_to_fib_prefix (const ip_prefix_t * ip_prefix,
+                        fib_prefix_t * fib_prefix)
+{
+  ip_address_to_fib_prefix (&ip_prefix->addr, fib_prefix);
+  fib_prefix->fp_len = ip_prefix->len;
+}
+
 static bool
 ip4_prefix_validate (const ip_prefix_t * ip)
 {
@@ -511,16 +571,11 @@ ip6_prefix_max_address_host_order (ip6_address_t * ip, u8 plen,
 u32
 ip6_mask_to_preflen (ip6_address_t * mask)
 {
-  u8 first1, first0;
-  if (mask->as_u64[0] == 0 && mask->as_u64[1] == 0)
-    return 0;
-  first1 = log2_first_set (clib_net_to_host_u64 (mask->as_u64[1]));
-  first0 = log2_first_set (clib_net_to_host_u64 (mask->as_u64[0]));
-
-  if (first1 != 0)
-    return 128 - first1;
-  else
-    return 64 - first0;
+  if (mask->as_u64[1] != 0)
+    return 128 - log2_first_set (clib_net_to_host_u64 (mask->as_u64[1]));
+  if (mask->as_u64[0] != 0)
+    return 64 - log2_first_set (clib_net_to_host_u64 (mask->as_u64[0]));
+  return 0;
 }
 
 /*