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