Line data Source code
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 <vppinfra/error.h>
21 : #include <nsim/nsim.h>
22 :
23 : typedef struct
24 : {
25 : f64 expired;
26 : u32 next_index;
27 : } nsim_tx_trace_t;
28 :
29 : #ifndef CLIB_MARCH_VARIANT
30 : /* packet trace format function */
31 : static u8 *
32 0 : format_nsim_tx_trace (u8 * s, va_list * args)
33 : {
34 0 : CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
35 0 : CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
36 0 : nsim_tx_trace_t *t = va_arg (*args, nsim_tx_trace_t *);
37 :
38 0 : s = format (s, "NSIM: tx at %.6f next_index %d", t->expired, t->next_index);
39 0 : return s;
40 : }
41 : #endif /* CLIB_MARCH_VARIANT */
42 :
43 : #define foreach_nsim_tx_error \
44 : _(TRANSMITTED, "Packets transmitted")
45 :
46 : typedef enum
47 : {
48 : #define _(sym,str) NSIM_TX_ERROR_##sym,
49 : foreach_nsim_tx_error
50 : #undef _
51 : NSIM_TX_N_ERROR,
52 : } nsim_tx_error_t;
53 :
54 : #ifndef CLIB_MARCH_VARIANT
55 : static char *nsim_tx_error_strings[] = {
56 : #define _(sym,string) string,
57 : foreach_nsim_tx_error
58 : #undef _
59 : };
60 : #endif /* CLIB_MARCH_VARIANT */
61 :
62 : typedef enum
63 : {
64 : NSIM_NEXT_DROP,
65 : NSIM_N_NEXT,
66 : } nsim_next_t;
67 :
68 : always_inline uword
69 0 : nsim_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
70 : vlib_frame_t * f, int is_trace)
71 : {
72 0 : nsim_main_t *nsm = &nsim_main;
73 0 : nsim_wheel_t *wp = nsm->wheel_by_thread[vm->thread_index];
74 : nsim_wheel_entry_t *ep;
75 : f64 now;
76 :
77 : /* Nothing on the scheduler wheel? */
78 0 : if (wp->cursize == 0)
79 0 : return 0;
80 :
81 : /* First entry on the wheel isn't expired? */
82 0 : ep = wp->entries + wp->head;
83 0 : now = vlib_time_now (vm);
84 0 : if (ep->tx_time > now)
85 0 : return 0;
86 :
87 0 : u32 n_burst = clib_min (wp->cursize, NSIM_MAX_TX_BURST), n_tx_packets = 0;
88 : u32 froms[NSIM_MAX_TX_BURST], *from;
89 : u16 nexts[NSIM_MAX_TX_BURST], *next;
90 :
91 0 : from = froms;
92 0 : next = nexts;
93 0 : while (n_tx_packets < n_burst && ep->tx_time <= now)
94 : {
95 : /* prefetch one line / 2 entries ahead */
96 0 : if ((((uword) ep) & (CLIB_CACHE_LINE_BYTES - 1)) == 0)
97 0 : clib_prefetch_load ((ep + 2));
98 :
99 0 : ep = wp->entries + wp->head;
100 0 : from[0] = ep->buffer_index;
101 0 : next[0] = ep->output_next_index;
102 :
103 0 : wp->head++;
104 0 : if (wp->head == wp->wheel_size)
105 0 : wp->head = 0;
106 :
107 0 : from += 1;
108 0 : next += 1;
109 0 : n_tx_packets++;
110 : }
111 :
112 0 : wp->cursize -= n_tx_packets;
113 0 : vlib_buffer_enqueue_to_next (vm, node, froms, nexts, n_tx_packets);
114 0 : vlib_node_increment_counter (vm, node->node_index,
115 : NSIM_TX_ERROR_TRANSMITTED, n_tx_packets);
116 0 : return n_tx_packets;
117 : }
118 :
119 2236 : VLIB_NODE_FN (nsim_input_node) (vlib_main_t * vm, vlib_node_runtime_t * node,
120 : vlib_frame_t * frame)
121 : {
122 0 : if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE))
123 0 : return nsim_input_inline (vm, node, frame, 1 /* is_trace */ );
124 : else
125 0 : return nsim_input_inline (vm, node, frame, 0 /* is_trace */ );
126 :
127 : }
128 :
129 : /* *INDENT-OFF* */
130 : #ifndef CLIB_MARCH_VARIANT
131 47624 : VLIB_REGISTER_NODE (nsim_input_node) =
132 : {
133 : .type = VLIB_NODE_TYPE_INPUT,
134 : .name = "nsim-wheel",
135 :
136 : /* Will be enabled if/when the feature is configured */
137 : .state = VLIB_NODE_STATE_DISABLED,
138 :
139 : .format_trace = format_nsim_tx_trace,
140 :
141 : .n_errors = NSIM_TX_N_ERROR,
142 : .error_strings = nsim_tx_error_strings,
143 : };
144 : #endif /* CLIB_MARCH_VARIANT */
145 : /* *INDENT-ON* */
146 :
147 : /*
148 : * fd.io coding-style-patch-verification: ON
149 : *
150 : * Local Variables:
151 : * eval: (c-set-style "gnu")
152 : * End:
153 : */
|