gbp: migrate old MULTIARCH macros to VLIB_NODE_FN
[vpp.git] / src / plugins / gbp / gbp_sclass.c
1 /*
2  * Copyright (c) 2018 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/gbp/gbp.h>
17 #include <vnet/l2/l2_input.h>
18 #include <vnet/l2/l2_output.h>
19
20 /**
21  * Grouping of global data for the GBP source EPG classification feature
22  */
23 typedef struct gbp_sclass_main_t_
24 {
25   /**
26    * Next nodes for L2 output features
27    */
28   u32 gel_l2_input_feat_next[32];
29   u32 gel_l2_output_feat_next[32];
30 } gbp_sclass_main_t;
31
32 static gbp_sclass_main_t gbp_sclass_main;
33
34 #define foreach_gbp_sclass                      \
35   _(DROP,    "drop")
36
37
38 typedef enum
39 {
40 #define _(sym,str) GBP_SCLASS_NEXT_##sym,
41   foreach_gbp_sclass
42 #undef _
43     GBP_SCLASS_N_NEXT,
44 } gbp_sclass_next_t;
45
46 typedef struct gbp_sclass_trace_t_
47 {
48   /* per-pkt trace data */
49   u32 epg;
50   u32 sclass;
51 } gbp_sclass_trace_t;
52
53 static_always_inline uword
54 gbp_sclass_inline (vlib_main_t * vm,
55                    vlib_node_runtime_t * node,
56                    vlib_frame_t * frame, int is_id_2_sclass, int is_l2)
57 {
58   u32 n_left_from, *from, *to_next, next_index;
59   gbp_sclass_main_t *glm;
60
61   glm = &gbp_sclass_main;
62   next_index = 0;
63   n_left_from = frame->n_vectors;
64   from = vlib_frame_vector_args (frame);
65
66   while (n_left_from > 0)
67     {
68       u32 n_left_to_next;
69
70       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
71
72       while (n_left_from > 0 && n_left_to_next > 0)
73         {
74           gbp_sclass_next_t next0;
75           vlib_buffer_t *b0;
76           epg_id_t epg0;
77           u16 sclass0;
78           u32 bi0;
79
80           next0 = GBP_SCLASS_NEXT_DROP;
81           bi0 = from[0];
82           to_next[0] = bi0;
83           from += 1;
84           to_next += 1;
85           n_left_from -= 1;
86           n_left_to_next -= 1;
87
88           b0 = vlib_get_buffer (vm, bi0);
89
90           if (is_id_2_sclass)
91             {
92               // output direction - convert from the SRC-EPD to the sclass
93               gbp_endpoint_group_t *gg;
94
95               epg0 = vnet_buffer2 (b0)->gbp.src_epg;
96               gg = gbp_epg_get (epg0);
97
98               if (NULL != gg)
99                 {
100                   sclass0 = vnet_buffer2 (b0)->gbp.sclass = gg->gg_sclass;
101                   if (is_l2)
102                     next0 =
103                       vnet_l2_feature_next (b0, glm->gel_l2_output_feat_next,
104                                             L2OUTPUT_FEAT_GBP_ID_2_SCLASS);
105                   else
106                     vnet_feature_next (&next0, b0);
107                 }
108               else
109                 sclass0 = 0;
110             }
111           else
112             {
113               /* input direction - convert from the sclass to the SRC-EGD */
114               sclass0 = vnet_buffer2 (b0)->gbp.sclass;
115               vnet_buffer2 (b0)->gbp.src_epg =
116                 gbp_epg_sclass_2_id (vnet_buffer2 (b0)->gbp.sclass);
117               epg0 = vnet_buffer2 (b0)->gbp.src_epg;
118
119               if (EPG_INVALID != epg0)
120                 {
121                   if (is_l2)
122                     next0 =
123                       vnet_l2_feature_next (b0, glm->gel_l2_input_feat_next,
124                                             L2INPUT_FEAT_GBP_SCLASS_2_ID);
125                   else
126                     vnet_feature_next (&next0, b0);
127                 }
128             }
129
130           if (PREDICT_FALSE ((b0->flags & VLIB_BUFFER_IS_TRACED)))
131             {
132               gbp_sclass_trace_t *t =
133                 vlib_add_trace (vm, node, b0, sizeof (*t));
134               t->epg = epg0;
135               t->sclass = sclass0;
136             }
137
138           vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
139                                            to_next, n_left_to_next,
140                                            bi0, next0);
141         }
142
143       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
144     }
145
146   return frame->n_vectors;
147 }
148
149 VLIB_NODE_FN (l2_gbp_id_2_sclass_node) (vlib_main_t * vm,
150                                         vlib_node_runtime_t * node,
151                                         vlib_frame_t * frame)
152 {
153   return (gbp_sclass_inline (vm, node, frame, 1, 1));
154 }
155
156 VLIB_NODE_FN (l2_gbp_sclass_2_id_node) (vlib_main_t * vm,
157                                         vlib_node_runtime_t * node,
158                                         vlib_frame_t * frame)
159 {
160   return (gbp_sclass_inline (vm, node, frame, 0, 1));
161 }
162
163 VLIB_NODE_FN (ip4_gbp_id_2_sclass_node) (vlib_main_t * vm,
164                                          vlib_node_runtime_t * node,
165                                          vlib_frame_t * frame)
166 {
167   return (gbp_sclass_inline (vm, node, frame, 1, 0));
168 }
169
170 VLIB_NODE_FN (ip4_gbp_sclass_2_id_node) (vlib_main_t * vm,
171                                          vlib_node_runtime_t * node,
172                                          vlib_frame_t * frame)
173 {
174   return (gbp_sclass_inline (vm, node, frame, 0, 0));
175 }
176
177 VLIB_NODE_FN (ip6_gbp_id_2_sclass_node) (vlib_main_t * vm,
178                                          vlib_node_runtime_t * node,
179                                          vlib_frame_t * frame)
180 {
181   return (gbp_sclass_inline (vm, node, frame, 1, 0));
182 }
183
184 VLIB_NODE_FN (ip6_gbp_sclass_2_id_node) (vlib_main_t * vm,
185                                          vlib_node_runtime_t * node,
186                                          vlib_frame_t * frame)
187 {
188   return (gbp_sclass_inline (vm, node, frame, 0, 0));
189 }
190
191 /* packet trace format function */
192 static u8 *
193 format_gbp_sclass_trace (u8 * s, va_list * args)
194 {
195   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
196   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
197   gbp_sclass_trace_t *t = va_arg (*args, gbp_sclass_trace_t *);
198
199   s = format (s, "epg:%d sclass:%d", t->epg, t->sclass);
200
201   return s;
202 }
203
204 /* *INDENT-OFF* */
205 VLIB_REGISTER_NODE (l2_gbp_id_2_sclass_node) = {
206   .name = "l2-gbp-id-2-sclass",
207   .vector_size = sizeof (u32),
208   .format_trace = format_gbp_sclass_trace,
209   .type = VLIB_NODE_TYPE_INTERNAL,
210
211   .n_next_nodes = GBP_SCLASS_N_NEXT,
212
213   .next_nodes = {
214     [GBP_SCLASS_NEXT_DROP] = "error-drop",
215   },
216 };
217 VLIB_REGISTER_NODE (l2_gbp_sclass_2_id_node) = {
218   .name = "l2-gbp-sclass-2-id",
219   .vector_size = sizeof (u32),
220   .format_trace = format_gbp_sclass_trace,
221   .type = VLIB_NODE_TYPE_INTERNAL,
222
223   .n_next_nodes = GBP_SCLASS_N_NEXT,
224
225   .next_nodes = {
226     [GBP_SCLASS_NEXT_DROP] = "error-drop",
227   },
228 };
229
230 VLIB_REGISTER_NODE (ip4_gbp_id_2_sclass_node) = {
231   .name = "ip4-gbp-id-2-sclass",
232   .vector_size = sizeof (u32),
233   .format_trace = format_gbp_sclass_trace,
234   .type = VLIB_NODE_TYPE_INTERNAL,
235
236   .n_next_nodes = GBP_SCLASS_N_NEXT,
237
238   .next_nodes = {
239     [GBP_SCLASS_NEXT_DROP] = "error-drop",
240   },
241 };
242 VLIB_REGISTER_NODE (ip4_gbp_sclass_2_id_node) = {
243   .name = "ip4-gbp-sclass-2-id",
244   .vector_size = sizeof (u32),
245   .format_trace = format_gbp_sclass_trace,
246   .type = VLIB_NODE_TYPE_INTERNAL,
247
248   .n_next_nodes = GBP_SCLASS_N_NEXT,
249
250   .next_nodes = {
251     [GBP_SCLASS_NEXT_DROP] = "error-drop",
252   },
253 };
254
255 VLIB_REGISTER_NODE (ip6_gbp_id_2_sclass_node) = {
256   .name = "ip6-gbp-id-2-sclass",
257   .vector_size = sizeof (u32),
258   .format_trace = format_gbp_sclass_trace,
259   .type = VLIB_NODE_TYPE_INTERNAL,
260
261   .n_next_nodes = GBP_SCLASS_N_NEXT,
262
263   .next_nodes = {
264     [GBP_SCLASS_NEXT_DROP] = "error-drop",
265   },
266 };
267 VLIB_REGISTER_NODE (ip6_gbp_sclass_2_id_node) = {
268   .name = "ip6-gbp-sclass-2-id",
269   .vector_size = sizeof (u32),
270   .format_trace = format_gbp_sclass_trace,
271   .type = VLIB_NODE_TYPE_INTERNAL,
272
273   .n_next_nodes = GBP_SCLASS_N_NEXT,
274
275   .next_nodes = {
276     [GBP_SCLASS_NEXT_DROP] = "error-drop",
277   },
278 };
279
280
281 VNET_FEATURE_INIT (ip4_gbp_sclass_2_id_feat, static) =
282 {
283   .arc_name = "ip4-unicast",
284   .node_name = "ip4-gbp-sclass-2-id",
285   .runs_before = VNET_FEATURES ("gbp-learn-ip4"),
286 };
287 VNET_FEATURE_INIT (ip6_gbp_sclass_2_id_feat, static) =
288 {
289   .arc_name = "ip6-unicast",
290   .node_name = "ip6-gbp-sclass-2-id",
291   .runs_before = VNET_FEATURES ("gbp-learn-ip6"),
292 };
293 VNET_FEATURE_INIT (ip4_gbp_id_2_sclass_feat, static) =
294 {
295   .arc_name = "ip4-output",
296   .node_name = "ip4-gbp-id-2-sclass",
297 };
298 VNET_FEATURE_INIT (ip6_gbp_id_2_sclass_feat, static) =
299 {
300   .arc_name = "ip6-output",
301   .node_name = "ip6-gbp-id-2-sclass",
302 };
303 /* *INDENT-ON* */
304
305 #ifndef CLIB_MARCH_VARIANT
306 void
307 gbp_sclass_enable_l2 (u32 sw_if_index)
308 {
309   l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_GBP_SCLASS_2_ID, 1);
310   l2output_intf_bitmap_enable (sw_if_index, L2OUTPUT_FEAT_GBP_ID_2_SCLASS, 1);
311 }
312
313 void
314 gbp_sclass_disable_l2 (u32 sw_if_index)
315 {
316   l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_GBP_SCLASS_2_ID, 0);
317   l2output_intf_bitmap_enable (sw_if_index, L2OUTPUT_FEAT_GBP_ID_2_SCLASS, 0);
318 }
319
320 void
321 gbp_sclass_enable_ip (u32 sw_if_index)
322 {
323   vnet_feature_enable_disable ("ip4-unicast",
324                                "ip4-gbp-sclass-2-id", sw_if_index, 1, 0, 0);
325   vnet_feature_enable_disable ("ip6-unicast",
326                                "ip6-gbp-sclass-2-id", sw_if_index, 1, 0, 0);
327   vnet_feature_enable_disable ("ip4-output",
328                                "ip4-gbp-id-2-sclass", sw_if_index, 1, 0, 0);
329   vnet_feature_enable_disable ("ip6-output",
330                                "ip6-gbp-id-2-sclass", sw_if_index, 1, 0, 0);
331 }
332
333 void
334 gbp_sclass_disable_ip (u32 sw_if_index)
335 {
336   vnet_feature_enable_disable ("ip4-unicast",
337                                "ip4-gbp-sclass-2-id", sw_if_index, 0, 0, 0);
338   vnet_feature_enable_disable ("ip6-unicast",
339                                "ip6-gbp-sclass-2-id", sw_if_index, 0, 0, 0);
340   vnet_feature_enable_disable ("ip4-output",
341                                "ip4-gbp-id-2-sclass", sw_if_index, 0, 0, 0);
342   vnet_feature_enable_disable ("ip6-output",
343                                "ip6-gbp-id-2-sclass", sw_if_index, 0, 0, 0);
344 }
345 #endif /* CLIB_MARCH_VARIANT */
346
347 static clib_error_t *
348 gbp_sclass_init (vlib_main_t * vm)
349 {
350   gbp_sclass_main_t *glm = &gbp_sclass_main;
351   vlib_node_t *node = vlib_get_node_by_name (vm, (u8 *) "l2-gbp-sclass-2-id");
352
353   /* Initialize the feature next-node indices */
354   feat_bitmap_init_next_nodes (vm,
355                                node->index,
356                                L2INPUT_N_FEAT,
357                                l2input_get_feat_names (),
358                                glm->gel_l2_input_feat_next);
359
360   node = vlib_get_node_by_name (vm, (u8 *) "l2-gbp-id-2-sclass");
361   feat_bitmap_init_next_nodes (vm,
362                                node->index,
363                                L2OUTPUT_N_FEAT,
364                                l2output_get_feat_names (),
365                                glm->gel_l2_output_feat_next);
366
367   return (NULL);
368 }
369
370 VLIB_INIT_FUNCTION (gbp_sclass_init);
371
372 /*
373  * fd.io coding-style-patch-verification: ON
374  *
375  * Local Variables:
376  * eval: (c-set-style "gnu")
377  * End:
378  */