hs-test: logging improvements
[vpp.git] / src / plugins / l3xc / l3xc_node.c
1 /*
2  * Copyright (c) 2019 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 <plugins/l3xc/l3xc.h>
17 #include <vnet/feature/feature.h>
18
19 typedef enum l3xc_next_t_
20 {
21   L3XC_NEXT_DROP,
22   L3XC_N_NEXT,
23 } l3xc_next_t;
24
25 typedef struct l3xc_input_trace_t_
26 {
27   index_t l3xci;
28   index_t lbi;
29 } l3xc_input_trace_t;
30
31 typedef enum
32 {
33 #define l3xc_error(n,s) L3XC_ERROR_##n,
34 #include "l3xc_error.def"
35 #undef l3xc_error
36   L3XC_N_ERROR,
37 } l3xc_error_t;
38
39 always_inline uword
40 l3xc_input_inline (vlib_main_t * vm,
41                    vlib_node_runtime_t * node,
42                    vlib_frame_t * frame, fib_protocol_t fproto)
43 {
44   vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b;
45   u16 nexts[VLIB_FRAME_SIZE], *next;
46   u32 n_left, *from;
47
48   from = vlib_frame_vector_args (frame);
49   n_left = frame->n_vectors;
50   b = bufs;
51   next = nexts;
52
53   vlib_get_buffers (vm, from, bufs, n_left);
54
55   while (n_left >= 8)
56     {
57       const l3xc_t *l3xc0, *l3xc1, *l3xc2, *l3xc3;
58       u32 l3xci0, l3xci1, l3xci2, l3xci3;
59       u32 next_u32;
60
61       /* Prefetch next iteration. */
62       {
63         vlib_prefetch_buffer_header (b[4], LOAD);
64         vlib_prefetch_buffer_header (b[5], LOAD);
65         vlib_prefetch_buffer_header (b[6], LOAD);
66         vlib_prefetch_buffer_header (b[7], LOAD);
67       }
68
69       l3xci0 =
70         *(u32 *) vnet_feature_next_with_data (&next_u32, b[0],
71                                               sizeof (l3xci0));
72       l3xci1 =
73         *(u32 *) vnet_feature_next_with_data (&next_u32, b[1],
74                                               sizeof (l3xci1));
75       l3xci2 =
76         *(u32 *) vnet_feature_next_with_data (&next_u32, b[2],
77                                               sizeof (l3xci2));
78       l3xci3 =
79         *(u32 *) vnet_feature_next_with_data (&next_u32, b[3],
80                                               sizeof (l3xci3));
81
82       l3xc0 = l3xc_get (l3xci0);
83       l3xc1 = l3xc_get (l3xci1);
84       l3xc2 = l3xc_get (l3xci2);
85       l3xc3 = l3xc_get (l3xci3);
86
87       next[0] = l3xc0->l3xc_dpo.dpoi_next_node;
88       next[1] = l3xc1->l3xc_dpo.dpoi_next_node;
89       next[2] = l3xc2->l3xc_dpo.dpoi_next_node;
90       next[3] = l3xc3->l3xc_dpo.dpoi_next_node;
91
92       vnet_buffer (b[0])->ip.adj_index[VLIB_TX] = l3xc0->l3xc_dpo.dpoi_index;
93       vnet_buffer (b[1])->ip.adj_index[VLIB_TX] = l3xc1->l3xc_dpo.dpoi_index;
94       vnet_buffer (b[2])->ip.adj_index[VLIB_TX] = l3xc2->l3xc_dpo.dpoi_index;
95       vnet_buffer (b[3])->ip.adj_index[VLIB_TX] = l3xc3->l3xc_dpo.dpoi_index;
96
97       if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
98         {
99           if (PREDICT_FALSE (b[0]->flags & VLIB_BUFFER_IS_TRACED))
100             {
101               l3xc_input_trace_t *tr;
102
103               tr = vlib_add_trace (vm, node, b[0], sizeof (*tr));
104               tr->l3xci = l3xci0;
105               tr->lbi = vnet_buffer (b[0])->ip.adj_index[VLIB_TX];
106             }
107           if (PREDICT_FALSE (b[1]->flags & VLIB_BUFFER_IS_TRACED))
108             {
109               l3xc_input_trace_t *tr;
110
111               tr = vlib_add_trace (vm, node, b[1], sizeof (*tr));
112               tr->l3xci = l3xci1;
113               tr->lbi = vnet_buffer (b[1])->ip.adj_index[VLIB_TX];
114             }
115           if (PREDICT_FALSE (b[2]->flags & VLIB_BUFFER_IS_TRACED))
116             {
117               l3xc_input_trace_t *tr;
118
119               tr = vlib_add_trace (vm, node, b[2], sizeof (*tr));
120               tr->l3xci = l3xci2;
121               tr->lbi = vnet_buffer (b[2])->ip.adj_index[VLIB_TX];
122             }
123           if (PREDICT_FALSE (b[3]->flags & VLIB_BUFFER_IS_TRACED))
124             {
125               l3xc_input_trace_t *tr;
126
127               tr = vlib_add_trace (vm, node, b[3], sizeof (*tr));
128               tr->l3xci = l3xci3;
129               tr->lbi = vnet_buffer (b[3])->ip.adj_index[VLIB_TX];
130             }
131         }
132
133       b += 4;
134       next += 4;
135       n_left -= 4;
136     }
137
138   while (n_left > 0)
139     {
140       u32 l3xci0, next_u32;
141       const l3xc_t *l3xc0;
142
143       l3xci0 =
144         *(u32 *) vnet_feature_next_with_data (&next_u32, b[0],
145                                               sizeof (l3xci0));
146
147       l3xc0 = l3xc_get (l3xci0);
148
149       next[0] = l3xc0->l3xc_dpo.dpoi_next_node;
150
151       vnet_buffer (b[0])->ip.adj_index[VLIB_TX] = l3xc0->l3xc_dpo.dpoi_index;
152
153       if (PREDICT_FALSE (b[0]->flags & VLIB_BUFFER_IS_TRACED))
154         {
155           l3xc_input_trace_t *tr;
156
157           tr = vlib_add_trace (vm, node, b[0], sizeof (*tr));
158           tr->l3xci = l3xci0;
159           tr->lbi = vnet_buffer (b[0])->ip.adj_index[VLIB_TX];
160         }
161
162       b += 1;
163       next += 1;
164       n_left -= 1;
165     }
166
167   vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
168   return frame->n_vectors;
169 }
170
171 static uword
172 l3xc_input_ip4 (vlib_main_t * vm,
173                 vlib_node_runtime_t * node, vlib_frame_t * frame)
174 {
175   return l3xc_input_inline (vm, node, frame, FIB_PROTOCOL_IP4);
176 }
177
178 static uword
179 l3xc_input_ip6 (vlib_main_t * vm,
180                 vlib_node_runtime_t * node, vlib_frame_t * frame)
181 {
182   return l3xc_input_inline (vm, node, frame, FIB_PROTOCOL_IP6);
183 }
184
185 static u8 *
186 format_l3xc_input_trace (u8 * s, va_list * args)
187 {
188   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
189   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
190   l3xc_input_trace_t *t = va_arg (*args, l3xc_input_trace_t *);
191
192   s = format (s, "l3xc-index:%d lb-index:%d", t->l3xci, t->lbi);
193   return s;
194 }
195
196 static char *l3xc_error_strings[] = {
197 #define l3xc_error(n,s) s,
198 #include "l3xc_error.def"
199 #undef l3xc_error
200 };
201
202 VLIB_REGISTER_NODE (l3xc_ip4_node) =
203 {
204   .function = l3xc_input_ip4,
205   .name = "l3xc-input-ip4",
206   .vector_size = sizeof (u32),
207   .format_trace = format_l3xc_input_trace,
208   .type = VLIB_NODE_TYPE_INTERNAL,
209   .n_errors = L3XC_N_ERROR,
210   .error_strings = l3xc_error_strings,
211   .n_next_nodes = L3XC_N_NEXT,
212   .next_nodes =
213   {
214     [L3XC_NEXT_DROP] = "error-drop",
215   }
216 };
217
218 VLIB_REGISTER_NODE (l3xc_ip6_node) =
219 {
220   .function = l3xc_input_ip6,
221   .name = "l3xc-input-ip6",
222   .vector_size = sizeof (u32),
223   .format_trace = format_l3xc_input_trace,
224   .type = VLIB_NODE_TYPE_INTERNAL,
225   .n_errors = 0,
226   .n_next_nodes = L3XC_N_NEXT,
227
228   .next_nodes =
229   {
230     [L3XC_NEXT_DROP] = "error-drop",
231   }
232 };
233
234 VNET_FEATURE_INIT (l3xc_ip4_feat, static) =
235 {
236   .arc_name = "ip4-unicast",
237   .node_name = "l3xc-input-ip4",
238   .runs_after = VNET_FEATURES ("acl-plugin-in-ip4-fa"),
239 };
240
241 VNET_FEATURE_INIT (l3xc_ip6_feat, static) =
242 {
243   .arc_name = "ip6-unicast",
244   .node_name = "l3xc-input-ip6",
245   .runs_after = VNET_FEATURES ("acl-plugin-in-ip6-fa"),
246 };
247
248 /*
249  * fd.io coding-style-patch-verification: ON
250  *
251  * Local Variables:
252  * eval: (c-set-style "gnu")
253  * End:
254  */