summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJieqiang Wang <jieqiang.wang@arm.com>2021-08-03 16:07:52 +0000
committerNeale Ranns <neale@graphiant.com>2021-10-20 18:17:20 +0000
commitcfdb15b3724d22d9c74e95ce0e7dabead7dfef45 (patch)
treef0318e344e7f6978e875af0c2e0139018cf7eb8c
parentd9e7ac3c9a02083485a898be5e7a977fcffe8a29 (diff)
ip6: fix IPv6 address calculation error using "ip route add" CLI
Using VPP CLI "ip route add" to add static IPv6 entries outputs wrong results. Fix this error by correctly calculating IPv6 addresses with different increased ranges and grouping ip4/ip6 prefix calculation functionality into two functions. Type: fix Signed-off-by: Jieqiang Wang <jieqiang.wang@arm.com> Reviewed-by: Lijian Zhang <lijian.zhang@arm.com> Reviewed-by: Tianyu Li <tianyu.li@arm.com> Change-Id: If954876301ca2095f9331799a086f75db936f246
-rw-r--r--src/vnet/fib/fib_types.c53
-rw-r--r--src/vnet/fib/fib_types.h5
-rw-r--r--src/vnet/ip/lookup.c23
3 files changed, 61 insertions, 20 deletions
diff --git a/src/vnet/fib/fib_types.c b/src/vnet/fib/fib_types.c
index eab5ca22571..15e795a72c9 100644
--- a/src/vnet/fib/fib_types.c
+++ b/src/vnet/fib/fib_types.c
@@ -785,3 +785,56 @@ fib_route_path_is_attached (const fib_route_path_t *rpath)
}
return (0);
}
+
+static void
+fib_prefix_ip4_addr_increment (fib_prefix_t *pfx)
+{
+ /* Calculate the addend based on the host length of address */
+ u32 incr = 1ULL << (32 - pfx->fp_len);
+ ip4_address_t dst = (pfx->fp_addr).ip4;
+ dst.as_u32 = clib_host_to_net_u32 (incr + clib_net_to_host_u32 (dst.as_u32));
+ pfx->fp_addr.ip4.as_u32 = dst.as_u32;
+}
+
+static void
+fib_prefix_ip6_addr_increment (fib_prefix_t *pfx)
+{
+ /*
+ * Calculate the addend based on the host length of address
+ * and which part(lower 64 bits or higher 64 bits) it lies
+ * in
+ */
+ u32 host_len = 128 - pfx->fp_len;
+ u64 incr = 1ULL << ((host_len > 64) ? (host_len - 64) : host_len);
+ i32 bucket = (host_len < 64 ? 1 : 0);
+ ip6_address_t dst = (pfx->fp_addr).ip6;
+ u64 tmp = incr + clib_net_to_host_u64 (dst.as_u64[bucket]);
+ /* Handle overflow */
+ if (bucket && (tmp < incr))
+ {
+ dst.as_u64[1] = clib_host_to_net_u64 (tmp);
+ dst.as_u64[0] = clib_host_to_net_u64 (1ULL + clib_net_to_host_u64 (dst.as_u64[0]));
+ }
+ else
+ dst.as_u64[bucket] = clib_host_to_net_u64 (tmp);
+
+ pfx->fp_addr.ip6.as_u128 = dst.as_u128;
+}
+
+/*
+ * Increase IPv4/IPv6 address according to the prefix length
+ */
+void fib_prefix_increment (fib_prefix_t *pfx)
+{
+ switch (pfx->fp_proto)
+ {
+ case FIB_PROTOCOL_IP4:
+ fib_prefix_ip4_addr_increment (pfx);
+ break;
+ case FIB_PROTOCOL_IP6:
+ fib_prefix_ip6_addr_increment (pfx);
+ break;
+ case FIB_PROTOCOL_MPLS:
+ break;
+ }
+}
diff --git a/src/vnet/fib/fib_types.h b/src/vnet/fib/fib_types.h
index 55b404b044e..dbd4e97e867 100644
--- a/src/vnet/fib/fib_types.h
+++ b/src/vnet/fib/fib_types.h
@@ -286,6 +286,11 @@ extern dpo_proto_t fib_proto_to_dpo(fib_protocol_t fib_proto);
extern fib_protocol_t dpo_proto_to_fib(dpo_proto_t dpo_proto);
/**
+ * \brief Increase IPv4/IPv6 address according to the prefix length
+ */
+extern void fib_prefix_increment (fib_prefix_t *pfx);
+
+/**
* Convert from BIER next-hop proto to FIB proto
*/
extern fib_protocol_t bier_hdr_proto_to_fib(bier_hdr_proto_id_t bproto);
diff --git a/src/vnet/ip/lookup.c b/src/vnet/ip/lookup.c
index 192c4c7cebc..2bb667bc65a 100644
--- a/src/vnet/ip/lookup.c
+++ b/src/vnet/ip/lookup.c
@@ -304,20 +304,17 @@ vnet_ip_route_cmd (vlib_main_t * vm,
}
else if (0 < vec_len (rpaths))
{
- u32 k, n, incr;
- ip46_address_t dst = prefixs[i].fp_addr;
+ u32 k, n;
f64 t[2];
n = count;
t[0] = vlib_time_now (vm);
- incr = 1 << ((FIB_PROTOCOL_IP4 == prefixs[0].fp_proto ? 32 : 128) -
- prefixs[i].fp_len);
for (k = 0; k < n; k++)
{
fib_prefix_t rpfx = {
.fp_len = prefixs[i].fp_len,
.fp_proto = prefixs[i].fp_proto,
- .fp_addr = dst,
+ .fp_addr = prefixs[i].fp_addr,
};
if (is_del)
@@ -329,21 +326,7 @@ vnet_ip_route_cmd (vlib_main_t * vm,
FIB_SOURCE_CLI,
FIB_ENTRY_FLAG_NONE, rpaths);
- if (FIB_PROTOCOL_IP4 == prefixs[0].fp_proto)
- {
- dst.ip4.as_u32 =
- clib_host_to_net_u32 (incr +
- clib_net_to_host_u32 (dst.
- ip4.as_u32));
- }
- else
- {
- int bucket = (incr < 64 ? 0 : 1);
- dst.ip6.as_u64[bucket] =
- clib_host_to_net_u64 (incr +
- clib_net_to_host_u64 (dst.ip6.as_u64
- [bucket]));
- }
+ fib_prefix_increment (&prefixs[i]);
}
t[1] = vlib_time_now (vm);