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