FD.io VPP  v16.12-rc0-308-g931be3a
Vector Packet Processing
node.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 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 #include "ssvm_eth.h"
16 
18 
19 typedef struct
20 {
24 
25 /* packet trace format function */
26 static u8 *
27 format_ssvm_eth_input_trace (u8 * s, va_list * args)
28 {
29  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
30  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
31  ssvm_eth_input_trace_t *t = va_arg (*args, ssvm_eth_input_trace_t *);
32 
33  s = format (s, "SSVM_ETH_INPUT: sw_if_index %d, next index %d",
34  t->sw_if_index, t->next_index);
35  return s;
36 }
37 
39 
40 #define foreach_ssvm_eth_input_error \
41 _(NO_BUFFERS, "Rx packet drops (no buffers)")
42 
43 typedef enum
44 {
45 #define _(sym,str) SSVM_ETH_INPUT_ERROR_##sym,
47 #undef _
50 
51 static char *ssvm_eth_input_error_strings[] = {
52 #define _(sym,string) string,
54 #undef _
55 };
56 
57 typedef enum
58 {
66 
67 static inline uword
69  ssvm_private_t * intfc, vlib_node_runtime_t * node)
70 {
71  ssvm_shared_header_t *sh = intfc->sh;
72  vlib_main_t *vm = em->vlib_main;
74  ssvm_eth_queue_elt_t *elt, *elts;
75  u32 elt_index;
76  u32 my_pid = intfc->my_pid;
77  int rx_queue_index;
78  u32 n_to_alloc = VLIB_FRAME_SIZE * 2;
79  u32 n_allocated, n_present_in_cache;
80 #if DPDK > 0
82 #else
83  u32 next_index = 0;
84 #endif
86  u32 n_left_to_next, *to_next;
87  u32 next0;
88  u32 n_buffers;
89  u32 n_available;
90  u32 bi0, saved_bi0;
91  vlib_buffer_t *b0, *prev;
92  u32 saved_cache_size = 0;
93  ethernet_header_t *eh0;
94  u16 type0;
95  u32 n_rx_bytes = 0, l3_offset0;
96  u32 cpu_index = os_get_cpu_number ();
97  u32 trace_cnt __attribute__ ((unused)) = vlib_get_trace_count (vm, node);
98  volatile u32 *lock;
99  u32 *elt_indices;
100  uword n_trace = vlib_get_trace_count (vm, node);
101 
102  /* Either side down? buh-bye... */
105  return 0;
106 
107  if (intfc->i_am_master)
109  else
111 
112  /* Nothing to do? */
113  if (q->cursize == 0)
114  return 0;
115 
117 
118  vec_reset_length (intfc->rx_queue);
119 
120  lock = (u32 *) q;
121  while (__sync_lock_test_and_set (lock, 1))
122  ;
123  while (q->cursize > 0)
124  {
125  unix_shared_memory_queue_sub_raw (q, (u8 *) & elt_index);
126  ASSERT (elt_index < 2048);
127  vec_add1 (intfc->rx_queue, elt_index);
128  }
130  *lock = 0;
131 
132  n_present_in_cache = vec_len (em->buffer_cache);
133 
134  if (vec_len (em->buffer_cache) < vec_len (intfc->rx_queue) * 2)
135  {
137  n_to_alloc + vec_len (em->buffer_cache) - 1);
138  n_allocated =
139  vlib_buffer_alloc (vm, &em->buffer_cache[n_present_in_cache],
140  n_to_alloc);
141 
142  n_present_in_cache += n_allocated;
143  _vec_len (em->buffer_cache) = n_present_in_cache;
144  }
145 
146  elts = (ssvm_eth_queue_elt_t *) (sh->opaque[CHUNK_POOL_INDEX]);
147 
148  n_buffers = vec_len (intfc->rx_queue);
149  rx_queue_index = 0;
150 
151  while (n_buffers > 0)
152  {
153  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
154 
155  while (n_buffers > 0 && n_left_to_next > 0)
156  {
157  elt = elts + intfc->rx_queue[rx_queue_index];
158 
159  saved_cache_size = n_present_in_cache;
160  if (PREDICT_FALSE (saved_cache_size == 0))
161  {
162  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
163  goto out;
164  }
165  saved_bi0 = bi0 = em->buffer_cache[--n_present_in_cache];
166  b0 = vlib_get_buffer (vm, bi0);
167  prev = 0;
168 
169  while (1)
170  {
172 
173  b0->current_data = elt->current_data_hint;
177 
178  clib_memcpy (b0->data + b0->current_data, elt->data,
179  b0->current_length);
180 
181  if (PREDICT_FALSE (prev != 0))
182  prev->next_buffer = bi0;
183 
185  {
186  prev = b0;
187  if (PREDICT_FALSE (n_present_in_cache == 0))
188  {
189  vlib_put_next_frame (vm, node, next_index,
190  n_left_to_next);
191  goto out;
192  }
193  bi0 = em->buffer_cache[--n_present_in_cache];
194  b0 = vlib_get_buffer (vm, bi0);
195  }
196  else
197  break;
198  }
199 
200  saved_cache_size = n_present_in_cache;
201 
202  to_next[0] = saved_bi0;
203  to_next++;
204  n_left_to_next--;
205 
206  b0 = vlib_get_buffer (vm, saved_bi0);
207  eh0 = vlib_buffer_get_current (b0);
208 
209  type0 = clib_net_to_host_u16 (eh0->type);
210 
212 
213  if (type0 == ETHERNET_TYPE_IP4)
215  else if (type0 == ETHERNET_TYPE_IP6)
217  else if (type0 == ETHERNET_TYPE_MPLS_UNICAST)
219 
220  l3_offset0 = ((next0 == SSVM_ETH_INPUT_NEXT_IP4_INPUT ||
223  sizeof (ethernet_header_t) : 0);
224 
225  n_rx_bytes += b0->current_length
227 
228  b0->current_data += l3_offset0;
229  b0->current_length -= l3_offset0;
231 
232  vnet_buffer (b0)->sw_if_index[VLIB_RX] = intfc->vlib_hw_if_index;
233  vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
234 
235  /*
236  * Turn this on if you run into
237  * "bad monkey" contexts, and you want to know exactly
238  * which nodes they've visited... See main.c...
239  */
241 
242  if (PREDICT_FALSE (n_trace > 0))
243  {
245 
246  vlib_trace_buffer (vm, node, next0, b0, /* follow_chain */ 1);
247  vlib_set_trace_count (vm, node, --n_trace);
248 
249  tr = vlib_add_trace (vm, node, b0, sizeof (*tr));
250 
251  tr->next_index = next0;
252  tr->sw_if_index = intfc->vlib_hw_if_index;
253  }
254 
255  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
256  to_next, n_left_to_next,
257  bi0, next0);
258  n_buffers--;
259  rx_queue_index++;
260  }
261 
262  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
263  }
264 
265 out:
266  if (em->buffer_cache)
267  _vec_len (em->buffer_cache) = saved_cache_size;
268  else
269  ASSERT (saved_cache_size == 0);
270 
271  ssvm_lock (sh, my_pid, 2);
272 
273  ASSERT (vec_len (intfc->rx_queue) > 0);
274 
275  n_available = (u32) pointer_to_uword (sh->opaque[CHUNK_POOL_NFREE]);
276  elt_indices = (u32 *) (sh->opaque[CHUNK_POOL_FREELIST_INDEX]);
277 
278  clib_memcpy (&elt_indices[n_available], intfc->rx_queue,
279  vec_len (intfc->rx_queue) * sizeof (u32));
280 
281  n_available += vec_len (intfc->rx_queue);
282  sh->opaque[CHUNK_POOL_NFREE] = uword_to_pointer (n_available, void *);
283 
284  ssvm_unlock (sh);
285 
286  vlib_error_count (vm, node->node_index, SSVM_ETH_INPUT_ERROR_NO_BUFFERS,
287  n_buffers);
288 
290  (vnet_get_main ()->interface_main.combined_sw_if_counters
291  + VNET_INTERFACE_COUNTER_RX, cpu_index,
292  intfc->vlib_hw_if_index, rx_queue_index, n_rx_bytes);
293 
294  return rx_queue_index;
295 }
296 
297 static uword
299  vlib_node_runtime_t * node, vlib_frame_t * frame)
300 {
302  ssvm_private_t *intfc;
303  uword n_rx_packets = 0;
304 
305  vec_foreach (intfc, em->intfcs)
306  {
307  n_rx_packets += ssvm_eth_device_input (em, intfc, node);
308  }
309 
310  return n_rx_packets;
311 }
312 
313 /* *INDENT-OFF* */
315  .function = ssvm_eth_input_node_fn,
316  .name = "ssvm_eth_input",
317  .vector_size = sizeof (u32),
318  .format_trace = format_ssvm_eth_input_trace,
320  .state = VLIB_NODE_STATE_DISABLED,
321 
323  .error_strings = ssvm_eth_input_error_strings,
324 
325  .n_next_nodes = SSVM_ETH_INPUT_N_NEXT,
326 
327  /* edit / add dispositions here */
328  .next_nodes = {
329  [SSVM_ETH_INPUT_NEXT_DROP] = "error-drop",
330  [SSVM_ETH_INPUT_NEXT_ETHERNET_INPUT] = "ethernet-input",
331  [SSVM_ETH_INPUT_NEXT_IP4_INPUT] = "ip4-input",
332  [SSVM_ETH_INPUT_NEXT_IP6_INPUT] = "ip6-input",
333  [SSVM_ETH_INPUT_NEXT_MPLS_INPUT] = "mpls-input",
334  },
335 };
336 
338 /* *INDENT-ON* */
339 
340 
341 /*
342  * fd.io coding-style-patch-verification: ON
343  *
344  * Local Variables:
345  * eval: (c-set-style "gnu")
346  * End:
347  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:396
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Release pointer to next frame vector data.
Definition: main.c:457
VLIB_NODE_FUNCTION_MULTIARCH(ethernet_input_not_l2_node, ethernet_input_not_l2)
Definition: node.c:1054
#define CLIB_UNUSED(x)
Definition: clib.h:79
u32 vlib_hw_if_index
Definition: ssvm.h:76
static u32 vlib_get_trace_count(vlib_main_t *vm, vlib_node_runtime_t *rt)
Definition: trace_funcs.h:143
bad routing header type(not 4)") sr_error (NO_MORE_SEGMENTS
#define VLIB_BUFFER_TRACE_TRAJECTORY_INIT(b)
Definition: buffer.h:402
static void vlib_error_count(vlib_main_t *vm, uword node_index, uword counter, uword increment)
Definition: error_funcs.h:55
u32 * buffer_cache
Definition: ssvm_eth.h:65
void * opaque[SSVM_N_OPAQUE]
Definition: ssvm.h:62
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:482
#define SSVM_BUFFER_NEXT_PRESENT
Definition: ssvm_eth.h:46
struct _vlib_node_registration vlib_node_registration_t
static u8 * format_ssvm_eth_input_trace(u8 *s, va_list *args)
Definition: node.c:27
ssvm_shared_header_t * sh
Definition: ssvm.h:73
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
static void vlib_trace_buffer(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, vlib_buffer_t *b, int follow_chain)
Definition: trace_funcs.h:104
static void vlib_buffer_init_for_free_list(vlib_buffer_t *_dst, vlib_buffer_free_list_t *fl)
Definition: buffer_funcs.h:606
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:78
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:190
vlib_node_registration_t ssvm_eth_input_node
(constructor) VLIB_REGISTER_NODE (ssvm_eth_input_node)
Definition: node.c:17
static uword pointer_to_uword(const void *p)
Definition: types.h:131
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:82
static void ssvm_unlock(ssvm_shared_header_t *h)
Definition: ssvm.h:102
ssvm_eth_input_error_t
Definition: node.c:43
static uword ssvm_eth_device_input(ssvm_eth_main_t *em, ssvm_private_t *intfc, vlib_node_runtime_t *node)
Definition: node.c:68
uword os_get_cpu_number(void)
Definition: unix-misc.c:224
vlib_main_t * vlib_main
Definition: ssvm_eth.h:79
#define PREDICT_FALSE(x)
Definition: clib.h:97
ssvm_private_t * intfcs
Definition: ssvm_eth.h:63
int unix_shared_memory_queue_sub_raw(unix_shared_memory_queue_t *q, u8 *elem)
#define VLIB_FRAME_SIZE
Definition: node.h:328
static uword ssvm_eth_input_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: node.c:298
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Finish enqueueing one buffer forward in the graph.
Definition: buffer_node.h:216
u32 * rx_queue
Definition: ssvm.h:81
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
Definition: node_funcs.h:350
#define uword_to_pointer(u, type)
Definition: types.h:136
#define clib_memcpy(a, b, c)
Definition: string.h:64
#define VLIB_BUFFER_TOTAL_LENGTH_VALID
Definition: buffer.h:99
#define ARRAY_LEN(x)
Definition: clib.h:59
u32 my_pid
Definition: ssvm.h:75
#define VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX
Definition: buffer.h:306
static void vlib_increment_combined_counter(vlib_combined_counter_main_t *cm, u32 cpu_index, u32 index, u32 packet_increment, u32 byte_increment)
Increment a combined counter.
Definition: counter.h:241
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
#define vnet_buffer(b)
Definition: buffer.h:333
vhost_vring_state_t state
Definition: vhost-user.h:80
u32 next_buffer
Next buffer for this linked-list of buffers.
Definition: buffer.h:117
u32 vlib_buffer_alloc(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Allocate buffers into supplied array.
Definition: dpdk_buffer.c:643
u8 data[SSVM_BUFFER_SIZE]
Definition: ssvm_eth.h:55
u64 uword
Definition: types.h:112
static void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace_funcs.h:55
u32 total_length_not_including_first_buffer
Only valid for first buffer in chain.
Definition: buffer.h:112
Definition: defs.h:47
unsigned short u16
Definition: types.h:57
ssvm_eth_main_t ssvm_eth_main
Definition: ssvm_eth.c:17
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
u16 total_length_not_including_first_buffer
Definition: ssvm_eth.h:51
ssvm_eth_input_next_t
Definition: node.c:57
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:143
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:418
u8 data[0]
Packet data.
Definition: buffer.h:154
#define vec_foreach(var, vec)
Vector iterator.
static char * ssvm_eth_input_error_strings[]
Definition: node.c:51
#define CLIB_MEMORY_BARRIER()
Definition: clib.h:101
static vlib_buffer_free_list_t * vlib_buffer_get_free_list(vlib_main_t *vm, u32 free_list_index)
Definition: buffer_funcs.h:337
static void vlib_set_trace_count(vlib_main_t *vm, vlib_node_runtime_t *rt, u32 count)
Definition: trace_funcs.h:159
u32 flags
buffer flags: VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:85
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:69
int i_am_master
Definition: ssvm.h:79
static void ssvm_lock(ssvm_shared_header_t *h, u32 my_pid, u32 tag)
Definition: ssvm.h:85
Definition: defs.h:46
#define foreach_ssvm_eth_input_error
Definition: node.c:40
struct _unix_shared_memory_queue unix_shared_memory_queue_t