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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 #include <plugins/gbp/gbp.h>
17 #include <vnet/l2/l2_input.h>
18 #include <vnet/l2/l2_output.h>
21 * Grouping of global data for the GBP source EPG classification feature
23 typedef struct gbp_sclass_main_t_
26 * Next nodes for L2 output features
28 u32 gel_l2_input_feat_next[32];
29 u32 gel_l2_output_feat_next[32];
32 static gbp_sclass_main_t gbp_sclass_main;
34 #define foreach_gbp_sclass \
40 #define _(sym,str) GBP_SCLASS_NEXT_##sym,
46 typedef struct gbp_sclass_trace_t_
48 /* per-pkt trace data */
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)
58 u32 n_left_from, *from, *to_next, next_index;
59 gbp_sclass_main_t *glm;
61 glm = &gbp_sclass_main;
63 n_left_from = frame->n_vectors;
64 from = vlib_frame_vector_args (frame);
66 while (n_left_from > 0)
70 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
72 while (n_left_from > 0 && n_left_to_next > 0)
74 gbp_sclass_next_t next0;
80 next0 = GBP_SCLASS_NEXT_DROP;
88 b0 = vlib_get_buffer (vm, bi0);
92 // output direction - convert from the SRC-EPD to the sclass
93 gbp_endpoint_group_t *gg;
95 epg0 = vnet_buffer2 (b0)->gbp.src_epg;
96 gg = gbp_epg_get (epg0);
100 sclass0 = vnet_buffer2 (b0)->gbp.sclass = gg->gg_sclass;
103 vnet_l2_feature_next (b0, glm->gel_l2_output_feat_next,
104 L2OUTPUT_FEAT_GBP_ID_2_SCLASS);
106 vnet_feature_next (&next0, b0);
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;
119 if (EPG_INVALID != epg0)
123 vnet_l2_feature_next (b0, glm->gel_l2_input_feat_next,
124 L2INPUT_FEAT_GBP_SCLASS_2_ID);
126 vnet_feature_next (&next0, b0);
130 if (PREDICT_FALSE ((b0->flags & VLIB_BUFFER_IS_TRACED)))
132 gbp_sclass_trace_t *t =
133 vlib_add_trace (vm, node, b0, sizeof (*t));
138 vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
139 to_next, n_left_to_next,
143 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
146 return frame->n_vectors;
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)
153 return (gbp_sclass_inline (vm, node, frame, 1, 1));
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)
160 return (gbp_sclass_inline (vm, node, frame, 0, 1));
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)
167 return (gbp_sclass_inline (vm, node, frame, 1, 0));
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)
174 return (gbp_sclass_inline (vm, node, frame, 0, 0));
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)
181 return (gbp_sclass_inline (vm, node, frame, 1, 0));
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)
188 return (gbp_sclass_inline (vm, node, frame, 0, 0));
191 /* packet trace format function */
193 format_gbp_sclass_trace (u8 * s, va_list * args)
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 *);
199 s = format (s, "epg:%d sclass:%d", t->epg, t->sclass);
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,
211 .n_next_nodes = GBP_SCLASS_N_NEXT,
214 [GBP_SCLASS_NEXT_DROP] = "error-drop",
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,
223 .n_next_nodes = GBP_SCLASS_N_NEXT,
226 [GBP_SCLASS_NEXT_DROP] = "error-drop",
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,
236 .n_next_nodes = GBP_SCLASS_N_NEXT,
239 [GBP_SCLASS_NEXT_DROP] = "error-drop",
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,
248 .n_next_nodes = GBP_SCLASS_N_NEXT,
251 [GBP_SCLASS_NEXT_DROP] = "error-drop",
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,
261 .n_next_nodes = GBP_SCLASS_N_NEXT,
264 [GBP_SCLASS_NEXT_DROP] = "error-drop",
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,
273 .n_next_nodes = GBP_SCLASS_N_NEXT,
276 [GBP_SCLASS_NEXT_DROP] = "error-drop",
281 VNET_FEATURE_INIT (ip4_gbp_sclass_2_id_feat, static) =
283 .arc_name = "ip4-unicast",
284 .node_name = "ip4-gbp-sclass-2-id",
285 .runs_before = VNET_FEATURES ("gbp-learn-ip4"),
287 VNET_FEATURE_INIT (ip6_gbp_sclass_2_id_feat, static) =
289 .arc_name = "ip6-unicast",
290 .node_name = "ip6-gbp-sclass-2-id",
291 .runs_before = VNET_FEATURES ("gbp-learn-ip6"),
293 VNET_FEATURE_INIT (ip4_gbp_id_2_sclass_feat, static) =
295 .arc_name = "ip4-output",
296 .node_name = "ip4-gbp-id-2-sclass",
298 VNET_FEATURE_INIT (ip6_gbp_id_2_sclass_feat, static) =
300 .arc_name = "ip6-output",
301 .node_name = "ip6-gbp-id-2-sclass",
305 #ifndef CLIB_MARCH_VARIANT
307 gbp_sclass_enable_l2 (u32 sw_if_index)
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);
314 gbp_sclass_disable_l2 (u32 sw_if_index)
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);
321 gbp_sclass_enable_ip (u32 sw_if_index)
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);
334 gbp_sclass_disable_ip (u32 sw_if_index)
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);
345 #endif /* CLIB_MARCH_VARIANT */
347 static clib_error_t *
348 gbp_sclass_init (vlib_main_t * vm)
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");
353 /* Initialize the feature next-node indices */
354 feat_bitmap_init_next_nodes (vm,
357 l2input_get_feat_names (),
358 glm->gel_l2_input_feat_next);
360 node = vlib_get_node_by_name (vm, (u8 *) "l2-gbp-id-2-sclass");
361 feat_bitmap_init_next_nodes (vm,
364 l2output_get_feat_names (),
365 glm->gel_l2_output_feat_next);
370 VLIB_INIT_FUNCTION (gbp_sclass_init);
373 * fd.io coding-style-patch-verification: ON
376 * eval: (c-set-style "gnu")