X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fsession%2Fsession_node.c;h=6011704c8d07e635cf617104bb18ca1414ecc541;hb=ac3c8dcb0;hp=1908a58f08f4b3bb012bef5f0dd316e0f845e407;hpb=0654242d1ef51566f0d58445a16053cf376e5a6e;p=vpp.git diff --git a/src/vnet/session/session_node.c b/src/vnet/session/session_node.c index 1908a58f08f..6011704c8d0 100644 --- a/src/vnet/session/session_node.c +++ b/src/vnet/session/session_node.c @@ -139,7 +139,7 @@ session_mq_listen_handler (session_worker_t *wrk, session_evt_elt_t *elt) a->sep_ext.ext_cfg = session_mq_get_ext_config (app, mp->ext_config); if ((rv = vnet_listen (a))) - clib_warning ("listen returned: %U", format_session_error, rv); + session_worker_stat_error_inc (wrk, rv, 1); app_wrk = application_get_worker (app, mp->wrk_index); mq_send_session_bound_cb (app_wrk->wrk_index, mp->context, a->handle, rv); @@ -178,6 +178,7 @@ session_mq_connect_one (session_connect_msg_t *mp) { vnet_connect_args_t _a, *a = &_a; app_worker_t *app_wrk; + session_worker_t *wrk; application_t *app; int rv; @@ -211,7 +212,8 @@ session_mq_connect_one (session_connect_msg_t *mp) if ((rv = vnet_connect (a))) { - clib_warning ("connect returned: %U", format_session_error, rv); + wrk = session_main_get_worker (vlib_get_thread_index ()); + session_worker_stat_error_inc (wrk, rv, 1); app_wrk = application_get_worker (app, mp->wrk_index); mq_send_session_connected_cb (app_wrk->wrk_index, mp->context, 0, rv); } @@ -224,23 +226,20 @@ static void session_mq_handle_connects_rpc (void *arg) { u32 max_connects = 32, n_connects = 0; - vlib_main_t *vm = vlib_get_main (); session_evt_elt_t *he, *elt, *next; - session_worker_t *fwrk, *wrk; + session_worker_t *fwrk; - ASSERT (vlib_get_thread_index () == 0); + ASSERT (session_vlib_thread_is_cl_thread ()); /* Pending connects on linked list pertaining to first worker */ - fwrk = session_main_get_worker (1); + fwrk = session_main_get_worker (transport_cl_thread ()); if (!fwrk->n_pending_connects) - goto update_state; - - vlib_worker_thread_barrier_sync (vm); + return; he = clib_llist_elt (fwrk->event_elts, fwrk->pending_connects); elt = clib_llist_next (fwrk->event_elts, evt_list, he); - /* Avoid holding the barrier for too long */ + /* Avoid holding the worker for too long */ while (n_connects < max_connects && elt != he) { next = clib_llist_next (fwrk->event_elts, evt_list, elt); @@ -254,45 +253,10 @@ session_mq_handle_connects_rpc (void *arg) /* Decrement with worker barrier */ fwrk->n_pending_connects -= n_connects; - - vlib_worker_thread_barrier_release (vm); - -update_state: - - /* Switch worker to poll mode if it was in interrupt mode and had work or - * back to interrupt if threshold of loops without a connect is passed. - * While in poll mode, reprogram connects rpc */ - wrk = session_main_get_worker (0); - if (wrk->state != SESSION_WRK_POLLING) + if (fwrk->n_pending_connects > 0) { - if (n_connects) - { - session_wrk_set_state (wrk, SESSION_WRK_POLLING); - vlib_node_set_state (vm, session_queue_node.index, - VLIB_NODE_STATE_POLLING); - wrk->no_connect_loops = 0; - } - } - else - { - if (!n_connects) - { - if (++wrk->no_connect_loops > 1e5) - { - session_wrk_set_state (wrk, SESSION_WRK_INTERRUPT); - vlib_node_set_state (vm, session_queue_node.index, - VLIB_NODE_STATE_INTERRUPT); - } - } - else - wrk->no_connect_loops = 0; - } - - if (wrk->state == SESSION_WRK_POLLING) - { - elt = session_evt_alloc_ctrl (wrk); - elt->evt.event_type = SESSION_CTRL_EVT_RPC; - elt->evt.rpc_args.fp = session_mq_handle_connects_rpc; + session_send_rpc_evt_to_thread_force (fwrk->vm->thread_index, + session_mq_handle_connects_rpc, 0); } } @@ -302,20 +266,28 @@ session_mq_connect_handler (session_worker_t *wrk, session_evt_elt_t *elt) u32 thread_index = wrk - session_main.wrk; session_evt_elt_t *he; - /* No workers, so just deal with the connect now */ - if (PREDICT_FALSE (!thread_index)) + if (PREDICT_FALSE (thread_index > transport_cl_thread ())) { - session_mq_connect_one (session_evt_ctrl_data (wrk, elt)); + clib_warning ("Connect on wrong thread. Dropping"); return; } - if (PREDICT_FALSE (thread_index != 1)) + /* If on worker, check if main has any pending messages. Avoids reordering + * with other control messages that need to be handled by main + */ + if (thread_index) { - clib_warning ("Connect on wrong thread. Dropping"); - return; + he = clib_llist_elt (wrk->event_elts, wrk->evts_pending_main); + + /* Events pending on main, postpone to avoid reordering */ + if (!clib_llist_is_empty (wrk->event_elts, evt_list, he)) + { + clib_llist_add_tail (wrk->event_elts, evt_list, elt, he); + return; + } } - /* Add to pending list to be handled by main thread */ + /* Add to pending list to be handled by first worker */ he = clib_llist_elt (wrk->event_elts, wrk->pending_connects); clib_llist_add_tail (wrk->event_elts, evt_list, elt, he); @@ -323,9 +295,8 @@ session_mq_connect_handler (session_worker_t *wrk, session_evt_elt_t *elt) wrk->n_pending_connects += 1; if (wrk->n_pending_connects == 1) { - vlib_node_set_interrupt_pending (vlib_get_main_by_index (0), - session_queue_node.index); - session_send_rpc_evt_to_thread (0, session_mq_handle_connects_rpc, 0); + session_send_rpc_evt_to_thread_force (thread_index, + session_mq_handle_connects_rpc, 0); } } @@ -351,7 +322,7 @@ session_mq_connect_uri_handler (session_worker_t *wrk, session_evt_elt_t *elt) a->app_index = app->app_index; if ((rv = vnet_connect_uri (a))) { - clib_warning ("connect_uri returned: %d", rv); + session_worker_stat_error_inc (wrk, rv, 1); app_wrk = application_get_worker (app, 0 /* default wrk only */ ); mq_send_session_connected_cb (app_wrk->wrk_index, mp->context, 0, rv); } @@ -433,7 +404,7 @@ session_mq_unlisten_handler (session_worker_t *wrk, session_evt_elt_t *elt) a->wrk_map_index = mp->wrk_index; if ((rv = vnet_unlisten (a))) - clib_warning ("unlisten returned: %d", rv); + session_worker_stat_error_inc (wrk, rv, 1); app_wrk = application_get_worker (app, a->wrk_map_index); if (!app_wrk) @@ -486,13 +457,13 @@ session_mq_accepted_reply_handler (session_worker_t *wrk, /* Special handling for cut-through sessions */ if (!session_has_transport (s)) { - s->session_state = SESSION_STATE_READY; + session_set_state (s, SESSION_STATE_READY); ct_session_connect_notify (s, SESSION_E_NONE); return; } old_state = s->session_state; - s->session_state = SESSION_STATE_READY; + session_set_state (s, SESSION_STATE_READY); if (!svm_fifo_is_empty_prod (s->rx_fifo)) app_worker_lock_and_send_event (app_wrk, s, SESSION_IO_EVT_RX); @@ -501,7 +472,7 @@ session_mq_accepted_reply_handler (session_worker_t *wrk, if (old_state >= SESSION_STATE_TRANSPORT_CLOSING) { app_worker_close_notify (app_wrk, s); - s->session_state = old_state; + session_set_state (s, old_state); return; } } @@ -632,6 +603,7 @@ session_mq_worker_update_handler (void *data) session_event_t *evt; session_t *s; application_t *app; + int rv; app = application_lookup (mp->client_index); if (!app) @@ -668,7 +640,9 @@ session_mq_worker_update_handler (void *data) return; } - app_worker_own_session (app_wrk, s); + rv = app_worker_own_session (app_wrk, s); + if (rv) + session_stat_error_inc (rv, 1); /* * Send reply @@ -812,6 +786,9 @@ session_wrk_handle_evts_main_rpc (void *args) case SESSION_CTRL_EVT_ACCEPTED_REPLY: session_mq_accepted_reply_handler (fwrk, elt); break; + case SESSION_CTRL_EVT_CONNECT: + session_mq_connect_handler (fwrk, elt); + break; default: clib_warning ("unhandled %u", elt->evt.event_type); ALWAYS_ASSERT (0); @@ -820,8 +797,11 @@ session_wrk_handle_evts_main_rpc (void *args) /* Regrab element in case pool moved */ elt = clib_llist_elt (fwrk->event_elts, ei); - session_evt_ctrl_data_free (fwrk, elt); - clib_llist_put (fwrk->event_elts, elt); + if (!clib_llist_elt_is_linked (elt, evt_list)) + { + session_evt_ctrl_data_free (fwrk, elt); + clib_llist_put (fwrk->event_elts, elt); + } ei = next_ei; } @@ -1126,6 +1106,8 @@ session_tx_fill_buffer (session_worker_t *wrk, session_tx_context_t *ctx, if (transport_connection_is_cless (ctx->tc)) { ip_copy (&ctx->tc->rmt_ip, &hdr->rmt_ip, ctx->tc->is_ip4); + ip_copy (&ctx->tc->lcl_ip, &hdr->lcl_ip, ctx->tc->is_ip4); + /* Local port assumed to be bound, not overwriting it */ ctx->tc->rmt_port = hdr->rmt_port; } hdr->data_offset += n_bytes_read; @@ -1188,6 +1170,11 @@ session_tx_not_ready (session_t * s, u8 peek_data) return 2; } } + else + { + if (s->session_state == SESSION_STATE_TRANSPORT_DELETED) + return 2; + } return 0; } @@ -1244,9 +1231,21 @@ session_tx_set_dequeue_params (vlib_main_t * vm, session_tx_context_t * ctx, svm_fifo_peek (ctx->s->tx_fifo, 0, sizeof (ctx->hdr), (u8 *) & ctx->hdr); + /* Zero length dgrams not supported */ + if (PREDICT_FALSE (ctx->hdr.data_length == 0)) + { + svm_fifo_dequeue_drop (ctx->s->tx_fifo, sizeof (ctx->hdr)); + ctx->max_len_to_snd = 0; + return; + } ASSERT (ctx->hdr.data_length > ctx->hdr.data_offset); len = ctx->hdr.data_length - ctx->hdr.data_offset; + if (ctx->hdr.gso_size) + { + ctx->sp.snd_mss = clib_min (ctx->sp.snd_mss, ctx->hdr.gso_size); + } + /* Process multiple dgrams if smaller than min (buf_space, mss). * This avoids handling multiple dgrams if they require buffer * chains */ @@ -1266,11 +1265,13 @@ session_tx_set_dequeue_params (vlib_main_t * vm, session_tx_context_t * ctx, { svm_fifo_peek (ctx->s->tx_fifo, offset, sizeof (ctx->hdr), (u8 *) & hdr); - ASSERT (hdr.data_length > hdr.data_offset); dgram_len = hdr.data_length - hdr.data_offset; - if (len + dgram_len > ctx->max_dequeue - || first_dgram_len != dgram_len) + if (offset + sizeof (hdr) + hdr.data_length > + ctx->max_dequeue || + first_dgram_len != dgram_len) break; + /* Assert here to allow test above with zero length dgrams */ + ASSERT (hdr.data_length > hdr.data_offset); len += dgram_len; offset += sizeof (hdr) + hdr.data_length; } @@ -1552,7 +1553,7 @@ session_tx_fifo_read_and_snd_i (session_worker_t * wrk, *n_tx_packets += ctx->n_segs_per_evt; SESSION_EVT (SESSION_EVT_DEQ, ctx->s, ctx->max_len_to_snd, ctx->max_dequeue, - ctx->s->tx_fifo->has_event, wrk->last_vlib_time); + ctx->s->tx_fifo->shr->has_event, wrk->last_vlib_time); ASSERT (ctx->left_to_snd == 0); @@ -1780,17 +1781,19 @@ session_event_dispatch_io (session_worker_t * wrk, vlib_node_runtime_t * node, app_wrk = app_worker_get (s->app_wrk_index); app_worker_builtin_rx (app_wrk, s); break; - case SESSION_IO_EVT_BUILTIN_TX: - s = session_get_from_handle_if_valid (e->session_handle); + case SESSION_IO_EVT_TX_MAIN: + s = session_get_if_valid (e->session_index, 0 /* main thread */); + if (PREDICT_FALSE (!s)) + break; wrk->ctx.s = s; if (PREDICT_TRUE (s != 0)) - session_tx_fifo_dequeue_internal (wrk, node, elt, n_tx_packets); + (smm->session_tx_fns[s->session_type]) (wrk, node, elt, n_tx_packets); break; default: clib_warning ("unhandled event type %d", e->event_type); } - SESSION_EVT (SESSION_IO_EVT_COUNTS, e->event_type, 1, wrk); + SESSION_EVT (SESSION_EVT_IO_EVT_COUNTS, e->event_type, 1, wrk); /* Regrab elements in case pool moved */ elt = clib_llist_elt (wrk->event_elts, ei); @@ -1940,6 +1943,8 @@ session_queue_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, if (wrk->trans_head == ((wrk->trans_tail + 1) & (wrk->trans_size - 1))) return 0; wrk->batch = vlib_dma_batch_new (vm, wrk->config_index); + if (!wrk->batch) + return 0; } /*