X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fsession%2Fsession.c;h=eaba80f24e24180b3f4f2f4e524db3a748a2d424;hb=309f7aac170767028a2e6e7e9424ec3d13304aff;hp=42f24d2fb215e53d2303bdcee7e5d56b7f2ccb73;hpb=5384cca85573f553452254abc888f0153a26c15e;p=vpp.git diff --git a/src/vnet/session/session.c b/src/vnet/session/session.c index 42f24d2fb21..eaba80f24e2 100644 --- a/src/vnet/session/session.c +++ b/src/vnet/session/session.c @@ -21,6 +21,8 @@ #include #include #include +#include +#include session_main_t session_main; @@ -36,8 +38,7 @@ session_send_evt_to_thread (void *data, void *args, u32 thread_index, mq = wrk->vpp_event_queue; if (PREDICT_FALSE (svm_msg_q_lock (mq))) return -1; - if (PREDICT_FALSE (svm_msg_q_is_full (mq) - || svm_msg_q_ring_is_full (mq, SESSION_MQ_IO_EVT_RING))) + if (PREDICT_FALSE (svm_msg_q_or_ring_is_full (mq, SESSION_MQ_IO_EVT_RING))) { svm_msg_q_unlock (mq); return -2; @@ -202,39 +203,25 @@ session_alloc (u32 thread_index) { session_worker_t *wrk = &session_main.wrk[thread_index]; session_t *s; - u8 will_expand = 0; - pool_get_aligned_will_expand (wrk->sessions, will_expand, - CLIB_CACHE_LINE_BYTES); - /* If we have peekers, let them finish */ - if (PREDICT_FALSE (will_expand && vlib_num_workers ())) - { - clib_rwlock_writer_lock (&wrk->peekers_rw_locks); - pool_get_aligned (wrk->sessions, s, CLIB_CACHE_LINE_BYTES); - clib_rwlock_writer_unlock (&wrk->peekers_rw_locks); - } - else - { - pool_get_aligned (wrk->sessions, s, CLIB_CACHE_LINE_BYTES); - } + + pool_get_aligned_safe (wrk->sessions, s, CLIB_CACHE_LINE_BYTES); clib_memset (s, 0, sizeof (*s)); s->session_index = s - wrk->sessions; s->thread_index = thread_index; s->app_index = APP_INVALID_INDEX; + return s; } void session_free (session_t * s) { - if (CLIB_DEBUG) - { - u8 thread_index = s->thread_index; - clib_memset (s, 0xFA, sizeof (*s)); - pool_put (session_main.wrk[thread_index].sessions, s); - return; - } + session_worker_t *wrk = &session_main.wrk[s->thread_index]; + SESSION_EVT (SESSION_EVT_FREE, s); - pool_put (session_main.wrk[s->thread_index].sessions, s); + if (CLIB_DEBUG) + clib_memset (s, 0xFA, sizeof (*s)); + pool_put (wrk->sessions, s); } u8 @@ -312,7 +299,7 @@ session_cleanup_half_open (session_handle_t ho_handle) * session should be removed. */ if (ho->connection_index == ~0) { - ho->session_state = SESSION_STATE_CLOSED; + session_set_state (ho, SESSION_STATE_CLOSED); return; } /* Migrated transports are no longer half-opens */ @@ -347,15 +334,15 @@ void session_half_open_delete_notify (transport_connection_t *tc) { /* Notification from ctrl thread accepted without rpc */ - if (!tc->thread_index) + if (tc->thread_index == transport_cl_thread ()) { session_half_open_free (ho_session_get (tc->s_index)); } else { void *args = uword_to_pointer ((uword) tc->s_index, void *); - session_send_rpc_evt_to_thread_force (0, session_half_open_free_rpc, - args); + session_send_rpc_evt_to_thread_force (transport_cl_thread (), + session_half_open_free_rpc, args); } } @@ -399,7 +386,7 @@ session_alloc_for_connection (transport_connection_t * tc) s = session_alloc (thread_index); s->session_type = session_type_from_proto_and_ip (tc->proto, tc->is_ip4); - s->session_state = SESSION_STATE_CLOSED; + session_set_state (s, SESSION_STATE_CLOSED); /* Attach transport to session and vice versa */ s->connection_index = tc->c_index; @@ -907,7 +894,7 @@ session_stream_connect_notify (transport_connection_t * tc, return app_worker_connect_notify (app_wrk, s, err, opaque); s = session_alloc_for_connection (tc); - s->session_state = SESSION_STATE_CONNECTING; + session_set_state (s, SESSION_STATE_CONNECTING); s->app_wrk_index = app_wrk->wrk_index; new_si = s->session_index; new_ti = s->thread_index; @@ -920,7 +907,7 @@ session_stream_connect_notify (transport_connection_t * tc, } s = session_get (new_si, new_ti); - s->session_state = SESSION_STATE_READY; + session_set_state (s, SESSION_STATE_READY); session_lookup_add_connection (tc, session_handle (s)); if (app_worker_connect_notify (app_wrk, s, SESSION_E_NONE, opaque)) @@ -1050,7 +1037,7 @@ session_dgram_connect_notify (transport_connection_t * tc, */ new_s = session_clone_safe (tc->s_index, old_thread_index); new_s->connection_index = tc->c_index; - new_s->session_state = SESSION_STATE_READY; + session_set_state (new_s, SESSION_STATE_READY); new_s->flags |= SESSION_F_IS_MIGRATING; if (!(tc->flags & TRANSPORT_CONNECTION_F_NO_LOOKUP)) @@ -1104,11 +1091,11 @@ session_transport_closing_notify (transport_connection_t * tc) * accept might be rejected */ if (s->session_state == SESSION_STATE_ACCEPTING) { - s->session_state = SESSION_STATE_TRANSPORT_CLOSING; + session_set_state (s, SESSION_STATE_TRANSPORT_CLOSING); return; } - s->session_state = SESSION_STATE_TRANSPORT_CLOSING; + session_set_state (s, SESSION_STATE_TRANSPORT_CLOSING); app_wrk = app_worker_get (s->app_wrk_index); app_worker_close_notify (app_wrk, s); } @@ -1149,7 +1136,7 @@ session_transport_delete_notify (transport_connection_t * tc) * because transport will soon be closed and closed sessions * are assumed to have been removed from the lookup table */ session_lookup_del_session (s); - s->session_state = SESSION_STATE_TRANSPORT_DELETED; + session_set_state (s, SESSION_STATE_TRANSPORT_DELETED); session_cleanup_notify (s, SESSION_CLEANUP_TRANSPORT); svm_fifo_dequeue_drop_all (s->tx_fifo); break; @@ -1160,7 +1147,7 @@ session_transport_delete_notify (transport_connection_t * tc) * session is just removed because both transport and app have * confirmed the close*/ session_lookup_del_session (s); - s->session_state = SESSION_STATE_TRANSPORT_DELETED; + session_set_state (s, SESSION_STATE_TRANSPORT_DELETED); session_cleanup_notify (s, SESSION_CLEANUP_TRANSPORT); svm_fifo_dequeue_drop_all (s->tx_fifo); session_program_transport_ctrl_evt (s, SESSION_CTRL_EVT_CLOSE); @@ -1204,17 +1191,15 @@ session_transport_closed_notify (transport_connection_t * tc) { session_transport_closing_notify (tc); svm_fifo_dequeue_drop_all (s->tx_fifo); - s->session_state = SESSION_STATE_TRANSPORT_CLOSED; + session_set_state (s, SESSION_STATE_TRANSPORT_CLOSED); } /* If app close has not been received or has not yet resulted in * a transport close, only mark the session transport as closed */ else if (s->session_state <= SESSION_STATE_CLOSING) - { - s->session_state = SESSION_STATE_TRANSPORT_CLOSED; - } + session_set_state (s, SESSION_STATE_TRANSPORT_CLOSED); /* If app also closed, switch to closed */ else if (s->session_state == SESSION_STATE_APP_CLOSED) - s->session_state = SESSION_STATE_CLOSED; + session_set_state (s, SESSION_STATE_CLOSED); app_wrk = app_worker_get_if_valid (s->app_wrk_index); if (app_wrk) @@ -1236,10 +1221,10 @@ session_transport_reset_notify (transport_connection_t * tc) return; if (s->session_state == SESSION_STATE_ACCEPTING) { - s->session_state = SESSION_STATE_TRANSPORT_CLOSING; + session_set_state (s, SESSION_STATE_TRANSPORT_CLOSING); return; } - s->session_state = SESSION_STATE_TRANSPORT_CLOSING; + session_set_state (s, SESSION_STATE_TRANSPORT_CLOSING); app_wrk = app_worker_get (s->app_wrk_index); app_worker_reset_notify (app_wrk, s); } @@ -1256,12 +1241,12 @@ session_stream_accept_notify (transport_connection_t * tc) return -1; if (s->session_state != SESSION_STATE_CREATED) return 0; - s->session_state = SESSION_STATE_ACCEPTING; + session_set_state (s, SESSION_STATE_ACCEPTING); if (app_worker_accept_notify (app_wrk, s)) { /* On transport delete, no notifications should be sent. Unless, the * accept is retried and successful. */ - s->session_state = SESSION_STATE_CREATED; + session_set_state (s, SESSION_STATE_CREATED); return -1; } return 0; @@ -1279,7 +1264,7 @@ session_stream_accept (transport_connection_t * tc, u32 listener_index, s = session_alloc_for_connection (tc); s->listener_handle = ((u64) thread_index << 32) | (u64) listener_index; - s->session_state = SESSION_STATE_CREATED; + session_set_state (s, SESSION_STATE_CREATED); if ((rv = app_worker_init_accepted (s))) { @@ -1323,6 +1308,7 @@ session_dgram_accept (transport_connection_t * tc, u32 listener_index, } session_lookup_add_connection (tc, session_handle (s)); + session_set_state (s, SESSION_STATE_ACCEPTING); app_wrk = app_worker_get (s->app_wrk_index); if ((rv = app_worker_accept_notify (app_wrk, s))) @@ -1360,7 +1346,7 @@ session_open_cl (session_endpoint_cfg_t *rmt, session_handle_t *rsh) app_wrk = app_worker_get (rmt->app_wrk_index); s = session_alloc_for_connection (tc); s->app_wrk_index = app_wrk->wrk_index; - s->session_state = SESSION_STATE_OPENED; + session_set_state (s, SESSION_STATE_OPENED); if (app_worker_init_connected (app_wrk, s)) { session_free (s); @@ -1468,12 +1454,12 @@ session_open (session_endpoint_cfg_t *rmt, session_handle_t *rsh) int session_listen (session_t * ls, session_endpoint_cfg_t * sep) { - transport_endpoint_t *tep; + transport_endpoint_cfg_t *tep; int tc_index; u32 s_index; /* Transport bind/listen */ - tep = session_endpoint_to_transport (sep); + tep = session_endpoint_to_transport_cfg (sep); s_index = ls->session_index; tc_index = transport_start_listen (session_get_transport_proto (ls), s_index, tep); @@ -1485,6 +1471,7 @@ session_listen (session_t * ls, session_endpoint_cfg_t * sep) * worker because local tables (for ct sessions) are not backed by a fib */ ls = listen_session_get (s_index); ls->connection_index = tc_index; + ls->opaque = sep->opaque; return 0; } @@ -1552,9 +1539,12 @@ session_close (session_t * s) return; } - /* App closed so stop propagating dequeue notifications */ - svm_fifo_clear_deq_ntf (s->tx_fifo); - s->session_state = SESSION_STATE_CLOSING; + /* App closed so stop propagating dequeue notifications. + * App might disconnect session before connected, in this case, + * tx_fifo may not be setup yet, so clear only it's inited. */ + if (s->tx_fifo) + svm_fifo_clear_deq_ntf (s->tx_fifo); + session_set_state (s, SESSION_STATE_CLOSING); session_program_transport_ctrl_evt (s, SESSION_CTRL_EVT_CLOSE); } @@ -1566,9 +1556,12 @@ session_reset (session_t * s) { if (s->session_state >= SESSION_STATE_CLOSING) return; - /* Drop all outstanding tx data */ - svm_fifo_dequeue_drop_all (s->tx_fifo); - s->session_state = SESSION_STATE_CLOSING; + /* Drop all outstanding tx data + * App might disconnect session before connected, in this case, + * tx_fifo may not be setup yet, so clear only it's inited. */ + if (s->tx_fifo) + svm_fifo_dequeue_drop_all (s->tx_fifo); + session_set_state (s, SESSION_STATE_CLOSING); session_program_transport_ctrl_evt (s, SESSION_CTRL_EVT_RESET); } @@ -1603,7 +1596,7 @@ session_transport_close (session_t * s) if (s->session_state >= SESSION_STATE_APP_CLOSED) { if (s->session_state == SESSION_STATE_TRANSPORT_CLOSED) - s->session_state = SESSION_STATE_CLOSED; + session_set_state (s, SESSION_STATE_CLOSED); /* If transport is already deleted, just free the session */ else if (s->session_state >= SESSION_STATE_TRANSPORT_DELETED) session_free_w_fifos (s); @@ -1616,7 +1609,7 @@ session_transport_close (session_t * s) * delete notify. This will finally lead to the complete cleanup of the * session. */ - s->session_state = SESSION_STATE_APP_CLOSED; + session_set_state (s, SESSION_STATE_APP_CLOSED); transport_close (session_get_transport_proto (s), s->connection_index, s->thread_index); @@ -1631,13 +1624,13 @@ session_transport_reset (session_t * s) if (s->session_state >= SESSION_STATE_APP_CLOSED) { if (s->session_state == SESSION_STATE_TRANSPORT_CLOSED) - s->session_state = SESSION_STATE_CLOSED; + session_set_state (s, SESSION_STATE_CLOSED); else if (s->session_state >= SESSION_STATE_TRANSPORT_DELETED) session_free_w_fifos (s); return; } - s->session_state = SESSION_STATE_APP_CLOSED; + session_set_state (s, SESSION_STATE_APP_CLOSED); transport_reset (session_get_transport_proto (s), s->connection_index, s->thread_index); } @@ -1695,7 +1688,7 @@ session_vpp_wrk_mqs_alloc (session_main_t *smm) * if larger than minimum size. */ mqs_seg_size = svm_msg_q_size_to_alloc (cfg) * vec_len (smm->wrk); - mqs_seg_size = mqs_seg_size + (32 << 10); + mqs_seg_size = mqs_seg_size + (1 << 20); mqs_seg_size = clib_max (mqs_seg_size, smm->wrk_mqs_segment_size); mqs_seg->ssvm.ssvm_size = mqs_seg_size; @@ -1868,6 +1861,44 @@ session_queue_run_on_main_thread (vlib_main_t * vm) vlib_node_set_interrupt_pending (vm, session_queue_node.index); } +static void +session_stats_collector_fn (vlib_stats_collector_data_t *d) +{ + u32 i, n_workers, n_wrk_sessions, n_sessions = 0; + session_main_t *smm = &session_main; + session_worker_t *wrk; + counter_t **counters; + counter_t *cb; + + n_workers = vec_len (smm->wrk); + vlib_stats_validate (d->entry_index, 0, n_workers - 1); + counters = d->entry->data; + cb = counters[0]; + + for (i = 0; i < vec_len (smm->wrk); i++) + { + wrk = session_main_get_worker (i); + n_wrk_sessions = pool_elts (wrk->sessions); + cb[i] = n_wrk_sessions; + n_sessions += n_wrk_sessions; + } + + vlib_stats_set_gauge (d->private_data, n_sessions); +} + +static void +session_stats_collector_init (void) +{ + vlib_stats_collector_reg_t reg = {}; + + reg.entry_index = + vlib_stats_add_counter_vector ("/sys/session/sessions_per_worker"); + reg.private_data = vlib_stats_add_gauge ("/sys/session/sessions_total"); + reg.collect_fn = session_stats_collector_fn; + vlib_stats_register_collector_fn (®); + vlib_stats_validate (reg.entry_index, 0, vlib_get_n_threads ()); +} + static clib_error_t * session_manager_main_enable (vlib_main_t * vm) { @@ -1888,6 +1919,7 @@ session_manager_main_enable (vlib_main_t * vm) /* Allocate cache line aligned worker contexts */ vec_validate_aligned (smm->wrk, num_threads - 1, CLIB_CACHE_LINE_BYTES); + clib_spinlock_init (&session_main.pool_realloc_lock); for (i = 0; i < num_threads; i++) { @@ -1896,15 +1928,14 @@ session_manager_main_enable (vlib_main_t * vm) wrk->new_head = clib_llist_make_head (wrk->event_elts, evt_list); wrk->old_head = clib_llist_make_head (wrk->event_elts, evt_list); wrk->pending_connects = clib_llist_make_head (wrk->event_elts, evt_list); + wrk->evts_pending_main = + clib_llist_make_head (wrk->event_elts, evt_list); wrk->vm = vlib_get_main_by_index (i); wrk->last_vlib_time = vlib_time_now (vm); wrk->last_vlib_us_time = wrk->last_vlib_time * CLIB_US_TIME_FREQ; wrk->timerfd = -1; vec_validate (wrk->session_to_enqueue, smm->last_transport_proto_type); - if (num_threads > 1) - clib_rwlock_init (&smm->wrk[i].peekers_rw_locks); - if (!smm->no_adaptive && smm->use_private_rx_mqs) session_wrk_enable_adaptive_mode (wrk); } @@ -1940,6 +1971,7 @@ session_manager_main_enable (vlib_main_t * vm) session_lookup_init (); app_namespaces_init (); transport_init (); + session_stats_collector_init (); smm->is_initialized = 1; done: @@ -1959,6 +1991,86 @@ session_manager_main_disable (vlib_main_t * vm) transport_enable_disable (vm, 0 /* is_en */ ); } +/* in this new callback, cookie hint the index */ +void +session_dma_completion_cb (vlib_main_t *vm, struct vlib_dma_batch *batch) +{ + session_worker_t *wrk; + wrk = session_main_get_worker (vm->thread_index); + session_dma_transfer *dma_transfer; + + dma_transfer = &wrk->dma_trans[wrk->trans_head]; + vec_add (wrk->pending_tx_buffers, dma_transfer->pending_tx_buffers, + vec_len (dma_transfer->pending_tx_buffers)); + vec_add (wrk->pending_tx_nexts, dma_transfer->pending_tx_nexts, + vec_len (dma_transfer->pending_tx_nexts)); + vec_reset_length (dma_transfer->pending_tx_buffers); + vec_reset_length (dma_transfer->pending_tx_nexts); + wrk->trans_head++; + if (wrk->trans_head == wrk->trans_size) + wrk->trans_head = 0; + return; +} + +static void +session_prepare_dma_args (vlib_dma_config_t *args) +{ + args->max_transfers = DMA_TRANS_SIZE; + args->max_transfer_size = 65536; + args->features = 0; + args->sw_fallback = 1; + args->barrier_before_last = 1; + args->callback_fn = session_dma_completion_cb; +} + +static void +session_node_enable_dma (u8 is_en, int n_vlibs) +{ + vlib_dma_config_t args; + session_prepare_dma_args (&args); + session_worker_t *wrk; + vlib_main_t *vm; + + int config_index = -1; + + if (is_en) + { + vm = vlib_get_main_by_index (0); + config_index = vlib_dma_config_add (vm, &args); + } + else + { + vm = vlib_get_main_by_index (0); + wrk = session_main_get_worker (0); + if (wrk->config_index >= 0) + vlib_dma_config_del (vm, wrk->config_index); + } + int i; + for (i = 0; i < n_vlibs; i++) + { + vm = vlib_get_main_by_index (i); + wrk = session_main_get_worker (vm->thread_index); + wrk->config_index = config_index; + if (is_en) + { + if (config_index >= 0) + wrk->dma_enabled = true; + wrk->dma_trans = (session_dma_transfer *) clib_mem_alloc ( + sizeof (session_dma_transfer) * DMA_TRANS_SIZE); + bzero (wrk->dma_trans, + sizeof (session_dma_transfer) * DMA_TRANS_SIZE); + } + else + { + if (wrk->dma_trans) + clib_mem_free (wrk->dma_trans); + } + wrk->trans_head = 0; + wrk->trans_tail = 0; + wrk->trans_size = DMA_TRANS_SIZE; + } +} + void session_node_enable_disable (u8 is_en) { @@ -1999,6 +2111,9 @@ session_node_enable_disable (u8 is_en) if (sm->use_private_rx_mqs) application_enable_rx_mqs_nodes (is_en); + + if (sm->dma_enabled) + session_node_enable_dma (is_en, n_vlibs); } clib_error_t * @@ -2070,6 +2185,9 @@ session_config_fn (vlib_main_t * vm, unformat_input_t * input) else clib_warning ("event queue length %d too small, ignored", nitems); } + else if (unformat (input, "wrk-mqs-segment-size %U", + unformat_memory_size, &smm->wrk_mqs_segment_size)) + ; else if (unformat (input, "preallocated-sessions %d", &smm->preallocated_sessions)) ; @@ -2138,6 +2256,8 @@ session_config_fn (vlib_main_t * vm, unformat_input_t * input) smm->use_private_rx_mqs = 1; else if (unformat (input, "no-adaptive")) smm->no_adaptive = 1; + else if (unformat (input, "use-dma")) + smm->dma_enabled = 1; /* * Deprecated but maintained for compatibility */ @@ -2146,7 +2266,7 @@ session_config_fn (vlib_main_t * vm, unformat_input_t * input) else if (unformat (input, "segment-baseva 0x%lx", &tmp)) ; else if (unformat (input, "evt_qs_seg_size %U", unformat_memory_size, - &tmp)) + &smm->wrk_mqs_segment_size)) ; else if (unformat (input, "event-queue-length %d", &nitems)) {