X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Furi%2Fvppcom.c;h=8d254cc49241b77fa6f2e163e215dee1777d7863;hb=7876d39f1453fc4db68cd3c43a2d7fe062e7f832;hp=783419bc238fbad0a669302139057a6a31ac37ee;hpb=cea194d8f973a2f2b5ef72d212533057174cc70a;p=vpp.git diff --git a/src/uri/vppcom.c b/src/uri/vppcom.c index 783419bc238..8d254cc4924 100644 --- a/src/uri/vppcom.c +++ b/src/uri/vppcom.c @@ -80,6 +80,12 @@ typedef struct u32 et_mask; } vppcom_epoll_t; +typedef struct +{ + u8 is_ip4; + ip46_address_t ip46; +} vppcom_ip46_t; + typedef struct { volatile session_state_t state; @@ -101,8 +107,8 @@ typedef struct u32 wait_cont_idx; vppcom_epoll_t vep; u32 vrf; - u8 is_ip4; - u8 ip[16]; + vppcom_ip46_t lcl_addr; + vppcom_ip46_t peer_addr; u16 port; u8 proto; u64 client_queue_address; @@ -130,7 +136,6 @@ typedef struct vppcom_main_t_ u8 init; u32 *client_session_index_fifo; volatile u32 bind_session_index; - u32 tx_event_id; int main_cpu; /* vpe input queue */ @@ -799,8 +804,8 @@ vppcom_send_connect_sock (session_t * session, u32 session_index) vcm->my_pid, session_index, session_index); cmp->vrf = session->vrf; - cmp->is_ip4 = session->is_ip4; - clib_memcpy (cmp->ip, session->ip, sizeof (cmp->ip)); + cmp->is_ip4 = session->peer_addr.is_ip4; + clib_memcpy (cmp->ip, &session->peer_addr.ip46, sizeof (cmp->ip)); cmp->port = session->port; cmp->proto = session->proto; clib_memcpy (cmp->options, session->options, sizeof (cmp->options)); @@ -1009,9 +1014,10 @@ vl_api_accept_session_t_handler (vl_api_accept_session_t * mp) session->state = STATE_ACCEPT; session->is_cut_thru = 0; session->is_server = 1; - session->port = ntohs (mp->port); - session->is_ip4 = mp->is_ip4; - clib_memcpy (session->ip, mp->ip, sizeof (session->ip)); + session->port = mp->port; + session->peer_addr.is_ip4 = mp->is_ip4; + clib_memcpy (&session->peer_addr.ip46, mp->ip, + sizeof (session->peer_addr.ip46)); /* Add it to lookup table */ hash_set (vcm->session_index_by_vpp_handles, mp->handle, session_index); @@ -1126,8 +1132,10 @@ vl_api_connect_sock_t_handler (vl_api_connect_sock_t * mp) session->client_queue_address = mp->client_queue_address; session->is_cut_thru = 1; session->is_server = 1; - session->is_ip4 = mp->is_ip4; session->port = mp->port; + session->peer_addr.is_ip4 = mp->is_ip4; + clib_memcpy (&session->peer_addr.ip46, mp->ip, + sizeof (session->peer_addr.ip46)); { void *oldheap; ssvm_shared_header_t *sh = seg->ssvm.sh; @@ -1141,7 +1149,6 @@ vl_api_connect_sock_t_handler (vl_api_connect_sock_t * mp) ssvm_pop_heap (oldheap); ssvm_unlock_non_recursive (sh); } - clib_memcpy (session->ip, mp->ip, sizeof (session->ip)); session->state = STATE_ACCEPT; if (VPPCOM_DEBUG > 1) @@ -1189,8 +1196,8 @@ vppcom_send_bind_sock (session_t * session) bmp->client_index = vcm->my_client_index; bmp->context = htonl (0xfeedface); bmp->vrf = session->vrf; - bmp->is_ip4 = session->is_ip4; - clib_memcpy (bmp->ip, session->ip, sizeof (bmp->ip)); + bmp->is_ip4 = session->lcl_addr.is_ip4; + clib_memcpy (bmp->ip, &session->lcl_addr.ip46, sizeof (bmp->ip)); bmp->port = session->port; bmp->proto = session->proto; clib_memcpy (bmp->options, session->options, sizeof (bmp->options)); @@ -1758,7 +1765,7 @@ vppcom_app_create (char *app_name) rv = vppcom_connect_to_vpp (app_name); if (rv) { - clib_warning ("[%s] couldn't connect to VPP.", vcm->my_pid); + clib_warning ("[%d] couldn't connect to VPP.", vcm->my_pid); return rv; } @@ -1833,7 +1840,7 @@ vppcom_session_create (u32 vrf, u8 proto, u8 is_nonblocking) session->vrf = vrf; session->proto = proto; session->state = STATE_START; - session->is_nonblocking = is_nonblocking; + session->is_nonblocking = is_nonblocking ? 1 : 0; clib_spinlock_unlock (&vcm->sessions_lockp); if (VPPCOM_DEBUG > 0) @@ -1917,19 +1924,17 @@ vppcom_session_close (uint32_t session_index) clib_spinlock_unlock (&vcm->sessions_lockp); } - if (session->is_cut_thru) + if (session->is_cut_thru && session->is_server && + (session->state == STATE_ACCEPT)) { - if (session->is_server) - { - rv = vppcom_session_unbind_cut_thru (session); - if ((VPPCOM_DEBUG > 0) && (rv < 0)) - clib_warning ("[%d] unbind cut-thru (session %d) failed, " - "rv = %s (%d)", - vcm->my_pid, session_index, - vppcom_retval_str (rv), rv); - } + rv = vppcom_session_unbind_cut_thru (session); + if ((VPPCOM_DEBUG > 0) && (rv < 0)) + clib_warning ("[%d] unbind cut-thru (session %d) failed, " + "rv = %s (%d)", + vcm->my_pid, session_index, + vppcom_retval_str (rv), rv); } - else if (session->is_server) + else if (session->is_server && session->is_listen) { rv = vppcom_session_unbind (session_index); if ((VPPCOM_DEBUG > 0) && (rv < 0)) @@ -1937,7 +1942,7 @@ vppcom_session_close (uint32_t session_index) vcm->my_pid, session_index, vppcom_retval_str (rv), rv); } - else + else if (session->state == STATE_CONNECT) { rv = vppcom_session_disconnect (session_index); if ((VPPCOM_DEBUG > 0) && (rv < 0)) @@ -1957,7 +1962,6 @@ vppcom_session_bind (uint32_t session_index, vppcom_endpt_t * ep) vppcom_main_t *vcm = &vppcom_main; session_t *session = 0; int rv; - ip46_address_t *ip46; if (!ep || !ep->ip) return VPPCOM_EINVAL; @@ -1973,14 +1977,21 @@ vppcom_session_bind (uint32_t session_index, vppcom_endpt_t * ep) return rv; } + if (session->is_vep) + { + clib_spinlock_unlock (&vcm->sessions_lockp); + if (VPPCOM_DEBUG > 0) + clib_warning ("[%d] invalid session, sid (%u) is an epoll session!", + vcm->my_pid, session_index); + return VPPCOM_EBADFD; + } + if (VPPCOM_DEBUG > 0) clib_warning ("[%d] sid %d", vcm->my_pid, session_index); session->vrf = ep->vrf; - session->is_ip4 = ep->is_ip4; - memset (session->ip, 0, sizeof (session->ip)); - ip46 = (ip46_address_t *) session->ip; - *ip46 = to_ip46 (!ep->is_ip4, ep->ip); + session->lcl_addr.is_ip4 = ep->is_ip4; + session->lcl_addr.ip46 = to_ip46 (!ep->is_ip4, ep->ip); session->port = ep->port; clib_spinlock_unlock (&vcm->sessions_lockp); @@ -2005,6 +2016,15 @@ vppcom_session_listen (uint32_t listen_session_index, uint32_t q_len) return rv; } + if (listen_session->is_vep) + { + clib_spinlock_unlock (&vcm->sessions_lockp); + if (VPPCOM_DEBUG > 0) + clib_warning ("[%d] invalid session, sid (%u) is an epoll session!", + vcm->my_pid, listen_session_index); + return VPPCOM_EBADFD; + } + if (VPPCOM_DEBUG > 0) clib_warning ("[%d] sid %d", vcm->my_pid, listen_session_index); @@ -2063,6 +2083,15 @@ vppcom_session_accept (uint32_t listen_session_index, vppcom_endpt_t * ep, return rv; } + if (listen_session->is_vep) + { + clib_spinlock_unlock (&vcm->sessions_lockp); + if (VPPCOM_DEBUG > 0) + clib_warning ("[%d] invalid session, sid (%u) is an epoll session!", + vcm->my_pid, listen_session_index); + return VPPCOM_EBADFD; + } + if (listen_session->state != STATE_LISTEN) { clib_spinlock_unlock (&vcm->sessions_lockp); @@ -2102,7 +2131,8 @@ vppcom_session_accept (uint32_t listen_session_index, vppcom_endpt_t * ep, clib_fifo_sub1 (vcm->client_session_index_fifo, client_session_index); rv = vppcom_session_at_index (client_session_index, &client_session); ASSERT (rv == VPPCOM_OK); - ASSERT (client_session->is_ip4 == listen_session->is_ip4); + ASSERT (client_session->peer_addr.is_ip4 == + listen_session->lcl_addr.is_ip4); if (VPPCOM_DEBUG > 0) clib_warning ("[%d] Got a request: client sid %d", vcm->my_pid, @@ -2110,12 +2140,14 @@ vppcom_session_accept (uint32_t listen_session_index, vppcom_endpt_t * ep, ep->vrf = client_session->vrf; ep->is_cut_thru = client_session->is_cut_thru; - ep->is_ip4 = client_session->is_ip4; + ep->is_ip4 = client_session->peer_addr.is_ip4; ep->port = client_session->port; - if (client_session->is_ip4) - clib_memcpy (ep->ip, client_session->ip, sizeof (ip4_address_t)); + if (client_session->peer_addr.is_ip4) + clib_memcpy (ep->ip, &client_session->peer_addr.ip46.ip4, + sizeof (ip4_address_t)); else - clib_memcpy (ep->ip, client_session->ip, sizeof (ip6_address_t)); + clib_memcpy (ep->ip, &client_session->peer_addr.ip46.ip6, + sizeof (ip6_address_t)); clib_spinlock_unlock (&vcm->sessions_lockp); return (int) client_session_index; } @@ -2126,7 +2158,6 @@ vppcom_session_connect (uint32_t session_index, vppcom_endpt_t * server_ep) vppcom_main_t *vcm = &vppcom_main; session_t *session = 0; int rv; - ip46_address_t *ip46; clib_spinlock_lock (&vcm->sessions_lockp); rv = vppcom_session_at_index (session_index, &session); @@ -2139,6 +2170,15 @@ vppcom_session_connect (uint32_t session_index, vppcom_endpt_t * server_ep) return rv; } + if (session->is_vep) + { + clib_spinlock_unlock (&vcm->sessions_lockp); + if (VPPCOM_DEBUG > 0) + clib_warning ("[%d] invalid session, sid (%u) is an epoll session!", + vcm->my_pid, session_index); + return VPPCOM_EBADFD; + } + if (session->state == STATE_CONNECT) { clib_spinlock_unlock (&vcm->sessions_lockp); @@ -2149,19 +2189,19 @@ vppcom_session_connect (uint32_t session_index, vppcom_endpt_t * server_ep) } session->vrf = server_ep->vrf; - session->is_ip4 = server_ep->is_ip4; - memset (session->ip, 0, sizeof (session->ip)); - ip46 = (ip46_address_t *) session->ip; - *ip46 = to_ip46 (!server_ep->is_ip4, server_ep->ip); + session->peer_addr.is_ip4 = server_ep->is_ip4; + session->peer_addr.ip46 = to_ip46 (!server_ep->is_ip4, server_ep->ip); session->port = server_ep->port; if (VPPCOM_DEBUG > 0) { u8 *ip_str = format (0, "%U", format_ip46_address, - &session->ip, session->is_ip4); - clib_warning ("[%d] connect sid %d to %s server port %d", + &session->peer_addr.ip46, + session->peer_addr.is_ip4); + clib_warning ("[%d] connect sid %d to %s server port %d proto %s", vcm->my_pid, session_index, ip_str, - clib_net_to_host_u16 (session->port)); + clib_net_to_host_u16 (session->port), + session->proto ? "UDP" : "TCP"); vec_free (ip_str); } @@ -2176,6 +2216,9 @@ vppcom_session_connect (uint32_t session_index, vppcom_endpt_t * server_ep) vcm->my_pid, vppcom_retval_str (rv), rv); return rv; } + if (VPPCOM_DEBUG > 0) + clib_warning ("[%d] sid %d connected!", vcm->my_pid, session_index); + return VPPCOM_OK; } @@ -2188,6 +2231,7 @@ vppcom_session_read (uint32_t session_index, void *buf, int n) int n_read = 0; int rv; char *fifo_str; + u32 poll_et; ASSERT (buf); @@ -2202,6 +2246,15 @@ vppcom_session_read (uint32_t session_index, void *buf, int n) return rv; } + if (session->is_vep) + { + clib_spinlock_unlock (&vcm->sessions_lockp); + if (VPPCOM_DEBUG > 0) + clib_warning ("[%d] invalid session, sid (%u) is an epoll session!", + vcm->my_pid, session_index); + return VPPCOM_EBADFD; + } + if (session->state == STATE_DISCONNECT) { clib_spinlock_unlock (&vcm->sessions_lockp); @@ -2215,6 +2268,8 @@ vppcom_session_read (uint32_t session_index, void *buf, int n) session->server_rx_fifo : session->server_tx_fifo); fifo_str = ((!session->is_cut_thru || session->is_server) ? "server_rx_fifo" : "server_tx_fifo"); + poll_et = EPOLLET & session->vep.ev.events; + clib_spinlock_unlock (&vcm->sessions_lockp); do { @@ -2222,10 +2277,12 @@ vppcom_session_read (uint32_t session_index, void *buf, int n) } while (!session->is_nonblocking && (n_read <= 0)); - if (n_read <= 0) - session->vep.et_mask |= EPOLLIN; - - clib_spinlock_unlock (&vcm->sessions_lockp); + if (poll_et && (n_read <= 0)) + { + clib_spinlock_lock (&vcm->sessions_lockp); + session->vep.et_mask |= EPOLLIN; + clib_spinlock_unlock (&vcm->sessions_lockp); + } if ((VPPCOM_DEBUG > 2) && (n_read > 0)) clib_warning ("[%d] sid %d, read %d bytes from %s (%p)", vcm->my_pid, @@ -2242,6 +2299,15 @@ vppcom_session_read_ready (session_t * session, u32 session_index) int ready = 0; /* Assumes caller has acquired spinlock: vcm->sessions_lockp */ + if (session->is_vep) + { + clib_spinlock_unlock (&vcm->sessions_lockp); + if (VPPCOM_DEBUG > 0) + clib_warning ("[%d] invalid session, sid (%u) is an epoll session!", + vcm->my_pid, session_index); + return VPPCOM_EBADFD; + } + if (session->state == STATE_DISCONNECT) { if (VPPCOM_DEBUG > 0) @@ -2265,7 +2331,7 @@ vppcom_session_read_ready (session_t * session, u32 session_index) session_index, session->is_server ? "server_rx_fifo" : "server_tx_fifo", rx_fifo, ready); - if (ready == 0) + if ((session->vep.ev.events & EPOLLET) && (ready == 0)) session->vep.et_mask |= EPOLLIN; return ready; @@ -2281,6 +2347,7 @@ vppcom_session_write (uint32_t session_index, void *buf, int n) session_fifo_event_t evt; int rv, n_write; char *fifo_str; + u32 poll_et; ASSERT (buf); @@ -2295,6 +2362,15 @@ vppcom_session_write (uint32_t session_index, void *buf, int n) return rv; } + if (session->is_vep) + { + clib_spinlock_unlock (&vcm->sessions_lockp); + if (VPPCOM_DEBUG > 0) + clib_warning ("[%d] invalid session, sid (%u) is an epoll session!", + vcm->my_pid, session_index); + return VPPCOM_EBADFD; + } + if (session->state == STATE_DISCONNECT) { clib_spinlock_unlock (&vcm->sessions_lockp); @@ -2308,6 +2384,10 @@ vppcom_session_write (uint32_t session_index, void *buf, int n) session->server_tx_fifo : session->server_rx_fifo); fifo_str = ((!session->is_cut_thru || session->is_server) ? "server_tx_fifo" : "server_rx_fifo"); + q = session->vpp_event_queue; + poll_et = EPOLLET & session->vep.ev.events; + clib_spinlock_unlock (&vcm->sessions_lockp); + do { n_write = svm_fifo_enqueue_nowait (tx_fifo, n, buf); @@ -2322,32 +2402,37 @@ vppcom_session_write (uint32_t session_index, void *buf, int n) /* Fabricate TX event, send to vpp */ evt.fifo = tx_fifo; evt.event_type = FIFO_EVENT_APP_TX; - evt.event_id = vcm->tx_event_id++; rval = vppcom_session_at_index (session_index, &session); if (PREDICT_FALSE (rval)) { - clib_spinlock_unlock (&vcm->sessions_lockp); if (VPPCOM_DEBUG > 1) clib_warning ("[%d] invalid session, sid (%u) has been closed!", vcm->my_pid, session_index); return rval; } - q = session->vpp_event_queue; ASSERT (q); unix_shared_memory_queue_add (q, (u8 *) & evt, 0 /* do wait for mutex */ ); } - if (n_write <= 0) - session->vep.et_mask |= EPOLLOUT; - - clib_spinlock_unlock (&vcm->sessions_lockp); + if (poll_et && (n_write <= 0)) + { + clib_spinlock_lock (&vcm->sessions_lockp); + session->vep.et_mask |= EPOLLOUT; + clib_spinlock_unlock (&vcm->sessions_lockp); + } if (VPPCOM_DEBUG > 2) - clib_warning ("[%d] sid %d, wrote %d bytes to %s (%p)", vcm->my_pid, - session_index, n_write, fifo_str, tx_fifo); - return n_write; + { + if (n_write == -2) + clib_warning ("[%d] sid %d, FIFO-FULL %s (%p)", vcm->my_pid, + session_index, fifo_str, tx_fifo); + else + clib_warning ("[%d] sid %d, wrote %d bytes to %s (%p)", vcm->my_pid, + session_index, n_write, fifo_str, tx_fifo); + } + return (n_write < 0) ? VPPCOM_EAGAIN : n_write; } static inline int @@ -2359,6 +2444,15 @@ vppcom_session_write_ready (session_t * session, u32 session_index) int ready; /* Assumes caller has acquired spinlock: vcm->sessions_lockp */ + if (session->is_vep) + { + clib_spinlock_unlock (&vcm->sessions_lockp); + if (VPPCOM_DEBUG > 0) + clib_warning ("[%d] invalid session, sid (%u) is an epoll session!", + vcm->my_pid, session_index); + return VPPCOM_EBADFD; + } + if (session->state == STATE_DISCONNECT) { if (VPPCOM_DEBUG > 0) @@ -2377,7 +2471,7 @@ vppcom_session_write_ready (session_t * session, u32 session_index) if (VPPCOM_DEBUG > 3) clib_warning ("[%d] sid %d, peek %s (%p), ready = %d", vcm->my_pid, session_index, fifo_str, tx_fifo, ready); - if (ready == 0) + if ((session->vep.ev.events & EPOLLET) && (ready == 0)) session->vep.et_mask |= EPOLLOUT; return ready; @@ -2397,19 +2491,19 @@ vppcom_select (unsigned long n_bits, unsigned long *read_map, ASSERT (sizeof (clib_bitmap_t) == sizeof (long int)); - if (read_map) + if (n_bits && read_map) { clib_bitmap_validate (vcm->rd_bitmap, minbits); clib_memcpy (vcm->rd_bitmap, read_map, vec_len (vcm->rd_bitmap)); memset (read_map, 0, vec_len (vcm->rd_bitmap)); } - if (write_map) + if (n_bits && write_map) { clib_bitmap_validate (vcm->wr_bitmap, minbits); clib_memcpy (vcm->wr_bitmap, write_map, vec_len (vcm->wr_bitmap)); memset (write_map, 0, vec_len (vcm->wr_bitmap)); } - if (except_map) + if (n_bits && except_map) { clib_bitmap_validate (vcm->ex_bitmap, minbits); clib_memcpy (vcm->ex_bitmap, except_map, vec_len (vcm->ex_bitmap)); @@ -3022,6 +3116,126 @@ done: return (rv != VPPCOM_OK) ? rv : num_ev; } +int +vppcom_session_attr (uint32_t session_index, uint32_t op, + void *buffer, uint32_t * buflen) +{ + vppcom_main_t *vcm = &vppcom_main; + session_t *session; + int rv = VPPCOM_OK; + u32 *flags = buffer; + vppcom_endpt_t *ep = buffer; + + VCL_LOCK_AND_GET_SESSION (session_index, &session); + switch (op) + { + case VPPCOM_ATTR_GET_NREAD: + rv = vppcom_session_read_ready (session, session_index); + if (VPPCOM_DEBUG > 0) + clib_warning ("VPPCOM_ATTR_GET_NREAD: nread = %d", rv); + + break; + + case VPPCOM_ATTR_PEEK_NREAD: + /* TBD */ + break; + + case VPPCOM_ATTR_GET_FLAGS: + if (buffer && buflen && (*buflen >= sizeof (*flags))) + { + *flags = O_RDWR | ((session->is_nonblocking) ? O_NONBLOCK : 0); + *buflen = sizeof (*flags); + if (VPPCOM_DEBUG > 0) + clib_warning ("VPPCOM_ATTR_GET_FLAGS: flags = 0x%08x, " + "is_nonblocking = %u", *flags, + session->is_nonblocking); + } + else + rv = VPPCOM_EINVAL; + break; + + case VPPCOM_ATTR_SET_FLAGS: + if (buffer && buflen && (*buflen >= sizeof (*flags))) + { + session->is_nonblocking = (*flags & O_NONBLOCK) ? 1 : 0; + if (VPPCOM_DEBUG > 0) + clib_warning ("VPPCOM_ATTR_SET_FLAGS: flags = 0x%08x, " + "is_nonblocking = %u", *flags, + session->is_nonblocking); + } + else + rv = VPPCOM_EINVAL; + break; + + case VPPCOM_ATTR_GET_PEER_ADDR: + if (buffer && buflen && (*buflen >= sizeof (*ep))) + { + ep->vrf = session->vrf; + ep->is_ip4 = session->peer_addr.is_ip4; + ep->port = session->port; + if (session->peer_addr.is_ip4) + clib_memcpy (ep->ip, &session->peer_addr.ip46.ip4, + sizeof (ip4_address_t)); + else + clib_memcpy (ep->ip, &session->peer_addr.ip46.ip6, + sizeof (ip6_address_t)); + *buflen = sizeof (*ep); + if (VPPCOM_DEBUG > 0) + clib_warning ("VPPCOM_ATTR_GET_PEER_ADDR: is_ip4 = %u, " + "addr = %U", ep->is_ip4, format_ip46_address, + &session->peer_addr.ip46, ep->is_ip4); + } + else + rv = VPPCOM_EINVAL; + break; + + case VPPCOM_ATTR_GET_LCL_ADDR: + if (buffer && buflen && (*buflen >= sizeof (*ep))) + { + ep->vrf = session->vrf; + ep->is_ip4 = session->lcl_addr.is_ip4; + ep->port = session->port; + if (session->lcl_addr.is_ip4) + clib_memcpy (ep->ip, &session->lcl_addr.ip46.ip4, + sizeof (ip4_address_t)); + else + clib_memcpy (ep->ip, &session->lcl_addr.ip46.ip6, + sizeof (ip6_address_t)); + *buflen = sizeof (*ep); + if (VPPCOM_DEBUG > 0) + if (VPPCOM_DEBUG > 0) + clib_warning ("VPPCOM_ATTR_GET_LCL_ADDR: is_ip4 = %u, " + "addr = %U", ep->is_ip4, format_ip46_address, + &session->lcl_addr.ip46, ep->is_ip4); + } + else + rv = VPPCOM_EINVAL; + break; + + case VPPCOM_ATTR_SET_REUSEADDR: + break; + + case VPPCOM_ATTR_SET_BROADCAST: + break; + + case VPPCOM_ATTR_SET_V6ONLY: + break; + + case VPPCOM_ATTR_SET_KEEPALIVE: + break; + + case VPPCOM_ATTR_SET_TCP_KEEPIDLE: + break; + + case VPPCOM_ATTR_SET_TCP_KEEPINTVL: + break; + } + +done: + clib_spinlock_unlock (&vcm->sessions_lockp); + return rv; +} + /* * fd.io coding-style-patch-verification: ON *