From cfdb15b3724d22d9c74e95ce0e7dabead7dfef45 Mon Sep 17 00:00:00 2001 From: Jieqiang Wang Date: Tue, 3 Aug 2021 16:07:52 +0000 Subject: 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 Reviewed-by: Lijian Zhang Reviewed-by: Tianyu Li Change-Id: If954876301ca2095f9331799a086f75db936f246 --- src/vnet/fib/fib_types.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++ src/vnet/fib/fib_types.h | 5 +++++ 2 files changed, 58 insertions(+) (limited to 'src/vnet/fib') 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 @@ -285,6 +285,11 @@ extern u8 * format_fib_forw_chain_type(u8 * s, va_list * args); 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 */ -- cgit 1.2.3-korg