FD.io VPP  v19.08.3-2-gbabecb413
Vector Packet Processing
nsim_input.c
Go to the documentation of this file.
1 /*
2  * nsim.c - skeleton vpp engine plug-in
3  *
4  * Copyright (c) <current-year> <your-organization>
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include <vlib/vlib.h>
19 #include <vnet/vnet.h>
20 #include <vnet/pg/pg.h>
21 #include <vppinfra/error.h>
22 #include <nsim/nsim.h>
23 
24 typedef struct
25 {
29 
30 #ifndef CLIB_MARCH_VARIANT
31 /* packet trace format function */
32 static u8 *
33 format_nsim_tx_trace (u8 * s, va_list * args)
34 {
35  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
36  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
37  nsim_tx_trace_t *t = va_arg (*args, nsim_tx_trace_t *);
38 
39  s = format (s, "NSIM: tx at %.6f next_index %d", t->expired, t->next_index);
40  return s;
41 }
42 #endif /* CLIB_MARCH_VARIANT */
43 
44 #define foreach_nsim_tx_error \
45 _(TRANSMITTED, "Packets transmitted")
46 
47 typedef enum
48 {
49 #define _(sym,str) NSIM_TX_ERROR_##sym,
51 #undef _
54 
55 #ifndef CLIB_MARCH_VARIANT
56 static char *nsim_tx_error_strings[] = {
57 #define _(sym,string) string,
59 #undef _
60 };
61 #endif /* CLIB_MARCH_VARIANT */
62 
63 typedef enum
64 {
67 } nsim_next_t;
68 
71  vlib_frame_t * f, int is_trace)
72 {
73  nsim_main_t *nsm = &nsim_main;
74  u32 my_thread_index = vm->thread_index;
75  nsim_wheel_t *wp = nsm->wheel_by_thread[my_thread_index];
76  f64 now = vlib_time_now (vm);
77  uword n_tx_packets = 0;
78  u32 bi0, next0;
79  u32 *to_next;
80  u32 next_index;
81  u32 n_left_to_next;
83 
84  /* Nothing on the scheduler wheel? */
85  if (wp->cursize == 0)
86  return 0;
87 
88  /* First entry on the wheel isn't expired? */
89  ep = wp->entries + wp->head;
90  if (ep->tx_time > now)
91  return n_tx_packets;
92 
93  next_index = node->cached_next_index;
94 
95  /* Be aware: this is not the usual coding pattern */
96  while (wp->cursize && ep->tx_time <= now)
97  {
98  vlib_buffer_t *b0;
99 
100  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
101 
102  while (n_left_to_next > 0)
103  {
104  /* prefetch one line / 2 entries ahead */
105  if ((((uword) ep) & (CLIB_CACHE_LINE_BYTES - 1)) == 0)
106  CLIB_PREFETCH ((ep + 2), CLIB_CACHE_LINE_BYTES, LOAD);
107  /* Pick up buffer from the wheel */
108  bi0 = ep->buffer_index;
109 
110  to_next[0] = bi0;
111  to_next += 1;
112  n_left_to_next -= 1;
113 
114  next0 = ep->output_next_index;
115 
116  /* verify speculative enqueue, maybe switch current next frame */
117  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
118  to_next, n_left_to_next,
119  bi0, next0);
120  /* Advance to the next ring entry */
121  wp->head++;
122  if (wp->head == wp->wheel_size)
123  wp->head = 0;
124  wp->cursize--;
125  ep = wp->entries + wp->head;
126  n_tx_packets++;
127 
128  if (is_trace)
129  {
130  b0 = vlib_get_buffer (vm, bi0);
131  if (b0->flags & VLIB_BUFFER_IS_TRACED)
132  {
133  nsim_tx_trace_t *t =
134  vlib_add_trace (vm, node, b0, sizeof (*t));
135  t->expired = now;
136  t->next_index = next0;
137  }
138  }
139 
140  /* Out of ring entries? */
141  if (PREDICT_FALSE (wp->cursize == 0))
142  break;
143  }
144 
145  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
146 
147  /* If the current entry hasn't expired, we're done */
148  if (ep->tx_time > now)
149  break;
150  }
152  NSIM_TX_ERROR_TRANSMITTED, n_tx_packets);
153  return n_tx_packets;
154 }
155 
157  vlib_frame_t * frame)
158 {
159  if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE))
160  return nsim_input_inline (vm, node, frame, 1 /* is_trace */ );
161  else
162  return nsim_input_inline (vm, node, frame, 0 /* is_trace */ );
163 
164 }
165 
166 /* *INDENT-OFF* */
167 #ifndef CLIB_MARCH_VARIANT
169 {
170  .type = VLIB_NODE_TYPE_INPUT,
171  .name = "nsim-wheel",
172 
173  /* Will be enabled if/when the feature is configured */
174  .state = VLIB_NODE_STATE_DISABLED,
175 
176  .format_trace = format_nsim_tx_trace,
177 
178  .n_errors = NSIM_TX_N_ERROR,
179  .error_strings = nsim_tx_error_strings,
180 };
181 #endif /* CLIB_MARCH_VARIANT */
182 /* *INDENT-ON* */
183 
184 /*
185  * fd.io coding-style-patch-verification: ON
186  *
187  * Local Variables:
188  * eval: (c-set-style "gnu")
189  * End:
190  */
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:124
static char * nsim_tx_error_strings[]
Definition: nsim_input.c:56
#define CLIB_UNUSED(x)
Definition: clib.h:83
Definition: nsim.h:28
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:279
u32 thread_index
Definition: main.h:218
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
#define VLIB_NODE_FN(node)
Definition: node.h:202
unsigned char u8
Definition: types.h:56
double f64
Definition: types.h:142
static u8 * format_nsim_tx_trace(u8 *s, va_list *args)
Definition: nsim_input.c:33
u32 cursize
Definition: nsim.h:41
#define always_inline
Definition: clib.h:99
unsigned int u32
Definition: types.h:88
nsim_tx_error_t
Definition: nsim_input.c:47
#define foreach_nsim_tx_error
Definition: nsim_input.c:44
nsim_next_t
Definition: nsim_input.c:63
#define PREDICT_FALSE(x)
Definition: clib.h:112
u32 node_index
Node index.
Definition: node.h:496
#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:218
#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:338
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:1150
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:80
vlib_main_t * vm
Definition: buffer.c:323
static uword nsim_input_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *f, int is_trace)
Definition: nsim_input.c:70
nsim_wheel_entry_t * entries
Definition: nsim.h:44
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:456
u32 head
Definition: nsim.h:42
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:515
nsim_wheel_t ** wheel_by_thread
Definition: nsim.h:64
vlib_node_registration_t nsim_input_node
(constructor) VLIB_REGISTER_NODE (nsim_input_node)
Definition: nsim_input.c:168
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
f64 tx_time
Definition: nsim.h:30
VLIB buffer representation.
Definition: buffer.h:102
u64 uword
Definition: types.h:112
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:302
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
u32 wheel_size
Definition: nsim.h:40
nsim_main_t nsim_main
Definition: nsim.c:59
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:85