diff options
author | Jieqiang Wang <jieqiang.wang@arm.com> | 2021-08-03 16:07:52 +0000 |
---|---|---|
committer | Neale Ranns <neale@graphiant.com> | 2021-10-20 18:17:20 +0000 |
commit | cfdb15b3724d22d9c74e95ce0e7dabead7dfef45 (patch) | |
tree | f0318e344e7f6978e875af0c2e0139018cf7eb8c | |
parent | d9e7ac3c9a02083485a898be5e7a977fcffe8a29 (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.c | 53 | ||||
-rw-r--r-- | src/vnet/fib/fib_types.h | 5 | ||||
-rw-r--r-- | src/vnet/ip/lookup.c | 23 |
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); |