FD.io VPP  v21.06-3-gbb25fbf28
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);
63  u32 node_index = hi->input_node_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",
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 */
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 */
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 
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",
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  {
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 =
171  vec_dup_aligned (hi->output_node_thread_runtimes, CLIB_CACHE_LINE_BYTES);
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 
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  {
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
251  clib_interrupt_free (&rt->rxq_interrupts);
252  }
253  }
254  if (something_changed_on_tx)
255  {
257  t = hi->output_node_thread_runtimes;
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",
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 }
im
vnet_interface_main_t * im
Definition: interface_output.c:395
vnet_hw_if_output_node_runtime_t
Definition: interface.h:629
clib_interrupt_free
static_always_inline void clib_interrupt_free(void **data)
Definition: interrupt.h:34
vlib_worker_thread_barrier_release
void vlib_worker_thread_barrier_release(vlib_main_t *vm)
Definition: threads.c:1386
thread_index
u32 thread_index
Definition: nat44_ei_hairpinning.c:492
VNET_HW_IF_RX_MODE_ADAPTIVE
@ VNET_HW_IF_RX_MODE_ADAPTIVE
Definition: interface.h:58
vlib_node_get_runtime_data
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_rxq_poll_vector_t::queue_id
u32 queue_id
Definition: interface.h:749
clib_max
#define clib_max(x, y)
Definition: clib.h:335
vnet_hw_if_rx_queue_t::mode
vnet_hw_if_rx_mode mode
Definition: interface.h:597
vlib_node_set_state
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
clib_bitmap_t
uword clib_bitmap_t
Definition: bitmap.h:50
vnet_hw_if_rx_queue_t::thread_index
u32 thread_index
Definition: interface.h:588
clib_interrupt_get_next
static_always_inline int clib_interrupt_get_next(void *in, int last)
Definition: interrupt.h:104
node_state_str
static char * node_state_str[]
Definition: runtime.c:33
vnet_interface_main_t
Definition: interface.h:989
vnet_hw_if_rx_queue_t::dev_instance
u32 dev_instance
Definition: interface.h:585
u16
unsigned short u16
Definition: types.h:57
VNET_HW_IF_RX_MODE_POLLING
@ VNET_HW_IF_RX_MODE_POLLING
Definition: interface.h:56
vm
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
node_index
node node_index
Definition: interface_output.c:420
VLIB_NODE_FLAG_ADAPTIVE_MODE
#define VLIB_NODE_FLAG_ADAPTIVE_MODE
Definition: node.h:296
hi
vl_api_ip4_address_t hi
Definition: arp.api:37
vnet_interface_main_t::hw_if_rx_queues
vnet_hw_if_rx_queue_t * hw_if_rx_queues
Definition: interface.h:995
ethernet.h
poll_data_sort
static int poll_data_sort(void *a1, void *a2)
Definition: runtime.c:40
ti
u32 ti
Definition: interface_output.c:405
pool_foreach
#define pool_foreach(VAR, POOL)
Iterate through pool.
Definition: pool.h:534
vnet_hw_if_rx_queue_t::queue_id
u32 queue_id
Definition: interface.h:594
vec_len
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
Definition: vec_bootstrap.h:142
feature.h
clib_interrupt_clear
static_always_inline void clib_interrupt_clear(void *in, int int_num)
Definition: interrupt.h:90
vec_elt_at_index
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
Definition: vec_bootstrap.h:203
vnet_get_hw_interface
static vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
Definition: interface_funcs.h:44
clib_interrupt_resize
__clib_export void clib_interrupt_resize(void **data, uword n_int)
Definition: interrupt.c:38
clib_bitmap_count_set_bits
static uword clib_bitmap_count_set_bits(uword *ai)
Return the number of set bits in a bitmap.
Definition: bitmap.h:468
vlib_worker_thread_barrier_sync
#define vlib_worker_thread_barrier_sync(X)
Definition: threads.h:194
rx_queue_funcs.h
vec_validate_aligned
#define vec_validate_aligned(V, I, A)
Make sure vector is long enough for given index (no header, specified alignment)
Definition: vec.h:534
clib_bitmap_free
#define clib_bitmap_free(v)
Free a bitmap.
Definition: bitmap.h:92
uword
u64 uword
Definition: types.h:112
vnet_hw_if_update_runtime_data
void vnet_hw_if_update_runtime_data(vnet_main_t *vnm, u32 hw_if_index)
Definition: runtime.c:58
vlib_node_state_t
vlib_node_state_t
Definition: node.h:239
VNET_HW_IF_RX_MODE_INTERRUPT
@ VNET_HW_IF_RX_MODE_INTERRUPT
Definition: interface.h:57
vnet_hw_if_tx_queue_t::queue_id
u32 queue_id
Definition: interface.h:609
i
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:261
vlib_node_set_flag
static void vlib_node_set_flag(vlib_main_t *vm, u32 node_index, u16 flag, u8 enable)
Definition: node_funcs.h:228
vnet_hw_if_get_tx_queue
static_always_inline vnet_hw_if_tx_queue_t * vnet_hw_if_get_tx_queue(vnet_main_t *vnm, u32 queue_index)
Definition: tx_queue_funcs.h:23
vec_validate
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment)
Definition: vec.h:523
vlib_worker_thread_barrier_held
u8 vlib_worker_thread_barrier_held(void)
Return true if the wroker thread barrier is held.
Definition: threads.c:1281
vnet_hw_if_rx_queue_set_int_pending
static_always_inline void vnet_hw_if_rx_queue_set_int_pending(vnet_main_t *vnm, u32 queue_index)
Definition: rx_queue_funcs.h:51
VNET_HW_IF_RX_MODE_DEFAULT
@ VNET_HW_IF_RX_MODE_DEFAULT
Definition: interface.h:59
clib_bitmap_set
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
vec_dup_aligned
#define vec_dup_aligned(V, A)
Return copy of vector (no header, alignment specified).
Definition: vec.h:453
CLIB_CACHE_LINE_BYTES
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
clib_interrupt_get_n_int
static_always_inline int clib_interrupt_get_n_int(void *d)
Definition: interrupt.h:44
VLIB_REGISTER_LOG_CLASS
VLIB_REGISTER_LOG_CLASS(if_rxq_log, static)
vec_add2_aligned
#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:656
vnet_hw_interface_t
Definition: interface.h:638
vnet_main_t
Definition: vnet.h:76
vec_free
#define vec_free(V)
Free vector's memory (no header).
Definition: vec.h:395
vnet_hw_if_rx_node_runtime_t
Definition: interface.h:752
format_vlib_node_name
format_function_t format_vlib_node_name
Definition: node_funcs.h:1235
ASSERT
#define ASSERT(truth)
Definition: error_bootstrap.h:69
vec_validate_init_empty
#define vec_validate_init_empty(V, I, INIT)
Make sure vector is long enough for given index and initialize empty space (no header,...
Definition: vec.h:570
ip.h
u32
unsigned int u32
Definition: types.h:88
vlib_get_main_by_index
static vlib_main_t * vlib_get_main_by_index(u32 thread_index)
Definition: global_funcs.h:29
vnet_hw_if_tx_queue_t
Definition: interface.h:602
vnet_hw_if_tx_queue_t::shared_queue
u8 shared_queue
Definition: interface.h:604
vec_sort_with_function
#define vec_sort_with_function(vec, f)
Sort a vector using the supplied element comparison function.
Definition: vec.h:1097
vlib_main_t
Definition: main.h:102
vlib_get_n_threads
static u32 vlib_get_n_threads()
Definition: global_funcs.h:23
vlib_get_main
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:38
unix.h
rt
vnet_interface_output_runtime_t * rt
Definition: interface_output.c:399
vnet_hw_if_tx_queue_t::threads
clib_bitmap_t * threads
Definition: interface.h:612
vnet_hw_if_rx_queue_t::hw_if_index
u32 hw_if_index
Definition: interface.h:582
log_debug
#define log_debug(fmt,...)
Definition: runtime.c:30
vnet_hw_if_rx_queue_t
Definition: interface.h:579
devices.h
tx_queue_funcs.h
vnet_hw_interface_t::input_node_index
u32 input_node_index
Definition: interface.h:718
vnet.h
clib_bitmap_foreach
#define clib_bitmap_foreach(i, ai)
Macro to iterate across set bits in a bitmap.
Definition: bitmap.h:361
vnet_hw_if_rxq_poll_vector_t::dev_instance
u32 dev_instance
Definition: interface.h:748
vnet_main_t::interface_main
vnet_interface_main_t interface_main
Definition: vnet.h:81
vlib_node_get_state
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
VNET_HW_IF_RX_MODE_UNKNOWN
@ VNET_HW_IF_RX_MODE_UNKNOWN
Definition: interface.h:55
vnet_hw_if_rxq_poll_vector_t
Definition: interface.h:746