aboutsummaryrefslogtreecommitdiffstats
path: root/src/vcl/vppcom.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vcl/vppcom.c')
-rw-r--r--src/vcl/vppcom.c234
1 files changed, 197 insertions, 37 deletions
diff --git a/src/vcl/vppcom.c b/src/vcl/vppcom.c
index a557093e897..4568ac618d5 100644
--- a/src/vcl/vppcom.c
+++ b/src/vcl/vppcom.c
@@ -351,10 +351,16 @@ vcl_session_accepted_handler (vcl_worker_t * wrk, session_accepted_msg_t * mp,
session->vpp_handle = mp->handle;
session->session_state = VCL_STATE_READY;
- if (mp->rmt.is_ip4)
+ if (mp->rmt.is_ip4 && mp->original_dst_port)
{
- session->original_dst_ip4 = mp->original_dst_ip4;
- session->original_dst_port = mp->original_dst_port;
+ transport_endpt_attr_t *tep_attr;
+ vec_add2 (session->tep_attrs, tep_attr, 1);
+ /* Expecting to receive this on accepted connections
+ * and the external transport endpoint received is
+ * the local one, prior to something like nat */
+ tep_attr->type = TRANSPORT_ENDPT_ATTR_EXT_ENDPT;
+ tep_attr->ext_endpt.port = mp->original_dst_port;
+ tep_attr->ext_endpt.ip.ip4.as_u32 = mp->original_dst_ip4;
}
session->transport.rmt_port = mp->rmt.port;
session->transport.is_ip4 = mp->rmt.is_ip4;
@@ -989,6 +995,24 @@ vcl_worker_rpc_handler (vcl_worker_t * wrk, void *data)
}
static void
+vcl_session_transport_attr_handler (vcl_worker_t *wrk, void *data)
+{
+ session_transport_attr_msg_t *mp = (session_transport_attr_msg_t *) data;
+ vcl_session_t *s;
+
+ s = vcl_session_get_w_vpp_handle (wrk, mp->handle);
+ if (!s)
+ {
+ VDBG (0, "session transport attr with wrong handle %llx", mp->handle);
+ return;
+ }
+
+ VDBG (0, "session %u [0x%llx]: transport attr %u", s->session_index,
+ s->vpp_handle, mp->attr.type);
+ vec_add1 (s->tep_attrs, mp->attr);
+}
+
+static void
vcl_session_transport_attr_reply_handler (vcl_worker_t *wrk, void *data)
{
session_transport_attr_reply_msg_t *mp;
@@ -1129,6 +1153,9 @@ vcl_handle_mq_event (vcl_worker_t * wrk, session_event_t * e)
case SESSION_CTRL_EVT_APP_WRK_RPC:
vcl_worker_rpc_handler (wrk, e->data);
break;
+ case SESSION_CTRL_EVT_TRANSPORT_ATTR:
+ vcl_session_transport_attr_handler (wrk, e->data);
+ break;
case SESSION_CTRL_EVT_TRANSPORT_ATTR_REPLY:
vcl_session_transport_attr_reply_handler (wrk, e->data);
break;
@@ -1754,6 +1781,10 @@ vppcom_unformat_proto (uint8_t * proto, char *proto_str)
*proto = VPPCOM_PROTO_SRTP;
else if (!strcmp (proto_str, "srtp"))
*proto = VPPCOM_PROTO_SRTP;
+ else if (!strcmp (proto_str, "HTTP"))
+ *proto = VPPCOM_PROTO_HTTP;
+ else if (!strcmp (proto_str, "http"))
+ *proto = VPPCOM_PROTO_HTTP;
else
return 1;
return 0;
@@ -2345,6 +2376,75 @@ vppcom_session_write_inline (vcl_worker_t *wrk, vcl_session_t *s, void *buf,
}
int
+vppcom_session_write_segments (uint32_t session_handle,
+ vppcom_data_segment_t *ds, uint32_t n_segments)
+{
+ vcl_worker_t *wrk = vcl_worker_get_current ();
+ int n_write = 0, n_bytes = 0, is_nonblocking;
+ vcl_session_t *s = 0;
+ svm_fifo_t *tx_fifo;
+ svm_msg_q_t *mq;
+ u8 is_ct;
+ u32 i;
+
+ if (PREDICT_FALSE (!ds))
+ return VPPCOM_EFAULT;
+
+ /* Accept zero length writes but just return */
+ if (PREDICT_FALSE (ds[0].len == 0))
+ return VPPCOM_OK;
+
+ s = vcl_session_get_w_handle (wrk, session_handle);
+ if (PREDICT_FALSE (!s || (s->flags & VCL_SESSION_F_IS_VEP)))
+ return VPPCOM_EBADFD;
+
+ if (PREDICT_FALSE (!vcl_session_is_open (s)))
+ return vcl_session_closed_error (s);
+
+ if (PREDICT_FALSE (s->flags & VCL_SESSION_F_WR_SHUTDOWN))
+ return VPPCOM_EPIPE;
+
+ is_nonblocking = vcl_session_has_attr (s, VCL_SESS_ATTR_NONBLOCK);
+ is_ct = vcl_session_is_ct (s);
+ mq = wrk->app_event_queue;
+ tx_fifo = is_ct ? s->ct_tx_fifo : s->tx_fifo;
+
+ for (i = 0; i < n_segments; i++)
+ n_bytes += ds[i].len;
+
+ if (svm_fifo_max_enqueue_prod (tx_fifo) < n_bytes)
+ {
+ if (is_nonblocking)
+ {
+ return VPPCOM_EWOULDBLOCK;
+ }
+ while (svm_fifo_max_enqueue_prod (tx_fifo) < n_bytes)
+ {
+ svm_fifo_add_want_deq_ntf (tx_fifo, SVM_FIFO_WANT_DEQ_NOTIF);
+ if (vcl_session_is_closing (s))
+ return vcl_session_closing_error (s);
+
+ svm_msg_q_wait (mq, SVM_MQ_WAIT_EMPTY);
+ vcl_worker_flush_mq_events (wrk);
+ }
+ }
+
+ n_write = svm_fifo_enqueue_segments (tx_fifo, (svm_fifo_seg_t *) ds,
+ n_segments, 0 /* allow_partial */);
+
+ /* The underlying fifo segment can run out of memory */
+ if (PREDICT_FALSE (n_write < 0))
+ return VPPCOM_EAGAIN;
+
+ if (svm_fifo_set_event (s->tx_fifo))
+ app_send_io_evt_to_vpp (s->vpp_evt_q,
+ s->tx_fifo->shr->master_session_index,
+ SESSION_IO_EVT_TX, SVM_Q_WAIT);
+
+ return n_write;
+}
+
+int
vppcom_session_write (uint32_t session_handle, void *buf, size_t n)
{
vcl_worker_t *wrk = vcl_worker_get_current ();
@@ -2534,6 +2634,9 @@ vcl_select_handle_mq_event (vcl_worker_t * wrk, session_event_t * e,
case SESSION_CTRL_EVT_APP_WRK_RPC:
vcl_worker_rpc_handler (wrk, e->data);
break;
+ case SESSION_CTRL_EVT_TRANSPORT_ATTR:
+ vcl_session_transport_attr_handler (wrk, e->data);
+ break;
default:
clib_warning ("unhandled: %u", e->event_type);
break;
@@ -2619,6 +2722,7 @@ vppcom_select_eventfd (vcl_worker_t * wrk, int n_bits,
vcl_mq_evt_conn_t *mqc;
int __clib_unused n_read;
int n_mq_evts, i;
+ double end = -1;
u64 buf;
if (PREDICT_FALSE (wrk->api_client_handle == ~0))
@@ -2628,23 +2732,45 @@ vppcom_select_eventfd (vcl_worker_t * wrk, int n_bits,
}
vec_validate (wrk->mq_events, pool_elts (wrk->mq_evt_conns));
- n_mq_evts = epoll_wait (wrk->mqs_epfd, wrk->mq_events,
- vec_len (wrk->mq_events), time_to_wait);
- for (i = 0; i < n_mq_evts; i++)
+ if (time_to_wait > 0)
+ end = clib_time_now (&wrk->clib_time) + (time_to_wait / 1e3);
+
+ do
{
- if (PREDICT_FALSE (wrk->mq_events[i].data.u32 == ~0))
+ n_mq_evts = epoll_wait (wrk->mqs_epfd, wrk->mq_events,
+ vec_len (wrk->mq_events), time_to_wait);
+ if (n_mq_evts < 0)
{
- vcl_api_handle_disconnect (wrk);
- continue;
+ if (errno == EINTR)
+ continue;
+
+ VDBG (0, "epoll_wait error %u", errno);
+ return 0;
+ }
+
+ if (n_mq_evts == 0)
+ return 0;
+
+ for (i = 0; i < n_mq_evts; i++)
+ {
+ if (PREDICT_FALSE (wrk->mq_events[i].data.u32 == ~0))
+ {
+ vcl_api_handle_disconnect (wrk);
+ continue;
+ }
+
+ mqc = vcl_mq_evt_conn_get (wrk, wrk->mq_events[i].data.u32);
+ n_read = read (mqc->mq_fd, &buf, sizeof (buf));
+ vcl_select_handle_mq (wrk, mqc->mq, n_bits, read_map, write_map,
+ except_map, 0, bits_set);
}
- mqc = vcl_mq_evt_conn_get (wrk, wrk->mq_events[i].data.u32);
- n_read = read (mqc->mq_fd, &buf, sizeof (buf));
- vcl_select_handle_mq (wrk, mqc->mq, n_bits, read_map, write_map,
- except_map, 0, bits_set);
+ if (*bits_set || !time_to_wait)
+ return (int) *bits_set;
}
+ while (end == -1 || clib_time_now (&wrk->clib_time) < end);
- return (n_mq_evts > 0 ? (int) *bits_set : 0);
+ return 0;
}
int
@@ -3286,6 +3412,9 @@ vcl_epoll_wait_handle_mq_event (vcl_worker_t * wrk, session_event_t * e,
case SESSION_CTRL_EVT_APP_WRK_RPC:
vcl_worker_rpc_handler (wrk, e->data);
break;
+ case SESSION_CTRL_EVT_TRANSPORT_ATTR:
+ vcl_session_transport_attr_handler (wrk, e->data);
+ break;
default:
VDBG (0, "unhandled: %u", e->event_type);
break;
@@ -3407,6 +3536,9 @@ vppcom_epoll_wait_eventfd (vcl_worker_t *wrk, struct epoll_event *events,
vec_len (wrk->mq_events), timeout_ms);
if (n_mq_evts < 0)
{
+ if (errno == EINTR)
+ continue;
+
VDBG (0, "epoll_wait error %u", errno);
return n_evts;
}
@@ -3573,7 +3705,7 @@ vppcom_session_attr (uint32_t session_handle, uint32_t op,
vcl_worker_t *wrk = vcl_worker_get_current ();
u32 *flags = buffer;
vppcom_endpt_t *ep = buffer;
- transport_endpt_attr_t tea;
+ transport_endpt_attr_t tea, *tepap;
vcl_session_t *session;
int rv = VPPCOM_OK;
@@ -3696,24 +3828,49 @@ vppcom_session_attr (uint32_t session_handle, uint32_t op,
rv = VPPCOM_EAFNOSUPPORT;
break;
}
- if (PREDICT_TRUE (buffer && buflen && (*buflen >= sizeof (*ep)) &&
- ep->ip))
+ if (PREDICT_FALSE (!buffer || !buflen || (*buflen < sizeof (*ep)) ||
+ !ep->ip))
{
- ep->is_ip4 = session->transport.is_ip4;
- ep->port = session->original_dst_port;
- clib_memcpy_fast (ep->ip, &session->original_dst_ip4,
- sizeof (ip4_address_t));
- *buflen = sizeof (*ep);
- VDBG (1,
- "VPPCOM_ATTR_GET_ORIGINAL_DST: sh %u, is_ip4 = %u, addr = %U"
- " port %d",
- session_handle, ep->is_ip4, vcl_format_ip4_address,
- (ip4_address_t *) (&session->original_dst_ip4),
- ep->is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
- clib_net_to_host_u16 (ep->port));
+ rv = VPPCOM_EINVAL;
+ break;
}
- else
- rv = VPPCOM_EINVAL;
+
+ tepap =
+ vcl_session_tep_attr_get (session, TRANSPORT_ENDPT_ATTR_EXT_ENDPT);
+ if (!tepap)
+ {
+ rv = VPPCOM_EINVAL;
+ break;
+ }
+ vcl_ip_copy_to_ep (&tepap->ext_endpt.ip, ep, tepap->ext_endpt.is_ip4);
+ ep->port = tepap->ext_endpt.port;
+ *buflen = sizeof (*ep);
+
+ VDBG (1,
+ "VPPCOM_ATTR_GET_ORIGINAL_DST: sh %u, is_ip4 = %u, "
+ "addr = %U port %d",
+ session_handle, ep->is_ip4, vcl_format_ip4_address,
+ (ip4_address_t *) ep->ip,
+ ep->is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
+ clib_net_to_host_u16 (ep->port));
+ break;
+
+ case VPPCOM_ATTR_GET_EXT_ENDPT:
+ if (PREDICT_FALSE (!buffer || !buflen || (*buflen < sizeof (*ep)) ||
+ !ep->ip))
+ {
+ rv = VPPCOM_EINVAL;
+ break;
+ }
+ tepap =
+ vcl_session_tep_attr_get (session, TRANSPORT_ENDPT_ATTR_EXT_ENDPT);
+ if (!tepap)
+ {
+ rv = VPPCOM_EINVAL;
+ break;
+ }
+ vcl_ip_copy_to_ep (&tepap->ext_endpt.ip, ep, tepap->ext_endpt.is_ip4);
+ ep->port = tepap->ext_endpt.port;
break;
case VPPCOM_ATTR_SET_LCL_ADDR:
@@ -3798,12 +3955,11 @@ vppcom_session_attr (uint32_t session_handle, uint32_t op,
case VPPCOM_ATTR_GET_TX_FIFO_LEN:
if (buffer && buflen && (*buflen >= sizeof (u32)))
{
-
/* VPP-TBD */
- *(size_t *) buffer = (session->sndbuf_size ? session->sndbuf_size :
- session->tx_fifo ?
- svm_fifo_size (session->tx_fifo) :
- vcm->cfg.tx_fifo_size);
+ *(u32 *) buffer =
+ (session->sndbuf_size ? session->sndbuf_size :
+ session->tx_fifo ? svm_fifo_size (session->tx_fifo) :
+ vcm->cfg.tx_fifo_size);
*buflen = sizeof (u32);
VDBG (2, "VPPCOM_ATTR_GET_TX_FIFO_LEN: %u (0x%x), buflen %d,"
@@ -4238,7 +4394,8 @@ vppcom_session_attr (uint32_t session_handle, uint32_t op,
break;
}
vcl_session_alloc_ext_cfg (session, TRANSPORT_ENDPT_EXT_CFG_NONE,
- *buflen + sizeof (u32));
+ *buflen +
+ TRANSPORT_ENDPT_EXT_CFG_HEADER_SIZE);
clib_memcpy (session->ext_config->data, buffer, *buflen);
session->ext_config->len = *buflen;
break;
@@ -4613,6 +4770,9 @@ vppcom_proto_str (vppcom_proto_t proto)
case VPPCOM_PROTO_SRTP:
proto_str = "SRTP";
break;
+ case VPPCOM_PROTO_HTTP:
+ proto_str = "HTTP";
+ break;
default:
proto_str = "UNKNOWN";
break;