GBP V2
[vpp.git] / src / plugins / gbp / gbp_classify.c
1 /*
2  * gbp.h : Group Based Policy
3  *
4  * Copyright (c) 2018 Cisco and/or its affiliates.
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 <plugins/gbp/gbp.h>
19
20 typedef enum gbp_src_classify_type_t_
21 {
22   GBP_SRC_CLASSIFY_NULL,
23   GBP_SRC_CLASSIFY_PORT,
24 } gbp_src_classify_type_t;
25
26 #define GBP_SRC_N_CLASSIFY (GBP_SRC_CLASSIFY_PORT + 1)
27
28 /**
29  * Grouping of global data for the GBP source EPG classification feature
30  */
31 typedef struct gbp_src_classify_main_t_
32 {
33   /**
34    * Next nodes for L2 output features
35    */
36   u32 l2_input_feat_next[GBP_SRC_N_CLASSIFY][32];
37 } gbp_src_classify_main_t;
38
39 static gbp_src_classify_main_t gbp_src_classify_main;
40
41 /**
42  * per-packet trace data
43  */
44 typedef struct gbp_classify_trace_t_
45 {
46   /* per-pkt trace data */
47   epg_id_t src_epg;
48 } gbp_classify_trace_t;
49
50 /*
51  * determine the SRC EPG form the input port
52  */
53 always_inline uword
54 gbp_classify_inline (vlib_main_t * vm,
55                      vlib_node_runtime_t * node,
56                      vlib_frame_t * frame,
57                      gbp_src_classify_type_t type, u8 is_l3)
58 {
59   gbp_src_classify_main_t *gscm = &gbp_src_classify_main;
60   u32 n_left_from, *from, *to_next;
61   u32 next_index;
62
63   next_index = 0;
64   n_left_from = frame->n_vectors;
65   from = vlib_frame_vector_args (frame);
66
67   while (n_left_from > 0)
68     {
69       u32 n_left_to_next;
70
71       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
72
73       while (n_left_from > 0 && n_left_to_next > 0)
74         {
75           u32 next0, bi0, src_epg, sw_if_index0;
76           vlib_buffer_t *b0;
77
78           bi0 = from[0];
79           to_next[0] = bi0;
80           from += 1;
81           to_next += 1;
82           n_left_from -= 1;
83           n_left_to_next -= 1;
84
85           b0 = vlib_get_buffer (vm, bi0);
86
87           sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
88
89           if (GBP_SRC_CLASSIFY_NULL == type)
90             {
91               src_epg = ~0;
92               next0 =
93                 vnet_l2_feature_next (b0, gscm->l2_input_feat_next[type],
94                                       L2INPUT_FEAT_GBP_NULL_CLASSIFY);
95             }
96           else
97             {
98               src_epg = gbp_port_to_epg (sw_if_index0);
99               if (is_l3)
100                 {
101                   /*
102                    * Go straight to looukp, do not pass go, do not collect $200
103                    */
104                   next0 = 0;
105                 }
106               else
107                 {
108                   next0 =
109                     vnet_l2_feature_next (b0, gscm->l2_input_feat_next[type],
110                                           L2INPUT_FEAT_GBP_SRC_CLASSIFY);
111                 }
112             }
113
114           vnet_buffer2 (b0)->gbp.src_epg = src_epg;
115
116           if (PREDICT_FALSE ((b0->flags & VLIB_BUFFER_IS_TRACED)))
117             {
118               gbp_classify_trace_t *t =
119                 vlib_add_trace (vm, node, b0, sizeof (*t));
120               t->src_epg = src_epg;
121             }
122
123           vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
124                                            to_next, n_left_to_next,
125                                            bi0, next0);
126         }
127
128       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
129     }
130
131   return frame->n_vectors;
132 }
133
134 static uword
135 gbp_src_classify (vlib_main_t * vm,
136                   vlib_node_runtime_t * node, vlib_frame_t * frame)
137 {
138   return (gbp_classify_inline (vm, node, frame, GBP_SRC_CLASSIFY_PORT, 0));
139 }
140
141 static uword
142 gbp_null_classify (vlib_main_t * vm,
143                    vlib_node_runtime_t * node, vlib_frame_t * frame)
144 {
145   return (gbp_classify_inline (vm, node, frame, GBP_SRC_CLASSIFY_NULL, 0));
146 }
147
148 static uword
149 gbp_ip4_src_classify (vlib_main_t * vm,
150                       vlib_node_runtime_t * node, vlib_frame_t * frame)
151 {
152   return (gbp_classify_inline (vm, node, frame, 0, 1));
153 }
154
155 static uword
156 gbp_ip6_src_classify (vlib_main_t * vm,
157                       vlib_node_runtime_t * node, vlib_frame_t * frame)
158 {
159   return (gbp_classify_inline (vm, node, frame, 0, 1));
160 }
161
162
163 /* packet trace format function */
164 static u8 *
165 format_gbp_classify_trace (u8 * s, va_list * args)
166 {
167   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
168   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
169   gbp_classify_trace_t *t = va_arg (*args, gbp_classify_trace_t *);
170
171   s = format (s, "src-epg:%d", t->src_epg);
172
173   return s;
174 }
175
176 /* *INDENT-OFF* */
177 VLIB_REGISTER_NODE (gbp_null_classify_node) = {
178   .function = gbp_null_classify,
179   .name = "gbp-null-classify",
180   .vector_size = sizeof (u32),
181   .format_trace = format_gbp_classify_trace,
182   .type = VLIB_NODE_TYPE_INTERNAL,
183
184   .n_errors = 0,
185   .n_next_nodes = 0,
186 };
187
188 VLIB_NODE_FUNCTION_MULTIARCH (gbp_null_classify_node, gbp_null_classify);
189
190 VLIB_REGISTER_NODE (gbp_src_classify_node) = {
191   .function = gbp_src_classify,
192   .name = "gbp-src-classify",
193   .vector_size = sizeof (u32),
194   .format_trace = format_gbp_classify_trace,
195   .type = VLIB_NODE_TYPE_INTERNAL,
196
197   .n_errors = 0,
198   .n_next_nodes = 0,
199 };
200
201 VLIB_NODE_FUNCTION_MULTIARCH (gbp_src_classify_node, gbp_src_classify);
202
203 VLIB_REGISTER_NODE (gbp_ip4_src_classify_node) = {
204   .function = gbp_ip4_src_classify,
205   .name = "ip4-gbp-src-classify",
206   .vector_size = sizeof (u32),
207   .format_trace = format_gbp_classify_trace,
208   .type = VLIB_NODE_TYPE_INTERNAL,
209
210   .n_errors = 0,
211   .n_next_nodes = 1,
212   .next_nodes = {
213     [0] = "ip4-lookup"
214   },
215 };
216
217 VLIB_NODE_FUNCTION_MULTIARCH (gbp_ip4_src_classify_node, gbp_ip4_src_classify);
218
219 VLIB_REGISTER_NODE (gbp_ip6_src_classify_node) = {
220   .function = gbp_ip6_src_classify,
221   .name = "ip6-gbp-src-classify",
222   .vector_size = sizeof (u32),
223   .format_trace = format_gbp_classify_trace,
224   .type = VLIB_NODE_TYPE_INTERNAL,
225
226   .n_errors = 0,
227   .n_next_nodes = 1,
228   .next_nodes = {
229     [0] = "ip6-lookup"
230   },
231 };
232
233 VLIB_NODE_FUNCTION_MULTIARCH (gbp_ip6_src_classify_node, gbp_ip6_src_classify);
234
235 VNET_FEATURE_INIT (gbp_ip4_src_classify_feat_node, static) =
236 {
237   .arc_name = "ip4-unicast",
238   .node_name = "ip4-gbp-src-classify",
239   .runs_before = VNET_FEATURES ("nat44-out2in"),
240 };
241 VNET_FEATURE_INIT (gbp_ip6_src_classify_feat_node, static) =
242 {
243   .arc_name = "ip6-unicast",
244   .node_name = "ip6-gbp-src-classify",
245   .runs_before = VNET_FEATURES ("nat66-out2in"),
246 };
247
248 static clib_error_t *
249 gbp_src_classify_init (vlib_main_t * vm)
250 {
251   gbp_src_classify_main_t *em = &gbp_src_classify_main;
252
253   /* Initialize the feature next-node indexes */
254   feat_bitmap_init_next_nodes (vm,
255                                gbp_src_classify_node.index,
256                                L2INPUT_N_FEAT,
257                                l2input_get_feat_names (),
258                                em->l2_input_feat_next[GBP_SRC_CLASSIFY_NULL]);
259   feat_bitmap_init_next_nodes (vm,
260                                gbp_null_classify_node.index,
261                                L2INPUT_N_FEAT,
262                                l2input_get_feat_names (),
263                                em->l2_input_feat_next[GBP_SRC_CLASSIFY_PORT]);
264
265   return 0;
266 }
267
268 VLIB_INIT_FUNCTION (gbp_src_classify_init);
269
270 /*
271  * fd.io coding-style-patch-verification: ON
272  *
273  * Local Variables:
274  * eval: (c-set-style "gnu")
275  * End:
276  */