blob: 28da12e22f4abeefcecf58d07e04c2ba055e2ea6 [file] [log] [blame]
Ahmed Abdelsalamc933bb72022-06-29 11:08:42 +00001/* SPDX-License-Identifier: Apache-2.0
2 * Copyright(c) 2022 Cisco Systems, Inc.
3 */
4
5/**
6 * @file
7 * @brief SR Path Tracing (PT)
8 *
9 * PT CLI
10 *
11 */
12
13#include <vlib/vlib.h>
14#include <vnet/vnet.h>
15#include <vnet/srv6/sr.h>
16#include <vnet/ip/ip.h>
17#include <vnet/srv6/sr_packet.h>
18#include <vnet/ip/ip6_packet.h>
19#include <vnet/fib/ip6_fib.h>
20#include <vnet/dpo/dpo.h>
21#include <vnet/adj/adj.h>
22#include <vnet/srv6/sr_pt.h>
23
24#include <vppinfra/error.h>
25#include <vppinfra/elog.h>
26
27sr_pt_main_t sr_pt_main;
28
29void *
30sr_pt_find_iface (u32 iface)
31{
32 sr_pt_main_t *sr_pt = &sr_pt_main;
33 uword *p;
34
35 /* Search for the item */
36 p = mhash_get (&sr_pt->sr_pt_iface_index_hash, &iface);
37 if (p)
38 {
39 /* Retrieve pt_iface */
40 return pool_elt_at_index (sr_pt->sr_pt_iface, p[0]);
41 }
42 return NULL;
43}
44
45int
46sr_pt_add_iface (u32 iface, u16 id, u8 ingress_load, u8 egress_load,
47 u8 tts_template)
48{
49 sr_pt_main_t *sr_pt = &sr_pt_main;
50 uword *p;
51
52 sr_pt_iface_t *ls = 0;
53
54 if (iface == (u32) ~0)
55 return SR_PT_ERR_IFACE_INVALID;
56
57 /* Search for the item */
58 p = mhash_get (&sr_pt->sr_pt_iface_index_hash, &iface);
59
60 if (p)
61 return SR_PT_ERR_EXIST;
62
63 if (id > SR_PT_ID_MAX)
64 return SR_PT_ERR_ID_INVALID;
65
66 if (ingress_load > SR_PT_LOAD_MAX || egress_load > SR_PT_LOAD_MAX)
67 return SR_PT_ERR_LOAD_INVALID;
68
69 if (tts_template > SR_PT_TTS_TEMPLATE_MAX)
70 return SR_PT_ERR_TTS_TEMPLATE_INVALID;
71
72 /* Create a new pt_iface */
73 pool_get (sr_pt->sr_pt_iface, ls);
74 clib_memset (ls, 0, sizeof (*ls));
75 ls->iface = iface;
76 ls->id = id;
77 ls->ingress_load = ingress_load;
78 ls->egress_load = egress_load;
79 ls->tts_template = tts_template;
80
81 /* Set hash key for searching pt_iface by iface */
82 mhash_set (&sr_pt->sr_pt_iface_index_hash, &iface, ls - sr_pt->sr_pt_iface,
83 NULL);
84 return 0;
85}
86
87int
88sr_pt_del_iface (u32 iface)
89{
90 sr_pt_main_t *sr_pt = &sr_pt_main;
91 uword *p;
92
93 sr_pt_iface_t *ls = 0;
94
95 if (iface == (u32) ~0)
96 return SR_PT_ERR_IFACE_INVALID;
97
98 /* Search for the item */
99 p = mhash_get (&sr_pt->sr_pt_iface_index_hash, &iface);
100
101 if (p)
102 {
103 /* Retrieve sr_pt_iface */
104 ls = pool_elt_at_index (sr_pt->sr_pt_iface, p[0]);
105 /* Delete sr_pt_iface */
106 pool_put (sr_pt->sr_pt_iface, ls);
107 mhash_unset (&sr_pt->sr_pt_iface_index_hash, &iface, NULL);
108 }
109 else
110 {
111 return SR_PT_ERR_NOENT;
112 }
113 return 0;
114}
115
116/**
117 * @brief "sr pt add iface" CLI function.
118 *
119 * @see sr_pt_add_iface
120 */
121static clib_error_t *
122sr_pt_add_iface_command_fn (vlib_main_t *vm, unformat_input_t *input,
123 vlib_cli_command_t *cmd)
124{
125 vnet_main_t *vnm = vnet_get_main ();
126 u32 iface = (u32) ~0;
127 u32 id = (u32) ~0;
128 u32 ingress_load = 0;
129 u32 egress_load = 0;
130 u32 tts_template = SR_PT_TTS_TEMPLATE_DEFAULT;
131
132 int rv;
133
134 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
135 {
136 if (unformat (input, "%U", unformat_vnet_sw_interface, vnm, &iface))
137 ;
138 else if (unformat (input, "id %u", &id))
139 ;
140 else if (unformat (input, "ingress-load %u", &ingress_load))
141 ;
142 else if (unformat (input, "egress-load %u", &egress_load))
143 ;
144 else if (unformat (input, "tts-template %u", &tts_template))
145 ;
146 else
147 break;
148 }
149
150 rv = sr_pt_add_iface (iface, id, ingress_load, egress_load, tts_template);
151
152 switch (rv)
153 {
154 case 0:
155 break;
156 case SR_PT_ERR_EXIST:
157 return clib_error_return (0, "Error: Identical iface already exists.");
158 case SR_PT_ERR_IFACE_INVALID:
159 return clib_error_return (0, "Error: The iface name invalid.");
160 case SR_PT_ERR_ID_INVALID:
161 return clib_error_return (0, "Error: The iface id value invalid.");
162 case SR_PT_ERR_LOAD_INVALID:
163 return clib_error_return (
164 0, "Error: The iface ingress or egress load value invalid.");
165 case SR_PT_ERR_TTS_TEMPLATE_INVALID:
166 return clib_error_return (
167 0, "Error: The iface TTS Template value invalid.");
168 default:
169 return clib_error_return (0, "Error: unknown error.");
170 }
171 return 0;
172}
173
174/**
175 * @brief "sr pt del iface" CLI function.
176 *
177 * @see sr_pt_del_iface
178 */
179static clib_error_t *
180sr_pt_del_iface_command_fn (vlib_main_t *vm, unformat_input_t *input,
181 vlib_cli_command_t *cmd)
182{
183 vnet_main_t *vnm = vnet_get_main ();
184 u32 iface = (u32) ~0;
185
186 int rv;
187
188 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
189 {
190 if (unformat (input, "%U", unformat_vnet_sw_interface, vnm, &iface))
191 ;
192 else
193 break;
194 }
195
196 rv = sr_pt_del_iface (iface);
197
198 switch (rv)
199 {
200 case 0:
201 break;
202 case SR_PT_ERR_NOENT:
203 return clib_error_return (0, "Error: No such iface.");
204 case SR_PT_ERR_IFACE_INVALID:
205 return clib_error_return (0, "Error: The iface name is not valid.");
206 default:
207 return clib_error_return (0, "Error: unknown error.");
208 }
209 return 0;
210}
211
212/**
213 * @brief CLI function to show all PT interfcaes
214 */
215static clib_error_t *
216sr_pt_show_iface_command_fn (vlib_main_t *vm, unformat_input_t *input,
217 vlib_cli_command_t *cmd)
218{
219 vnet_main_t *vnm = vnet_get_main ();
220 sr_pt_main_t *sr_pt = &sr_pt_main;
221 sr_pt_iface_t **sr_pt_iface_list = 0;
222 sr_pt_iface_t *ls;
223 int i;
224
225 vlib_cli_output (vm, "SR PT Interfaces");
226 vlib_cli_output (vm, "==================================");
227
228 pool_foreach (ls, sr_pt->sr_pt_iface)
229 {
230 vec_add1 (sr_pt_iface_list, ls);
231 };
232
233 for (i = 0; i < vec_len (sr_pt_iface_list); i++)
234 {
235 ls = sr_pt_iface_list[i];
236 vlib_cli_output (
237 vm,
238 "\tiface : \t%U\n\tid : \t%d\n\tingress-load: "
239 "\t%d\n\tegress-load : \t%d\n\ttts-template: \t%d ",
240 format_vnet_sw_if_index_name, vnm, ls->iface, ls->id, ls->ingress_load,
241 ls->egress_load, ls->tts_template);
242 vlib_cli_output (vm, "--------------------------------");
243 }
244
245 return 0;
246}
247
248VLIB_CLI_COMMAND (sr_pt_add_iface_command, static) = {
249 .path = "sr pt add iface",
250 .short_help = "sr pt add iface <iface-name> id <pt-iface-id> ingress-load "
251 "<ingress-load-value> egress-load <egress-load-value> "
252 "tts-template <tts-template-value>",
253 .function = sr_pt_add_iface_command_fn,
254};
255
256VLIB_CLI_COMMAND (sr_pt_del_iface_command, static) = {
257 .path = "sr pt del iface",
258 .short_help = "sr pt del iface <iface-name>",
259 .function = sr_pt_del_iface_command_fn,
260};
261
262VLIB_CLI_COMMAND (sr_pt_show_iface_command, static) = {
263 .path = "sr pt show iface",
264 .short_help = "sr pt show iface",
265 .function = sr_pt_show_iface_command_fn,
266};
267
268/**
269 * * @brief SR PT initialization
270 * */
271clib_error_t *
272sr_pt_init (vlib_main_t *vm)
273{
274 sr_pt_main_t *pt = &sr_pt_main;
275 mhash_init (&pt->sr_pt_iface_index_hash, sizeof (uword), sizeof (u32));
276 return 0;
277}
278
279VLIB_INIT_FUNCTION (sr_pt_init);