2 * Copyright (c) 2017 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
5 * You may obtain a copy of the License at:
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
18 #include <svm/svm_fifo_segment.h>
19 #include <vcl/vppcom.h>
20 #include <vcl/vcl_event.h>
21 #include <vcl/vcl_debug.h>
22 #include <vcl/vcl_private.h>
25 vppcom_app_state_str (app_state_t state)
32 st = "STATE_APP_START";
35 case STATE_APP_CONN_VPP:
36 st = "STATE_APP_CONN_VPP";
39 case STATE_APP_ENABLED:
40 st = "STATE_APP_ENABLED";
43 case STATE_APP_ATTACHED:
44 st = "STATE_APP_ATTACHED";
48 st = "UNKNOWN_APP_STATE";
56 vppcom_session_state_str (session_state_t state)
78 case STATE_CLOSE_ON_EMPTY:
79 st = "STATE_CLOSE_ON_EMPTY";
82 case STATE_DISCONNECT:
83 st = "STATE_DISCONNECT";
99 format_ip4_address (u8 * s, va_list * args)
101 u8 *a = va_arg (*args, u8 *);
102 return format (s, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
106 format_ip6_address (u8 * s, va_list * args)
108 ip6_address_t *a = va_arg (*args, ip6_address_t *);
109 u32 i, i_max_n_zero, max_n_zeros, i_first_zero, n_zeros, last_double_colon;
111 i_max_n_zero = ARRAY_LEN (a->as_u16);
113 i_first_zero = i_max_n_zero;
115 for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
117 u32 is_zero = a->as_u16[i] == 0;
118 if (is_zero && i_first_zero >= ARRAY_LEN (a->as_u16))
124 if ((!is_zero && n_zeros > max_n_zeros)
125 || (i + 1 >= ARRAY_LEN (a->as_u16) && n_zeros > max_n_zeros))
127 i_max_n_zero = i_first_zero;
128 max_n_zeros = n_zeros;
129 i_first_zero = ARRAY_LEN (a->as_u16);
134 last_double_colon = 0;
135 for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
137 if (i == i_max_n_zero && max_n_zeros > 1)
139 s = format (s, "::");
140 i += max_n_zeros - 1;
141 last_double_colon = 1;
145 s = format (s, "%s%x",
146 (last_double_colon || i == 0) ? "" : ":",
147 clib_net_to_host_u16 (a->as_u16[i]));
148 last_double_colon = 0;
155 /* Format an IP46 address. */
157 format_ip46_address (u8 * s, va_list * args)
159 ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
160 ip46_type_t type = va_arg (*args, ip46_type_t);
166 is_ip4 = ip46_address_is_ip4 (ip46);
177 format (s, "%U", format_ip4_address, &ip46->ip4) :
178 format (s, "%U", format_ip6_address, &ip46->ip6);
182 * VPPCOM Utility Functions
186 vppcom_session_table_del_listener (u64 listener_handle)
188 listener_handle |= 1ULL << 63;
189 hash_unset (vcm->session_index_by_vpp_handles, listener_handle);
193 vppcom_wait_for_app_state_change (app_state_t app_state)
195 f64 timeout = clib_time_now (&vcm->clib_time) + vcm->cfg.app_timeout;
197 while (clib_time_now (&vcm->clib_time) < timeout)
199 if (vcm->app_state == app_state)
202 VDBG (0, "VCL<%d>: timeout waiting for state %s (%d)", getpid (),
203 vppcom_app_state_str (app_state), app_state);
204 vcl_evt (VCL_EVT_SESSION_TIMEOUT, vcm, app_state);
206 return VPPCOM_ETIMEDOUT;
210 vppcom_wait_for_session_state_change (u32 session_index,
211 session_state_t state,
214 f64 timeout = clib_time_now (&vcm->clib_time) + wait_for_time;
215 vcl_session_t *volatile session;
221 rv = vppcom_session_at_index (session_index, &session);
222 if (PREDICT_FALSE (rv))
224 VCL_SESSION_UNLOCK ();
227 if (session->session_state & state)
229 VCL_SESSION_UNLOCK ();
232 if (session->session_state & STATE_FAILED)
234 VCL_SESSION_UNLOCK ();
235 return VPPCOM_ECONNREFUSED;
238 VCL_SESSION_UNLOCK ();
240 while (clib_time_now (&vcm->clib_time) < timeout);
242 VDBG (0, "VCL<%d>: timeout waiting for state 0x%x (%s)", getpid (), state,
243 vppcom_session_state_str (state));
244 vcl_evt (VCL_EVT_SESSION_TIMEOUT, session, session_state);
246 return VPPCOM_ETIMEDOUT;
250 vppcom_app_session_enable (void)
254 if (vcm->app_state != STATE_APP_ENABLED)
256 vppcom_send_session_enable_disable (1 /* is_enabled == TRUE */ );
257 rv = vppcom_wait_for_app_state_change (STATE_APP_ENABLED);
258 if (PREDICT_FALSE (rv))
260 VDBG (0, "VCL<%d>: application session enable timed out! "
261 "returning %d (%s)", getpid (), rv, vppcom_retval_str (rv));
269 vppcom_app_attach (void)
273 vppcom_app_send_attach ();
274 rv = vppcom_wait_for_app_state_change (STATE_APP_ATTACHED);
275 if (PREDICT_FALSE (rv))
277 VDBG (0, "VCL<%d>: application attach timed out! returning %d (%s)",
278 getpid (), rv, vppcom_retval_str (rv));
286 vppcom_session_unbind (u32 session_index)
288 vcl_session_t *session = 0;
292 VCL_SESSION_LOCK_AND_GET (session_index, &session);
294 vpp_handle = session->vpp_handle;
295 vppcom_session_table_del_listener (vpp_handle);
296 session->vpp_handle = ~0;
297 session->session_state = STATE_DISCONNECT;
299 VCL_SESSION_UNLOCK ();
301 VDBG (1, "VCL<%d>: vpp handle 0x%llx, sid %u: sending unbind msg! new state"
302 " 0x%x (%s)", getpid (), vpp_handle, session_index, STATE_DISCONNECT,
303 vppcom_session_state_str (STATE_DISCONNECT));
304 vcl_evt (VCL_EVT_UNBIND, session);
305 vppcom_send_unbind_sock (vpp_handle);
312 vppcom_session_disconnect (u32 session_index)
315 vcl_session_t *session;
317 session_state_t state;
319 VCL_SESSION_LOCK_AND_GET (session_index, &session);
321 vpp_handle = session->vpp_handle;
322 state = session->session_state;
323 VCL_SESSION_UNLOCK ();
325 VDBG (1, "VCL<%d>: vpp handle 0x%llx, sid %u state 0x%x (%s)", getpid (),
326 vpp_handle, session_index, state, vppcom_session_state_str (state));
328 if (PREDICT_FALSE (state & STATE_LISTEN))
330 clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: "
331 "Cannot disconnect a listen socket!",
332 getpid (), vpp_handle, session_index);
337 /* The peer has already initiated the close,
338 * so send the disconnect session reply.
340 if (state & STATE_CLOSE_ON_EMPTY)
342 //XXX alagalah - Check and drain here?
343 vppcom_send_disconnect_session_reply (vpp_handle,
344 session_index, 0 /* rv */ );
345 VDBG (1, "VCL<%d>: vpp handle 0x%llx, sid %u: sending disconnect "
346 "REPLY...", getpid (), vpp_handle, session_index);
349 /* Otherwise, send a disconnect session msg...
353 VDBG (1, "VCL<%d>: vpp handle 0x%llx, sid %u: sending disconnect...",
354 getpid (), vpp_handle, session_index);
356 vppcom_send_disconnect_session (vpp_handle, session_index);
364 * VPPCOM Public API functions
367 vppcom_app_create (char *app_name)
369 vppcom_cfg_t *vcl_cfg = &vcm->cfg;
375 vppcom_cfg (&vcm->cfg);
377 clib_spinlock_init (&vcm->session_fifo_lockp);
378 clib_fifo_validate (vcm->client_session_index_fifo,
379 vcm->cfg.listen_queue_size);
380 clib_spinlock_init (&vcm->sessions_lockp);
383 vcm->main_cpu = os_get_thread_index ();
385 vcm->session_index_by_vpp_handles = hash_create (0, sizeof (uword));
387 clib_time_init (&vcm->clib_time);
388 vppcom_init_error_string_table ();
389 svm_fifo_segment_main_init (vcl_cfg->segment_baseva,
390 20 /* timeout in secs */ );
393 if (vcm->my_client_index == ~0)
395 /* API hookup and connect to VPP */
396 vppcom_api_hookup ();
398 vcm->app_state = STATE_APP_START;
399 rv = vppcom_connect_to_vpp (app_name);
402 clib_warning ("VCL<%d>: ERROR: couldn't connect to VPP!",
407 /* State event handling thread */
409 rv = vce_start_event_thread (&(vcm->event_thread), 20);
411 VDBG (0, "VCL<%d>: sending session enable", getpid ());
413 rv = vppcom_app_session_enable ();
416 clib_warning ("VCL<%d>: ERROR: vppcom_app_session_enable() "
417 "failed!", getpid ());
421 VDBG (0, "VCL<%d>: sending app attach", getpid ());
423 rv = vppcom_app_attach ();
426 clib_warning ("VCL<%d>: ERROR: vppcom_app_attach() failed!",
431 VDBG (0, "VCL<%d>: app_name '%s', my_client_index %d (0x%x)",
432 getpid (), app_name, vcm->my_client_index, vcm->my_client_index);
439 vppcom_app_destroy (void)
442 f64 orig_app_timeout;
444 if (vcm->my_client_index == ~0)
447 VDBG (0, "VCL<%d>: detaching from VPP, my_client_index %d (0x%x)",
448 getpid (), vcm->my_client_index, vcm->my_client_index);
449 vcl_evt (VCL_EVT_DETACH, vcm);
451 vppcom_app_send_detach ();
452 orig_app_timeout = vcm->cfg.app_timeout;
453 vcm->cfg.app_timeout = 2.0;
454 rv = vppcom_wait_for_app_state_change (STATE_APP_ENABLED);
455 vcm->cfg.app_timeout = orig_app_timeout;
456 if (PREDICT_FALSE (rv))
457 VDBG (0, "VCL<%d>: application detach timed out! returning %d (%s)",
458 getpid (), rv, vppcom_retval_str (rv));
461 vl_client_disconnect_from_vlib ();
462 vcm->my_client_index = ~0;
463 vcm->app_state = STATE_APP_START;
467 vppcom_session_create (u8 proto, u8 is_nonblocking)
469 vcl_session_t *session;
473 pool_get (vcm->sessions, session);
474 memset (session, 0, sizeof (*session));
475 session_index = session - vcm->sessions;
477 session->session_type = proto;
478 session->session_state = STATE_START;
479 session->vpp_handle = ~0;
482 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_NONBLOCK);
484 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_NONBLOCK);
486 vcl_evt (VCL_EVT_CREATE, session, session_type, session->session_state,
487 is_nonblocking, session_index);
489 VCL_SESSION_UNLOCK ();
491 VDBG (0, "VCL<%d>: sid %u", getpid (), session_index);
493 return (int) session_index;
497 vppcom_session_close (uint32_t session_index)
499 vcl_session_t *session = 0;
507 session_state_t state;
509 VCL_SESSION_LOCK_AND_GET (session_index, &session);
510 is_vep = session->is_vep;
511 is_vep_session = session->is_vep_session;
512 next_sid = session->vep.next_sid;
513 vep_idx = session->vep.vep_idx;
514 state = session->session_state;
515 vpp_handle = session->vpp_handle;
516 VCL_SESSION_UNLOCK ();
518 if (VPPCOM_DEBUG > 0)
521 clib_warning ("VCL<%d>: vep_idx %u / sid %u: "
522 "closing epoll session...",
523 getpid (), session_index, session_index);
525 clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %d: "
526 "closing session...",
527 getpid (), vpp_handle, session_index);
532 while (next_sid != ~0)
534 rv = vppcom_epoll_ctl (session_index, EPOLL_CTL_DEL, next_sid, 0);
535 if (PREDICT_FALSE (rv < 0))
536 VDBG (0, "VCL<%d>: vpp handle 0x%llx, sid %u: EPOLL_CTL_DEL "
537 "vep_idx %u failed! rv %d (%s)",
538 getpid (), vpp_handle, next_sid, vep_idx,
539 rv, vppcom_retval_str (rv));
541 VCL_SESSION_LOCK_AND_GET (session_index, &session);
542 next_sid = session->vep.next_sid;
543 VCL_SESSION_UNLOCK ();
550 rv = vppcom_epoll_ctl (vep_idx, EPOLL_CTL_DEL, session_index, 0);
552 VDBG (0, "VCL<%d>: vpp handle 0x%llx, sid %u: EPOLL_CTL_DEL "
553 "vep_idx %u failed! rv %d (%s)",
554 getpid (), vpp_handle, session_index,
555 vep_idx, rv, vppcom_retval_str (rv));
558 if (state & STATE_LISTEN)
560 rv = vppcom_session_unbind (session_index);
561 if (PREDICT_FALSE (rv < 0))
562 VDBG (0, "VCL<%d>: vpp handle 0x%llx, sid %u: listener unbind "
563 "failed! rv %d (%s)",
564 getpid (), vpp_handle, session_index,
565 rv, vppcom_retval_str (rv));
568 else if (state & (CLIENT_STATE_OPEN | SERVER_STATE_OPEN))
570 rv = vppcom_session_disconnect (session_index);
571 if (PREDICT_FALSE (rv < 0))
572 clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: "
573 "session disconnect failed! rv %d (%s)",
574 getpid (), vpp_handle, session_index,
575 rv, vppcom_retval_str (rv));
579 VCL_SESSION_LOCK_AND_GET (session_index, &session);
580 vpp_handle = session->vpp_handle;
581 if (vpp_handle != ~0)
583 p = hash_get (vcm->session_index_by_vpp_handles, vpp_handle);
585 hash_unset (vcm->session_index_by_vpp_handles, vpp_handle);
587 pool_put_index (vcm->sessions, session_index);
589 VCL_SESSION_UNLOCK ();
591 if (VPPCOM_DEBUG > 0)
594 clib_warning ("VCL<%d>: vep_idx %u / sid %u: epoll session removed.",
595 getpid (), session_index, session_index);
597 clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: session removed.",
598 getpid (), vpp_handle, session_index);
602 vcl_evt (VCL_EVT_CLOSE, session, rv);
608 vppcom_session_bind (uint32_t session_index, vppcom_endpt_t * ep)
610 vcl_session_t *session = 0;
614 return VPPCOM_EINVAL;
616 VCL_SESSION_LOCK_AND_GET (session_index, &session);
620 VCL_SESSION_UNLOCK ();
621 clib_warning ("VCL<%d>: ERROR: sid %u: cannot "
622 "bind to an epoll session!", getpid (), session_index);
627 session->transport.is_ip4 = ep->is_ip4;
628 session->transport.lcl_ip = to_ip46 (ep->is_ip4 ? IP46_TYPE_IP4 :
629 IP46_TYPE_IP6, ep->ip);
630 session->transport.lcl_port = ep->port;
632 VDBG (0, "VCL<%d>: sid %u: binding to local %s address %U port %u, "
633 "proto %s", getpid (), session_index,
634 session->transport.is_ip4 ? "IPv4" : "IPv6",
635 format_ip46_address, &session->transport.lcl_ip,
636 session->transport.is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
637 clib_net_to_host_u16 (session->transport.lcl_port),
638 session->session_type ? "UDP" : "TCP");
639 vcl_evt (VCL_EVT_BIND, session);
640 VCL_SESSION_UNLOCK ();
646 vppcom_session_listen (uint32_t listen_session_index, uint32_t q_len)
648 vcl_session_t *listen_session = 0;
649 u64 listen_vpp_handle;
652 if (q_len == 0 || q_len == ~0)
653 q_len = vcm->cfg.listen_queue_size;
655 VCL_SESSION_LOCK_AND_GET (listen_session_index, &listen_session);
657 if (listen_session->is_vep)
659 VCL_SESSION_UNLOCK ();
660 clib_warning ("VCL<%d>: ERROR: sid %u: cannot listen on an "
661 "epoll session!", getpid (), listen_session_index);
666 listen_vpp_handle = listen_session->vpp_handle;
667 if (listen_session->session_state & STATE_LISTEN)
669 VCL_SESSION_UNLOCK ();
670 VDBG (0, "VCL<%d>: vpp handle 0x%llx, sid %u: already in listen state!",
671 getpid (), listen_vpp_handle, listen_session_index);
676 VDBG (0, "VCL<%d>: vpp handle 0x%llx, sid %u: sending VPP bind+listen "
677 "request...", getpid (), listen_vpp_handle, listen_session_index);
679 vppcom_send_bind_sock (listen_session, listen_session_index);
680 VCL_SESSION_UNLOCK ();
682 vppcom_wait_for_session_state_change (listen_session_index, STATE_LISTEN,
683 vcm->cfg.session_timeout);
685 VCL_SESSION_LOCK_AND_GET (listen_session_index, &listen_session);
686 if (PREDICT_FALSE (retval))
688 VDBG (0, "VCL<%d>: vpp handle 0x%llx, sid %u: bind+listen failed! "
689 "returning %d (%s)", getpid (), listen_session->vpp_handle,
690 listen_session_index, retval, vppcom_retval_str (retval));
691 VCL_SESSION_UNLOCK ();
696 VCL_ACCEPT_FIFO_LOCK ();
697 clib_fifo_validate (vcm->client_session_index_fifo, q_len);
698 VCL_ACCEPT_FIFO_UNLOCK ();
700 VCL_SESSION_UNLOCK ();
707 validate_args_session_accept_ (vcl_session_t * listen_session)
709 u32 listen_session_index = listen_session - vcm->sessions;
711 /* Input validation - expects spinlock on sessions_lockp */
712 if (listen_session->is_vep)
714 clib_warning ("VCL<%d>: ERROR: sid %u: cannot accept on an "
715 "epoll session!", getpid (), listen_session_index);
716 return VPPCOM_EBADFD;
719 if (listen_session->session_state != STATE_LISTEN)
721 clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: "
722 "not in listen state! state 0x%x (%s)", getpid (),
723 listen_session->vpp_handle, listen_session_index,
724 listen_session->session_state,
725 vppcom_session_state_str (listen_session->session_state));
726 return VPPCOM_EBADFD;
732 vppcom_session_accept (uint32_t listen_session_index, vppcom_endpt_t * ep,
735 vcl_session_t *listen_session = 0;
736 vcl_session_t *client_session = 0;
737 u32 client_session_index = ~0;
739 u64 listen_vpp_handle;
740 vce_event_handler_reg_t *reg;
742 vce_event_connect_request_t *result;
745 int millisecond_timeout = 1;
746 int hours_timeout = 20 * 60 * 60;
748 VCL_SESSION_LOCK_AND_GET (listen_session_index, &listen_session);
749 listen_vpp_handle = listen_session->vpp_handle; // For debugging
751 rv = validate_args_session_accept_ (listen_session);
754 VCL_SESSION_UNLOCK ();
758 /* Using an aggressive timer of 1ms and a generous timer of
759 * 20 hours, we can implement a blocking and non-blocking listener
760 * as both event and time driven */
761 gettimeofday (&tv, NULL);
762 ts.tv_nsec = (tv.tv_usec * 1000) + (1000 * millisecond_timeout);
763 ts.tv_sec = tv.tv_sec;
765 /* Predict that the Listener is blocking more often than not */
766 if (PREDICT_TRUE (!VCL_SESS_ATTR_TEST (listen_session->attr,
767 VCL_SESS_ATTR_NONBLOCK)))
768 ts.tv_sec += hours_timeout;
770 VCL_SESSION_UNLOCK ();
772 /* Register handler for connect_request event on listen_session_index */
774 evk.session_index = listen_session_index;
775 evk.eid = VCL_EVENT_CONNECT_REQ_ACCEPTED;
776 reg = vce_register_handler (&vcm->event_thread, &evk,
777 vce_connect_request_handler_fn, 0);
779 ev = vce_get_event_from_index (&vcm->event_thread, reg->ev_idx);
780 pthread_mutex_lock (®->handler_lock);
783 VCL_EVENTS_UNLOCK ();
784 rv = pthread_cond_timedwait (®->handler_cond,
785 ®->handler_lock, &ts);
792 ev = vce_get_event_from_index (&vcm->event_thread, reg->ev_idx);
794 result = vce_get_event_data (ev, sizeof (*result));
795 client_session_index = result->accepted_session_index;
796 VCL_EVENTS_UNLOCK ();
798 /* Remove from the FIFO used to service epoll */
799 VCL_ACCEPT_FIFO_LOCK ();
800 if (clib_fifo_elts (vcm->client_session_index_fifo))
802 u32 tmp_client_session_index;
803 clib_fifo_sub1 (vcm->client_session_index_fifo,
804 tmp_client_session_index);
805 /* It wasn't ours... put it back ... */
806 if (tmp_client_session_index != client_session_index)
807 clib_fifo_add1 (vcm->client_session_index_fifo,
808 tmp_client_session_index);
810 VCL_ACCEPT_FIFO_UNLOCK ();
814 rv = vppcom_session_at_index (client_session_index, &client_session);
815 if (PREDICT_FALSE (rv))
817 rv = VPPCOM_ECONNABORTED;
818 clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: client sid %u "
819 "lookup failed! returning %d (%s)", getpid (),
820 listen_vpp_handle, listen_session_index,
821 client_session_index, rv, vppcom_retval_str (rv));
825 if (flags & O_NONBLOCK)
826 VCL_SESS_ATTR_SET (client_session->attr, VCL_SESS_ATTR_NONBLOCK);
828 VCL_SESS_ATTR_CLR (client_session->attr, VCL_SESS_ATTR_NONBLOCK);
830 VDBG (0, "VCL<%d>: vpp handle 0x%llx, sid %u: Got a client request! "
831 "vpp handle 0x%llx, sid %u, flags %d, is_nonblocking %u",
832 getpid (), listen_vpp_handle, listen_session_index,
833 client_session->vpp_handle, client_session_index,
834 flags, VCL_SESS_ATTR_TEST (client_session->attr,
835 VCL_SESS_ATTR_NONBLOCK));
839 ep->is_ip4 = client_session->transport.is_ip4;
840 ep->port = client_session->transport.rmt_port;
841 if (client_session->transport.is_ip4)
842 clib_memcpy (ep->ip, &client_session->transport.rmt_ip.ip4,
843 sizeof (ip4_address_t));
845 clib_memcpy (ep->ip, &client_session->transport.rmt_ip.ip6,
846 sizeof (ip6_address_t));
849 vppcom_send_accept_session_reply (client_session->vpp_handle,
850 client_session->client_context,
853 VDBG (0, "VCL<%d>: vpp handle 0x%llx, sid %u: accepted vpp handle 0x%llx,"
854 " sid %u connection from peer %s address %U port %u to local %s address"
856 getpid (), listen_vpp_handle,
857 listen_session_index, client_session->vpp_handle,
858 client_session_index,
859 client_session->transport.is_ip4 ? "IPv4" : "IPv6",
860 format_ip46_address, &client_session->transport.rmt_ip,
861 client_session->transport.is_ip4 ?
862 IP46_TYPE_IP4 : IP46_TYPE_IP6,
863 clib_net_to_host_u16 (client_session->transport.rmt_port),
864 client_session->transport.is_ip4 ? "IPv4" : "IPv6",
865 format_ip46_address, &client_session->transport.lcl_ip,
866 client_session->transport.is_ip4 ?
867 IP46_TYPE_IP4 : IP46_TYPE_IP6,
868 clib_net_to_host_u16 (client_session->transport.lcl_port));
869 vcl_evt (VCL_EVT_ACCEPT, client_session, listen_session,
870 client_session_index);
871 VCL_SESSION_UNLOCK ();
873 rv = (int) client_session_index;
874 vce_clear_event (&vcm->event_thread, reg->ev_idx);
875 if (vcm->session_io_thread.io_sessions_lockp)
877 /* Throw this new accepted session index into the rx poll thread pool */
878 VCL_IO_SESSIONS_LOCK ();
879 u32 *active_session_index;
880 pool_get (vcm->session_io_thread.active_session_indexes,
881 active_session_index);
882 *active_session_index = client_session_index;
883 VCL_IO_SESSIONS_UNLOCK ();
886 vce_unregister_handler (&vcm->event_thread, reg);
887 pthread_mutex_unlock (®->handler_lock);
894 vppcom_session_connect (uint32_t session_index, vppcom_endpt_t * server_ep)
896 vcl_session_t *session = 0;
898 int rv, retval = VPPCOM_OK;
900 VCL_SESSION_LOCK_AND_GET (session_index, &session);
902 if (PREDICT_FALSE (session->is_vep))
904 VCL_SESSION_UNLOCK ();
905 clib_warning ("VCL<%d>: ERROR: sid %u: cannot "
906 "connect on an epoll session!", getpid (), session_index);
911 if (PREDICT_FALSE (session->session_state & CLIENT_STATE_OPEN))
913 VDBG (0, "VCL<%d>: vpp handle 0x%llx, sid %u: session already "
914 "connected to %s %U port %d proto %s, state 0x%x (%s)",
915 getpid (), session->vpp_handle, session_index,
916 session->transport.is_ip4 ? "IPv4" : "IPv6",
918 &session->transport.rmt_ip, session->transport.is_ip4 ?
919 IP46_TYPE_IP4 : IP46_TYPE_IP6,
920 clib_net_to_host_u16 (session->transport.rmt_port),
921 session->session_type ? "UDP" : "TCP", session->session_state,
922 vppcom_session_state_str (session->session_state));
924 VCL_SESSION_UNLOCK ();
928 session->transport.is_ip4 = server_ep->is_ip4;
929 if (session->transport.is_ip4)
930 clib_memcpy (&session->transport.rmt_ip.ip4, server_ep->ip,
931 sizeof (ip4_address_t));
933 clib_memcpy (&session->transport.rmt_ip.ip6, server_ep->ip,
934 sizeof (ip6_address_t));
935 session->transport.rmt_port = server_ep->port;
937 VDBG (0, "VCL<%d>: vpp handle 0x%llx, sid %u: connecting to server %s %U "
939 getpid (), session->vpp_handle, session_index,
940 session->transport.is_ip4 ? "IPv4" : "IPv6",
942 &session->transport.rmt_ip, session->transport.is_ip4 ?
943 IP46_TYPE_IP4 : IP46_TYPE_IP6,
944 clib_net_to_host_u16 (session->transport.rmt_port),
945 session->session_type ? "UDP" : "TCP");
947 vppcom_send_connect_sock (session, session_index);
948 VCL_SESSION_UNLOCK ();
951 vppcom_wait_for_session_state_change (session_index, STATE_CONNECT,
952 vcm->cfg.session_timeout);
954 VCL_SESSION_LOCK_AND_GET (session_index, &session);
955 vpp_handle = session->vpp_handle;
956 VCL_SESSION_UNLOCK ();
959 if (PREDICT_FALSE (retval))
962 if (VPPCOM_DEBUG > 0)
965 clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: connect "
966 "failed! returning %d (%s)", getpid (), vpp_handle,
967 session_index, rv, vppcom_retval_str (rv));
969 clib_warning ("VCL<%d>: no session for sid %u: connect failed! "
970 "returning %d (%s)", getpid (),
971 session_index, rv, vppcom_retval_str (rv));
975 VDBG (0, "VCL<%d>: vpp handle 0x%llx, sid %u: connected!",
976 getpid (), vpp_handle, session_index);
982 vppcom_session_read_internal (uint32_t session_index, void *buf, int n,
985 vcl_session_t *session = 0;
993 session_state_t state;
997 VCL_SESSION_LOCK_AND_GET (session_index, &session);
999 is_nonblocking = VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_NONBLOCK);
1000 rx_fifo = session->rx_fifo;
1001 state = session->session_state;
1002 vpp_handle = session->vpp_handle;
1004 if (PREDICT_FALSE (session->is_vep))
1006 VCL_SESSION_UNLOCK ();
1007 clib_warning ("VCL<%d>: ERROR: sid %u: cannot "
1008 "read from an epoll session!", getpid (), session_index);
1013 if (PREDICT_FALSE (!(state & (SERVER_STATE_OPEN | CLIENT_STATE_OPEN))))
1015 VCL_SESSION_UNLOCK ();
1016 rv = ((state & STATE_DISCONNECT) ? VPPCOM_ECONNRESET : VPPCOM_ENOTCONN);
1018 VDBG (0, "VCL<%d>: vpp handle 0x%llx, sid %u: %s session is not open! "
1019 "state 0x%x (%s), returning %d (%s)",
1020 getpid (), vpp_handle, session_index, state,
1021 vppcom_session_state_str (state), rv, vppcom_retval_str (rv));
1025 VCL_SESSION_UNLOCK ();
1030 n_read = svm_fifo_peek (rx_fifo, 0, n, buf);
1032 n_read = svm_fifo_dequeue_nowait (rx_fifo, n, buf);
1034 while (!is_nonblocking && (n_read <= 0));
1038 VCL_SESSION_LOCK_AND_GET (session_index, &session);
1040 poll_et = (((EPOLLET | EPOLLIN) & session->vep.ev.events) ==
1041 (EPOLLET | EPOLLIN));
1043 session->vep.et_mask |= EPOLLIN;
1045 if (state & STATE_CLOSE_ON_EMPTY)
1047 rv = VPPCOM_ECONNRESET;
1049 VDBG (1, "VCL<%d>: vpp handle 0x%llx, sid %u: Empty fifo with "
1050 "session state 0x%x (%s)! Setting state to 0x%x (%s), "
1051 "returning %d (%s)",
1052 getpid (), session->vpp_handle, session_index,
1053 state, vppcom_session_state_str (state),
1055 vppcom_session_state_str (STATE_DISCONNECT), rv,
1056 vppcom_retval_str (rv));
1058 session->session_state = STATE_DISCONNECT;
1063 VCL_SESSION_UNLOCK ();
1068 if (VPPCOM_DEBUG > 2)
1071 clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: read %d bytes "
1072 "from (%p)", getpid (), vpp_handle,
1073 session_index, n_read, rx_fifo);
1075 clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: nothing read! "
1076 "returning %d (%s)", getpid (), vpp_handle,
1077 session_index, rv, vppcom_retval_str (rv));
1084 vppcom_session_read (uint32_t session_index, void *buf, size_t n)
1086 return (vppcom_session_read_internal (session_index, buf, n, 0));
1090 vppcom_session_peek (uint32_t session_index, void *buf, int n)
1092 return (vppcom_session_read_internal (session_index, buf, n, 1));
1096 vppcom_session_read_ready (vcl_session_t * session, u32 session_index)
1101 session_state_t state = session->session_state;
1102 u64 vpp_handle = session->vpp_handle;
1104 /* Assumes caller has acquired spinlock: vcm->sessions_lockp */
1105 if (PREDICT_FALSE (session->is_vep))
1107 clib_warning ("VCL<%d>: ERROR: sid %u: cannot read from an "
1108 "epoll session!", getpid (), session_index);
1113 if (session->session_state & STATE_LISTEN)
1115 VCL_ACCEPT_FIFO_LOCK ();
1116 ready = clib_fifo_elts (vcm->client_session_index_fifo);
1117 VCL_ACCEPT_FIFO_UNLOCK ();
1121 if (!(state & (SERVER_STATE_OPEN | CLIENT_STATE_OPEN | STATE_LISTEN)))
1123 rv = ((state & STATE_DISCONNECT) ? VPPCOM_ECONNRESET :
1126 VDBG (1, "VCL<%d>: vpp handle 0x%llx, sid %u: session is not open!"
1127 " state 0x%x (%s), returning %d (%s)",
1128 getpid (), vpp_handle, session_index,
1129 state, vppcom_session_state_str (state),
1130 rv, vppcom_retval_str (rv));
1134 ready = svm_fifo_max_dequeue (session->rx_fifo);
1140 ((EPOLLET | EPOLLIN) & session->vep.ev.events) == (EPOLLET | EPOLLIN);
1142 session->vep.et_mask |= EPOLLIN;
1144 if (state & STATE_CLOSE_ON_EMPTY)
1146 rv = VPPCOM_ECONNRESET;
1148 VDBG (1, "VCL<%d>: vpp handle 0x%llx, sid %u: Empty fifo with "
1149 "session state 0x%x (%s)! Setting state to 0x%x (%s), "
1150 "returning %d (%s)",
1151 getpid (), session_index, vpp_handle,
1152 state, vppcom_session_state_str (state),
1154 vppcom_session_state_str (STATE_DISCONNECT), rv,
1155 vppcom_retval_str (rv));
1156 session->session_state = STATE_DISCONNECT;
1162 if (!svm_msg_q_is_empty (vcm->app_event_queue) &&
1163 !pthread_mutex_trylock (&vcm->app_event_queue->q->mutex))
1165 u32 i, n_to_dequeue = vcm->app_event_queue->q->cursize;
1166 svm_msg_q_msg_t msg;
1168 for (i = 0; i < n_to_dequeue; i++)
1170 svm_queue_sub_raw (vcm->app_event_queue->q, (u8 *) & msg);
1171 svm_msg_q_free_msg (vcm->app_event_queue, &msg);
1174 pthread_mutex_unlock (&vcm->app_event_queue->q->mutex);
1181 vppcom_session_write (uint32_t session_index, void *buf, size_t n)
1183 vcl_session_t *session = 0;
1184 svm_fifo_t *tx_fifo = 0;
1186 session_state_t state;
1187 int rv, n_write, is_nonblocking;
1193 VCL_SESSION_LOCK_AND_GET (session_index, &session);
1195 tx_fifo = session->tx_fifo;
1196 is_nonblocking = VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_NONBLOCK);
1197 vpp_handle = session->vpp_handle;
1198 state = session->session_state;
1200 if (PREDICT_FALSE (session->is_vep))
1202 VCL_SESSION_UNLOCK ();
1203 clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: "
1204 "cannot write to an epoll session!",
1205 getpid (), vpp_handle, session_index);
1211 if (!(session->session_state & (SERVER_STATE_OPEN | CLIENT_STATE_OPEN)))
1214 ((session->session_state & STATE_DISCONNECT) ? VPPCOM_ECONNRESET :
1217 VCL_SESSION_UNLOCK ();
1218 VDBG (1, "VCL<%d>: vpp handle 0x%llx, sid %u: session is not open! "
1220 getpid (), vpp_handle, session_index,
1221 state, vppcom_session_state_str (state));
1225 VCL_SESSION_UNLOCK ();
1229 n_write = svm_fifo_enqueue_nowait (tx_fifo, n, (void *) buf);
1231 while (!is_nonblocking && (n_write <= 0));
1233 /* If event wasn't set, add one
1235 * To reduce context switching, can check if an
1236 * event is already there for this event_key, but for now
1237 * this will suffice. */
1239 if ((n_write > 0) && svm_fifo_set_event (tx_fifo))
1241 /* Send TX event to vpp */
1242 VCL_SESSION_LOCK_AND_GET (session_index, &session);
1243 mq = session->vpp_evt_q;
1245 app_send_io_evt_to_vpp (mq, tx_fifo, FIFO_EVENT_APP_TX, SVM_Q_WAIT);
1246 VCL_SESSION_UNLOCK ();
1247 VDBG (1, "VCL<%d>: vpp handle 0x%llx, sid %u: added FIFO_EVENT_APP_TX "
1248 "to vpp_event_q %p, n_write %d", getpid (),
1249 vpp_handle, session_index, mq, n_write);
1254 VCL_SESSION_LOCK_AND_GET (session_index, &session);
1256 poll_et = (((EPOLLET | EPOLLOUT) & session->vep.ev.events) ==
1257 (EPOLLET | EPOLLOUT));
1259 session->vep.et_mask |= EPOLLOUT;
1261 if (session->session_state & STATE_CLOSE_ON_EMPTY)
1263 rv = VPPCOM_ECONNRESET;
1265 VDBG (1, "VCL<%d>: vpp handle 0x%llx, sid %u: Empty fifo with "
1266 "session state 0x%x (%s)! Setting state to 0x%x (%s), "
1267 "returning %d (%s)",
1268 getpid (), session->vpp_handle, session_index,
1269 session->session_state,
1270 vppcom_session_state_str (session->session_state),
1272 vppcom_session_state_str (STATE_DISCONNECT), rv,
1273 vppcom_retval_str (rv));
1275 session->session_state = STATE_DISCONNECT;
1280 VCL_SESSION_UNLOCK ();
1285 if (VPPCOM_DEBUG > 2)
1288 clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: "
1289 "FIFO-FULL (%p)", getpid (), vpp_handle,
1290 session_index, tx_fifo);
1292 clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: "
1293 "wrote %d bytes tx-fifo: (%p)", getpid (),
1294 vpp_handle, session_index, n_write, tx_fifo);
1301 vppcom_session_write_ready (vcl_session_t * session, u32 session_index)
1309 /* Assumes caller has acquired spinlock: vcm->sessions_lockp */
1310 if (PREDICT_FALSE (session->is_vep))
1312 clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: "
1313 "cannot write to an epoll session!",
1314 getpid (), session->vpp_handle, session_index);
1319 if (PREDICT_FALSE (session->session_state & STATE_LISTEN))
1321 clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: "
1322 "cannot write to a listen session!",
1323 getpid (), session->vpp_handle, session_index);
1328 if (!(session->session_state & (SERVER_STATE_OPEN | CLIENT_STATE_OPEN)))
1330 session_state_t state = session->session_state;
1332 rv = ((state & STATE_DISCONNECT) ? VPPCOM_ECONNRESET : VPPCOM_ENOTCONN);
1334 clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: "
1335 "session is not open! state 0x%x (%s), "
1336 "returning %d (%s)", getpid (), session->vpp_handle,
1338 state, vppcom_session_state_str (state),
1339 rv, vppcom_retval_str (rv));
1343 ready = svm_fifo_max_enqueue (session->tx_fifo);
1345 VDBG (3, "VCL<%d>: vpp handle 0x%llx, sid %u: peek %s (%p), ready = %d",
1346 getpid (), session->vpp_handle, session_index, session->tx_fifo,
1351 poll_et = (((EPOLLET | EPOLLOUT) & session->vep.ev.events) ==
1352 (EPOLLET | EPOLLOUT));
1354 session->vep.et_mask |= EPOLLOUT;
1356 if (session->session_state & STATE_CLOSE_ON_EMPTY)
1358 rv = VPPCOM_ECONNRESET;
1360 VDBG (1, "VCL<%d>: vpp handle 0x%llx, sid %u: Empty fifo with "
1361 "session state 0x%x (%s)! Setting state to 0x%x (%s), "
1362 "returning %d (%s)", getpid (),
1363 session->vpp_handle, session_index,
1364 session->session_state,
1365 vppcom_session_state_str (session->session_state),
1367 vppcom_session_state_str (STATE_DISCONNECT), rv,
1368 vppcom_retval_str (rv));
1369 session->session_state = STATE_DISCONNECT;
1379 vppcom_select (unsigned long n_bits, unsigned long *read_map,
1380 unsigned long *write_map, unsigned long *except_map,
1381 double time_to_wait)
1384 vcl_session_t *session = 0;
1385 int rv, bits_set = 0;
1386 f64 timeout = clib_time_now (&vcm->clib_time) + time_to_wait;
1387 u32 minbits = clib_max (n_bits, BITS (uword));
1389 ASSERT (sizeof (clib_bitmap_t) == sizeof (long int));
1391 if (n_bits && read_map)
1393 clib_bitmap_validate (vcm->rd_bitmap, minbits);
1394 clib_memcpy (vcm->rd_bitmap, read_map,
1395 vec_len (vcm->rd_bitmap) * sizeof (clib_bitmap_t));
1396 memset (read_map, 0, vec_len (vcm->rd_bitmap) * sizeof (clib_bitmap_t));
1398 if (n_bits && write_map)
1400 clib_bitmap_validate (vcm->wr_bitmap, minbits);
1401 clib_memcpy (vcm->wr_bitmap, write_map,
1402 vec_len (vcm->wr_bitmap) * sizeof (clib_bitmap_t));
1403 memset (write_map, 0,
1404 vec_len (vcm->wr_bitmap) * sizeof (clib_bitmap_t));
1406 if (n_bits && except_map)
1408 clib_bitmap_validate (vcm->ex_bitmap, minbits);
1409 clib_memcpy (vcm->ex_bitmap, except_map,
1410 vec_len (vcm->ex_bitmap) * sizeof (clib_bitmap_t));
1411 memset (except_map, 0,
1412 vec_len (vcm->ex_bitmap) * sizeof (clib_bitmap_t));
1422 clib_bitmap_foreach (session_index, vcm->rd_bitmap,
1425 rv = vppcom_session_at_index (session_index, &session);
1428 VCL_SESSION_UNLOCK();
1429 VDBG (1, "VCL<%d>: session %d specified in read_map is"
1430 " closed.", getpid (),
1432 bits_set = VPPCOM_EBADFD;
1435 if (session->session_state & STATE_LISTEN)
1437 vce_event_handler_reg_t *reg = 0;
1438 vce_event_key_t evk;
1440 /* Check if handler already registered for this
1442 * If not, register handler for connect_request event
1443 * on listen_session_index
1445 evk.session_index = session_index;
1446 evk.eid = VCL_EVENT_CONNECT_REQ_ACCEPTED;
1447 reg = vce_get_event_handler (&vcm->event_thread, &evk);
1449 reg = vce_register_handler (&vcm->event_thread, &evk,
1450 vce_poll_wait_connect_request_handler_fn,
1451 0 /* No callback args */);
1452 rv = vppcom_session_read_ready (session, session_index);
1455 vce_unregister_handler (&vcm->event_thread, reg);
1459 rv = vppcom_session_read_ready (session, session_index);
1460 VCL_SESSION_UNLOCK();
1461 if (except_map && vcm->ex_bitmap &&
1462 clib_bitmap_get (vcm->ex_bitmap, session_index) &&
1465 clib_bitmap_set_no_check (except_map, session_index, 1);
1470 clib_bitmap_set_no_check (read_map, session_index, 1);
1478 clib_bitmap_foreach (session_index, vcm->wr_bitmap,
1481 rv = vppcom_session_at_index (session_index, &session);
1484 VCL_SESSION_UNLOCK();
1485 VDBG (0, "VCL<%d>: session %d specified in "
1486 "write_map is closed.", getpid (),
1488 bits_set = VPPCOM_EBADFD;
1492 rv = vppcom_session_write_ready (session, session_index);
1493 VCL_SESSION_UNLOCK();
1494 if (write_map && (rv > 0))
1496 clib_bitmap_set_no_check (write_map, session_index, 1);
1504 clib_bitmap_foreach (session_index, vcm->ex_bitmap,
1507 rv = vppcom_session_at_index (session_index, &session);
1510 VCL_SESSION_UNLOCK();
1511 VDBG (1, "VCL<%d>: session %d specified in except_map "
1512 "is closed.", getpid (),
1514 bits_set = VPPCOM_EBADFD;
1518 rv = vppcom_session_read_ready (session, session_index);
1519 VCL_SESSION_UNLOCK();
1522 clib_bitmap_set_no_check (except_map, session_index, 1);
1530 while ((time_to_wait == -1) || (clib_time_now (&vcm->clib_time) < timeout));
1537 vep_verify_epoll_chain (u32 vep_idx)
1539 vcl_session_t *session;
1540 vppcom_epoll_t *vep;
1544 if (VPPCOM_DEBUG <= 1)
1547 /* Assumes caller has acquired spinlock: vcm->sessions_lockp */
1548 rv = vppcom_session_at_index (vep_idx, &session);
1549 if (PREDICT_FALSE (rv))
1551 clib_warning ("VCL<%d>: ERROR: Invalid vep_idx (%u)!",
1552 getpid (), vep_idx);
1555 if (PREDICT_FALSE (!session->is_vep))
1557 clib_warning ("VCL<%d>: ERROR: vep_idx (%u) is not a vep!",
1558 getpid (), vep_idx);
1561 vep = &session->vep;
1562 clib_warning ("VCL<%d>: vep_idx (%u): Dumping epoll chain\n"
1565 " is_vep_session = %u\n"
1566 " next_sid = 0x%x (%u)\n"
1567 " wait_cont_idx = 0x%x (%u)\n"
1568 "}\n", getpid (), vep_idx,
1569 session->is_vep, session->is_vep_session,
1570 vep->next_sid, vep->next_sid,
1571 session->wait_cont_idx, session->wait_cont_idx);
1573 for (sid = vep->next_sid; sid != ~0; sid = vep->next_sid)
1575 rv = vppcom_session_at_index (sid, &session);
1576 if (PREDICT_FALSE (rv))
1578 clib_warning ("VCL<%d>: ERROR: Invalid sid (%u)!", getpid (), sid);
1581 if (PREDICT_FALSE (session->is_vep))
1582 clib_warning ("VCL<%d>: ERROR: sid (%u) is a vep!",
1583 getpid (), vep_idx);
1584 else if (PREDICT_FALSE (!session->is_vep_session))
1586 clib_warning ("VCL<%d>: ERROR: session (%u) "
1587 "is not a vep session!", getpid (), sid);
1590 vep = &session->vep;
1591 if (PREDICT_FALSE (vep->vep_idx != vep_idx))
1592 clib_warning ("VCL<%d>: ERROR: session (%u) vep_idx (%u) != "
1593 "vep_idx (%u)!", getpid (),
1594 sid, session->vep.vep_idx, vep_idx);
1595 if (session->is_vep_session)
1597 clib_warning ("vep_idx[%u]: sid 0x%x (%u)\n"
1599 " next_sid = 0x%x (%u)\n"
1600 " prev_sid = 0x%x (%u)\n"
1601 " vep_idx = 0x%x (%u)\n"
1602 " ev.events = 0x%x\n"
1603 " ev.data.u64 = 0x%llx\n"
1607 vep->next_sid, vep->next_sid,
1608 vep->prev_sid, vep->prev_sid,
1609 vep->vep_idx, vep->vep_idx,
1610 vep->ev.events, vep->ev.data.u64, vep->et_mask);
1615 clib_warning ("VCL<%d>: vep_idx (%u): Dump complete!\n",
1616 getpid (), vep_idx);
1620 vppcom_epoll_create (void)
1622 vcl_session_t *vep_session;
1625 VCL_SESSION_LOCK ();
1626 pool_get (vcm->sessions, vep_session);
1627 memset (vep_session, 0, sizeof (*vep_session));
1628 vep_idx = vep_session - vcm->sessions;
1630 vep_session->is_vep = 1;
1631 vep_session->vep.vep_idx = ~0;
1632 vep_session->vep.next_sid = ~0;
1633 vep_session->vep.prev_sid = ~0;
1634 vep_session->wait_cont_idx = ~0;
1635 vep_session->vpp_handle = ~0;
1636 vep_session->poll_reg = 0;
1638 vcl_evt (VCL_EVT_EPOLL_CREATE, vep_session, vep_idx);
1639 VCL_SESSION_UNLOCK ();
1641 VDBG (0, "VCL<%d>: Created vep_idx %u / sid %u!",
1642 getpid (), vep_idx, vep_idx);
1648 vppcom_epoll_ctl (uint32_t vep_idx, int op, uint32_t session_index,
1649 struct epoll_event *event)
1651 vcl_session_t *vep_session;
1652 vcl_session_t *session;
1655 if (vep_idx == session_index)
1657 clib_warning ("VCL<%d>: ERROR: vep_idx == session_index (%u)!",
1658 getpid (), vep_idx);
1659 return VPPCOM_EINVAL;
1662 VCL_SESSION_LOCK ();
1663 rv = vppcom_session_at_index (vep_idx, &vep_session);
1664 if (PREDICT_FALSE (rv))
1666 clib_warning ("VCL<%d>: ERROR: Invalid vep_idx (%u)!", vep_idx);
1669 if (PREDICT_FALSE (!vep_session->is_vep))
1671 clib_warning ("VCL<%d>: ERROR: vep_idx (%u) is not a vep!",
1672 getpid (), vep_idx);
1677 ASSERT (vep_session->vep.vep_idx == ~0);
1678 ASSERT (vep_session->vep.prev_sid == ~0);
1680 rv = vppcom_session_at_index (session_index, &session);
1681 if (PREDICT_FALSE (rv))
1683 VDBG (0, "VCL<%d>: ERROR: Invalid session_index (%u)!",
1684 getpid (), session_index);
1687 if (PREDICT_FALSE (session->is_vep))
1689 clib_warning ("ERROR: session_index (%u) is a vep!", vep_idx);
1697 if (PREDICT_FALSE (!event))
1699 clib_warning ("VCL<%d>: ERROR: EPOLL_CTL_ADD: NULL pointer to "
1700 "epoll_event structure!", getpid ());
1704 if (vep_session->vep.next_sid != ~0)
1706 vcl_session_t *next_session;
1707 rv = vppcom_session_at_index (vep_session->vep.next_sid,
1709 if (PREDICT_FALSE (rv))
1711 clib_warning ("VCL<%d>: ERROR: EPOLL_CTL_ADD: Invalid "
1712 "vep.next_sid (%u) on vep_idx (%u)!",
1713 getpid (), vep_session->vep.next_sid, vep_idx);
1716 ASSERT (next_session->vep.prev_sid == vep_idx);
1717 next_session->vep.prev_sid = session_index;
1719 session->vep.next_sid = vep_session->vep.next_sid;
1720 session->vep.prev_sid = vep_idx;
1721 session->vep.vep_idx = vep_idx;
1722 session->vep.et_mask = VEP_DEFAULT_ET_MASK;
1723 session->vep.ev = *event;
1724 session->is_vep = 0;
1725 session->is_vep_session = 1;
1726 vep_session->vep.next_sid = session_index;
1728 /* VCL Event Register handler */
1729 if (session->session_state & STATE_LISTEN)
1731 /* Register handler for connect_request event on listen_session_index */
1732 vce_event_key_t evk;
1733 evk.session_index = session_index;
1734 evk.eid = VCL_EVENT_CONNECT_REQ_ACCEPTED;
1735 vep_session->poll_reg =
1736 vce_register_handler (&vcm->event_thread, &evk,
1737 vce_poll_wait_connect_request_handler_fn,
1738 0 /* No callback args */ );
1740 VDBG (1, "VCL<%d>: EPOLL_CTL_ADD: vep_idx %u, "
1741 "sid %u, events 0x%x, data 0x%llx!",
1742 getpid (), vep_idx, session_index,
1743 event->events, event->data.u64);
1744 vcl_evt (VCL_EVT_EPOLL_CTLADD, session, event->events, event->data.u64);
1748 if (PREDICT_FALSE (!event))
1750 clib_warning ("VCL<%d>: ERROR: EPOLL_CTL_MOD: NULL pointer to "
1751 "epoll_event structure!", getpid ());
1755 else if (PREDICT_FALSE (!session->is_vep_session))
1757 clib_warning ("VCL<%d>: ERROR: sid %u EPOLL_CTL_MOD: "
1758 "not a vep session!", getpid (), session_index);
1762 else if (PREDICT_FALSE (session->vep.vep_idx != vep_idx))
1764 clib_warning ("VCL<%d>: ERROR: sid %u EPOLL_CTL_MOD: "
1765 "vep_idx (%u) != vep_idx (%u)!",
1766 getpid (), session_index,
1767 session->vep.vep_idx, vep_idx);
1771 session->vep.et_mask = VEP_DEFAULT_ET_MASK;
1772 session->vep.ev = *event;
1773 VDBG (1, "VCL<%d>: EPOLL_CTL_MOD: vep_idx %u, sid %u, events 0x%x,"
1774 " data 0x%llx!", getpid (), vep_idx, session_index, event->events,
1779 if (PREDICT_FALSE (!session->is_vep_session))
1781 clib_warning ("VCL<%d>: ERROR: sid %u EPOLL_CTL_DEL: "
1782 "not a vep session!", getpid (), session_index);
1786 else if (PREDICT_FALSE (session->vep.vep_idx != vep_idx))
1788 clib_warning ("VCL<%d>: ERROR: sid %u EPOLL_CTL_DEL: "
1789 "vep_idx (%u) != vep_idx (%u)!",
1790 getpid (), session_index,
1791 session->vep.vep_idx, vep_idx);
1796 /* VCL Event Un-register handler */
1797 if ((session->session_state & STATE_LISTEN) && vep_session->poll_reg)
1799 (void) vce_unregister_handler (&vcm->event_thread,
1800 vep_session->poll_reg);
1803 vep_session->wait_cont_idx =
1804 (vep_session->wait_cont_idx == session_index) ?
1805 session->vep.next_sid : vep_session->wait_cont_idx;
1807 if (session->vep.prev_sid == vep_idx)
1808 vep_session->vep.next_sid = session->vep.next_sid;
1811 vcl_session_t *prev_session;
1812 rv = vppcom_session_at_index (session->vep.prev_sid, &prev_session);
1813 if (PREDICT_FALSE (rv))
1815 clib_warning ("VCL<%d>: ERROR: EPOLL_CTL_DEL: Invalid "
1816 "vep.prev_sid (%u) on sid (%u)!",
1817 getpid (), session->vep.prev_sid, session_index);
1820 ASSERT (prev_session->vep.next_sid == session_index);
1821 prev_session->vep.next_sid = session->vep.next_sid;
1823 if (session->vep.next_sid != ~0)
1825 vcl_session_t *next_session;
1826 rv = vppcom_session_at_index (session->vep.next_sid, &next_session);
1827 if (PREDICT_FALSE (rv))
1829 clib_warning ("VCL<%d>: ERROR: EPOLL_CTL_DEL: Invalid "
1830 "vep.next_sid (%u) on sid (%u)!",
1831 getpid (), session->vep.next_sid, session_index);
1834 ASSERT (next_session->vep.prev_sid == session_index);
1835 next_session->vep.prev_sid = session->vep.prev_sid;
1838 memset (&session->vep, 0, sizeof (session->vep));
1839 session->vep.next_sid = ~0;
1840 session->vep.prev_sid = ~0;
1841 session->vep.vep_idx = ~0;
1842 session->is_vep_session = 0;
1843 VDBG (1, "VCL<%d>: EPOLL_CTL_DEL: vep_idx %u, sid %u!",
1844 getpid (), vep_idx, session_index);
1845 vcl_evt (VCL_EVT_EPOLL_CTLDEL, session, vep_idx);
1849 clib_warning ("VCL<%d>: ERROR: Invalid operation (%d)!", getpid (), op);
1853 vep_verify_epoll_chain (vep_idx);
1856 VCL_SESSION_UNLOCK ();
1861 vppcom_epoll_wait (uint32_t vep_idx, struct epoll_event *events,
1862 int maxevents, double wait_for_time)
1864 vcl_session_t *vep_session;
1866 f64 timeout = clib_time_now (&vcm->clib_time) + wait_for_time;
1867 u32 keep_trying = 1;
1869 u32 vep_next_sid, wait_cont_idx;
1872 if (PREDICT_FALSE (maxevents <= 0))
1874 clib_warning ("VCL<%d>: ERROR: Invalid maxevents (%d)!",
1875 getpid (), maxevents);
1876 return VPPCOM_EINVAL;
1878 memset (events, 0, sizeof (*events) * maxevents);
1880 VCL_SESSION_LOCK_AND_GET (vep_idx, &vep_session);
1881 vep_next_sid = vep_session->vep.next_sid;
1882 is_vep = vep_session->is_vep;
1883 wait_cont_idx = vep_session->wait_cont_idx;
1884 VCL_SESSION_UNLOCK ();
1886 if (PREDICT_FALSE (!is_vep))
1888 clib_warning ("VCL<%d>: ERROR: vep_idx (%u) is not a vep!",
1889 getpid (), vep_idx);
1893 if (PREDICT_FALSE (vep_next_sid == ~0))
1895 VDBG (1, "VCL<%d>: WARNING: vep_idx (%u) is empty!",
1896 getpid (), vep_idx);
1904 vcl_session_t *session;
1906 for (sid = (wait_cont_idx == ~0) ? vep_next_sid : wait_cont_idx;
1907 sid != ~0; sid = next_sid)
1909 u32 session_events, et_mask, clear_et_mask, session_vep_idx;
1910 u8 add_event, is_vep_session;
1912 u64 session_ev_data;
1914 VCL_SESSION_LOCK_AND_GET (sid, &session);
1915 next_sid = session->vep.next_sid;
1916 session_events = session->vep.ev.events;
1917 et_mask = session->vep.et_mask;
1918 is_vep = session->is_vep;
1919 is_vep_session = session->is_vep_session;
1920 session_vep_idx = session->vep.vep_idx;
1921 session_ev_data = session->vep.ev.data.u64;
1923 VCL_SESSION_UNLOCK ();
1925 if (PREDICT_FALSE (is_vep))
1927 VDBG (0, "VCL<%d>: ERROR: sid (%u) is a vep!",
1928 getpid (), vep_idx);
1932 if (PREDICT_FALSE (!is_vep_session))
1934 VDBG (0, "VCL<%d>: ERROR: session (%u) is not "
1935 "a vep session!", getpid (), sid);
1939 if (PREDICT_FALSE (session_vep_idx != vep_idx))
1941 clib_warning ("VCL<%d>: ERROR: session (%u) "
1942 "vep_idx (%u) != vep_idx (%u)!",
1943 getpid (), sid, session_vep_idx, vep_idx);
1948 add_event = clear_et_mask = 0;
1950 if (EPOLLIN & session_events)
1952 VCL_SESSION_LOCK_AND_GET (sid, &session);
1953 ready = vppcom_session_read_ready (session, sid);
1954 VCL_SESSION_UNLOCK ();
1955 if ((ready > 0) && (EPOLLIN & et_mask))
1958 events[num_ev].events |= EPOLLIN;
1959 if (((EPOLLET | EPOLLIN) & session_events) ==
1960 (EPOLLET | EPOLLIN))
1961 clear_et_mask |= EPOLLIN;
1968 case VPPCOM_ECONNRESET:
1969 events[num_ev].events |= EPOLLHUP | EPOLLRDHUP;
1973 events[num_ev].events |= EPOLLERR;
1979 if (EPOLLOUT & session_events)
1981 VCL_SESSION_LOCK_AND_GET (sid, &session);
1982 ready = vppcom_session_write_ready (session, sid);
1983 VCL_SESSION_UNLOCK ();
1984 if ((ready > 0) && (EPOLLOUT & et_mask))
1987 events[num_ev].events |= EPOLLOUT;
1988 if (((EPOLLET | EPOLLOUT) & session_events) ==
1989 (EPOLLET | EPOLLOUT))
1990 clear_et_mask |= EPOLLOUT;
1997 case VPPCOM_ECONNRESET:
1998 events[num_ev].events |= EPOLLHUP;
2002 events[num_ev].events |= EPOLLERR;
2010 events[num_ev].data.u64 = session_ev_data;
2011 if (EPOLLONESHOT & session_events)
2013 VCL_SESSION_LOCK_AND_GET (sid, &session);
2014 session->vep.ev.events = 0;
2015 VCL_SESSION_UNLOCK ();
2018 if (num_ev == maxevents)
2020 VCL_SESSION_LOCK_AND_GET (vep_idx, &vep_session);
2021 vep_session->wait_cont_idx = next_sid;
2022 VCL_SESSION_UNLOCK ();
2026 if (wait_cont_idx != ~0)
2029 next_sid = vep_next_sid;
2030 else if (next_sid == wait_cont_idx)
2034 if (wait_for_time != -1)
2035 keep_trying = (clib_time_now (&vcm->clib_time) <= timeout) ? 1 : 0;
2037 while ((num_ev == 0) && keep_trying);
2039 if (wait_cont_idx != ~0)
2041 VCL_SESSION_LOCK_AND_GET (vep_idx, &vep_session);
2042 vep_session->wait_cont_idx = ~0;
2043 VCL_SESSION_UNLOCK ();
2046 return (rv != VPPCOM_OK) ? rv : num_ev;
2050 vppcom_session_attr (uint32_t session_index, uint32_t op,
2051 void *buffer, uint32_t * buflen)
2053 vcl_session_t *session;
2055 u32 *flags = buffer;
2056 vppcom_endpt_t *ep = buffer;
2058 VCL_SESSION_LOCK_AND_GET (session_index, &session);
2064 case VPPCOM_ATTR_GET_NREAD:
2065 rv = vppcom_session_read_ready (session, session_index);
2066 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_NREAD: sid %u, nread = %d",
2070 case VPPCOM_ATTR_GET_NWRITE:
2071 rv = vppcom_session_write_ready (session, session_index);
2072 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_NWRITE: sid %u, nwrite = %d",
2073 getpid (), session_index, rv);
2076 case VPPCOM_ATTR_GET_FLAGS:
2077 if (PREDICT_TRUE (buffer && buflen && (*buflen >= sizeof (*flags))))
2079 *flags = O_RDWR | (VCL_SESS_ATTR_TEST (session->attr,
2080 VCL_SESS_ATTR_NONBLOCK));
2081 *buflen = sizeof (*flags);
2082 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_FLAGS: sid %u, flags = 0x%08x, "
2083 "is_nonblocking = %u", getpid (),
2084 session_index, *flags,
2085 VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_NONBLOCK));
2091 case VPPCOM_ATTR_SET_FLAGS:
2092 if (PREDICT_TRUE (buffer && buflen && (*buflen == sizeof (*flags))))
2094 if (*flags & O_NONBLOCK)
2095 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_NONBLOCK);
2097 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_NONBLOCK);
2099 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_FLAGS: sid %u, flags = 0x%08x,"
2100 " is_nonblocking = %u",
2101 getpid (), session_index, *flags,
2102 VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_NONBLOCK));
2108 case VPPCOM_ATTR_GET_PEER_ADDR:
2109 if (PREDICT_TRUE (buffer && buflen &&
2110 (*buflen >= sizeof (*ep)) && ep->ip))
2112 ep->is_ip4 = session->transport.is_ip4;
2113 ep->port = session->transport.rmt_port;
2114 if (session->transport.is_ip4)
2115 clib_memcpy (ep->ip, &session->transport.rmt_ip.ip4,
2116 sizeof (ip4_address_t));
2118 clib_memcpy (ep->ip, &session->transport.rmt_ip.ip6,
2119 sizeof (ip6_address_t));
2120 *buflen = sizeof (*ep);
2121 VDBG (1, "VCL<%d>: VPPCOM_ATTR_GET_PEER_ADDR: sid %u, is_ip4 = %u, "
2122 "addr = %U, port %u", getpid (),
2123 session_index, ep->is_ip4, format_ip46_address,
2124 &session->transport.rmt_ip,
2125 ep->is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
2126 clib_net_to_host_u16 (ep->port));
2132 case VPPCOM_ATTR_GET_LCL_ADDR:
2133 if (PREDICT_TRUE (buffer && buflen &&
2134 (*buflen >= sizeof (*ep)) && ep->ip))
2136 ep->is_ip4 = session->transport.is_ip4;
2137 ep->port = session->transport.lcl_port;
2138 if (session->transport.is_ip4)
2139 clib_memcpy (ep->ip, &session->transport.lcl_ip.ip4,
2140 sizeof (ip4_address_t));
2142 clib_memcpy (ep->ip, &session->transport.lcl_ip.ip6,
2143 sizeof (ip6_address_t));
2144 *buflen = sizeof (*ep);
2145 VDBG (1, "VCL<%d>: VPPCOM_ATTR_GET_LCL_ADDR: sid %u, is_ip4 = %u,"
2146 " addr = %U port %d", getpid (),
2147 session_index, ep->is_ip4, format_ip46_address,
2148 &session->transport.lcl_ip,
2149 ep->is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
2150 clib_net_to_host_u16 (ep->port));
2156 case VPPCOM_ATTR_GET_LIBC_EPFD:
2157 rv = session->libc_epfd;
2158 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_LIBC_EPFD: libc_epfd %d",
2162 case VPPCOM_ATTR_SET_LIBC_EPFD:
2163 if (PREDICT_TRUE (buffer && buflen &&
2164 (*buflen == sizeof (session->libc_epfd))))
2166 session->libc_epfd = *(int *) buffer;
2167 *buflen = sizeof (session->libc_epfd);
2169 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_LIBC_EPFD: libc_epfd %d, "
2170 "buflen %d", getpid (), session->libc_epfd, *buflen);
2176 case VPPCOM_ATTR_GET_PROTOCOL:
2177 if (buffer && buflen && (*buflen >= sizeof (int)))
2179 *(int *) buffer = session->session_type;
2180 *buflen = sizeof (int);
2182 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_PROTOCOL: %d (%s), buflen %d",
2183 getpid (), *(int *) buffer, *(int *) buffer ? "UDP" : "TCP",
2190 case VPPCOM_ATTR_GET_LISTEN:
2191 if (buffer && buflen && (*buflen >= sizeof (int)))
2193 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
2194 VCL_SESS_ATTR_LISTEN);
2195 *buflen = sizeof (int);
2197 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_LISTEN: %d, buflen %d",
2198 getpid (), *(int *) buffer, *buflen);
2204 case VPPCOM_ATTR_GET_ERROR:
2205 if (buffer && buflen && (*buflen >= sizeof (int)))
2207 *(int *) buffer = 0;
2208 *buflen = sizeof (int);
2210 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_ERROR: %d, buflen %d, #VPP-TBD#",
2211 getpid (), *(int *) buffer, *buflen);
2217 case VPPCOM_ATTR_GET_TX_FIFO_LEN:
2218 if (buffer && buflen && (*buflen >= sizeof (u32)))
2222 *(size_t *) buffer = (session->sndbuf_size ? session->sndbuf_size :
2223 session->tx_fifo ? session->tx_fifo->nitems :
2224 vcm->cfg.tx_fifo_size);
2225 *buflen = sizeof (u32);
2227 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_TX_FIFO_LEN: %u (0x%x), "
2228 "buflen %d, #VPP-TBD#", getpid (),
2229 *(size_t *) buffer, *(size_t *) buffer, *buflen);
2235 case VPPCOM_ATTR_SET_TX_FIFO_LEN:
2236 if (buffer && buflen && (*buflen == sizeof (u32)))
2239 session->sndbuf_size = *(u32 *) buffer;
2240 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_TX_FIFO_LEN: %u (0x%x), "
2241 "buflen %d, #VPP-TBD#", getpid (),
2242 session->sndbuf_size, session->sndbuf_size, *buflen);
2248 case VPPCOM_ATTR_GET_RX_FIFO_LEN:
2249 if (buffer && buflen && (*buflen >= sizeof (u32)))
2253 *(size_t *) buffer = (session->rcvbuf_size ? session->rcvbuf_size :
2254 session->rx_fifo ? session->rx_fifo->nitems :
2255 vcm->cfg.rx_fifo_size);
2256 *buflen = sizeof (u32);
2258 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_RX_FIFO_LEN: %u (0x%x), "
2259 "buflen %d, #VPP-TBD#", getpid (),
2260 *(size_t *) buffer, *(size_t *) buffer, *buflen);
2266 case VPPCOM_ATTR_SET_RX_FIFO_LEN:
2267 if (buffer && buflen && (*buflen == sizeof (u32)))
2270 session->rcvbuf_size = *(u32 *) buffer;
2271 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_RX_FIFO_LEN: %u (0x%x), "
2272 "buflen %d, #VPP-TBD#", getpid (),
2273 session->sndbuf_size, session->sndbuf_size, *buflen);
2279 case VPPCOM_ATTR_GET_REUSEADDR:
2280 if (buffer && buflen && (*buflen >= sizeof (int)))
2283 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
2284 VCL_SESS_ATTR_REUSEADDR);
2285 *buflen = sizeof (int);
2287 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_REUSEADDR: %d, "
2288 "buflen %d, #VPP-TBD#", getpid (), *(int *) buffer, *buflen);
2294 case VPPCOM_ATTR_SET_REUSEADDR:
2295 if (buffer && buflen && (*buflen == sizeof (int)) &&
2296 !VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_LISTEN))
2299 if (*(int *) buffer)
2300 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_REUSEADDR);
2302 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_REUSEADDR);
2304 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_REUSEADDR: %d, buflen %d,"
2305 " #VPP-TBD#", getpid (),
2306 VCL_SESS_ATTR_TEST (session->attr,
2307 VCL_SESS_ATTR_REUSEADDR), *buflen);
2313 case VPPCOM_ATTR_GET_REUSEPORT:
2314 if (buffer && buflen && (*buflen >= sizeof (int)))
2317 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
2318 VCL_SESS_ATTR_REUSEPORT);
2319 *buflen = sizeof (int);
2321 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_REUSEPORT: %d, buflen %d,"
2322 " #VPP-TBD#", getpid (), *(int *) buffer, *buflen);
2328 case VPPCOM_ATTR_SET_REUSEPORT:
2329 if (buffer && buflen && (*buflen == sizeof (int)) &&
2330 !VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_LISTEN))
2333 if (*(int *) buffer)
2334 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_REUSEPORT);
2336 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_REUSEPORT);
2338 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_REUSEPORT: %d, buflen %d,"
2339 " #VPP-TBD#", getpid (),
2340 VCL_SESS_ATTR_TEST (session->attr,
2341 VCL_SESS_ATTR_REUSEPORT), *buflen);
2347 case VPPCOM_ATTR_GET_BROADCAST:
2348 if (buffer && buflen && (*buflen >= sizeof (int)))
2351 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
2352 VCL_SESS_ATTR_BROADCAST);
2353 *buflen = sizeof (int);
2355 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_BROADCAST: %d, buflen %d,"
2356 " #VPP-TBD#", getpid (), *(int *) buffer, *buflen);
2362 case VPPCOM_ATTR_SET_BROADCAST:
2363 if (buffer && buflen && (*buflen == sizeof (int)))
2366 if (*(int *) buffer)
2367 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_BROADCAST);
2369 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_BROADCAST);
2371 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_BROADCAST: %d, buflen %d, "
2372 "#VPP-TBD#", getpid (),
2373 VCL_SESS_ATTR_TEST (session->attr,
2374 VCL_SESS_ATTR_BROADCAST), *buflen);
2380 case VPPCOM_ATTR_GET_V6ONLY:
2381 if (buffer && buflen && (*buflen >= sizeof (int)))
2384 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
2385 VCL_SESS_ATTR_V6ONLY);
2386 *buflen = sizeof (int);
2388 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_V6ONLY: %d, buflen %d, "
2389 "#VPP-TBD#", getpid (), *(int *) buffer, *buflen);
2395 case VPPCOM_ATTR_SET_V6ONLY:
2396 if (buffer && buflen && (*buflen == sizeof (int)))
2399 if (*(int *) buffer)
2400 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_V6ONLY);
2402 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_V6ONLY);
2404 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_V6ONLY: %d, buflen %d, "
2405 "#VPP-TBD#", getpid (),
2406 VCL_SESS_ATTR_TEST (session->attr,
2407 VCL_SESS_ATTR_V6ONLY), *buflen);
2413 case VPPCOM_ATTR_GET_KEEPALIVE:
2414 if (buffer && buflen && (*buflen >= sizeof (int)))
2417 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
2418 VCL_SESS_ATTR_KEEPALIVE);
2419 *buflen = sizeof (int);
2421 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_KEEPALIVE: %d, buflen %d, "
2422 "#VPP-TBD#", getpid (), *(int *) buffer, *buflen);
2428 case VPPCOM_ATTR_SET_KEEPALIVE:
2429 if (buffer && buflen && (*buflen == sizeof (int)))
2432 if (*(int *) buffer)
2433 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_KEEPALIVE);
2435 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_KEEPALIVE);
2437 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_KEEPALIVE: %d, buflen %d, "
2438 "#VPP-TBD#", getpid (),
2439 VCL_SESS_ATTR_TEST (session->attr,
2440 VCL_SESS_ATTR_KEEPALIVE), *buflen);
2446 case VPPCOM_ATTR_GET_TCP_NODELAY:
2447 if (buffer && buflen && (*buflen >= sizeof (int)))
2450 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
2451 VCL_SESS_ATTR_TCP_NODELAY);
2452 *buflen = sizeof (int);
2454 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_TCP_NODELAY: %d, buflen %d, "
2455 "#VPP-TBD#", getpid (), *(int *) buffer, *buflen);
2461 case VPPCOM_ATTR_SET_TCP_NODELAY:
2462 if (buffer && buflen && (*buflen == sizeof (int)))
2465 if (*(int *) buffer)
2466 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_TCP_NODELAY);
2468 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_TCP_NODELAY);
2470 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_TCP_NODELAY: %d, buflen %d, "
2471 "#VPP-TBD#", getpid (),
2472 VCL_SESS_ATTR_TEST (session->attr,
2473 VCL_SESS_ATTR_TCP_NODELAY), *buflen);
2479 case VPPCOM_ATTR_GET_TCP_KEEPIDLE:
2480 if (buffer && buflen && (*buflen >= sizeof (int)))
2483 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
2484 VCL_SESS_ATTR_TCP_KEEPIDLE);
2485 *buflen = sizeof (int);
2487 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_TCP_KEEPIDLE: %d, buflen %d, "
2488 "#VPP-TBD#", getpid (), *(int *) buffer, *buflen);
2494 case VPPCOM_ATTR_SET_TCP_KEEPIDLE:
2495 if (buffer && buflen && (*buflen == sizeof (int)))
2498 if (*(int *) buffer)
2499 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_TCP_KEEPIDLE);
2501 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_TCP_KEEPIDLE);
2503 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_TCP_KEEPIDLE: %d, buflen %d, "
2504 "#VPP-TBD#", getpid (),
2505 VCL_SESS_ATTR_TEST (session->attr,
2506 VCL_SESS_ATTR_TCP_KEEPIDLE), *buflen);
2512 case VPPCOM_ATTR_GET_TCP_KEEPINTVL:
2513 if (buffer && buflen && (*buflen >= sizeof (int)))
2516 *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
2517 VCL_SESS_ATTR_TCP_KEEPINTVL);
2518 *buflen = sizeof (int);
2520 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_TCP_KEEPINTVL: %d, buflen %d, "
2521 "#VPP-TBD#", getpid (), *(int *) buffer, *buflen);
2527 case VPPCOM_ATTR_SET_TCP_KEEPINTVL:
2528 if (buffer && buflen && (*buflen == sizeof (int)))
2531 if (*(int *) buffer)
2532 VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_TCP_KEEPINTVL);
2534 VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_TCP_KEEPINTVL);
2536 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_TCP_KEEPINTVL: %d, buflen %d, "
2537 "#VPP-TBD#", getpid (),
2538 VCL_SESS_ATTR_TEST (session->attr,
2539 VCL_SESS_ATTR_TCP_KEEPINTVL), *buflen);
2545 case VPPCOM_ATTR_GET_TCP_USER_MSS:
2546 if (buffer && buflen && (*buflen >= sizeof (u32)))
2549 *(u32 *) buffer = session->user_mss;
2550 *buflen = sizeof (int);
2552 VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_TCP_USER_MSS: %d, buflen %d,"
2553 " #VPP-TBD#", getpid (), *(int *) buffer, *buflen);
2559 case VPPCOM_ATTR_SET_TCP_USER_MSS:
2560 if (buffer && buflen && (*buflen == sizeof (u32)))
2563 session->user_mss = *(u32 *) buffer;
2565 VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_TCP_USER_MSS: %u, buflen %d, "
2566 "#VPP-TBD#", getpid (), session->user_mss, *buflen);
2578 VCL_SESSION_UNLOCK ();
2583 vppcom_session_recvfrom (uint32_t session_index, void *buffer,
2584 uint32_t buflen, int flags, vppcom_endpt_t * ep)
2587 vcl_session_t *session = 0;
2591 VCL_SESSION_LOCK ();
2592 rv = vppcom_session_at_index (session_index, &session);
2593 if (PREDICT_FALSE (rv))
2595 VCL_SESSION_UNLOCK ();
2596 VDBG (0, "VCL<%d>: invalid session, sid (%u) has been closed!",
2597 getpid (), session_index);
2599 VCL_SESSION_UNLOCK ();
2602 ep->is_ip4 = session->transport.is_ip4;
2603 ep->port = session->transport.rmt_port;
2604 if (session->transport.is_ip4)
2605 clib_memcpy (ep->ip, &session->transport.rmt_ip.ip4,
2606 sizeof (ip4_address_t));
2608 clib_memcpy (ep->ip, &session->transport.rmt_ip.ip6,
2609 sizeof (ip6_address_t));
2610 VCL_SESSION_UNLOCK ();
2614 rv = vppcom_session_read (session_index, buffer, buflen);
2615 else if (flags & MSG_PEEK)
2616 rv = vppcom_session_peek (session_index, buffer, buflen);
2619 clib_warning ("VCL<%d>: Unsupport flags for recvfrom %d",
2621 rv = VPPCOM_EAFNOSUPPORT;
2629 vppcom_session_sendto (uint32_t session_index, void *buffer,
2630 uint32_t buflen, int flags, vppcom_endpt_t * ep)
2633 return VPPCOM_EINVAL;
2638 return VPPCOM_EINVAL;
2643 // TBD check the flags and do the right thing
2644 VDBG (2, "VCL<%d>: handling flags 0x%u (%d) not implemented yet.",
2645 getpid (), flags, flags);
2648 return (vppcom_session_write (session_index, buffer, buflen));
2652 vppcom_poll (vcl_poll_t * vp, uint32_t n_sids, double wait_for_time)
2654 f64 timeout = clib_time_now (&vcm->clib_time) + wait_for_time;
2655 u32 i, keep_trying = 1;
2658 VDBG (3, "VCL<%d>: vp %p, nsids %u, wait_for_time %f",
2659 getpid (), vp, n_sids, wait_for_time);
2662 return VPPCOM_EFAULT;
2666 vcl_session_t *session;
2668 for (i = 0; i < n_sids; i++)
2670 ASSERT (vp[i].revents);
2672 VCL_SESSION_LOCK_AND_GET (vp[i].sid, &session);
2673 VCL_SESSION_UNLOCK ();
2678 if (POLLIN & vp[i].events)
2680 VCL_SESSION_LOCK_AND_GET (vp[i].sid, &session);
2681 rv = vppcom_session_read_ready (session, vp[i].sid);
2682 VCL_SESSION_UNLOCK ();
2685 *vp[i].revents |= POLLIN;
2692 case VPPCOM_ECONNRESET:
2693 *vp[i].revents = POLLHUP;
2697 *vp[i].revents = POLLERR;
2704 if (POLLOUT & vp[i].events)
2706 VCL_SESSION_LOCK_AND_GET (vp[i].sid, &session);
2707 rv = vppcom_session_write_ready (session, vp[i].sid);
2708 VCL_SESSION_UNLOCK ();
2711 *vp[i].revents |= POLLOUT;
2718 case VPPCOM_ECONNRESET:
2719 *vp[i].revents = POLLHUP;
2723 *vp[i].revents = POLLERR;
2730 if (0) // Note "done:" label used by VCL_SESSION_LOCK_AND_GET()
2733 *vp[i].revents = POLLNVAL;
2737 if (wait_for_time != -1)
2738 keep_trying = (clib_time_now (&vcm->clib_time) <= timeout) ? 1 : 0;
2740 while ((num_ev == 0) && keep_trying);
2742 if (VPPCOM_DEBUG > 3)
2744 clib_warning ("VCL<%d>: returning %d", getpid (), num_ev);
2745 for (i = 0; i < n_sids; i++)
2747 clib_warning ("VCL<%d>: vp[%d].sid %d (0x%x), .events 0x%x, "
2748 ".revents 0x%x", getpid (), i, vp[i].sid, vp[i].sid,
2749 vp[i].events, *vp[i].revents);
2756 * fd.io coding-style-patch-verification: ON
2759 * eval: (c-set-style "gnu")