aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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);