+ else if (PREDICT_FALSE (!session->is_vep_session))
+ {
+ VDBG (0, "sid %u EPOLL_CTL_MOD: not a vep session!",
+ session_handle);
+ rv = VPPCOM_EINVAL;
+ goto done;
+ }
+ else if (PREDICT_FALSE (session->vep.vep_sh != vep_handle))
+ {
+ VDBG (0, "EPOLL_CTL_MOD: sh %u vep_sh (%u) != vep_sh (%u)!",
+ session_handle, session->vep.vep_sh, vep_handle);
+ rv = VPPCOM_EINVAL;
+ goto done;
+ }
+ session->vep.et_mask = VEP_DEFAULT_ET_MASK;
+ session->vep.ev = *event;
+ VDBG (1, "EPOLL_CTL_MOD: vep_sh %u, sh %u, events 0x%x, data 0x%llx!",
+ vep_handle, session_handle, event->events, event->data.u64);
+ break;
+
+ case EPOLL_CTL_DEL:
+ if (PREDICT_FALSE (!session->is_vep_session))
+ {
+ VDBG (0, "EPOLL_CTL_DEL: %u not a vep session!", session_handle);
+ rv = VPPCOM_EINVAL;
+ goto done;
+ }
+ else if (PREDICT_FALSE (session->vep.vep_sh != vep_handle))
+ {
+ VDBG (0, "EPOLL_CTL_DEL: sh %u vep_sh (%u) != vep_sh (%u)!",
+ session_handle, session->vep.vep_sh, vep_handle);
+ rv = VPPCOM_EINVAL;
+ goto done;
+ }
+
+ vep_session->wait_cont_idx =
+ (vep_session->wait_cont_idx == session_handle) ?
+ session->vep.next_sh : vep_session->wait_cont_idx;
+
+ if (session->vep.prev_sh == vep_handle)
+ vep_session->vep.next_sh = session->vep.next_sh;
+ else
+ {
+ vcl_session_t *prev_session;
+ prev_session = vcl_session_get_w_handle (wrk, session->vep.prev_sh);
+ if (PREDICT_FALSE (!prev_session))
+ {
+ VDBG (0, "EPOLL_CTL_DEL: Invalid prev_sid (%u) on sid (%u)!",
+ session->vep.prev_sh, session_handle);
+ return VPPCOM_EBADFD;
+ }
+ ASSERT (prev_session->vep.next_sh == session_handle);
+ prev_session->vep.next_sh = session->vep.next_sh;
+ }
+ if (session->vep.next_sh != ~0)
+ {
+ vcl_session_t *next_session;
+ next_session = vcl_session_get_w_handle (wrk, session->vep.next_sh);
+ if (PREDICT_FALSE (!next_session))
+ {
+ VDBG (0, "EPOLL_CTL_DEL: Invalid next_sid (%u) on sid (%u)!",
+ session->vep.next_sh, session_handle);
+ return VPPCOM_EBADFD;
+ }
+ ASSERT (next_session->vep.prev_sh == session_handle);
+ next_session->vep.prev_sh = session->vep.prev_sh;
+ }
+
+ memset (&session->vep, 0, sizeof (session->vep));
+ session->vep.next_sh = ~0;
+ session->vep.prev_sh = ~0;
+ session->vep.vep_sh = ~0;
+ session->is_vep_session = 0;
+ VDBG (1, "EPOLL_CTL_DEL: vep_idx %u, sid %u!", vep_handle,
+ session_handle);
+ vcl_evt (VCL_EVT_EPOLL_CTLDEL, session, vep_sh);
+ break;
+
+ default:
+ VDBG (0, "Invalid operation (%d)!", op);
+ rv = VPPCOM_EINVAL;
+ }
+
+ vep_verify_epoll_chain (wrk, vep_handle);
+
+done:
+ return rv;
+}
+
+static inline void
+vcl_epoll_wait_handle_mq_event (vcl_worker_t * wrk, session_event_t * e,
+ struct epoll_event *events, u32 * num_ev)
+{
+ session_disconnected_msg_t *disconnected_msg;
+ session_connected_msg_t *connected_msg;
+ u32 sid = ~0, session_events;
+ u64 session_evt_data = ~0;
+ vcl_session_t *session;
+ u8 add_event = 0;
+
+ switch (e->event_type)
+ {
+ case FIFO_EVENT_APP_RX:
+ ASSERT (e->fifo->client_thread_index == vcl_get_worker_index ());
+ vcl_fifo_rx_evt_valid_or_break (e->fifo);
+ sid = e->fifo->client_session_index;
+ if (!(session = vcl_session_get (wrk, sid)))
+ break;
+ session_events = session->vep.ev.events;
+ if (!(EPOLLIN & session->vep.ev.events) || session->has_rx_evt)
+ break;
+ add_event = 1;
+ events[*num_ev].events |= EPOLLIN;
+ session_evt_data = session->vep.ev.data.u64;
+ session->has_rx_evt = 1;
+ break;
+ case FIFO_EVENT_APP_TX:
+ sid = e->fifo->client_session_index;
+ if (!(session = vcl_session_get (wrk, sid)))
+ break;
+ session_events = session->vep.ev.events;
+ if (!(EPOLLOUT & session_events))
+ break;
+ add_event = 1;
+ events[*num_ev].events |= EPOLLOUT;
+ session_evt_data = session->vep.ev.data.u64;
+ break;
+ case SESSION_IO_EVT_CT_TX:
+ vcl_fifo_rx_evt_valid_or_break (e->fifo);
+ session = vcl_ct_session_get_from_fifo (wrk, e->fifo, 0);
+ if (PREDICT_FALSE (!session))
+ break;
+ sid = session->session_index;
+ session_events = session->vep.ev.events;
+ if (!(EPOLLIN & session->vep.ev.events) || session->has_rx_evt)
+ break;
+ add_event = 1;
+ events[*num_ev].events |= EPOLLIN;
+ session_evt_data = session->vep.ev.data.u64;
+ session->has_rx_evt = 1;
+ break;
+ case SESSION_IO_EVT_CT_RX:
+ session = vcl_ct_session_get_from_fifo (wrk, e->fifo, 1);
+ if (PREDICT_FALSE (!session))
+ break;
+ sid = session->session_index;
+ session_events = session->vep.ev.events;
+ if (!(EPOLLOUT & session_events))
+ break;
+ add_event = 1;
+ events[*num_ev].events |= EPOLLOUT;
+ session_evt_data = session->vep.ev.data.u64;
+ break;
+ case SESSION_CTRL_EVT_ACCEPTED:
+ session = vcl_session_accepted (wrk,
+ (session_accepted_msg_t *) e->data);
+ if (!session)
+ break;
+
+ session_events = session->vep.ev.events;
+ if (!(EPOLLIN & session_events))
+ break;
+
+ add_event = 1;
+ events[*num_ev].events |= EPOLLIN;
+ session_evt_data = session->vep.ev.data.u64;
+ break;
+ case SESSION_CTRL_EVT_CONNECTED:
+ connected_msg = (session_connected_msg_t *) e->data;
+ vcl_session_connected_handler (wrk, connected_msg);
+ /* Generate EPOLLOUT because there's no connected event */
+ sid = vcl_session_index_from_vpp_handle (wrk, connected_msg->handle);
+ if (!(session = vcl_session_get (wrk, sid)))
+ break;
+ session_events = session->vep.ev.events;
+ if (EPOLLOUT & session_events)
+ {
+ add_event = 1;
+ events[*num_ev].events |= EPOLLOUT;
+ session_evt_data = session->vep.ev.data.u64;
+ }
+ break;
+ case SESSION_CTRL_EVT_DISCONNECTED:
+ disconnected_msg = (session_disconnected_msg_t *) e->data;
+ session = vcl_session_disconnected_handler (wrk, disconnected_msg);
+ if (!session)
+ break;
+ add_event = 1;
+ events[*num_ev].events |= EPOLLHUP | EPOLLRDHUP;
+ session_evt_data = session->vep.ev.data.u64;
+ session_events = session->vep.ev.events;
+ break;
+ case SESSION_CTRL_EVT_RESET:
+ sid = vcl_session_reset_handler (wrk, (session_reset_msg_t *) e->data);
+ if (!(session = vcl_session_get (wrk, sid)))
+ break;
+ add_event = 1;
+ events[*num_ev].events |= EPOLLHUP | EPOLLRDHUP;
+ session_evt_data = session->vep.ev.data.u64;
+ session_events = session->vep.ev.events;
+ break;
+ default:
+ VDBG (0, "unhandled: %u", e->event_type);
+ break;
+ }
+
+ if (add_event)
+ {
+ events[*num_ev].data.u64 = session_evt_data;
+ if (EPOLLONESHOT & session_events)
+ {
+ session = vcl_session_get (wrk, sid);
+ session->vep.ev.events = 0;
+ }
+ *num_ev += 1;
+ }
+}
+
+static int
+vcl_epoll_wait_handle_mq (vcl_worker_t * wrk, svm_msg_q_t * mq,
+ struct epoll_event *events, u32 maxevents,
+ double wait_for_time, u32 * num_ev)
+{
+ svm_msg_q_msg_t *msg;
+ session_event_t *e;
+ int i;
+
+ if (vec_len (wrk->mq_msg_vector) && svm_msg_q_is_empty (mq))
+ goto handle_dequeued;
+
+ svm_msg_q_lock (mq);
+ if (svm_msg_q_is_empty (mq))
+ {
+ if (!wait_for_time)
+ {
+ svm_msg_q_unlock (mq);
+ return 0;
+ }
+ else if (wait_for_time < 0)
+ {
+ svm_msg_q_wait (mq);
+ }
+ else
+ {
+ if (svm_msg_q_timedwait (mq, wait_for_time / 1e3))
+ {
+ svm_msg_q_unlock (mq);
+ return 0;
+ }
+ }
+ }
+ vcl_mq_dequeue_batch (wrk, mq);
+ svm_msg_q_unlock (mq);
+
+handle_dequeued:
+ for (i = 0; i < vec_len (wrk->mq_msg_vector); i++)
+ {
+ msg = vec_elt_at_index (wrk->mq_msg_vector, i);
+ e = svm_msg_q_msg_data (mq, msg);
+ if (*num_ev < maxevents)
+ vcl_epoll_wait_handle_mq_event (wrk, e, events, num_ev);
+ else
+ vec_add1 (wrk->unhandled_evts_vector, *e);
+ svm_msg_q_free_msg (mq, msg);
+ }
+ vec_reset_length (wrk->mq_msg_vector);
+
+ return *num_ev;
+}
+
+static int
+vppcom_epoll_wait_condvar (vcl_worker_t * wrk, struct epoll_event *events,
+ int maxevents, u32 n_evts, double wait_for_time)
+{
+ vcl_cut_through_registration_t *cr;
+ double total_wait = 0, wait_slice;
+ int rv;
+
+ wait_for_time = (wait_for_time == -1) ? (double) 10e9 : wait_for_time;
+ wait_slice = wrk->cut_through_registrations ? 10e-6 : wait_for_time;
+
+ do
+ {
+ vcl_ct_registration_lock (wrk);
+ /* *INDENT-OFF* */
+ pool_foreach (cr, wrk->cut_through_registrations, ({
+ vcl_epoll_wait_handle_mq (wrk, cr->mq, events, maxevents, 0, &n_evts);
+ }));
+ /* *INDENT-ON* */
+ vcl_ct_registration_unlock (wrk);
+
+ rv = vcl_epoll_wait_handle_mq (wrk, wrk->app_event_queue, events,
+ maxevents, n_evts ? 0 : wait_slice,
+ &n_evts);
+ if (rv)
+ total_wait += wait_slice;
+ if (n_evts)
+ return n_evts;
+ }
+ while (total_wait < wait_for_time);
+ return n_evts;
+}
+
+static int
+vppcom_epoll_wait_eventfd (vcl_worker_t * wrk, struct epoll_event *events,
+ int maxevents, u32 n_evts, double wait_for_time)
+{
+ vcl_mq_evt_conn_t *mqc;
+ int __clib_unused n_read;
+ int n_mq_evts, i;
+ u64 buf;
+
+ vec_validate (wrk->mq_events, pool_elts (wrk->mq_evt_conns));
+again:
+ n_mq_evts = epoll_wait (wrk->mqs_epfd, wrk->mq_events,
+ vec_len (wrk->mq_events), wait_for_time);
+ for (i = 0; i < n_mq_evts; i++)
+ {
+ mqc = vcl_mq_evt_conn_get (wrk, wrk->mq_events[i].data.u32);
+ n_read = read (mqc->mq_fd, &buf, sizeof (buf));
+ vcl_epoll_wait_handle_mq (wrk, mqc->mq, events, maxevents, 0, &n_evts);
+ }
+ if (!n_evts && n_mq_evts > 0)
+ goto again;
+
+ return (int) n_evts;
+}
+
+int
+vppcom_epoll_wait (uint32_t vep_handle, struct epoll_event *events,
+ int maxevents, double wait_for_time)
+{
+ vcl_worker_t *wrk = vcl_worker_get_current ();
+ vcl_session_t *vep_session;
+ u32 n_evts = 0;
+ int i;
+
+ if (PREDICT_FALSE (maxevents <= 0))
+ {
+ clib_warning ("VCL<%d>: ERROR: Invalid maxevents (%d)!",
+ getpid (), maxevents);
+ return VPPCOM_EINVAL;
+ }
+
+ vep_session = vcl_session_get_w_handle (wrk, vep_handle);
+ if (!vep_session)
+ return VPPCOM_EBADFD;
+
+ if (PREDICT_FALSE (!vep_session->is_vep))
+ {
+ clib_warning ("VCL<%d>: ERROR: vep_idx (%u) is not a vep!",
+ getpid (), vep_handle);
+ return VPPCOM_EINVAL;
+ }
+
+ memset (events, 0, sizeof (*events) * maxevents);
+
+ if (vec_len (wrk->unhandled_evts_vector))
+ {
+ for (i = 0; i < vec_len (wrk->unhandled_evts_vector); i++)
+ {
+ vcl_epoll_wait_handle_mq_event (wrk, &wrk->unhandled_evts_vector[i],
+ events, &n_evts);
+ if (n_evts == maxevents)
+ {
+ i += 1;
+ break;
+ }
+ }
+
+ vec_delete (wrk->unhandled_evts_vector, i, 0);
+ }
+
+ if (vcm->cfg.use_mq_eventfd)
+ return vppcom_epoll_wait_eventfd (wrk, events, maxevents, n_evts,
+ wait_for_time);
+
+ return vppcom_epoll_wait_condvar (wrk, events, maxevents, n_evts,
+ wait_for_time);
+}
+
+int
+vppcom_session_attr (uint32_t session_handle, uint32_t op,
+ void *buffer, uint32_t * buflen)
+{
+ vcl_worker_t *wrk = vcl_worker_get_current ();
+ vcl_session_t *session;
+ int rv = VPPCOM_OK;
+ u32 *flags = buffer;
+ vppcom_endpt_t *ep = buffer;
+
+ session = vcl_session_get_w_handle (wrk, session_handle);
+ if (!session)
+ return VPPCOM_EBADFD;
+
+ switch (op)
+ {
+ case VPPCOM_ATTR_GET_NREAD:
+ rv = vppcom_session_read_ready (session);
+ VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_NREAD: sid %u, nread = %d",
+ getpid (), rv);
+ break;
+
+ case VPPCOM_ATTR_GET_NWRITE:
+ rv = vppcom_session_write_ready (session);
+ VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_NWRITE: sid %u, nwrite = %d",
+ getpid (), session_handle, rv);
+ break;
+
+ case VPPCOM_ATTR_GET_FLAGS:
+ if (PREDICT_TRUE (buffer && buflen && (*buflen >= sizeof (*flags))))
+ {
+ *flags = O_RDWR | (VCL_SESS_ATTR_TEST (session->attr,
+ VCL_SESS_ATTR_NONBLOCK));
+ *buflen = sizeof (*flags);
+ VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_FLAGS: sid %u, flags = 0x%08x, "
+ "is_nonblocking = %u", getpid (),
+ session_handle, *flags,
+ VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_NONBLOCK));
+ }
+ else
+ rv = VPPCOM_EINVAL;
+ break;
+
+ case VPPCOM_ATTR_SET_FLAGS:
+ if (PREDICT_TRUE (buffer && buflen && (*buflen == sizeof (*flags))))
+ {
+ if (*flags & O_NONBLOCK)
+ VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_NONBLOCK);
+ else
+ VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_NONBLOCK);
+
+ VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_FLAGS: sid %u, flags = 0x%08x,"
+ " is_nonblocking = %u",
+ getpid (), session_handle, *flags,
+ VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_NONBLOCK));
+ }
+ else
+ rv = VPPCOM_EINVAL;
+ break;
+
+ case VPPCOM_ATTR_GET_PEER_ADDR:
+ if (PREDICT_TRUE (buffer && buflen &&
+ (*buflen >= sizeof (*ep)) && ep->ip))
+ {
+ ep->is_ip4 = session->transport.is_ip4;
+ ep->port = session->transport.rmt_port;
+ if (session->transport.is_ip4)
+ clib_memcpy_fast (ep->ip, &session->transport.rmt_ip.ip4,
+ sizeof (ip4_address_t));
+ else
+ clib_memcpy_fast (ep->ip, &session->transport.rmt_ip.ip6,
+ sizeof (ip6_address_t));
+ *buflen = sizeof (*ep);
+ VDBG (1, "VCL<%d>: VPPCOM_ATTR_GET_PEER_ADDR: sid %u, is_ip4 = %u, "
+ "addr = %U, port %u", getpid (),
+ session_handle, ep->is_ip4, format_ip46_address,
+ &session->transport.rmt_ip,
+ ep->is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
+ clib_net_to_host_u16 (ep->port));
+ }
+ else
+ rv = VPPCOM_EINVAL;
+ break;
+
+ case VPPCOM_ATTR_GET_LCL_ADDR:
+ if (PREDICT_TRUE (buffer && buflen &&
+ (*buflen >= sizeof (*ep)) && ep->ip))
+ {
+ ep->is_ip4 = session->transport.is_ip4;
+ ep->port = session->transport.lcl_port;
+ if (session->transport.is_ip4)
+ clib_memcpy_fast (ep->ip, &session->transport.lcl_ip.ip4,
+ sizeof (ip4_address_t));
+ else
+ clib_memcpy_fast (ep->ip, &session->transport.lcl_ip.ip6,
+ sizeof (ip6_address_t));
+ *buflen = sizeof (*ep);
+ VDBG (1, "VCL<%d>: VPPCOM_ATTR_GET_LCL_ADDR: sid %u, is_ip4 = %u,"
+ " addr = %U port %d", getpid (),
+ session_handle, ep->is_ip4, format_ip46_address,
+ &session->transport.lcl_ip,
+ ep->is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
+ clib_net_to_host_u16 (ep->port));
+ }
+ else
+ rv = VPPCOM_EINVAL;
+ break;
+
+ case VPPCOM_ATTR_GET_LIBC_EPFD:
+ rv = session->libc_epfd;
+ VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_LIBC_EPFD: libc_epfd %d",
+ getpid (), rv);
+ break;
+
+ case VPPCOM_ATTR_SET_LIBC_EPFD:
+ if (PREDICT_TRUE (buffer && buflen &&
+ (*buflen == sizeof (session->libc_epfd))))
+ {
+ session->libc_epfd = *(int *) buffer;
+ *buflen = sizeof (session->libc_epfd);
+
+ VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_LIBC_EPFD: libc_epfd %d, "
+ "buflen %d", getpid (), session->libc_epfd, *buflen);
+ }
+ else
+ rv = VPPCOM_EINVAL;
+ break;
+
+ case VPPCOM_ATTR_GET_PROTOCOL:
+ if (buffer && buflen && (*buflen >= sizeof (int)))
+ {
+ *(int *) buffer = session->session_type;
+ *buflen = sizeof (int);
+
+ VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_PROTOCOL: %d (%s), buflen %d",
+ getpid (), *(int *) buffer, *(int *) buffer ? "UDP" : "TCP",
+ *buflen);
+ }
+ else
+ rv = VPPCOM_EINVAL;
+ break;
+
+ case VPPCOM_ATTR_GET_LISTEN:
+ if (buffer && buflen && (*buflen >= sizeof (int)))
+ {
+ *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
+ VCL_SESS_ATTR_LISTEN);
+ *buflen = sizeof (int);
+
+ VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_LISTEN: %d, buflen %d",
+ getpid (), *(int *) buffer, *buflen);
+ }
+ else
+ rv = VPPCOM_EINVAL;
+ break;
+
+ case VPPCOM_ATTR_GET_ERROR:
+ if (buffer && buflen && (*buflen >= sizeof (int)))
+ {
+ *(int *) buffer = 0;
+ *buflen = sizeof (int);
+
+ VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_ERROR: %d, buflen %d, #VPP-TBD#",
+ getpid (), *(int *) buffer, *buflen);
+ }
+ else
+ rv = VPPCOM_EINVAL;
+ break;
+
+ 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 ? session->tx_fifo->nitems :
+ vcm->cfg.tx_fifo_size);
+ *buflen = sizeof (u32);
+
+ VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_TX_FIFO_LEN: %u (0x%x), "
+ "buflen %d, #VPP-TBD#", getpid (),
+ *(size_t *) buffer, *(size_t *) buffer, *buflen);
+ }
+ else
+ rv = VPPCOM_EINVAL;
+ break;
+
+ case VPPCOM_ATTR_SET_TX_FIFO_LEN:
+ if (buffer && buflen && (*buflen == sizeof (u32)))
+ {
+ /* VPP-TBD */
+ session->sndbuf_size = *(u32 *) buffer;
+ VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_TX_FIFO_LEN: %u (0x%x), "
+ "buflen %d, #VPP-TBD#", getpid (),
+ session->sndbuf_size, session->sndbuf_size, *buflen);
+ }
+ else
+ rv = VPPCOM_EINVAL;
+ break;
+
+ case VPPCOM_ATTR_GET_RX_FIFO_LEN:
+ if (buffer && buflen && (*buflen >= sizeof (u32)))
+ {
+
+ /* VPP-TBD */
+ *(size_t *) buffer = (session->rcvbuf_size ? session->rcvbuf_size :
+ session->rx_fifo ? session->rx_fifo->nitems :
+ vcm->cfg.rx_fifo_size);
+ *buflen = sizeof (u32);
+
+ VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_RX_FIFO_LEN: %u (0x%x), "
+ "buflen %d, #VPP-TBD#", getpid (),
+ *(size_t *) buffer, *(size_t *) buffer, *buflen);
+ }
+ else
+ rv = VPPCOM_EINVAL;
+ break;
+
+ case VPPCOM_ATTR_SET_RX_FIFO_LEN:
+ if (buffer && buflen && (*buflen == sizeof (u32)))
+ {
+ /* VPP-TBD */
+ session->rcvbuf_size = *(u32 *) buffer;
+ VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_RX_FIFO_LEN: %u (0x%x), "
+ "buflen %d, #VPP-TBD#", getpid (),
+ session->sndbuf_size, session->sndbuf_size, *buflen);
+ }
+ else
+ rv = VPPCOM_EINVAL;
+ break;
+
+ case VPPCOM_ATTR_GET_REUSEADDR:
+ if (buffer && buflen && (*buflen >= sizeof (int)))
+ {
+ /* VPP-TBD */
+ *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
+ VCL_SESS_ATTR_REUSEADDR);
+ *buflen = sizeof (int);
+
+ VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_REUSEADDR: %d, "
+ "buflen %d, #VPP-TBD#", getpid (), *(int *) buffer, *buflen);
+ }
+ else
+ rv = VPPCOM_EINVAL;
+ break;
+
+ case VPPCOM_ATTR_SET_REUSEADDR:
+ if (buffer && buflen && (*buflen == sizeof (int)) &&
+ !VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_LISTEN))
+ {
+ /* VPP-TBD */
+ if (*(int *) buffer)
+ VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_REUSEADDR);
+ else
+ VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_REUSEADDR);
+
+ VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_REUSEADDR: %d, buflen %d,"
+ " #VPP-TBD#", getpid (),
+ VCL_SESS_ATTR_TEST (session->attr,
+ VCL_SESS_ATTR_REUSEADDR), *buflen);
+ }
+ else
+ rv = VPPCOM_EINVAL;
+ break;
+
+ case VPPCOM_ATTR_GET_REUSEPORT:
+ if (buffer && buflen && (*buflen >= sizeof (int)))
+ {
+ /* VPP-TBD */
+ *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
+ VCL_SESS_ATTR_REUSEPORT);
+ *buflen = sizeof (int);
+
+ VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_REUSEPORT: %d, buflen %d,"
+ " #VPP-TBD#", getpid (), *(int *) buffer, *buflen);
+ }
+ else
+ rv = VPPCOM_EINVAL;
+ break;
+
+ case VPPCOM_ATTR_SET_REUSEPORT:
+ if (buffer && buflen && (*buflen == sizeof (int)) &&
+ !VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_LISTEN))
+ {
+ /* VPP-TBD */
+ if (*(int *) buffer)
+ VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_REUSEPORT);
+ else
+ VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_REUSEPORT);
+
+ VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_REUSEPORT: %d, buflen %d,"
+ " #VPP-TBD#", getpid (),
+ VCL_SESS_ATTR_TEST (session->attr,
+ VCL_SESS_ATTR_REUSEPORT), *buflen);
+ }
+ else
+ rv = VPPCOM_EINVAL;
+ break;
+
+ case VPPCOM_ATTR_GET_BROADCAST:
+ if (buffer && buflen && (*buflen >= sizeof (int)))
+ {
+ /* VPP-TBD */
+ *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
+ VCL_SESS_ATTR_BROADCAST);
+ *buflen = sizeof (int);
+
+ VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_BROADCAST: %d, buflen %d,"
+ " #VPP-TBD#", getpid (), *(int *) buffer, *buflen);
+ }
+ else
+ rv = VPPCOM_EINVAL;
+ break;
+
+ case VPPCOM_ATTR_SET_BROADCAST:
+ if (buffer && buflen && (*buflen == sizeof (int)))
+ {
+ /* VPP-TBD */
+ if (*(int *) buffer)
+ VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_BROADCAST);
+ else
+ VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_BROADCAST);
+
+ VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_BROADCAST: %d, buflen %d, "
+ "#VPP-TBD#", getpid (),
+ VCL_SESS_ATTR_TEST (session->attr,
+ VCL_SESS_ATTR_BROADCAST), *buflen);
+ }
+ else
+ rv = VPPCOM_EINVAL;
+ break;
+
+ case VPPCOM_ATTR_GET_V6ONLY:
+ if (buffer && buflen && (*buflen >= sizeof (int)))
+ {
+ /* VPP-TBD */
+ *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
+ VCL_SESS_ATTR_V6ONLY);
+ *buflen = sizeof (int);
+
+ VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_V6ONLY: %d, buflen %d, "
+ "#VPP-TBD#", getpid (), *(int *) buffer, *buflen);
+ }
+ else
+ rv = VPPCOM_EINVAL;
+ break;
+
+ case VPPCOM_ATTR_SET_V6ONLY:
+ if (buffer && buflen && (*buflen == sizeof (int)))
+ {
+ /* VPP-TBD */
+ if (*(int *) buffer)
+ VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_V6ONLY);
+ else
+ VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_V6ONLY);
+
+ VDBG (2, "VCL<%d>: VPPCOM_ATTR_SET_V6ONLY: %d, buflen %d, "
+ "#VPP-TBD#", getpid (),
+ VCL_SESS_ATTR_TEST (session->attr,
+ VCL_SESS_ATTR_V6ONLY), *buflen);
+ }
+ else
+ rv = VPPCOM_EINVAL;
+ break;
+
+ case VPPCOM_ATTR_GET_KEEPALIVE:
+ if (buffer && buflen && (*buflen >= sizeof (int)))
+ {
+ /* VPP-TBD */
+ *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr,
+ VCL_SESS_ATTR_KEEPALIVE);
+ *buflen = sizeof (int);
+
+ VDBG (2, "VCL<%d>: VPPCOM_ATTR_GET_KEEPALIVE: %d, buflen %d, "
+ "#VPP-TBD#", getpid (), *(int *) buffer, *buflen);
+ }
+ else
+ rv = VPPCOM_EINVAL;
+ break;
+
+ case VPPCOM_ATTR_SET_KEEPALIVE:
+ if (buffer && buflen && (*buflen == sizeof (int)))