Add VLIB_NODE_FN() macro to simplify multiversioning of node functions
[vpp.git] / src / plugins / avf / input.c
1 /*
2  *------------------------------------------------------------------
3  * Copyright (c) 2018 Cisco and/or its affiliates.
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *------------------------------------------------------------------
16  */
17
18 #include <vlib/vlib.h>
19 #include <vlib/unix/unix.h>
20 #include <vlib/pci/pci.h>
21 #include <vnet/ethernet/ethernet.h>
22 #include <vnet/devices/devices.h>
23
24 #include <avf/avf.h>
25
26 #define foreach_avf_input_error \
27   _(BUFFER_ALLOC, "buffer alloc error") \
28   _(RX_PACKET_ERROR, "Rx packet errors")
29
30 typedef enum
31 {
32 #define _(f,s) AVF_INPUT_ERROR_##f,
33   foreach_avf_input_error
34 #undef _
35     AVF_INPUT_N_ERROR,
36 } avf_input_error_t;
37
38 static __clib_unused char *avf_input_error_strings[] = {
39 #define _(n,s) s,
40   foreach_avf_input_error
41 #undef _
42 };
43
44 #define AVF_RX_DESC_STATUS(x)           (1 << x)
45 #define AVF_RX_DESC_STATUS_DD           AVF_RX_DESC_STATUS(0)
46 #define AVF_RX_DESC_STATUS_EOP          AVF_RX_DESC_STATUS(1)
47
48 static_always_inline void
49 avf_input_trace (vlib_main_t * vm, vlib_node_runtime_t * node, u32 next0,
50                  vlib_buffer_t * b0, uword * n_trace, avf_device_t * ad,
51                  avf_rx_vector_entry_t * rxve)
52 {
53   avf_input_trace_t *tr;
54   vlib_trace_buffer (vm, node, next0, b0, /* follow_chain */ 0);
55   vlib_set_trace_count (vm, node, --(*n_trace));
56   tr = vlib_add_trace (vm, node, b0, sizeof (*tr));
57   tr->next_index = next0;
58   tr->hw_if_index = ad->hw_if_index;
59   clib_memcpy (&tr->rxve, rxve, sizeof (avf_rx_vector_entry_t));
60 }
61
62 #define AVF_INPUT_REFILL_TRESHOLD 32
63 static_always_inline void
64 avf_rxq_refill (vlib_main_t * vm, vlib_node_runtime_t * node, avf_rxq_t * rxq,
65                 int use_iova)
66 {
67   u16 n_refill, mask, n_alloc, slot;
68   avf_rx_desc_t *d;
69
70   n_refill = rxq->size - 1 - rxq->n_bufs;
71   if (PREDICT_TRUE (n_refill <= AVF_INPUT_REFILL_TRESHOLD))
72     return;
73
74   mask = rxq->size - 1;
75   slot = (rxq->next - n_refill - 1) & mask;
76
77   n_refill &= ~7;               /* round to 8 */
78   n_alloc = vlib_buffer_alloc_to_ring (vm, rxq->bufs, slot, rxq->size,
79                                        n_refill);
80
81   if (PREDICT_FALSE (n_alloc != n_refill))
82     {
83       vlib_error_count (vm, node->node_index,
84                         AVF_INPUT_ERROR_BUFFER_ALLOC, 1);
85       if (n_alloc)
86         vlib_buffer_free (vm, rxq->bufs + slot, n_alloc);
87       return;
88     }
89
90   rxq->n_bufs += n_alloc;
91
92   while (n_alloc--)
93     {
94       u64 addr;
95       d = ((avf_rx_desc_t *) rxq->descs) + slot;
96       if (use_iova)
97         {
98           vlib_buffer_t *b = vlib_get_buffer (vm, rxq->bufs[slot]);
99           addr = pointer_to_uword (b->data);
100         }
101       else
102         addr = vlib_get_buffer_data_physical_address (vm, rxq->bufs[slot]);
103       d->qword[0] = addr;
104       d->qword[1] = 0;
105       slot = (slot + 1) & mask;
106     }
107
108   CLIB_MEMORY_BARRIER ();
109   *(rxq->qrx_tail) = slot;
110 }
111
112 static_always_inline void
113 avf_check_for_error (vlib_node_runtime_t * node, avf_rx_vector_entry_t * rxve,
114                      vlib_buffer_t * b, u32 * next)
115 {
116   avf_main_t *am = &avf_main;
117   avf_ptype_t *ptype;
118   if (PREDICT_FALSE (rxve->error))
119     {
120       b->error = node->errors[AVF_INPUT_ERROR_RX_PACKET_ERROR];
121       ptype = am->ptypes + rxve->ptype;
122       /* retract */
123       vlib_buffer_advance (b, --ptype->buffer_advance);
124       *next = VNET_DEVICE_INPUT_NEXT_DROP;
125     }
126 }
127
128 static_always_inline u32
129 avf_find_next (avf_rx_vector_entry_t * rxve, vlib_buffer_t * b,
130                int maybe_tagged)
131 {
132   avf_main_t *am = &avf_main;
133   ethernet_header_t *e = (ethernet_header_t *) b->data;
134   avf_ptype_t *ptype;
135   if (maybe_tagged && ethernet_frame_is_tagged (e->type))
136     return VNET_DEVICE_INPUT_NEXT_ETHERNET_INPUT;
137   ptype = am->ptypes + rxve->ptype;
138   vlib_buffer_advance (b, ptype->buffer_advance);
139   b->flags |= ptype->flags;
140   return ptype->next_node;
141 }
142
143
144 static_always_inline uword
145 avf_device_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
146                          vlib_frame_t * frame, avf_device_t * ad, u16 qid,
147                          int with_features_or_tracing)
148 {
149   avf_main_t *am = &avf_main;
150   vnet_main_t *vnm = vnet_get_main ();
151   u32 thr_idx = vlib_get_thread_index ();
152   avf_per_thread_data_t *ptd =
153     vec_elt_at_index (am->per_thread_data, thr_idx);
154   avf_rxq_t *rxq = vec_elt_at_index (ad->rxqs, qid);
155   avf_rx_vector_entry_t *rxve;
156   uword n_trace = vlib_get_trace_count (vm, node);
157   u32 next_index = VNET_DEVICE_INPUT_NEXT_ETHERNET_INPUT;
158   avf_rx_desc_t *d;
159   u32 *to_next = 0;
160   u32 n_rx_packets = 0;
161   u32 n_rx_bytes = 0;
162   u32 sw_if_idx[VLIB_N_RX_TX] = {[VLIB_RX] = ad->sw_if_index,[VLIB_TX] = ~0 };
163   u16 mask = rxq->size - 1;
164   u16 n_rxv = 0;
165   u8 maybe_error = 0;
166
167   /* fetch up to AVF_RX_VECTOR_SZ from the rx ring, unflatten them and
168      copy needed data from descriptor to rx vector */
169   d = rxq->descs + rxq->next;
170   while ((d->qword[1] & AVF_RX_DESC_STATUS_DD) && n_rxv < AVF_RX_VECTOR_SZ)
171     {
172       u16 next_pf = (rxq->next + 8) & mask;
173       CLIB_PREFETCH (rxq->descs + next_pf, CLIB_CACHE_LINE_BYTES, LOAD);
174       rxve = ptd->rx_vector + n_rxv;
175       rxve->bi = rxq->bufs[rxq->next];
176       rxve->status = avf_get_u64_bits (d, 8, 18, 0);
177       rxve->error = avf_get_u64_bits (d, 8, 26, 19);
178       rxve->ptype = avf_get_u64_bits (d, 8, 37, 30);
179       rxve->length = avf_get_u64_bits (d, 8, 63, 38);
180       maybe_error |= rxve->error;
181
182       /* deal with chained buffers */
183       while (PREDICT_FALSE ((d->qword[1] & AVF_RX_DESC_STATUS_EOP) == 0))
184         {
185           clib_error ("fixme");
186         }
187
188       /* next */
189       rxq->next = (rxq->next + 1) & mask;
190       d = rxq->descs + rxq->next;
191       n_rxv++;
192       rxq->n_bufs--;
193     }
194
195   if (n_rxv == 0)
196     return 0;
197
198   /* refill rx ring */
199   if (ad->flags & AVF_DEVICE_F_IOVA)
200     avf_rxq_refill (vm, node, rxq, 1 /* use_iova */ );
201   else
202     avf_rxq_refill (vm, node, rxq, 0 /* use_iova */ );
203
204   n_rx_packets = n_rxv;
205   rxve = ptd->rx_vector;
206   while (n_rxv)
207     {
208       u32 n_left_to_next;
209       u32 bi0, bi1, bi2, bi3;
210       vlib_buffer_t *b0, *b1, *b2, *b3;
211       u32 next0, next1, next2, next3;
212
213       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
214
215       while (n_rxv >= 12 && n_left_to_next >= 4)
216         {
217           vlib_buffer_t *p;
218           p = vlib_get_buffer (vm, rxve[8].bi);
219           vlib_prefetch_buffer_header (p, LOAD);
220           CLIB_PREFETCH (p->data, CLIB_CACHE_LINE_BYTES, LOAD);
221
222           p = vlib_get_buffer (vm, rxve[9].bi);
223           vlib_prefetch_buffer_header (p, LOAD);
224           CLIB_PREFETCH (p->data, CLIB_CACHE_LINE_BYTES, LOAD);
225
226           p = vlib_get_buffer (vm, rxve[10].bi);
227           vlib_prefetch_buffer_header (p, LOAD);
228           CLIB_PREFETCH (p->data, CLIB_CACHE_LINE_BYTES, LOAD);
229
230           p = vlib_get_buffer (vm, rxve[11].bi);
231           vlib_prefetch_buffer_header (p, LOAD);
232           CLIB_PREFETCH (p->data, CLIB_CACHE_LINE_BYTES, LOAD);
233
234           to_next[0] = bi0 = rxve[0].bi;
235           to_next[1] = bi1 = rxve[1].bi;
236           to_next[2] = bi2 = rxve[2].bi;
237           to_next[3] = bi3 = rxve[3].bi;
238
239           b0 = vlib_get_buffer (vm, bi0);
240           b1 = vlib_get_buffer (vm, bi1);
241           b2 = vlib_get_buffer (vm, bi2);
242           b3 = vlib_get_buffer (vm, bi3);
243
244           b0->current_length = rxve[0].length;
245           b1->current_length = rxve[1].length;
246           b2->current_length = rxve[2].length;
247           b3->current_length = rxve[3].length;
248
249           n_rx_bytes += b0->current_length;
250           n_rx_bytes += b1->current_length;
251           n_rx_bytes += b2->current_length;
252           n_rx_bytes += b3->current_length;
253
254           if (PREDICT_TRUE (ad->per_interface_next_index == ~0))
255             {
256               ethernet_header_t *e0, *e1, *e2, *e3;
257
258               e0 = (ethernet_header_t *) b0->data;
259               e1 = (ethernet_header_t *) b1->data;
260               e2 = (ethernet_header_t *) b2->data;
261               e3 = (ethernet_header_t *) b3->data;
262
263               if (ethernet_frame_is_any_tagged_x4 (e0->type, e1->type,
264                                                    e2->type, e3->type))
265                 {
266                   next0 = avf_find_next (rxve, b0, 1);
267                   next1 = avf_find_next (rxve + 1, b1, 1);
268                   next2 = avf_find_next (rxve + 2, b2, 1);
269                   next3 = avf_find_next (rxve + 3, b3, 1);
270                 }
271               else
272                 {
273                   next0 = avf_find_next (rxve, b0, 0);
274                   next1 = avf_find_next (rxve + 1, b1, 0);
275                   next2 = avf_find_next (rxve + 2, b2, 0);
276                   next3 = avf_find_next (rxve + 3, b3, 0);
277                 }
278
279               if (with_features_or_tracing)
280                 vnet_feature_start_device_input_x4 (ad->sw_if_index, &next0,
281                                                     &next1, &next2, &next3,
282                                                     b0, b1, b2, b3);
283
284               if (PREDICT_FALSE (maybe_error))
285                 {
286                   avf_check_for_error (node, rxve + 0, b0, &next0);
287                   avf_check_for_error (node, rxve + 1, b1, &next1);
288                   avf_check_for_error (node, rxve + 2, b2, &next2);
289                   avf_check_for_error (node, rxve + 3, b3, &next3);
290                 }
291             }
292           else
293             next0 = next1 = next2 = next3 = ad->per_interface_next_index;
294
295           clib_memcpy (vnet_buffer (b0)->sw_if_index, sw_if_idx,
296                        sizeof (sw_if_idx));
297           clib_memcpy (vnet_buffer (b1)->sw_if_index, sw_if_idx,
298                        sizeof (sw_if_idx));
299           clib_memcpy (vnet_buffer (b2)->sw_if_index, sw_if_idx,
300                        sizeof (sw_if_idx));
301           clib_memcpy (vnet_buffer (b3)->sw_if_index, sw_if_idx,
302                        sizeof (sw_if_idx));
303
304           VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
305           VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b1);
306           VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b2);
307           VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b3);
308
309           if (with_features_or_tracing && PREDICT_FALSE (n_trace))
310             {
311               avf_input_trace (vm, node, next0, b0, &n_trace, ad, rxve);
312               if (n_trace)
313                 avf_input_trace (vm, node, next1, b1, &n_trace, ad, rxve + 1);
314               if (n_trace)
315                 avf_input_trace (vm, node, next2, b2, &n_trace, ad, rxve + 2);
316               if (n_trace)
317                 avf_input_trace (vm, node, next3, b3, &n_trace, ad, rxve + 3);
318             }
319
320           /* next */
321           to_next += 4;
322           n_left_to_next -= 4;
323           rxve += 4;
324           n_rxv -= 4;
325
326           /* enqueue */
327           vlib_validate_buffer_enqueue_x4 (vm, node, next_index, to_next,
328                                            n_left_to_next, bi0, bi1, bi2, bi3,
329                                            next0, next1, next2, next3);
330         }
331       while (n_rxv && n_left_to_next)
332         {
333           bi0 = rxve[0].bi;
334           to_next[0] = bi0;
335           b0 = vlib_get_buffer (vm, bi0);
336
337           b0->current_length = rxve->length;
338           n_rx_bytes += b0->current_length;
339
340           if (PREDICT_TRUE (ad->per_interface_next_index == ~0))
341             {
342               next0 = avf_find_next (rxve, b0, 1);
343               if (with_features_or_tracing)
344                 vnet_feature_start_device_input_x1 (ad->sw_if_index, &next0,
345                                                     b0);
346               avf_check_for_error (node, rxve + 0, b0, &next0);
347             }
348           else
349             next0 = ad->per_interface_next_index;
350
351           clib_memcpy (vnet_buffer (b0)->sw_if_index, sw_if_idx,
352                        sizeof (sw_if_idx));
353
354           VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
355           if (with_features_or_tracing && PREDICT_FALSE (n_trace > 0))
356             avf_input_trace (vm, node, next0, b0, &n_trace, ad, rxve);
357
358           /* next */
359           to_next += 1;
360           n_left_to_next -= 1;
361           rxve += 1;
362           n_rxv -= 1;
363
364           /* enqueue */
365           vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
366                                            n_left_to_next, bi0, next0);
367         }
368       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
369     }
370
371   vlib_increment_combined_counter (vnm->interface_main.combined_sw_if_counters
372                                    + VNET_INTERFACE_COUNTER_RX, thr_idx,
373                                    ad->hw_if_index, n_rx_packets, n_rx_bytes);
374
375   return n_rx_packets;
376 }
377
378 VLIB_NODE_FN (avf_input_node) (vlib_main_t * vm, vlib_node_runtime_t * node,
379                                vlib_frame_t * frame)
380 {
381   u32 n_rx = 0;
382   avf_main_t *am = &avf_main;
383   vnet_device_input_runtime_t *rt = (void *) node->runtime_data;
384   vnet_device_and_queue_t *dq;
385
386   foreach_device_and_queue (dq, rt->devices_and_queues)
387   {
388     avf_device_t *ad;
389     ad = vec_elt_at_index (am->devices, dq->dev_instance);
390     if ((ad->flags & AVF_DEVICE_F_ADMIN_UP) == 0)
391       continue;
392     if (vnet_device_input_have_features (ad->sw_if_index) ||
393         vlib_get_trace_count (vm, node))
394       n_rx += avf_device_input_inline (vm, node, frame, ad, dq->queue_id, 1);
395     else
396       n_rx += avf_device_input_inline (vm, node, frame, ad, dq->queue_id, 0);
397   }
398   return n_rx;
399 }
400
401 #ifndef CLIB_MARCH_VARIANT
402 /* *INDENT-OFF* */
403 VLIB_REGISTER_NODE (avf_input_node) = {
404   .name = "avf-input",
405   .sibling_of = "device-input",
406   .format_trace = format_avf_input_trace,
407   .type = VLIB_NODE_TYPE_INPUT,
408   .state = VLIB_NODE_STATE_DISABLED,
409   .n_errors = AVF_INPUT_N_ERROR,
410   .error_strings = avf_input_error_strings,
411 };
412 #endif
413
414 /* *INDENT-ON* */
415
416
417 /*
418  * fd.io coding-style-patch-verification: ON
419  *
420  * Local Variables:
421  * eval: (c-set-style "gnu")
422  * End:
423  */