From d0df49f26eabf2f534b567f3370e50c4e804aeea Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Wed, 8 Aug 2018 01:06:40 -0700 Subject: [PATCH] Use IP address types on UDP encap API Change-Id: I3c714c519b6d0009329b50947ce250c18ee2a85a Signed-off-by: Neale Ranns --- src/vnet/fib/fib_types.c | 34 +++++++++ src/vnet/fib/fib_types.h | 10 +++ src/vnet/ip/format.h | 6 -- src/vnet/ip/ip6_packet.h | 7 ++ src/vnet/ip/ip_types.api | 7 ++ src/vnet/ip/ip_types_api.c | 143 +++++++++++++++++++++++++++-------- src/vnet/ip/ip_types_api.h | 18 ++++- src/vnet/udp/udp.api | 83 +++++++++++++------- src/vnet/udp/udp_api.c | 101 ++++++++++++++----------- src/vpp-api/vapi/vapi_json_parser.py | 1 - test/test_udp.py | 15 ++-- test/vpp_ip.py | 135 +++++++++++++++++++++++++++++++++ test/vpp_papi_provider.py | 42 +++++----- test/vpp_udp_encap.py | 46 +++++------ 14 files changed, 482 insertions(+), 166 deletions(-) create mode 100644 test/vpp_ip.py diff --git a/src/vnet/fib/fib_types.c b/src/vnet/fib/fib_types.c index 1046e45b2f7..542cf1d7faf 100644 --- a/src/vnet/fib/fib_types.c +++ b/src/vnet/fib/fib_types.c @@ -282,6 +282,40 @@ fib_proto_to_link (fib_protocol_t proto) return (0); } +ip46_type_t +fib_proto_to_ip46 (fib_protocol_t fproto) +{ + switch (fproto) + { + case FIB_PROTOCOL_IP4: + return (IP46_TYPE_IP4); + case FIB_PROTOCOL_IP6: + return (IP46_TYPE_IP6); + case FIB_PROTOCOL_MPLS: + return (IP46_TYPE_ANY); + } + ASSERT(0); + return (IP46_TYPE_ANY); +} + +fib_protocol_t +fib_proto_from_ip46 (ip46_type_t iproto) +{ + switch (iproto) + { + case IP46_TYPE_IP4: + return FIB_PROTOCOL_IP4; + case IP46_TYPE_IP6: + return FIB_PROTOCOL_IP6; + case IP46_TYPE_ANY: + ASSERT(0); + return FIB_PROTOCOL_IP4; + } + + ASSERT(0); + return FIB_PROTOCOL_IP4; +} + fib_forward_chain_type_t fib_forw_chain_type_from_dpo_proto (dpo_proto_t proto) { diff --git a/src/vnet/fib/fib_types.h b/src/vnet/fib/fib_types.h index 7f186ac6f6a..805f8e1b964 100644 --- a/src/vnet/fib/fib_types.h +++ b/src/vnet/fib/fib_types.h @@ -82,6 +82,16 @@ fib_ip_proto(bool is_ip6) return (is_ip6) ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4; } +/** + * @brief Convert from fib_protocol to ip46_type + */ +extern ip46_type_t fib_proto_to_ip46(fib_protocol_t fproto); + +/** + * @brief Convert from ip46_type to fib_protocol + */ +extern fib_protocol_t fib_proto_from_ip46(ip46_type_t iproto); + /** * @brief Convert from a protocol to a link type */ diff --git a/src/vnet/ip/format.h b/src/vnet/ip/format.h index 9ebcf084be3..4d63ba43653 100644 --- a/src/vnet/ip/format.h +++ b/src/vnet/ip/format.h @@ -60,12 +60,6 @@ format_function_t format_ip_adjacency_packet_data; format_function_t format_ip46_address; -typedef enum -{ - IP46_TYPE_ANY, - IP46_TYPE_IP4, - IP46_TYPE_IP6 -} ip46_type_t; /* unformat_ip46_address expects arguments (ip46_address_t *, ip46_type_t) * The type argument is used to enforce a particular IP version. */ unformat_function_t unformat_ip46_address; diff --git a/src/vnet/ip/ip6_packet.h b/src/vnet/ip/ip6_packet.h index b8f8d6e8657..ceaa7ec7acc 100644 --- a/src/vnet/ip/ip6_packet.h +++ b/src/vnet/ip/ip6_packet.h @@ -67,6 +67,13 @@ typedef CLIB_PACKED (struct { }) ip6_address_fib_t; /* *INDENT-ON* */ +typedef enum +{ + IP46_TYPE_ANY, + IP46_TYPE_IP4, + IP46_TYPE_IP6 +} ip46_type_t; + /* *INDENT-OFF* */ typedef CLIB_PACKED (union { struct { diff --git a/src/vnet/ip/ip_types.api b/src/vnet/ip/ip_types.api index 72eadaf92df..e418ed3a1c6 100644 --- a/src/vnet/ip/ip_types.api +++ b/src/vnet/ip/ip_types.api @@ -41,3 +41,10 @@ typedef prefix { vl_api_address_t address; u8 address_length; }; + +typedef mprefix { + vl_api_address_family_t af; + u16 grp_address_length; + vl_api_address_union_t grp_address; + vl_api_address_union_t src_address; +}; diff --git a/src/vnet/ip/ip_types_api.c b/src/vnet/ip/ip_types_api.c index 7fa8e404c78..f173c28c83b 100644 --- a/src/vnet/ip/ip_types_api.c +++ b/src/vnet/ip/ip_types_api.c @@ -29,42 +29,75 @@ #include #undef vl_printfun - -void -ip_address_decode (const vl_api_address_t * in, ip46_address_t * out) +static ip46_type_t +ip_address_union_decode (const vl_api_address_union_t * in, + vl_api_address_family_t af, ip46_address_t * out) { - switch (in->af) + ip46_type_t type; + + switch (clib_net_to_host_u32 (af)) { case ADDRESS_IP4: memset (out, 0, sizeof (*out)); - clib_memcpy (&out->ip4, &in->un.ip4, sizeof (out->ip4)); + clib_memcpy (&out->ip4, &in->ip4, sizeof (out->ip4)); + type = IP46_TYPE_IP4; break; case ADDRESS_IP6: - clib_memcpy (&out->ip6, &in->un.ip6, sizeof (out->ip6)); + clib_memcpy (&out->ip6, &in->ip6, sizeof (out->ip6)); + type = IP46_TYPE_IP6; + break; + default: + ASSERT (!"Unkown address family in API address type"); + type = IP46_TYPE_ANY; break; } + + return type; } -void -ip_address_encode (const ip46_address_t * in, vl_api_address_t * out) +ip46_type_t +ip_address_decode (const vl_api_address_t * in, ip46_address_t * out) { - if (ip46_address_is_ip4 (in)) - { - memset (out, 0, sizeof (*out)); - out->af = ADDRESS_IP4; - clib_memcpy (&out->un.ip4, &in->ip4, sizeof (out->un.ip4)); - } + return (ip_address_union_decode (&in->un, in->af, out)); +} + +static void +ip_address_union_encode (const ip46_address_t * in, + vl_api_address_family_t af, + vl_api_address_union_t * out) +{ + if (ADDRESS_IP6 == clib_net_to_host_u32 (af)) + memcpy (out->ip6.address, &in->ip6, sizeof (out->ip6)); else + memcpy (out->ip4.address, &in->ip4, sizeof (out->ip4)); +} + +void +ip_address_encode (const ip46_address_t * in, + ip46_type_t type, vl_api_address_t * out) +{ + switch (type) { - out->af = ADDRESS_IP6; - clib_memcpy (&out->un.ip6, &in->ip6, sizeof (out->un.ip6)); + case IP46_TYPE_IP4: + out->af = clib_net_to_host_u32 (ADDRESS_IP4); + break; + case IP46_TYPE_IP6: + out->af = clib_net_to_host_u32 (ADDRESS_IP6); + break; + case IP46_TYPE_ANY: + if (ip46_address_is_ip4 (in)) + out->af = clib_net_to_host_u32 (ADDRESS_IP4); + else + out->af = clib_net_to_host_u32 (ADDRESS_IP6); + break; } + ip_address_union_encode (in, out->af, &out->un); } void ip_prefix_decode (const vl_api_prefix_t * in, fib_prefix_t * out) { - switch (in->address.af) + switch (clib_net_to_host_u32 (in->address.af)) { case ADDRESS_IP4: out->fp_proto = FIB_PROTOCOL_IP4; @@ -80,20 +113,70 @@ ip_prefix_decode (const vl_api_prefix_t * in, fib_prefix_t * out) void ip_prefix_encode (const fib_prefix_t * in, vl_api_prefix_t * out) { - switch (in->fp_proto) - { - case FIB_PROTOCOL_IP4: - out->address.af = ADDRESS_IP4; - break; - case FIB_PROTOCOL_IP6: - out->address.af = ADDRESS_IP6; - break; - case FIB_PROTOCOL_MPLS: - ASSERT (0); - break; - } out->address_length = in->fp_len; - ip_address_encode (&in->fp_addr, &out->address); + ip_address_encode (&in->fp_addr, + fib_proto_to_ip46 (in->fp_proto), &out->address); +} + +void +ip_mprefix_encode (const mfib_prefix_t * in, vl_api_mprefix_t * out) +{ + out->af = (FIB_PROTOCOL_IP6 == in->fp_proto ? ADDRESS_IP6 : ADDRESS_IP4); + out->af = clib_host_to_net_u32 (out->af); + out->grp_address_length = clib_host_to_net_u16 (in->fp_len); + + ip_address_union_encode (&in->fp_grp_addr, out->af, &out->grp_address); + ip_address_union_encode (&in->fp_src_addr, out->af, &out->src_address); +} + +void +ip_mprefix_decode (const vl_api_mprefix_t * in, mfib_prefix_t * out) +{ + out->fp_proto = (ADDRESS_IP6 == clib_net_to_host_u32 (in->af) ? + FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4); + out->fp_len = clib_net_to_host_u16 (in->grp_address_length); + + ip_address_union_decode (&in->grp_address, in->af, &out->fp_grp_addr); + ip_address_union_decode (&in->src_address, in->af, &out->fp_src_addr); +} + +u8 * +format_vl_api_address (u8 * s, va_list * args) +{ + const vl_api_address_t *addr = va_arg (*args, vl_api_address_t *); + + if (ADDRESS_IP6 == clib_net_to_host_u32 (addr->af)) + s = format (s, "ip6:%U", format_ip6_address, addr->un.ip6.address); + else + s = format (s, "ip4:%U", format_ip4_address, addr->un.ip4.address); + + return s; +} + +u8 * +format_vl_api_address_union (u8 * s, va_list * args) +{ + const vl_api_address_union_t *addr = + va_arg (*args, vl_api_address_union_t *); + vl_api_address_family_t af = va_arg (*args, vl_api_address_family_t); + + if (ADDRESS_IP6 == af) + s = format (s, "ip6:%U", format_ip6_address, addr->ip6.address); + else + s = format (s, "ip4:%U", format_ip4_address, addr->ip4.address); + + return s; +} + +u8 * +format_vl_api_prefix (u8 * s, va_list * args) +{ + const vl_api_prefix_t *pfx = va_arg (*args, vl_api_prefix_t *); + + s = format (s, "%U/%d", format_vl_api_address, + &pfx->address, pfx->address_length); + + return s; } /* diff --git a/src/vnet/ip/ip_types_api.h b/src/vnet/ip/ip_types_api.h index 2ad59ae438e..1bc899a4588 100644 --- a/src/vnet/ip/ip_types_api.h +++ b/src/vnet/ip/ip_types_api.h @@ -22,23 +22,35 @@ #include #include +#include /** * Forward declarations so we need not #include the API definitions here */ struct _vl_api_address; struct _vl_api_prefix; +struct _vl_api_mprefix; -extern void ip_address_decode (const struct _vl_api_address *in, - ip46_address_t * out); +extern ip46_type_t ip_address_decode (const struct _vl_api_address *in, + ip46_address_t * out); extern void ip_address_encode (const ip46_address_t * in, - struct _vl_api_address *out); + ip46_type_t type, struct _vl_api_address *out); extern void ip_prefix_decode (const struct _vl_api_prefix *in, fib_prefix_t * out); extern void ip_prefix_encode (const fib_prefix_t * in, struct _vl_api_prefix *out); +extern void ip_mprefix_decode (const struct _vl_api_mprefix *in, + mfib_prefix_t * out); +extern void ip_mprefix_encode (const mfib_prefix_t * in, + struct _vl_api_mprefix *out); + +extern u8 *format_vl_api_address (u8 * s, va_list * args); +extern u8 *format_vl_api_address_union (u8 * s, va_list * args); +extern u8 *format_vl_api_prefix (u8 * s, va_list * args); +extern u8 *format_vl_api_mprefix (u8 * s, va_list * args); + #endif /* diff --git a/src/vnet/udp/udp.api b/src/vnet/udp/udp.api index 9f5e2ece6ba..8788fba162d 100644 --- a/src/vnet/udp/udp.api +++ b/src/vnet/udp/udp.api @@ -1,5 +1,6 @@ +/* Hey Emacs use -*- mode: C -*- */ /* - * Copyright (c) 2016 Cisco and/or its affiliates. + * Copyright (c) 2018 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -13,51 +14,79 @@ * limitations under the License. */ -/** \file +/** + * @file + * + * This file defines vpp UDP control-plane API messages which are generally + * called through a shared memory interface. + */ - This file defines vpp UDP control-plane API messages which are generally - called through a shared memory interface. -*/ +option version = "1.1.0"; -option version = "1.0.0"; +import "vnet/ip/ip_types.api"; -/** \brief Add / del table request - A table can be added multiple times, but need be deleted only once. - @param client_index - opaque cookie to identify the sender - @param context - sender context, to match reply w/ request - @param is_ipv6 - V4 or V6 table - @param table_id - table ID associated with the encap destination -*/ -autoreply define udp_encap_add_del + +/** + * @brief UDP Encap object + * @param table_id - table ID associated with the encap destination + * @param dst_ip - Encap destination address + * @param src_ip - Encap source address + * @param dst_port - Encap destination port + * @param src_port - Encap source port + * @param id - The ID assigned to this encap object by the caller + */ +typedef udp_encap { - u32 client_index; - u32 context; u32 id; u32 table_id; - u8 is_ip6; - u8 is_add; u16 src_port; u16 dst_port; - u8 src_ip[16]; - u8 dst_ip[16]; + vl_api_address_t src_ip; + vl_api_address_t dst_ip; +}; + +/** + * @brief Add UDP encap + * @param client_index - opaque cookie to identify the sender + * @param context - sender context, to match reply w/ request + * @param udp_encap - UDP encap description + */ +autoreply define udp_encap_add +{ + u32 client_index; + u32 context; + vl_api_udp_encap_t udp_encap; }; +/** + * @brief Del UDP encap + * @param client_index - opaque cookie to identify the sender + * @param context - sender context, to match reply w/ request + * @param id - ID of the encap object the client chose during the add +*/ +autoreply define udp_encap_del +{ + u32 client_index; + u32 context; + u32 id; +}; + +/** + * @brief dump UDP encaps + */ define udp_encap_dump { u32 client_index; u32 context; }; +/** + * @brief UDP encap details during dump + */ define udp_encap_details { u32 context; - u32 id; - u32 table_id; - u8 is_ip6; - u16 src_port; - u16 dst_port; - u8 src_ip[16]; - u8 dst_ip[16]; + vl_api_udp_encap_t udp_encap; }; /* diff --git a/src/vnet/udp/udp_api.c b/src/vnet/udp/udp_api.c index d643f682a30..43a39b82ef0 100644 --- a/src/vnet/udp/udp_api.c +++ b/src/vnet/udp/udp_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Cisco and/or its affiliates. + * Copyright (c) 2018 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -18,6 +18,7 @@ #include #include +#include #include @@ -38,8 +39,9 @@ #include -#define foreach_udp_api_msg \ - _(UDP_ENCAP_ADD_DEL, udp_encap_add_del) \ +#define foreach_udp_api_msg \ +_(UDP_ENCAP_DEL, udp_encap_del) \ +_(UDP_ENCAP_ADD, udp_encap_add) \ _(UDP_ENCAP_DUMP, udp_encap_dump) static void @@ -47,33 +49,44 @@ send_udp_encap_details (const udp_encap_t * ue, vl_api_registration_t * reg, u32 context) { vl_api_udp_encap_details_t *mp; - fib_table_t *fib_table; mp = vl_msg_api_alloc (sizeof (*mp)); memset (mp, 0, sizeof (*mp)); mp->_vl_msg_id = ntohs (VL_API_UDP_ENCAP_DETAILS); mp->context = context; - mp->is_ip6 = (ue->ue_ip_proto == FIB_PROTOCOL_IP6); - if (FIB_PROTOCOL_IP4 == ue->ue_ip_proto) { - clib_memcpy (mp->src_ip, &ue->ue_hdrs.ip4.ue_ip4.src_address, 4); - clib_memcpy (mp->dst_ip, &ue->ue_hdrs.ip4.ue_ip4.dst_address, 4); - mp->src_port = htons (ue->ue_hdrs.ip4.ue_udp.src_port); - mp->dst_port = htons (ue->ue_hdrs.ip4.ue_udp.dst_port); + clib_memcpy (&mp->udp_encap.src_ip.un.ip4, + &ue->ue_hdrs.ip4.ue_ip4.src_address, 4); + clib_memcpy (&mp->udp_encap.dst_ip.un.ip4, + &ue->ue_hdrs.ip4.ue_ip4.dst_address, 4); + mp->udp_encap.dst_ip.af = clib_host_to_net_u32 (ADDRESS_IP4); + mp->udp_encap.src_ip.af = clib_host_to_net_u32 (ADDRESS_IP4); + + /* ports aren't byte swapped because they are stored in network + * byte order */ + mp->udp_encap.src_port = ue->ue_hdrs.ip4.ue_udp.src_port; + mp->udp_encap.dst_port = ue->ue_hdrs.ip4.ue_udp.dst_port; } else { - clib_memcpy (mp->src_ip, &ue->ue_hdrs.ip6.ue_ip6.src_address, 16); - clib_memcpy (mp->dst_ip, &ue->ue_hdrs.ip6.ue_ip6.dst_address, 16); - mp->src_port = htons (ue->ue_hdrs.ip6.ue_udp.src_port); - mp->dst_port = htons (ue->ue_hdrs.ip6.ue_udp.dst_port); + clib_memcpy (&mp->udp_encap.src_ip.un.ip6, + &ue->ue_hdrs.ip6.ue_ip6.src_address, 16); + clib_memcpy (&mp->udp_encap.dst_ip.un.ip6, + &ue->ue_hdrs.ip6.ue_ip6.dst_address, 16); + mp->udp_encap.dst_ip.af = clib_host_to_net_u32 (ADDRESS_IP6); + mp->udp_encap.src_ip.af = clib_host_to_net_u32 (ADDRESS_IP6); + + /* ports aren't byte swapped because they are stored in network + * byte order */ + mp->udp_encap.src_port = ue->ue_hdrs.ip6.ue_udp.src_port; + mp->udp_encap.dst_port = ue->ue_hdrs.ip6.ue_udp.dst_port; } - fib_table = fib_table_get (ue->ue_fib_index, ue->ue_ip_proto); - mp->table_id = htonl (fib_table->ft_table_id); - mp->id = htonl (ue->ue_id); + mp->udp_encap.table_id = + htonl (fib_table_get_table_id (ue->ue_fib_index, ue->ue_ip_proto)); + mp->udp_encap.id = htonl (ue->ue_id); vl_api_send_msg (reg, (u8 *) mp); } @@ -98,19 +111,21 @@ vl_api_udp_encap_dump_t_handler (vl_api_udp_encap_dump_t * mp, } static void -vl_api_udp_encap_add_del_t_handler (vl_api_udp_encap_add_del_t * mp, - vlib_main_t * vm) +vl_api_udp_encap_add_t_handler (vl_api_udp_encap_add_t * mp, vlib_main_t * vm) { - vl_api_udp_encap_add_del_reply_t *rmp; + vl_api_udp_encap_add_reply_t *rmp; ip46_address_t src_ip, dst_ip; u32 fib_index, table_id, ue_id; fib_protocol_t fproto; + ip46_type_t itype; int rv = 0; - ue_id = ntohl (mp->id); - table_id = ntohl (mp->table_id); - fproto = (mp->is_ip6 ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4); + ue_id = ntohl (mp->udp_encap.id); + table_id = ntohl (mp->udp_encap.table_id); + itype = ip_address_decode (&mp->udp_encap.src_ip, &src_ip); + itype = ip_address_decode (&mp->udp_encap.dst_ip, &dst_ip); + fproto = fib_proto_from_ip46 (itype); fib_index = fib_table_find (fproto, table_id); if (~0 == fib_index) @@ -119,31 +134,25 @@ vl_api_udp_encap_add_del_t_handler (vl_api_udp_encap_add_del_t * mp, goto done; } - if (FIB_PROTOCOL_IP4 == fproto) - { - clib_memcpy (&src_ip.ip4, mp->src_ip, 4); - clib_memcpy (&dst_ip.ip4, mp->dst_ip, 4); - } - else - { - clib_memcpy (&src_ip.ip6, mp->src_ip, 16); - clib_memcpy (&dst_ip.ip6, mp->dst_ip, 16); - } - - if (mp->is_add) - { - udp_encap_add_and_lock (ue_id, fproto, fib_index, - &src_ip, &dst_ip, - ntohs (mp->src_port), - ntohs (mp->dst_port), UDP_ENCAP_FIXUP_NONE); - } - else - { - udp_encap_unlock (ue_id); - } + udp_encap_add_and_lock (ue_id, fproto, fib_index, + &src_ip, &dst_ip, + ntohs (mp->udp_encap.src_port), + ntohs (mp->udp_encap.dst_port), + UDP_ENCAP_FIXUP_NONE); done: - REPLY_MACRO (VL_API_UDP_ENCAP_ADD_DEL_REPLY); + REPLY_MACRO (VL_API_UDP_ENCAP_ADD_REPLY); +} + +static void +vl_api_udp_encap_del_t_handler (vl_api_udp_encap_del_t * mp, vlib_main_t * vm) +{ + vl_api_udp_encap_del_reply_t *rmp; + int rv = 0; + + udp_encap_unlock (ntohl (mp->id)); + + REPLY_MACRO (VL_API_UDP_ENCAP_DEL_REPLY); } #define vl_msg_name_crc_list diff --git a/src/vpp-api/vapi/vapi_json_parser.py b/src/vpp-api/vapi/vapi_json_parser.py index 0da2a5e32b3..58a75777f11 100644 --- a/src/vpp-api/vapi/vapi_json_parser.py +++ b/src/vpp-api/vapi/vapi_json_parser.py @@ -347,7 +347,6 @@ class JsonParser(object): if len(self.messages) == 0: for e in self.exceptions: self.logger.error(e) - raise Exception("No messages parsed.") for jn, j in self.messages_by_json.items(): remove = [] for n, m in j.items(): diff --git a/test/test_udp.py b/test/test_udp.py index 230335ff169..b0c6ee9c46a 100644 --- a/test/test_udp.py +++ b/test/test_udp.py @@ -1,7 +1,7 @@ #!/usr/bin/env python import unittest from framework import VppTestCase, VppTestRunner -from vpp_udp_encap import VppUdpEncap +from vpp_udp_encap import * from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpTable, VppMplsLabel from scapy.packet import Raw @@ -100,19 +100,24 @@ class TestUdpEncap(VppTestCase): self.pg2.local_ip6, self.pg2.remote_ip6, 332, 442, - table_id=2, - is_ip6=1) + table_id=2) udp_encap_3 = VppUdpEncap(self, 3, self.pg3.local_ip6, self.pg3.remote_ip6, 333, 443, - table_id=3, - is_ip6=1) + table_id=3) udp_encap_0.add_vpp_config() udp_encap_1.add_vpp_config() udp_encap_2.add_vpp_config() udp_encap_3.add_vpp_config() + self.logger.info(self.vapi.cli("sh udp encap")) + + self.assertTrue(find_udp_encap(self, udp_encap_2)) + self.assertTrue(find_udp_encap(self, udp_encap_3)) + self.assertTrue(find_udp_encap(self, udp_encap_0)) + self.assertTrue(find_udp_encap(self, udp_encap_1)) + # # Routes via each UDP encap object - all combinations of v4 and v6. # diff --git a/test/vpp_ip.py b/test/vpp_ip.py new file mode 100644 index 00000000000..912d8430d81 --- /dev/null +++ b/test/vpp_ip.py @@ -0,0 +1,135 @@ +""" + IP Types + +""" + +from ipaddress import ip_address + + +class IpAddressFamily: + ADDRESS_IP4 = 0 + ADDRESS_IP6 = 1 + + +INVALID_INDEX = 0xffffffff + + +def compare_ip_address(api_address, py_address): + if 4 is py_address.version: + if py_address.packed == api_address.ip4.address: + return True + else: + if py_address.packed == api_address.ip6.address: + return True + return False + + +class VppIpAddressUnion(): + def __init__(self, addr): + self.addr = addr + self.ip_addr = ip_address(unicode(self.addr)) + + @property + def version(self): + return self.ip_addr.version + + @property + def address(self): + return self.addr + + def encode(self): + if self.ip_addr.version is 6: + return { + 'ip6': { + 'address': self.ip_addr.packed + }, + } + else: + return { + 'ip4': { + 'address': self.ip_addr.packed + }, + } + + +class VppIpAddress(): + def __init__(self, addr): + self.addr = VppIpAddressUnion(addr) + + def encode(self): + if self.addr.version is 6: + return { + 'af': IpAddressFamily.ADDRESS_IP6, + 'un': self.addr.encode() + } + else: + return { + 'af': IpAddressFamily.ADDRESS_IP4, + 'un': self.addr.encode() + } + + @property + def address(self): + return self.addr.address + + +class VppIpPrefix(): + def __init__(self, addr, len): + self.addr = VppIpAddress(addr) + self.len = len + + def __eq__(self, other): + if self.addr == other.addr and self.len == other.len: + return True + return False + + def encode(self): + return {'address': self.addr.encode(), + 'address_length': self.len} + + @property + def address(self): + return self.addr.address + + +class VppIpMPrefix(): + def __init__(self, saddr, gaddr, len): + self.saddr = saddr + self.gaddr = gaddr + self.len = len + self.ip_saddr = ip_address(unicode(self.saddr)) + self.ip_gaddr = ip_address(unicode(self.gaddr)) + + def encode(self): + + if 6 is self.ip_saddr.version: + prefix = { + 'af': IpAddressFamily.ADDRESS_IP6, + 'grp_address': { + 'ip6': { + 'address': self.ip_gaddr.packed + }, + }, + 'src_address': { + 'ip6': { + 'address': self.ip_saddr.packed + }, + }, + 'grp_address_length': self.len, + } + else: + prefix = { + 'af': IpAddressFamily.ADDRESS_IP4, + 'grp_address': { + 'ip4': { + 'address': self.ip_gaddr.packed + }, + }, + 'src_address': { + 'ip4': { + 'address': self.ip_saddr.packed + }, + }, + 'grp_address_length': self.len, + } + return prefix diff --git a/test/vpp_papi_provider.py b/test/vpp_papi_provider.py index bd4787d3e9e..f9ac7694bf6 100644 --- a/test/vpp_papi_provider.py +++ b/test/vpp_papi_provider.py @@ -1149,15 +1149,13 @@ class VppPapiProvider(object): 'session_id': session_id} ) - def udp_encap_add_del(self, - id, - src_ip, - dst_ip, - src_port, - dst_port, - table_id=0, - is_add=1, - is_ip6=0): + def udp_encap_add(self, + id, + src_ip, + dst_ip, + src_port, + dst_port, + table_id=0): """ Add a GRE tunnel :param id: user provided ID :param src_ip: @@ -1165,21 +1163,23 @@ class VppPapiProvider(object): :param src_port: :param dst_port: :param outer_fib_id: (Default value = 0) - :param is_add: (Default value = 1) - :param is_ipv6: (Default value = 0) """ return self.api( - self.papi.udp_encap_add_del, - {'id': id, - 'is_add': is_add, - 'is_ip6': is_ip6, - 'src_ip': src_ip, - 'dst_ip': dst_ip, - 'src_port': src_port, - 'dst_port': dst_port, - 'table_id': table_id} - ) + self.papi.udp_encap_add, + { + 'udp_encap': { + 'id': id, + 'src_ip': src_ip, + 'dst_ip': dst_ip, + 'src_port': src_port, + 'dst_port': dst_port, + 'table_id': table_id + } + }) + + def udp_encap_del(self, id): + return self.api(self.papi.udp_encap_del, {'id': id}) def udp_encap_dump(self): return self.api(self.papi.udp_encap_dump, {}) diff --git a/test/vpp_udp_encap.py b/test/vpp_udp_encap.py index d4daa7430b3..002f9f4023a 100644 --- a/test/vpp_udp_encap.py +++ b/test/vpp_udp_encap.py @@ -5,13 +5,21 @@ from vpp_object import * from socket import inet_pton, inet_ntop, AF_INET, AF_INET6 +from vpp_ip import * -def find_udp_encap(test, id): +def find_udp_encap(test, ue): encaps = test.vapi.udp_encap_dump() for e in encaps: - if id == e.id: + if ue.id == e.udp_encap.id \ + and compare_ip_address(e.udp_encap.src_ip.un, + ue.src_ip.addr.ip_addr) \ + and compare_ip_address(e.udp_encap.dst_ip.un, + ue.dst_ip.addr.ip_addr) \ + and e.udp_encap.dst_port == ue.dst_port \ + and e.udp_encap.src_port == ue.src_port: return True + return False @@ -24,48 +32,32 @@ class VppUdpEncap(VppObject): dst_ip, src_port, dst_port, - table_id=0, - is_ip6=0): + table_id=0): self._test = test self.id = id self.table_id = table_id - self.is_ip6 = is_ip6 self.src_ip_s = src_ip self.dst_ip_s = dst_ip - if is_ip6: - self.src_ip = inet_pton(AF_INET6, src_ip) - self.dst_ip = inet_pton(AF_INET6, dst_ip) - else: - self.src_ip = inet_pton(AF_INET, src_ip) - self.dst_ip = inet_pton(AF_INET, dst_ip) + self.src_ip = VppIpAddress(src_ip) + self.dst_ip = VppIpAddress(dst_ip) self.src_port = src_port self.dst_port = dst_port def add_vpp_config(self): - self._test.vapi.udp_encap_add_del( + self._test.vapi.udp_encap_add( self.id, - self.src_ip, - self.dst_ip, + self.src_ip.encode(), + self.dst_ip.encode(), self.src_port, self.dst_port, - self.table_id, - is_ip6=self.is_ip6, - is_add=1) + self.table_id) self._test.registry.register(self, self._test.logger) def remove_vpp_config(self): - self._test.vapi.udp_encap_add_del( - self.id, - self.src_ip, - self.dst_ip, - self.src_port, - self.dst_port, - self.table_id, - is_ip6=self.is_ip6, - is_add=0) + self._test.vapi.udp_encap_del(self.id) def query_vpp_config(self): - return find_udp_encap(self._test, self.id) + return find_udp_encap(self._test, self) def __str__(self): return self.object_id() -- 2.16.6