devargs: make bus optional
[dpdk.git] / lib / ipsec / ipsec_telemetry.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2021 Intel Corporation
3  */
4
5 #include <rte_ipsec.h>
6 #include <rte_telemetry.h>
7 #include <rte_malloc.h>
8 #include "sa.h"
9
10
11 struct ipsec_telemetry_entry {
12         LIST_ENTRY(ipsec_telemetry_entry) next;
13         const struct rte_ipsec_sa *sa;
14 };
15 static LIST_HEAD(ipsec_telemetry_head, ipsec_telemetry_entry)
16                 ipsec_telemetry_list = LIST_HEAD_INITIALIZER();
17
18 static int
19 handle_telemetry_cmd_ipsec_sa_list(const char *cmd __rte_unused,
20                 const char *params __rte_unused,
21                 struct rte_tel_data *data)
22 {
23         struct ipsec_telemetry_entry *entry;
24         rte_tel_data_start_array(data, RTE_TEL_U64_VAL);
25
26         LIST_FOREACH(entry, &ipsec_telemetry_list, next) {
27                 const struct rte_ipsec_sa *sa = entry->sa;
28                 rte_tel_data_add_array_u64(data, rte_be_to_cpu_32(sa->spi));
29         }
30
31         return 0;
32 }
33
34 /**
35  * Handle IPsec SA statistics telemetry request
36  *
37  * Return dict of SA's with dict of key/value counters
38  *
39  * {
40  *     "SA_SPI_XX": {"count": 0, "bytes": 0, "errors": 0},
41  *     "SA_SPI_YY": {"count": 0, "bytes": 0, "errors": 0}
42  * }
43  *
44  */
45 static int
46 handle_telemetry_cmd_ipsec_sa_stats(const char *cmd __rte_unused,
47                 const char *params,
48                 struct rte_tel_data *data)
49 {
50         struct ipsec_telemetry_entry *entry;
51         const struct rte_ipsec_sa *sa;
52         uint32_t sa_spi = 0;
53
54         if (params) {
55                 sa_spi = rte_cpu_to_be_32((uint32_t)strtoul(params, NULL, 0));
56                 if (sa_spi == 0)
57                         return -EINVAL;
58         }
59
60         rte_tel_data_start_dict(data);
61
62         LIST_FOREACH(entry, &ipsec_telemetry_list, next) {
63                 char sa_name[64];
64                 sa = entry->sa;
65                 static const char *name_pkt_cnt = "count";
66                 static const char *name_byte_cnt = "bytes";
67                 static const char *name_error_cnt = "errors";
68                 struct rte_tel_data *sa_data;
69
70                 /* If user provided SPI only get telemetry for that SA */
71                 if (sa_spi && (sa_spi != sa->spi))
72                         continue;
73
74                 /* allocate telemetry data struct for SA telemetry */
75                 sa_data = rte_tel_data_alloc();
76                 if (!sa_data)
77                         return -ENOMEM;
78
79                 rte_tel_data_start_dict(sa_data);
80
81                 /* add telemetry key/values pairs */
82                 rte_tel_data_add_dict_u64(sa_data, name_pkt_cnt,
83                                         sa->statistics.count);
84
85                 rte_tel_data_add_dict_u64(sa_data, name_byte_cnt,
86                                         sa->statistics.bytes -
87                                         (sa->statistics.count * sa->hdr_len));
88
89                 rte_tel_data_add_dict_u64(sa_data, name_error_cnt,
90                                         sa->statistics.errors.count);
91
92                 /* generate telemetry label */
93                 snprintf(sa_name, sizeof(sa_name), "SA_SPI_%i",
94                                 rte_be_to_cpu_32(sa->spi));
95
96                 /* add SA telemetry to dictionary container */
97                 rte_tel_data_add_dict_container(data, sa_name, sa_data, 0);
98         }
99
100         return 0;
101 }
102
103 static int
104 handle_telemetry_cmd_ipsec_sa_details(const char *cmd __rte_unused,
105                 const char *params,
106                 struct rte_tel_data *data)
107 {
108         struct ipsec_telemetry_entry *entry;
109         const struct rte_ipsec_sa *sa;
110         uint32_t sa_spi = 0;
111
112         if (params)
113                 sa_spi = rte_cpu_to_be_32((uint32_t)strtoul(params, NULL, 0));
114         /* valid SPI needed */
115         if (sa_spi == 0)
116                 return -EINVAL;
117
118
119         rte_tel_data_start_dict(data);
120
121         LIST_FOREACH(entry, &ipsec_telemetry_list, next) {
122                 uint64_t mode;
123                 sa = entry->sa;
124                 if (sa_spi != sa->spi)
125                         continue;
126
127                 /* add SA configuration key/values pairs */
128                 rte_tel_data_add_dict_string(data, "Type",
129                         (sa->type & RTE_IPSEC_SATP_PROTO_MASK) ==
130                         RTE_IPSEC_SATP_PROTO_AH ? "AH" : "ESP");
131
132                 rte_tel_data_add_dict_string(data, "Direction",
133                         (sa->type & RTE_IPSEC_SATP_DIR_MASK) ==
134                         RTE_IPSEC_SATP_DIR_IB ? "Inbound" : "Outbound");
135
136                 mode = sa->type & RTE_IPSEC_SATP_MODE_MASK;
137
138                 if (mode == RTE_IPSEC_SATP_MODE_TRANS) {
139                         rte_tel_data_add_dict_string(data, "Mode", "Transport");
140                 } else {
141                         rte_tel_data_add_dict_string(data, "Mode", "Tunnel");
142
143                         if ((sa->type & RTE_IPSEC_SATP_NATT_MASK) ==
144                                 RTE_IPSEC_SATP_NATT_ENABLE) {
145                                 if (sa->type & RTE_IPSEC_SATP_MODE_TUNLV4) {
146                                         rte_tel_data_add_dict_string(data,
147                                                 "Tunnel-Type",
148                                                 "IPv4-UDP");
149                                 } else if (sa->type &
150                                                 RTE_IPSEC_SATP_MODE_TUNLV6) {
151                                         rte_tel_data_add_dict_string(data,
152                                                 "Tunnel-Type",
153                                                 "IPv4-UDP");
154                                 }
155                         } else {
156                                 if (sa->type & RTE_IPSEC_SATP_MODE_TUNLV4) {
157                                         rte_tel_data_add_dict_string(data,
158                                                 "Tunnel-Type",
159                                                 "IPv4-UDP");
160                                 } else if (sa->type &
161                                                 RTE_IPSEC_SATP_MODE_TUNLV6) {
162                                         rte_tel_data_add_dict_string(data,
163                                                 "Tunnel-Type",
164                                                 "IPv4-UDP");
165                                 }
166                         }
167                 }
168
169                 rte_tel_data_add_dict_string(data,
170                                 "extended-sequence-number",
171                                 (sa->type & RTE_IPSEC_SATP_ESN_MASK) ==
172                                  RTE_IPSEC_SATP_ESN_ENABLE ?
173                                 "enabled" : "disabled");
174
175                 if ((sa->type & RTE_IPSEC_SATP_DIR_MASK) ==
176                         RTE_IPSEC_SATP_DIR_IB)
177
178                         if (sa->sqn.inb.rsn[sa->sqn.inb.rdidx])
179                                 rte_tel_data_add_dict_u64(data,
180                                 "sequence-number",
181                                 sa->sqn.inb.rsn[sa->sqn.inb.rdidx]->sqn);
182                         else
183                                 rte_tel_data_add_dict_u64(data,
184                                         "sequence-number", 0);
185                 else
186                         rte_tel_data_add_dict_u64(data, "sequence-number",
187                                         sa->sqn.outb);
188
189                 rte_tel_data_add_dict_string(data,
190                                 "explicit-congestion-notification",
191                                 (sa->type & RTE_IPSEC_SATP_ECN_MASK) ==
192                                 RTE_IPSEC_SATP_ECN_ENABLE ?
193                                 "enabled" : "disabled");
194
195                 rte_tel_data_add_dict_string(data,
196                                 "copy-DSCP",
197                                 (sa->type & RTE_IPSEC_SATP_DSCP_MASK) ==
198                                 RTE_IPSEC_SATP_DSCP_ENABLE ?
199                                 "enabled" : "disabled");
200         }
201
202         return 0;
203 }
204
205
206 int
207 rte_ipsec_telemetry_sa_add(const struct rte_ipsec_sa *sa)
208 {
209         struct ipsec_telemetry_entry *entry = rte_zmalloc(NULL,
210                         sizeof(struct ipsec_telemetry_entry), 0);
211         if (entry == NULL)
212                 return -ENOMEM;
213         entry->sa = sa;
214         LIST_INSERT_HEAD(&ipsec_telemetry_list, entry, next);
215         return 0;
216 }
217
218 void
219 rte_ipsec_telemetry_sa_del(const struct rte_ipsec_sa *sa)
220 {
221         struct ipsec_telemetry_entry *entry;
222         LIST_FOREACH(entry, &ipsec_telemetry_list, next) {
223                 if (sa == entry->sa) {
224                         LIST_REMOVE(entry, next);
225                         rte_free(entry);
226                         return;
227                 }
228         }
229 }
230
231
232 RTE_INIT(rte_ipsec_telemetry_init)
233 {
234         rte_telemetry_register_cmd("/ipsec/sa/list",
235                 handle_telemetry_cmd_ipsec_sa_list,
236                 "Return list of IPsec SAs with telemetry enabled.");
237         rte_telemetry_register_cmd("/ipsec/sa/stats",
238                 handle_telemetry_cmd_ipsec_sa_stats,
239                 "Returns IPsec SA stastistics. Parameters: int sa_spi");
240         rte_telemetry_register_cmd("/ipsec/sa/details",
241                 handle_telemetry_cmd_ipsec_sa_details,
242                 "Returns IPsec SA configuration. Parameters: int sa_spi");
243 }