session: api to add new transport types
[vpp.git] / src / vnet / fib / fib_entry_delegate.c
1 /*
2  * Copyright (c) 2016 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 <vnet/fib/fib_entry_delegate.h>
17 #include <vnet/fib/fib_entry.h>
18 #include <vnet/fib/fib_attached_export.h>
19
20 static fib_entry_delegate_t *fib_entry_delegate_pool;
21
22 fib_entry_delegate_t *
23 fib_entry_delegate_get (index_t fedi)
24 {
25     return (pool_elt_at_index(fib_entry_delegate_pool, fedi));
26 }
27
28 fib_node_index_t
29 fib_entry_delegate_get_index (const fib_entry_delegate_t *fed)
30 {
31     return (fed - fib_entry_delegate_pool);
32 }
33
34 static fib_entry_delegate_t *
35 fib_entry_delegate_find_i (const fib_entry_t *fib_entry,
36                            fib_entry_delegate_type_t type,
37                            u32 *index)
38 {
39     fib_entry_delegate_t *delegate;
40     index_t *fedi;
41     int ii;
42
43     ii = 0;
44     vec_foreach(fedi, fib_entry->fe_delegates)
45     {
46         delegate = fib_entry_delegate_get(*fedi);
47
48         if (delegate->fd_type == type)
49         {
50             if (NULL != index)
51                 *index = ii;
52
53             return (delegate);
54         }
55         else
56         {
57             ii++;
58         }
59     }
60
61     return (NULL);
62 }
63
64 fib_entry_delegate_t *
65 fib_entry_delegate_find (const fib_entry_t *fib_entry,
66                         fib_entry_delegate_type_t type)
67 {
68     return (fib_entry_delegate_find_i(fib_entry, type, NULL));
69 }
70
71 void
72 fib_entry_delegate_remove (fib_entry_t *fib_entry,
73                            fib_entry_delegate_type_t type)
74 {
75     fib_entry_delegate_t *fed;
76     u32 index = ~0;
77
78     fed = fib_entry_delegate_find_i(fib_entry, type, &index);
79
80     ASSERT(NULL != fed);
81
82     vec_del1(fib_entry->fe_delegates, index);
83
84     pool_put(fib_entry_delegate_pool, fed);
85 }
86
87 static int
88 fib_entry_delegate_cmp_for_sort (void * v1,
89                                  void * v2)
90 {
91     fib_entry_delegate_t *delegate1, *delegate2;
92     index_t *fedi1 = v1, *fedi2 = v2;
93
94     delegate1 = fib_entry_delegate_get(*fedi1);
95     delegate2 = fib_entry_delegate_get(*fedi2);
96
97     return (delegate1->fd_type - delegate2->fd_type);
98 }
99
100 static void
101 fib_entry_delegate_init (fib_entry_t *fib_entry,
102                          fib_entry_delegate_type_t type)
103
104 {
105     fib_entry_delegate_t *delegate;
106
107     pool_get_zero(fib_entry_delegate_pool, delegate);
108
109     delegate->fd_entry_index = fib_entry_get_index(fib_entry);
110     delegate->fd_type = type;
111
112     vec_add1(fib_entry->fe_delegates, delegate - fib_entry_delegate_pool);
113     vec_sort_with_function(fib_entry->fe_delegates,
114                            fib_entry_delegate_cmp_for_sort);
115 }
116
117 fib_entry_delegate_t *
118 fib_entry_delegate_find_or_add (fib_entry_t *fib_entry,
119                                 fib_entry_delegate_type_t fdt)
120 {
121     fib_entry_delegate_t *delegate;
122
123     delegate = fib_entry_delegate_find(fib_entry, fdt);
124
125     if (NULL == delegate)
126     {
127         fib_entry_delegate_init(fib_entry, fdt);
128     }
129
130     return (fib_entry_delegate_find(fib_entry, fdt));
131 }
132
133 fib_entry_delegate_type_t
134 fib_entry_chain_type_to_delegate_type (fib_forward_chain_type_t fct)
135 {
136     switch (fct)
137     {
138     case FIB_FORW_CHAIN_TYPE_UNICAST_IP4:
139         return (FIB_ENTRY_DELEGATE_CHAIN_UNICAST_IP4);
140     case FIB_FORW_CHAIN_TYPE_UNICAST_IP6:
141         return (FIB_ENTRY_DELEGATE_CHAIN_UNICAST_IP6);
142     case FIB_FORW_CHAIN_TYPE_MPLS_EOS:
143         return (FIB_ENTRY_DELEGATE_CHAIN_MPLS_EOS);
144     case FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS:
145         return (FIB_ENTRY_DELEGATE_CHAIN_MPLS_NON_EOS);
146     case FIB_FORW_CHAIN_TYPE_ETHERNET:
147         return (FIB_ENTRY_DELEGATE_CHAIN_ETHERNET);
148     case FIB_FORW_CHAIN_TYPE_MCAST_IP4:
149     case FIB_FORW_CHAIN_TYPE_MCAST_IP6:
150     case FIB_FORW_CHAIN_TYPE_BIER:
151         break;
152     case FIB_FORW_CHAIN_TYPE_NSH:
153         return (FIB_ENTRY_DELEGATE_CHAIN_NSH);
154     }
155     ASSERT(0);
156     return (FIB_ENTRY_DELEGATE_CHAIN_UNICAST_IP4);
157 }
158
159 fib_forward_chain_type_t
160 fib_entry_delegate_type_to_chain_type (fib_entry_delegate_type_t fdt)
161 {
162     switch (fdt)
163     {
164     case FIB_ENTRY_DELEGATE_CHAIN_UNICAST_IP4:
165         return (FIB_FORW_CHAIN_TYPE_UNICAST_IP4);
166     case FIB_ENTRY_DELEGATE_CHAIN_UNICAST_IP6:
167         return (FIB_FORW_CHAIN_TYPE_UNICAST_IP6);
168     case FIB_ENTRY_DELEGATE_CHAIN_MPLS_EOS:
169         return (FIB_FORW_CHAIN_TYPE_MPLS_EOS);
170     case FIB_ENTRY_DELEGATE_CHAIN_MPLS_NON_EOS:
171         return (FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS);
172     case FIB_ENTRY_DELEGATE_CHAIN_ETHERNET:
173         return (FIB_FORW_CHAIN_TYPE_ETHERNET);
174     case FIB_ENTRY_DELEGATE_CHAIN_NSH:
175         return (FIB_FORW_CHAIN_TYPE_NSH);
176     case FIB_ENTRY_DELEGATE_COVERED:
177     case FIB_ENTRY_DELEGATE_ATTACHED_IMPORT:
178     case FIB_ENTRY_DELEGATE_ATTACHED_EXPORT:
179     case FIB_ENTRY_DELEGATE_BFD:
180     case FIB_ENTRY_DELEGATE_TRACK:
181         break;
182     }
183     ASSERT(0);
184     return (FIB_FORW_CHAIN_TYPE_UNICAST_IP4);
185 }
186
187 /**
188  * typedef for printing a delegate
189  */
190 typedef u8 * (*fib_entry_delegate_format_t)(const fib_entry_delegate_t *fed,
191                                             u8 *s);
192
193 /**
194  * Print a delegate that represents a forwarding chain
195  */
196 static u8 *
197 fib_entry_delegate_fmt_fwd_chain (const fib_entry_delegate_t *fed,
198                                   u8 *s)
199 {
200     s = format(s, "%U-chain\n  %U",
201                format_fib_forw_chain_type,
202                fib_entry_delegate_type_to_chain_type(fed->fd_type),
203                format_dpo_id, &fed->fd_dpo, 2);
204
205     return (s);
206 }
207
208 /**
209  * Print a delegate that represents cover tracking
210  */
211 static u8 *
212 fib_entry_delegate_fmt_covered (const fib_entry_delegate_t *fed,
213                                   u8 *s)
214 {
215     s = format(s, "covered:[");
216     s = fib_node_children_format(fed->fd_list, s);
217     s = format(s, "]");
218
219     return (s);
220 }
221
222 /**
223  * Print a delegate that represents attached-import tracking
224  */
225 static u8 *
226 fib_entry_delegate_fmt_import (const fib_entry_delegate_t *fed,
227                                u8 *s)
228 {
229     s = format(s, "import:");
230     s = fib_ae_import_format(fed->fd_index, s);
231
232     return (s);
233 }
234
235 /**
236  * Print a delegate that represents attached-export tracking
237  */
238 static u8 *
239 fib_entry_delegate_fmt_export (const fib_entry_delegate_t *fed,
240                                u8 *s)
241 {
242     s = format(s, "export:");
243     s = fib_ae_export_format(fed->fd_index, s);
244
245     return (s);
246 }
247
248 /**
249  * Print a delegate that represents BFD tracking
250  */
251 static u8 *
252 fib_entry_delegate_fmt_bfd (const fib_entry_delegate_t *fed,
253                                u8 *s)
254 {
255     s = format(s, "BFD:%d", fed->fd_bfd_state);
256
257     return (s);
258 }
259
260 /**
261  * Print a delegate that represents tracking
262  */
263 static u8 *
264 fib_entry_delegate_fmt_track (const fib_entry_delegate_t *fed,
265                               u8 *s)
266 {
267     u32 indent = format_get_indent (s);
268
269     s = format(s, "track: sibling:%d", fed->fd_track.fedt_sibling);
270
271     s = format(s, "\n%UChildren:", format_white_space, indent);
272     s = fib_node_children_format(fed->fd_track.fedt_node.fn_children, s);
273
274     return (s);
275 }
276
277 /**
278  * A delegate type to formatter map
279  */
280 static fib_entry_delegate_format_t fed_formatters[] =
281 {
282     [FIB_ENTRY_DELEGATE_CHAIN_UNICAST_IP4] = fib_entry_delegate_fmt_fwd_chain,
283     [FIB_ENTRY_DELEGATE_CHAIN_UNICAST_IP6] = fib_entry_delegate_fmt_fwd_chain,
284     [FIB_ENTRY_DELEGATE_CHAIN_MPLS_EOS] = fib_entry_delegate_fmt_fwd_chain,
285     [FIB_ENTRY_DELEGATE_CHAIN_MPLS_NON_EOS] = fib_entry_delegate_fmt_fwd_chain,
286     [FIB_ENTRY_DELEGATE_CHAIN_ETHERNET] = fib_entry_delegate_fmt_fwd_chain,
287     [FIB_ENTRY_DELEGATE_CHAIN_NSH] = fib_entry_delegate_fmt_fwd_chain,
288     [FIB_ENTRY_DELEGATE_COVERED] = fib_entry_delegate_fmt_covered,
289     [FIB_ENTRY_DELEGATE_ATTACHED_IMPORT] = fib_entry_delegate_fmt_import,
290     [FIB_ENTRY_DELEGATE_ATTACHED_EXPORT] = fib_entry_delegate_fmt_export,
291     [FIB_ENTRY_DELEGATE_BFD] = fib_entry_delegate_fmt_bfd,
292     [FIB_ENTRY_DELEGATE_TRACK] = fib_entry_delegate_fmt_track,
293 };
294
295 u8 *
296 format_fib_entry_delegate (u8 * s, va_list * args)
297 {
298     fib_entry_delegate_t *fed;
299     index_t fedi;
300
301     fedi = va_arg (*args, index_t);
302     fed = fib_entry_delegate_get(fedi);
303
304     return (fed_formatters[fed->fd_type](fed, s));
305 }
306
307 static clib_error_t *
308 show_fib_entry_delegate_command (vlib_main_t * vm,
309                                  unformat_input_t * input,
310                                  vlib_cli_command_t * cmd)
311 {
312     fib_node_index_t fedi;
313
314     if (unformat (input, "%d", &fedi))
315     {
316         /*
317          * show one in detail
318          */
319         if (!pool_is_free_index(fib_entry_delegate_pool, fedi))
320         {
321             vlib_cli_output (vm, "%d@%U",
322                              fedi,
323                              format_fib_entry_delegate, fedi);
324         }
325         else
326         {
327             vlib_cli_output (vm, "entry %d invalid", fedi);
328         }
329     }
330     else
331     {
332         /*
333          * show all
334          */
335         vlib_cli_output (vm, "FIB Entry Delegates:");
336         pool_foreach_index(fedi, fib_entry_delegate_pool,
337         ({
338             vlib_cli_output (vm, "%d@%U",
339                              fedi,
340                              format_fib_entry_delegate, fedi);
341         }));
342     }
343
344     return (NULL);
345 }
346
347 VLIB_CLI_COMMAND (show_fib_entry, static) = {
348   .path = "show fib entry-delegate",
349   .function = show_fib_entry_delegate_command,
350   .short_help = "show fib entry delegate",
351 };