FD.io VPP  v21.06-1-gbb7418cf9
Vector Packet Processing
runtime.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
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.
14  */
15 
16 #include <vnet/vnet.h>
17 #include <vnet/devices/devices.h>
18 #include <vnet/feature/feature.h>
19 #include <vnet/ip/ip.h>
20 #include <vnet/ethernet/ethernet.h>
23 #include <vlib/unix/unix.h>
24 
25 VLIB_REGISTER_LOG_CLASS (if_rxq_log, static) = {
26  .class_name = "interface",
27  .subclass_name = "runtime",
28 };
29 
30 #define log_debug(fmt, ...) vlib_log_debug (if_rxq_log.class, fmt, __VA_ARGS__)
31 #define log_err(fmt, ...) vlib_log_err (if_rxq_log.class, fmt, __VA_ARGS__)
32 
33 static char *node_state_str[] = {
34  [VLIB_NODE_STATE_DISABLED] = "disabled",
35  [VLIB_NODE_STATE_POLLING] = "polling",
36  [VLIB_NODE_STATE_INTERRUPT] = "interrupt",
37 };
38 
39 static int
40 poll_data_sort (void *a1, void *a2)
41 {
44 
45  if (pv1->dev_instance > pv2->dev_instance)
46  return 1;
47  else if (pv1->dev_instance < pv2->dev_instance)
48  return -1;
49  else if (pv1->queue_id > pv2->queue_id)
50  return 1;
51  else if (pv1->queue_id < pv2->queue_id)
52  return -1;
53  else
54  return 0;
55 }
56 
57 void
59 {
62  vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
65  vnet_hw_if_rxq_poll_vector_t *pv, **d = 0;
66  vnet_hw_if_output_node_runtime_t *new_out_runtimes = 0;
67  vlib_node_state_t *per_thread_node_state = 0;
68  u32 n_threads = vlib_get_n_threads ();
69  u16 *per_thread_node_adaptive = 0;
70  int something_changed_on_rx = 0;
71  int something_changed_on_tx = 0;
72  clib_bitmap_t *pending_int = 0;
73  int last_int = -1;
74 
75  log_debug ("update node '%U' triggered by interface %v",
76  format_vlib_node_name, vm, node_index, hi->name);
77 
78  vec_validate (d, n_threads - 1);
79  vec_validate_init_empty (per_thread_node_state, n_threads - 1,
80  VLIB_NODE_STATE_DISABLED);
81  vec_validate_init_empty (per_thread_node_adaptive, n_threads - 1, 0);
82 
83  /* find out desired node state on each thread */
84  pool_foreach (rxq, im->hw_if_rx_queues)
85  {
86  u32 ti = rxq->thread_index;
87  vnet_hw_interface_t *rxq_hi;
88 
91 
92  rxq_hi = vnet_get_hw_interface (vnm, rxq->hw_if_index);
93 
94  if (rxq_hi->input_node_index != node_index)
95  continue;
96 
97  if (rxq->mode == VNET_HW_IF_RX_MODE_POLLING)
98  {
99  per_thread_node_state[ti] = VLIB_NODE_STATE_POLLING;
100  per_thread_node_adaptive[ti] = 0;
101  }
102 
103  if (per_thread_node_state[ti] == VLIB_NODE_STATE_POLLING)
104  continue;
105 
106  if (rxq->mode == VNET_HW_IF_RX_MODE_INTERRUPT ||
108  per_thread_node_state[ti] = VLIB_NODE_STATE_INTERRUPT;
109 
110  if (rxq->mode == VNET_HW_IF_RX_MODE_ADAPTIVE)
111  per_thread_node_adaptive[ti] = 1;
112  }
113 
114  /* construct per-thread polling vectors */
115  pool_foreach (rxq, im->hw_if_rx_queues)
116  {
117  u32 ti = rxq->thread_index;
118  vnet_hw_interface_t *rxq_hi;
119 
120  rxq_hi = vnet_get_hw_interface (vnm, rxq->hw_if_index);
121 
122  if (rxq_hi->input_node_index != node_index)
123  continue;
124 
125  if (rxq->mode == VNET_HW_IF_RX_MODE_INTERRUPT ||
127  last_int = clib_max (last_int, rxq - im->hw_if_rx_queues);
128 
129  if (per_thread_node_state[ti] != VLIB_NODE_STATE_POLLING)
130  continue;
131 
132  vec_add2_aligned (d[ti], pv, 1, CLIB_CACHE_LINE_BYTES);
133  pv->dev_instance = rxq->dev_instance;
134  pv->queue_id = rxq->queue_id;
135  }
136 
137  /* sort poll vectors and compare them with active ones to avoid
138  * unnecesary barrier */
139  for (int i = 0; i < n_threads; i++)
140  {
142  vlib_node_state_t old_state;
144 
145  old_state = vlib_node_get_state (ovm, node_index);
146  if (per_thread_node_state[i] != old_state)
147  {
148  something_changed_on_rx = 1;
149  log_debug ("state changed for node %U on thread %u from %s to %s",
150  format_vlib_node_name, vm, node_index, i,
151  node_state_str[old_state],
152  node_state_str[per_thread_node_state[i]]);
153  }
154 
155  /* check if something changed */
156  if (something_changed_on_rx == 0)
157  {
159  rt = vlib_node_get_runtime_data (ovm, node_index);
160  if (vec_len (rt->rxq_poll_vector) != vec_len (d[i]))
161  something_changed_on_rx = 1;
162  else if (memcmp (d[i], rt->rxq_poll_vector,
163  vec_len (d[i]) * sizeof (**d)))
164  something_changed_on_rx = 1;
165  if (clib_interrupt_get_n_int (rt->rxq_interrupts) != last_int + 1)
166  something_changed_on_rx = 1;
167  }
168  }
169 
170  new_out_runtimes =
172  vec_validate_aligned (new_out_runtimes, n_threads - 1,
174 
175  if (vec_len (hi->output_node_thread_runtimes) != vec_len (new_out_runtimes))
176  something_changed_on_tx = 1;
177 
178  for (int i = 0; i < vec_len (hi->tx_queue_indices); i++)
179  {
181  u32 queue_index = hi->tx_queue_indices[i];
182  vnet_hw_if_tx_queue_t *txq = vnet_hw_if_get_tx_queue (vnm, queue_index);
183  uword n_threads = clib_bitmap_count_set_bits (txq->threads);
184 
185  clib_bitmap_foreach (thread_index, txq->threads)
186  {
188  rt = vec_elt_at_index (new_out_runtimes, thread_index);
189  if ((rt->frame.queue_id != txq->queue_id) ||
190  (rt->n_threads != n_threads))
191  {
192  log_debug ("tx queue data changed for interface %v, thread %u "
193  "(queue_id %u -> %u, n_threads %u -> %u)",
194  hi->name, thread_index, rt->frame.queue_id,
195  txq->queue_id, rt->n_threads, n_threads);
196  something_changed_on_tx = 1;
197  rt->frame.queue_id = txq->queue_id;
198  rt->frame.shared_queue = txq->shared_queue;
199  rt->frame.shared_queue = n_threads > 1 ? 1 : 0;
200  rt->n_threads = n_threads;
201  }
202  }
203  }
204 
205  if (something_changed_on_rx || something_changed_on_tx)
206  {
207  int with_barrier;
208 
210  {
211  with_barrier = 0;
212  log_debug ("%s", "already running under the barrier");
213  }
214  else
215  with_barrier = 1;
216 
217  if (with_barrier)
219 
220  if (something_changed_on_rx)
221  {
222  for (int i = 0; i < n_threads; i++)
223  {
226  rt = vlib_node_get_runtime_data (vm, node_index);
227  pv = rt->rxq_poll_vector;
228  rt->rxq_poll_vector = d[i];
229  d[i] = pv;
230 
231  if (rt->rxq_interrupts)
232  {
233  void *in = rt->rxq_interrupts;
234  int int_num = -1;
235  while ((int_num = clib_interrupt_get_next (in, int_num)) !=
236  -1)
237  {
238  clib_interrupt_clear (in, int_num);
239  pending_int = clib_bitmap_set (pending_int, int_num, 1);
240  last_int = clib_max (last_int, int_num);
241  }
242  }
243 
244  vlib_node_set_state (vm, node_index, per_thread_node_state[i]);
246  per_thread_node_adaptive[i]);
247 
248  if (last_int >= 0)
249  clib_interrupt_resize (&rt->rxq_interrupts, last_int + 1);
250  else
252  }
253  }
254  if (something_changed_on_tx)
255  {
258  hi->output_node_thread_runtimes = new_out_runtimes;
259  new_out_runtimes = t;
260  }
261 
262  if (with_barrier)
264  }
265  else
266  log_debug ("skipping update of node '%U', no changes detected",
267  format_vlib_node_name, vm, node_index);
268 
269  if (pending_int)
270  {
271  int i;
272  clib_bitmap_foreach (i, pending_int)
273  {
275  }
276  clib_bitmap_free (pending_int);
277  }
278 
279  for (int i = 0; i < n_threads; i++)
280  vec_free (d[i]);
281 
282  vec_free (d);
283  vec_free (per_thread_node_state);
284  vec_free (per_thread_node_adaptive);
285  vec_free (new_out_runtimes);
286 }
vnet_hw_if_output_node_runtime_t * output_node_thread_runtimes
Definition: interface.h:673
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:524
static_always_inline int clib_interrupt_get_n_int(void *d)
Definition: interrupt.h:44
vnet_hw_if_tx_frame_t frame
Definition: interface.h:632
clib_bitmap_t * threads
Definition: interface.h:612
#define log_debug(fmt,...)
Definition: runtime.c:30
vnet_interface_output_runtime_t * rt
static_always_inline vnet_hw_if_tx_queue_t * vnet_hw_if_get_tx_queue(vnet_main_t *vnm, u32 queue_index)
format_function_t format_vlib_node_name
Definition: node_funcs.h:1235
#define pool_foreach(VAR, POOL)
Iterate through pool.
Definition: pool.h:534
vnet_interface_main_t interface_main
Definition: vnet.h:81
u32 thread_index
#define vec_add2_aligned(V, P, N, A)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:657
#define clib_bitmap_foreach(i, ai)
Macro to iterate across set bits in a bitmap.
Definition: bitmap.h:361
static vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
static uword * clib_bitmap_set(uword *ai, uword i, uword value)
Sets the ith bit of a bitmap to new_value Removes trailing zeros from the bitmap. ...
Definition: bitmap.h:167
static_always_inline void vnet_hw_if_rx_queue_set_int_pending(vnet_main_t *vnm, u32 queue_index)
static int poll_data_sort(void *a1, void *a2)
Definition: runtime.c:40
#define vec_validate_aligned(V, I, A)
Make sure vector is long enough for given index (no header, specified alignment)
Definition: vec.h:535
#define vlib_worker_thread_barrier_sync(X)
Definition: threads.h:194
unsigned int u32
Definition: types.h:88
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
static vlib_node_state_t vlib_node_get_state(vlib_main_t *vm, u32 node_index)
Get node dispatch state.
Definition: node_funcs.h:219
static_always_inline void clib_interrupt_free(void **data)
Definition: interrupt.h:34
u8 vlib_worker_thread_barrier_held(void)
Return true if the wroker thread barrier is held.
Definition: threads.c:1281
unsigned short u16
Definition: types.h:57
vnet_hw_if_rxq_poll_vector_t * rxq_poll_vector
Definition: interface.h:754
__clib_export void clib_interrupt_resize(void **data, uword n_int)
Definition: interrupt.c:38
static void * vlib_node_get_runtime_data(vlib_main_t *vm, u32 node_index)
Get node runtime private data by node index.
Definition: node_funcs.h:137
vnet_hw_if_rx_mode mode
Definition: interface.h:597
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
void vnet_hw_if_update_runtime_data(vnet_main_t *vnm, u32 hw_if_index)
Definition: runtime.c:58
#define VLIB_NODE_FLAG_ADAPTIVE_MODE
Definition: node.h:297
vnet_hw_if_rx_queue_t * hw_if_rx_queues
Definition: interface.h:995
u32 ti
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:261
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:395
vnet_interface_main_t * im
static_always_inline void clib_interrupt_clear(void *in, int int_num)
Definition: interrupt.h:90
static void vlib_node_set_flag(vlib_main_t *vm, u32 node_index, u16 flag, u8 enable)
Definition: node_funcs.h:228
#define ASSERT(truth)
#define clib_bitmap_free(v)
Free a bitmap.
Definition: bitmap.h:92
static void vlib_node_set_state(vlib_main_t *vm, u32 node_index, vlib_node_state_t new_state)
Set node dispatch state.
Definition: node_funcs.h:175
static_always_inline int clib_interrupt_get_next(void *in, int last)
Definition: interrupt.h:104
static u32 vlib_get_n_threads()
Definition: global_funcs.h:23
#define clib_max(x, y)
Definition: clib.h:335
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:38
vl_api_ip4_address_t hi
Definition: arp.api:37
static uword clib_bitmap_count_set_bits(uword *ai)
Return the number of set bits in a bitmap.
Definition: bitmap.h:468
static vlib_main_t * vlib_get_main_by_index(u32 thread_index)
Definition: global_funcs.h:29
#define vec_dup_aligned(V, A)
Return copy of vector (no header, alignment specified).
Definition: vec.h:453
VLIB_REGISTER_LOG_CLASS(if_rxq_log, static)
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
u64 uword
Definition: types.h:112
#define vec_sort_with_function(vec, f)
Sort a vector using the supplied element comparison function.
Definition: vec.h:1098
node node_index
static char * node_state_str[]
Definition: runtime.c:33
void vlib_worker_thread_barrier_release(vlib_main_t *vm)
Definition: threads.c:1386
vlib_node_state_t
Definition: node.h:240
uword clib_bitmap_t
Definition: bitmap.h:50
#define vec_validate_init_empty(V, I, INIT)
Make sure vector is long enough for given index and initialize empty space (no header, unspecified alignment)
Definition: vec.h:571
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59