summaryrefslogtreecommitdiffstats
path: root/src/vcl/vppcom.c
diff options
context:
space:
mode:
authorFlorin Coras <fcoras@cisco.com>2020-03-29 18:54:04 +0000
committerFlorin Coras <fcoras@cisco.com>2020-04-01 20:24:38 +0000
commit0a1e183e5aa45fb0050eb03e1c8ebdb9f426a374 (patch)
treedc3a7789b55bebff61d566d54e4801536691bd7a /src/vcl/vppcom.c
parent9076789779c5a038ec17936130a556703c234fa8 (diff)
session udp: support connect on listeners
Type: feature Signed-off-by: Florin Coras <fcoras@cisco.com> Change-Id: I6aaaec20a2b6d4c6ddfbe659d9402acc1be2f7e2
Diffstat (limited to 'src/vcl/vppcom.c')
-rw-r--r--src/vcl/vppcom.c33
1 files changed, 29 insertions, 4 deletions
diff --git a/src/vcl/vppcom.c b/src/vcl/vppcom.c
index 03bd32c5446..ba1f1166556 100644
--- a/src/vcl/vppcom.c
+++ b/src/vcl/vppcom.c
@@ -231,7 +231,10 @@ vcl_send_session_connect (vcl_worker_t * wrk, vcl_session_t * s)
clib_memcpy_fast (&mp->ip, &s->transport.rmt_ip, sizeof (mp->ip));
clib_memcpy_fast (&mp->lcl_ip, &s->transport.lcl_ip, sizeof (mp->lcl_ip));
mp->port = s->transport.rmt_port;
+ mp->lcl_port = s->transport.lcl_port;
mp->proto = s->session_type;
+ if (s->flags & VCL_SESSION_F_CONNECTED)
+ mp->flags |= TRANSPORT_CFG_F_CONNECTED;
app_send_ctrl_evt_to_vpp (mq, app_evt);
}
@@ -612,11 +615,21 @@ vcl_session_unlisten_reply_handler (vcl_worker_t * wrk, void *data)
vcl_session_t *s;
s = vcl_session_get_w_vpp_handle (wrk, mp->handle);
- if (!s || s->session_state != STATE_DISCONNECT)
+ if (!s)
{
VDBG (0, "Unlisten reply with wrong handle %llx", mp->handle);
return;
}
+ if (s->session_state != STATE_DISCONNECT)
+ {
+ /* Connected udp listener */
+ if (s->session_type == VPPCOM_PROTO_UDP
+ && s->session_state == STATE_CLOSED)
+ return;
+
+ VDBG (0, "Unlisten session in wrong state %llx", mp->handle);
+ return;
+ }
if (mp->retval)
VDBG (0, "ERROR: session %u [0xllx]: unlisten failed: %U",
@@ -1686,13 +1699,24 @@ vppcom_session_connect (uint32_t session_handle, vppcom_endpt_t * server_ep)
return VPPCOM_OK;
}
+ /* Attempt to connect a connectionless listener */
+ if (PREDICT_FALSE (session->session_state & STATE_LISTEN))
+ {
+ if (session->session_type != VPPCOM_PROTO_UDP)
+ return VPPCOM_EINVAL;
+ vcl_send_session_unlisten (wrk, session);
+ session->session_state = STATE_CLOSED;
+ }
+
session->transport.is_ip4 = server_ep->is_ip4;
vcl_ip_copy_from_ep (&session->transport.rmt_ip, server_ep);
session->transport.rmt_port = server_ep->port;
session->parent_handle = VCL_INVALID_SESSION_HANDLE;
+ session->flags |= VCL_SESSION_F_CONNECTED;
- VDBG (0, "session handle %u: connecting to server %s %U "
+ VDBG (0, "session handle %u (%s): connecting to peer %s %U "
"port %d proto %s", session_handle,
+ vppcom_session_state_str (session->session_state),
session->transport.is_ip4 ? "IPv4" : "IPv6",
format_ip46_address,
&session->transport.rmt_ip, session->transport.is_ip4 ?
@@ -3562,7 +3586,7 @@ vppcom_session_recvfrom (uint32_t session_handle, void *buffer,
return VPPCOM_EAFNOSUPPORT;
}
- if (ep && !rv)
+ if (ep && rv > 0)
{
session = vcl_session_get_w_handle (wrk, session_handle);
if (session->transport.is_ip4)
@@ -3594,7 +3618,8 @@ vppcom_session_sendto (uint32_t session_handle, void *buffer,
if (!s)
return VPPCOM_EBADFD;
- if (s->session_type != VPPCOM_PROTO_UDP)
+ if (s->session_type != VPPCOM_PROTO_UDP
+ || (s->flags & VCL_SESSION_F_CONNECTED))
return VPPCOM_EINVAL;
/* Session not connected/bound in vpp. Create it by 'connecting' it */