blob: 5d907eaf639bf7af8a4551929a031266e73165b6 [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 *
Ahmed Abdelsalamb0057282022-06-29 16:30:21 +00009 * SR PT CLI
Ahmed Abdelsalamc933bb72022-06-29 11:08:42 +000010 *
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 {
Ahmed Abdelsalamb0057282022-06-29 16:30:21 +000039 /* Retrieve sr_pt_iface */
Ahmed Abdelsalamc933bb72022-06-29 11:08:42 +000040 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
Ahmed Abdelsalamb0057282022-06-29 16:30:21 +000072 /* Create a new sr_pt_iface */
73 pool_get_zero (sr_pt->sr_pt_iface, ls);
Ahmed Abdelsalamc933bb72022-06-29 11:08:42 +000074 ls->iface = iface;
75 ls->id = id;
76 ls->ingress_load = ingress_load;
77 ls->egress_load = egress_load;
78 ls->tts_template = tts_template;
79
Ahmed Abdelsalamb0057282022-06-29 16:30:21 +000080 /* Set hash key for searching sr_pt_iface by iface */
Ahmed Abdelsalamc933bb72022-06-29 11:08:42 +000081 mhash_set (&sr_pt->sr_pt_iface_index_hash, &iface, ls - sr_pt->sr_pt_iface,
82 NULL);
83 return 0;
84}
85
86int
87sr_pt_del_iface (u32 iface)
88{
89 sr_pt_main_t *sr_pt = &sr_pt_main;
90 uword *p;
91
92 sr_pt_iface_t *ls = 0;
93
94 if (iface == (u32) ~0)
95 return SR_PT_ERR_IFACE_INVALID;
96
97 /* Search for the item */
98 p = mhash_get (&sr_pt->sr_pt_iface_index_hash, &iface);
99
100 if (p)
101 {
102 /* Retrieve sr_pt_iface */
103 ls = pool_elt_at_index (sr_pt->sr_pt_iface, p[0]);
104 /* Delete sr_pt_iface */
105 pool_put (sr_pt->sr_pt_iface, ls);
106 mhash_unset (&sr_pt->sr_pt_iface_index_hash, &iface, NULL);
107 }
108 else
109 {
110 return SR_PT_ERR_NOENT;
111 }
112 return 0;
113}
114
115/**
116 * @brief "sr pt add iface" CLI function.
117 *
118 * @see sr_pt_add_iface
119 */
120static clib_error_t *
121sr_pt_add_iface_command_fn (vlib_main_t *vm, unformat_input_t *input,
122 vlib_cli_command_t *cmd)
123{
124 vnet_main_t *vnm = vnet_get_main ();
125 u32 iface = (u32) ~0;
126 u32 id = (u32) ~0;
127 u32 ingress_load = 0;
128 u32 egress_load = 0;
129 u32 tts_template = SR_PT_TTS_TEMPLATE_DEFAULT;
130
131 int rv;
132
133 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
134 {
135 if (unformat (input, "%U", unformat_vnet_sw_interface, vnm, &iface))
136 ;
137 else if (unformat (input, "id %u", &id))
138 ;
139 else if (unformat (input, "ingress-load %u", &ingress_load))
140 ;
141 else if (unformat (input, "egress-load %u", &egress_load))
142 ;
143 else if (unformat (input, "tts-template %u", &tts_template))
144 ;
145 else
146 break;
147 }
148
149 rv = sr_pt_add_iface (iface, id, ingress_load, egress_load, tts_template);
150
151 switch (rv)
152 {
153 case 0:
154 break;
155 case SR_PT_ERR_EXIST:
156 return clib_error_return (0, "Error: Identical iface already exists.");
157 case SR_PT_ERR_IFACE_INVALID:
158 return clib_error_return (0, "Error: The iface name invalid.");
159 case SR_PT_ERR_ID_INVALID:
160 return clib_error_return (0, "Error: The iface id value invalid.");
161 case SR_PT_ERR_LOAD_INVALID:
162 return clib_error_return (
163 0, "Error: The iface ingress or egress load value invalid.");
164 case SR_PT_ERR_TTS_TEMPLATE_INVALID:
165 return clib_error_return (
166 0, "Error: The iface TTS Template value invalid.");
167 default:
168 return clib_error_return (0, "Error: unknown error.");
169 }
170 return 0;
171}
172
173/**
174 * @brief "sr pt del iface" CLI function.
175 *
176 * @see sr_pt_del_iface
177 */
178static clib_error_t *
179sr_pt_del_iface_command_fn (vlib_main_t *vm, unformat_input_t *input,
180 vlib_cli_command_t *cmd)
181{
182 vnet_main_t *vnm = vnet_get_main ();
183 u32 iface = (u32) ~0;
184
185 int rv;
186
187 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
188 {
189 if (unformat (input, "%U", unformat_vnet_sw_interface, vnm, &iface))
190 ;
191 else
192 break;
193 }
194
195 rv = sr_pt_del_iface (iface);
196
197 switch (rv)
198 {
199 case 0:
200 break;
201 case SR_PT_ERR_NOENT:
202 return clib_error_return (0, "Error: No such iface.");
203 case SR_PT_ERR_IFACE_INVALID:
204 return clib_error_return (0, "Error: The iface name is not valid.");
205 default:
206 return clib_error_return (0, "Error: unknown error.");
207 }
208 return 0;
209}
210
211/**
Ahmed Abdelsalamb0057282022-06-29 16:30:21 +0000212 * @brief CLI function to show all SR PT interfcaes
Ahmed Abdelsalamc933bb72022-06-29 11:08:42 +0000213 */
214static clib_error_t *
215sr_pt_show_iface_command_fn (vlib_main_t *vm, unformat_input_t *input,
216 vlib_cli_command_t *cmd)
217{
218 vnet_main_t *vnm = vnet_get_main ();
219 sr_pt_main_t *sr_pt = &sr_pt_main;
220 sr_pt_iface_t **sr_pt_iface_list = 0;
221 sr_pt_iface_t *ls;
222 int i;
223
224 vlib_cli_output (vm, "SR PT Interfaces");
225 vlib_cli_output (vm, "==================================");
226
227 pool_foreach (ls, sr_pt->sr_pt_iface)
228 {
229 vec_add1 (sr_pt_iface_list, ls);
230 };
231
232 for (i = 0; i < vec_len (sr_pt_iface_list); i++)
233 {
234 ls = sr_pt_iface_list[i];
235 vlib_cli_output (
236 vm,
237 "\tiface : \t%U\n\tid : \t%d\n\tingress-load: "
238 "\t%d\n\tegress-load : \t%d\n\ttts-template: \t%d ",
239 format_vnet_sw_if_index_name, vnm, ls->iface, ls->id, ls->ingress_load,
240 ls->egress_load, ls->tts_template);
241 vlib_cli_output (vm, "--------------------------------");
242 }
243
244 return 0;
245}
246
247VLIB_CLI_COMMAND (sr_pt_add_iface_command, static) = {
248 .path = "sr pt add iface",
249 .short_help = "sr pt add iface <iface-name> id <pt-iface-id> ingress-load "
250 "<ingress-load-value> egress-load <egress-load-value> "
251 "tts-template <tts-template-value>",
252 .function = sr_pt_add_iface_command_fn,
253};
254
255VLIB_CLI_COMMAND (sr_pt_del_iface_command, static) = {
256 .path = "sr pt del iface",
257 .short_help = "sr pt del iface <iface-name>",
258 .function = sr_pt_del_iface_command_fn,
259};
260
261VLIB_CLI_COMMAND (sr_pt_show_iface_command, static) = {
262 .path = "sr pt show iface",
263 .short_help = "sr pt show iface",
264 .function = sr_pt_show_iface_command_fn,
265};
266
267/**
268 * * @brief SR PT initialization
269 * */
270clib_error_t *
271sr_pt_init (vlib_main_t *vm)
272{
273 sr_pt_main_t *pt = &sr_pt_main;
274 mhash_init (&pt->sr_pt_iface_index_hash, sizeof (uword), sizeof (u32));
275 return 0;
276}
277
278VLIB_INIT_FUNCTION (sr_pt_init);