diff options
Diffstat (limited to 'src')
23 files changed, 222 insertions, 61 deletions
diff --git a/src/plugins/hs_apps/CMakeLists.txt b/src/plugins/hs_apps/CMakeLists.txt index eae100949d4..7cccf14aee7 100644 --- a/src/plugins/hs_apps/CMakeLists.txt +++ b/src/plugins/hs_apps/CMakeLists.txt @@ -74,4 +74,9 @@ if(VPP_BUILD_VCL_TESTS) NO_INSTALL ) endforeach() + + add_vpp_executable(vcl_test_cl_udp SOURCES "vcl/vcl_test_cl_udp.c" + LINK_LIBRARIES vppcom pthread ${EPOLL_LIB} + NO_INSTALL + ) endif(VPP_BUILD_VCL_TESTS) diff --git a/src/plugins/hs_apps/vcl/vcl_test_cl_udp.c b/src/plugins/hs_apps/vcl/vcl_test_cl_udp.c new file mode 100644 index 00000000000..066635e3d9b --- /dev/null +++ b/src/plugins/hs_apps/vcl/vcl_test_cl_udp.c @@ -0,0 +1,156 @@ +/* SPDX-License-Identifier: Apache-2.0 + * Copyright(c) 2025 Cisco Systems, Inc. + */ + +#include <sys/types.h> +#include <sys/socket.h> +#include <string.h> +#include <vcl/vppcom.h> +#include <hs_apps/vcl/vcl_test.h> + +typedef enum vt_clu_type_ +{ + VT_CLU_TYPE_NONE = 0, + VT_CLU_TYPE_SERVER, + VT_CLU_TYPE_CLIENT, +} vt_clu_type_t; + +typedef struct vtclu_main_ +{ + vt_clu_type_t app_type; + vppcom_endpt_t endpt; + union + { + struct sockaddr_storage srvr_addr; + struct sockaddr_storage clnt_addr; + }; + uint16_t port; +} vt_clu_main_t; + +static vt_clu_main_t vt_clu_main; + +static void +vt_clu_parse_args (vt_clu_main_t *vclum, int argc, char **argv) +{ + int c; + + memset (vclum, 0, sizeof (*vclum)); + vclum->port = VCL_TEST_SERVER_PORT; + + opterr = 0; + while ((c = getopt (argc, argv, "s:c:")) != -1) + switch (c) + { + case 's': + vclum->app_type = VT_CLU_TYPE_SERVER; + if (inet_pton ( + AF_INET, optarg, + &((struct sockaddr_in *) &vclum->srvr_addr)->sin_addr) != 1) + vtwrn ("couldn't parse ipv4 addr %s", optarg); + break; + case 'c': + vclum->app_type = VT_CLU_TYPE_CLIENT; + if (inet_pton ( + AF_INET, optarg, + &((struct sockaddr_in *) &vclum->clnt_addr)->sin_addr) != 1) + break; + } + + if (vclum->app_type == VT_CLU_TYPE_NONE) + { + vtwrn ("client or server must be configured"); + exit (1); + } + + vclum->endpt.is_ip4 = 1; + vclum->endpt.ip = + (uint8_t *) &((struct sockaddr_in *) &vclum->srvr_addr)->sin_addr; + vclum->endpt.port = htons (vclum->endpt.port); +} + +int +main (int argc, char **argv) +{ + vt_clu_main_t *vclum = &vt_clu_main; + int rv, vcl_sh; + const int buflen = 64; + char buf[buflen]; + + struct sockaddr_in _addr; + vppcom_endpt_t rmt_ep = { .ip = (void *) &_addr }; + + vt_clu_parse_args (vclum, argc, argv); + + rv = vppcom_app_create ("vcl_test_cl_udp"); + if (rv) + vtfail ("vppcom_app_create()", rv); + + vcl_sh = vppcom_session_create (VPPCOM_PROTO_UDP, 0 /* is_nonblocking */); + if (vcl_sh < 0) + { + vterr ("vppcom_session_create()", vcl_sh); + return vcl_sh; + } + + if (vclum->app_type == VT_CLU_TYPE_SERVER) + { + /* Listen is implicit */ + rv = vppcom_session_bind (vcl_sh, &vclum->endpt); + if (rv < 0) + { + vterr ("vppcom_session_bind()", rv); + return rv; + } + + rv = vppcom_session_recvfrom (vcl_sh, buf, buflen, 0, &rmt_ep); + if (rv < 0) + { + vterr ("vppcom_session_recvfrom()", rv); + return rv; + } + buf[rv] = 0; + vtinf ("Received message from client: %s", buf); + + char *msg = "hello cl udp client"; + int msg_len = strnlen (msg, buflen); + memcpy (buf, msg, msg_len); + /* send 2 times to be sure */ + for (int i = 0; i < 2; i++) + { + rv = vppcom_session_sendto (vcl_sh, buf, msg_len, 0, &rmt_ep); + if (rv < 0) + { + vterr ("vppcom_session_sendto()", rv); + return rv; + } + usleep (500); + } + } + else if (vclum->app_type == VT_CLU_TYPE_CLIENT) + { + char *msg = "hello cl udp server"; + int msg_len = strnlen (msg, buflen); + memcpy (buf, msg, msg_len); + + /* send 3 times to be sure */ + for (int i = 0; i < 3; i++) + { + rv = vppcom_session_sendto (vcl_sh, buf, msg_len, 0, &vclum->endpt); + if (rv < 0) + { + vterr ("vppcom_session_sendto()", rv); + return rv; + } + usleep (500); + } + + rv = vppcom_session_recvfrom (vcl_sh, buf, buflen, 0, &rmt_ep); + if (rv < 0) + { + vterr ("vppcom_session_recvfrom()", rv); + return rv; + } + buf[rv] = 0; + vtinf ("Received message from server: %s", buf); + } +}
\ No newline at end of file diff --git a/src/plugins/nat/det44/det44.h b/src/plugins/nat/det44/det44.h index e576bfb65e8..683f554f03c 100644 --- a/src/plugins/nat/det44/det44.h +++ b/src/plugins/nat/det44/det44.h @@ -38,7 +38,6 @@ #include <vnet/ip/reass/ip4_sv_reass.h> #include <nat/lib/lib.h> -#include <nat/lib/inlines.h> #include <nat/lib/ipfix_logging.h> #include <nat/lib/nat_proto.h> diff --git a/src/plugins/nat/det44/det44_in2out.c b/src/plugins/nat/det44/det44_in2out.c index 3f5e05a064c..39a9ecabac7 100644 --- a/src/plugins/nat/det44/det44_in2out.c +++ b/src/plugins/nat/det44/det44_in2out.c @@ -21,6 +21,7 @@ #include <vlib/vlib.h> #include <vnet/vnet.h> #include <vnet/ip/ip.h> +#include <vnet/ip/ip4_to_ip6.h> #include <vnet/fib/ip4_fib.h> #include <vppinfra/error.h> #include <vppinfra/elog.h> @@ -29,7 +30,6 @@ #include <nat/det44/det44_inlines.h> #include <nat/lib/lib.h> -#include <nat/lib/inlines.h> #include <nat/lib/nat_inlines.h> typedef enum diff --git a/src/plugins/nat/det44/det44_out2in.c b/src/plugins/nat/det44/det44_out2in.c index ab6acd4f8e9..dd89606ff10 100644 --- a/src/plugins/nat/det44/det44_out2in.c +++ b/src/plugins/nat/det44/det44_out2in.c @@ -21,6 +21,7 @@ #include <vlib/vlib.h> #include <vnet/vnet.h> #include <vnet/ip/ip.h> +#include <vnet/ip/ip4_to_ip6.h> #include <vnet/fib/ip4_fib.h> #include <vppinfra/error.h> #include <vppinfra/elog.h> @@ -29,7 +30,6 @@ #include <nat/det44/det44_inlines.h> #include <nat/lib/lib.h> -#include <nat/lib/inlines.h> #include <nat/lib/nat_inlines.h> typedef enum diff --git a/src/plugins/nat/dslite/dslite.h b/src/plugins/nat/dslite/dslite.h index f05670c9bf5..979afb476b7 100644 --- a/src/plugins/nat/dslite/dslite.h +++ b/src/plugins/nat/dslite/dslite.h @@ -22,7 +22,6 @@ #include <nat/lib/lib.h> #include <nat/lib/alloc.h> -#include <nat/lib/inlines.h> typedef struct { diff --git a/src/plugins/nat/dslite/dslite_in2out.c b/src/plugins/nat/dslite/dslite_in2out.c index 522c3cf4123..806969f5f4d 100644 --- a/src/plugins/nat/dslite/dslite_in2out.c +++ b/src/plugins/nat/dslite/dslite_in2out.c @@ -12,6 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include <vnet/ip/ip4_to_ip6.h> #include <nat/dslite/dslite.h> #include <nat/lib/nat_syslog.h> diff --git a/src/plugins/nat/dslite/dslite_out2in.c b/src/plugins/nat/dslite/dslite_out2in.c index 531bbb468bb..9ec48d458e5 100644 --- a/src/plugins/nat/dslite/dslite_out2in.c +++ b/src/plugins/nat/dslite/dslite_out2in.c @@ -12,6 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include <vnet/ip/ip4_to_ip6.h> #include <nat/dslite/dslite.h> typedef enum diff --git a/src/plugins/nat/lib/inlines.h b/src/plugins/nat/lib/inlines.h deleted file mode 100644 index 24e3ba83a5b..00000000000 --- a/src/plugins/nat/lib/inlines.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2020 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: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/** - * @brief Common NAT inline functions - */ -#ifndef included_nat_inlines_h__ -#define included_nat_inlines_h__ - -#include <vnet/ip/icmp46_packet.h> - -static_always_inline u64 -icmp_type_is_error_message (u8 icmp_type) -{ - int bmp = 0; - bmp |= 1 << ICMP4_destination_unreachable; - bmp |= 1 << ICMP4_time_exceeded; - bmp |= 1 << ICMP4_parameter_problem; - bmp |= 1 << ICMP4_source_quench; - bmp |= 1 << ICMP4_redirect; - bmp |= 1 << ICMP4_alternate_host_address; - - return (1ULL << icmp_type) & bmp; -} - -#endif /* included_nat_inlines_h__ */ -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/plugins/nat/lib/ipfix_logging.c b/src/plugins/nat/lib/ipfix_logging.c index 593fa09f7e2..f569ccd1918 100644 --- a/src/plugins/nat/lib/ipfix_logging.c +++ b/src/plugins/nat/lib/ipfix_logging.c @@ -22,7 +22,6 @@ #include <vlibmemory/api.h> #include <vppinfra/atomics.h> #include <nat/lib/ipfix_logging.h> -#include <nat/lib/inlines.h> vlib_node_registration_t nat_ipfix_flush_node; nat_ipfix_logging_main_t nat_ipfix_logging_main; diff --git a/src/plugins/nat/lib/nat_syslog.c b/src/plugins/nat/lib/nat_syslog.c index 98777ebf280..93756a561bc 100644 --- a/src/plugins/nat/lib/nat_syslog.c +++ b/src/plugins/nat/lib/nat_syslog.c @@ -21,7 +21,6 @@ #include <vnet/syslog/syslog.h> #include <nat/lib/nat_syslog.h> -#include <nat/lib/inlines.h> #include <nat/lib/nat_syslog_constants.h> diff --git a/src/plugins/nat/nat44-ed/nat44_ed.h b/src/plugins/nat/nat44-ed/nat44_ed.h index 706511475cf..c3a959b0635 100644 --- a/src/plugins/nat/nat44-ed/nat44_ed.h +++ b/src/plugins/nat/nat44-ed/nat44_ed.h @@ -31,7 +31,6 @@ #include <vlibapi/api.h> #include <nat/lib/lib.h> -#include <nat/lib/inlines.h> /* default number of worker handoff frame queue elements */ #define NAT_FQ_NELTS_DEFAULT 64 diff --git a/src/plugins/nat/nat44-ed/nat44_ed_inlines.h b/src/plugins/nat/nat44-ed/nat44_ed_inlines.h index 04e5236b7f9..8cd93f263c6 100644 --- a/src/plugins/nat/nat44-ed/nat44_ed_inlines.h +++ b/src/plugins/nat/nat44-ed/nat44_ed_inlines.h @@ -27,6 +27,7 @@ #include <nat/lib/log.h> #include <nat/lib/ipfix_logging.h> #include <nat/nat44-ed/nat44_ed.h> +#include <vnet/ip/ip4_to_ip6.h> always_inline void init_ed_k (clib_bihash_kv_16_8_t *kv, u32 l_addr, u16 l_port, u32 r_addr, diff --git a/src/plugins/nat/nat44-ei/nat44_ei.c b/src/plugins/nat/nat44-ei/nat44_ei.c index e16625a2946..d1959f72ae7 100644 --- a/src/plugins/nat/nat44-ei/nat44_ei.c +++ b/src/plugins/nat/nat44-ei/nat44_ei.c @@ -21,6 +21,7 @@ #include <vnet/vnet.h> #include <vnet/ip/ip.h> #include <vnet/ip/ip4.h> +#include <vnet/ip/ip4_to_ip6.h> #include <vnet/ip/ip_table.h> #include <vnet/ip/reass/ip4_sv_reass.h> #include <vnet/fib/fib_table.h> diff --git a/src/plugins/nat/nat44-ei/nat44_ei.h b/src/plugins/nat/nat44-ei/nat44_ei.h index b4aa0f26c0b..786fb0cfc2c 100644 --- a/src/plugins/nat/nat44-ei/nat44_ei.h +++ b/src/plugins/nat/nat44-ei/nat44_ei.h @@ -35,7 +35,6 @@ #include <vppinfra/hash.h> #include <nat/lib/lib.h> -#include <nat/lib/inlines.h> #include <nat/lib/nat_proto.h> /* default number of worker handoff frame queue elements */ diff --git a/src/plugins/nat/nat44-ei/nat44_ei_in2out.c b/src/plugins/nat/nat44-ei/nat44_ei_in2out.c index 3b981d69986..2fbf2832d5e 100644 --- a/src/plugins/nat/nat44-ei/nat44_ei_in2out.c +++ b/src/plugins/nat/nat44-ei/nat44_ei_in2out.c @@ -21,6 +21,7 @@ #include <vnet/vnet.h> #include <vnet/ip/ip.h> +#include <vnet/ip/ip4_to_ip6.h> #include <vnet/ethernet/ethernet.h> #include <vnet/udp/udp_local.h> #include <vnet/fib/ip4_fib.h> diff --git a/src/plugins/nat/nat44-ei/nat44_ei_out2in.c b/src/plugins/nat/nat44-ei/nat44_ei_out2in.c index 5d91cb04f7c..805a6962868 100644 --- a/src/plugins/nat/nat44-ei/nat44_ei_out2in.c +++ b/src/plugins/nat/nat44-ei/nat44_ei_out2in.c @@ -21,6 +21,7 @@ #include <vnet/vnet.h> #include <vnet/ip/ip.h> +#include <vnet/ip/ip4_to_ip6.h> #include <vnet/ethernet/ethernet.h> #include <vnet/udp/udp_local.h> #include <vnet/fib/ip4_fib.h> diff --git a/src/plugins/nat/nat64/nat64.c b/src/plugins/nat/nat64/nat64.c index 950eea60e5e..c59cfbbbd55 100644 --- a/src/plugins/nat/nat64/nat64.c +++ b/src/plugins/nat/nat64/nat64.c @@ -15,6 +15,7 @@ #include <vppinfra/crc32.h> #include <vnet/fib/ip4_fib.h> +#include <vnet/ip/ip4_to_ip6.h> #include <vnet/ip/reass/ip4_sv_reass.h> #include <vnet/ip/reass/ip6_sv_reass.h> diff --git a/src/plugins/nat/nat64/nat64.h b/src/plugins/nat/nat64/nat64.h index 9eb8d915390..2577880c7a4 100644 --- a/src/plugins/nat/nat64/nat64.h +++ b/src/plugins/nat/nat64/nat64.h @@ -30,7 +30,6 @@ #include <vnet/ip/reass/ip4_sv_reass.h> #include <nat/lib/lib.h> -#include <nat/lib/inlines.h> #include <nat/lib/nat_inlines.h> #include <nat/nat64/nat64_db.h> diff --git a/src/plugins/nat/nat64/nat64_db.c b/src/plugins/nat/nat64/nat64_db.c index e4e9febcb12..6ba77c58965 100644 --- a/src/plugins/nat/nat64/nat64_db.c +++ b/src/plugins/nat/nat64/nat64_db.c @@ -16,7 +16,6 @@ #include <vnet/fib/fib_table.h> #include <nat/lib/ipfix_logging.h> #include <nat/lib/nat_syslog.h> -#include <nat/lib/inlines.h> #include <nat/nat64/nat64_db.h> int diff --git a/src/vcl/vppcom.c b/src/vcl/vppcom.c index b4f985e5562..1e9c915ce39 100644 --- a/src/vcl/vppcom.c +++ b/src/vcl/vppcom.c @@ -4557,17 +4557,31 @@ vppcom_session_sendto (uint32_t session_handle, void *buffer, if (ep->app_tlvs) vcl_handle_ep_app_tlvs (s, ep); - /* Session not connected/bound in vpp. Create it by 'connecting' it */ + /* Session not connected/bound in vpp. Create it by binding it */ if (PREDICT_FALSE (s->session_state == VCL_STATE_CLOSED)) { u32 session_index = s->session_index; f64 timeout = vcm->cfg.session_timeout; int rv; - vcl_send_session_connect (wrk, s); - rv = vppcom_wait_for_session_state_change (session_index, - VCL_STATE_READY, - timeout); + /* VPP assumes sockets are bound, not ideal, but for now + * connect socket, grab lcl ip:port pair and use it to bind */ + if (s->transport.rmt_port == 0 || + ip46_address_is_zero (&s->transport.lcl_ip)) + { + vcl_send_session_connect (wrk, s); + rv = vppcom_wait_for_session_state_change ( + session_index, VCL_STATE_READY, timeout); + if (rv < 0) + return rv; + vcl_send_session_disconnect (wrk, s); + rv = vppcom_wait_for_session_state_change ( + session_index, VCL_STATE_DETACHED, timeout); + s->session_state = VCL_STATE_CLOSED; + } + vcl_send_session_listen (wrk, s); + rv = vppcom_wait_for_session_state_change ( + session_index, VCL_STATE_LISTEN, timeout); if (rv < 0) return rv; s = vcl_session_get (wrk, session_index); diff --git a/src/vnet/ip/ip4_to_ip6.h b/src/vnet/ip/ip4_to_ip6.h index d356fd5411c..3c14a59f174 100644 --- a/src/vnet/ip/ip4_to_ip6.h +++ b/src/vnet/ip/ip4_to_ip6.h @@ -37,6 +37,20 @@ static u8 icmp_to_icmp6_updater_pointer_table[] = #define frag_id_4to6(id) (id) +always_inline u64 +icmp_type_is_error_message (u8 icmp_type) +{ + int bmp = 0; + bmp |= 1 << ICMP4_destination_unreachable; + bmp |= 1 << ICMP4_time_exceeded; + bmp |= 1 << ICMP4_parameter_problem; + bmp |= 1 << ICMP4_source_quench; + bmp |= 1 << ICMP4_redirect; + bmp |= 1 << ICMP4_alternate_host_address; + + return (1ULL << icmp_type) & bmp; +} + /** * @brief Get TCP/UDP port number or ICMP id from IPv4 packet. * @@ -70,9 +84,14 @@ ip4_get_port (ip4_header_t *ip, u8 sender) * - outer ICMP header length (2*sizeof (icmp46_header_t)) * - inner IP header length * - first 8 bytes of payload of original packet in case of ICMP error + * + * Also make sure we only attempt to parse payload as IP packet if it's + * an ICMP error. */ else if (clib_net_to_host_u16 (ip->length) >= - 2 * sizeof (ip4_header_t) + 2 * sizeof (icmp46_header_t) + 8) + 2 * sizeof (ip4_header_t) + 2 * sizeof (icmp46_header_t) + + 8 && + icmp_type_is_error_message (icmp->type)) { ip = (ip4_header_t *) (icmp + 2); if (PREDICT_TRUE ((ip->protocol == IP_PROTOCOL_TCP) || diff --git a/src/vnet/ip/ip6_to_ip4.h b/src/vnet/ip/ip6_to_ip4.h index ebabcd0b797..931d2da0fa3 100644 --- a/src/vnet/ip/ip6_to_ip4.h +++ b/src/vnet/ip/ip6_to_ip4.h @@ -168,7 +168,19 @@ ip6_get_port (vlib_main_t *vm, vlib_buffer_t *b, ip6_header_t *ip6, if (dst_port) *dst_port = ((u16 *) (icmp))[2]; } - else if (clib_net_to_host_u16 (ip6->payload_length) >= 64) + /* + * if there is enough data and ICMP type indicates ICMP error, then parse + * inner packet + * + * ICMP6 errors are: + * 1 - destination_unreachable + * 2 - packet_too_big + * 3 - time_exceeded + * 4 - parameter_problem + */ + else if (clib_net_to_host_u16 (ip6->payload_length) >= 64 && + icmp->type >= ICMP6_destination_unreachable && + icmp->type <= ICMP6_parameter_problem) { u16 ip6_pay_len; ip6_header_t *inner_ip6; |