Line data Source code
1 : /* SPDX-License-Identifier: BSD-2-Clause
2 : * Copyright(c) HCL TECHNOLOGIES LTD
3 : * Submitted on behalf of a third-party: Intel Corporation, a
4 : * Delaware corporation, having its principal place of business
5 : * at 2200 Mission College Boulevard,
6 : * Santa Clara, California 95052, USA
7 : */
8 :
9 : #include "vr_dpdk_n3k_offloads.h"
10 :
11 : #include <stdio.h>
12 : #include <stdbool.h>
13 :
14 : #include <arpa/inet.h>
15 :
16 : #include <rte_byteorder.h>
17 : #include <rte_common.h>
18 : #include <rte_log.h>
19 :
20 : #include <vr_dpdk.h>
21 : #include <vr_flow.h>
22 : #include <vr_offloads.h>
23 :
24 : #include "vr_dpdk_n3k_interface.h"
25 : #include "vr_dpdk_n3k_missing_mirror.h"
26 : #include "vr_dpdk_n3k_mpls.h"
27 : #include "vr_dpdk_n3k_flow.h"
28 : #include "vr_dpdk_n3k_vxlan.h"
29 : #include "vr_dpdk_n3k_packet_metadata.h"
30 : #include "vr_dpdk_n3k_packet_parser.h"
31 : #include "vr_dpdk_n3k_config.h"
32 : #include "vr_dpdk_n3k_offload_hold.h"
33 :
34 : extern unsigned int vr_bridge_entries;
35 : extern unsigned int datapath_offloads;
36 :
37 : rte_spinlock_t vr_dpdk_n3k_offload_spinlock __rte_cache_aligned;
38 :
39 : static void
40 0 : debug_print_packet_key_and_metadata(
41 : const struct vr_packet *pkt,
42 : const struct vr_dpdk_n3k_packet_key *key,
43 : const struct vr_dpdk_n3k_packet_metadata *metadata)
44 : {
45 : char ip_addr[40];
46 :
47 0 : RTE_LOG(DEBUG, OFFLOAD_PACKET, "%s: printing parsed packet\n", __func__);
48 0 : RTE_LOG(DEBUG, OFFLOAD_PACKET, "%s: pkt=%p\n", __func__, pkt);
49 :
50 0 : RTE_LOG(DEBUG, OFFLOAD_PACKET, "%s: key\n", __func__);
51 0 : RTE_LOG(DEBUG, OFFLOAD_PACKET, "%s: key->nh_id = %u\n", __func__,
52 : key->nh_id);
53 :
54 0 : RTE_LOG(DEBUG, OFFLOAD_PACKET, "%s: key->src_ip = %s\n", __func__,
55 : vr_dpdk_n3k_convert_ip_to_str(ip_addr, &key->ip.src, key->ip.type));
56 0 : RTE_LOG(DEBUG, OFFLOAD_PACKET, "%s: key->dst_ip = %s\n", __func__,
57 : vr_dpdk_n3k_convert_ip_to_str(ip_addr, &key->ip.dst, key->ip.type));
58 :
59 0 : RTE_LOG(DEBUG, OFFLOAD_PACKET, "%s: key->proto = %u\n", __func__,
60 : key->proto);
61 0 : RTE_LOG(DEBUG, OFFLOAD_PACKET, "%s: key->src_port = %u\n", __func__,
62 : rte_be_to_cpu_16(key->src_port));
63 0 : RTE_LOG(DEBUG, OFFLOAD_PACKET, "%s: key->dst_port = %u\n", __func__,
64 : rte_be_to_cpu_16(key->dst_port));
65 :
66 0 : RTE_LOG(DEBUG, OFFLOAD_PACKET, "%s: metadata\n", __func__);
67 :
68 0 : RTE_LOG(DEBUG, OFFLOAD_PACKET,
69 : "%s: metadata->eth_hdr = %u\n", __func__,
70 : metadata->eth_hdr_present);
71 :
72 0 : if (metadata->eth_hdr_present) {
73 0 : RTE_LOG(DEBUG, OFFLOAD_PACKET,
74 : "%s: metadata->inner_src_mac = " MAC_FORMAT "\n", __func__,
75 : MAC_VALUE(&metadata->inner_src_mac[0]));
76 0 : RTE_LOG(DEBUG, OFFLOAD_PACKET,
77 : "%s: metadata->inner_dst_mac = " MAC_FORMAT "\n", __func__,
78 : MAC_VALUE(&metadata->inner_dst_mac[0]));
79 : }
80 0 : }
81 :
82 : static int
83 0 : vr_dpdk_n3k_offload_packet_parse(struct vr_packet *pkt)
84 : {
85 0 : RTE_LOG(DEBUG, OFFLOAD_PACKET, "%s() called; pkt=%p\n", __func__, pkt);
86 :
87 : struct vr_dpdk_n3k_packet_key key;
88 : struct vr_dpdk_n3k_packet_metadata metadata;
89 : int ret;
90 :
91 0 : ret = vr_dpdk_n3k_parse_packet(pkt, &key, &metadata);
92 0 : if (ret != 0) {
93 0 : RTE_LOG(DEBUG, OFFLOAD_PACKET,
94 : "%s(): vr_dpdk_n3k_parse_packet() returned %d for pkt=%p\n",
95 : __func__, ret, pkt);
96 0 : return ret;
97 : } else
98 0 : debug_print_packet_key_and_metadata(pkt, &key, &metadata);
99 :
100 0 : ret = vr_dpdk_n3k_packet_metadata_insert_copy(&key, &metadata, false);
101 0 : if (ret != 0) {
102 0 : RTE_LOG(DEBUG, OFFLOAD_PACKET,
103 : "%s(): vr_dpdk_n3k_packet_metadata_insert_copy() returned %d for pkt=%p\n",
104 : __func__, ret, pkt);
105 : }
106 0 : return ret;
107 : }
108 :
109 : /* When vrouter calls this function, all the packet processing had stopped (by
110 : * shutting interfaces) and all the structures have been re-initialized.
111 : * Because of that, we don't need to consider interaction of this callback with
112 : * other threads, except of interaction with service cores (which are
113 : * unaffected by the reset) -- we need to provide thread safety wrt to
114 : * aging_service_core and remove_unused_metadata_service_core.
115 : */
116 : static int
117 0 : vr_dpdk_n3k_offload_soft_reset(void)
118 : {
119 0 : struct vrouter *router = vrouter_get(0);
120 : int ret;
121 :
122 0 : vr_dpdk_n3k_offload_interface_exit();
123 0 : ret = vr_dpdk_n3k_offload_interface_init(router->vr_max_interfaces);
124 0 : if (ret)
125 0 : return ret;
126 :
127 0 : vr_dpdk_n3k_offload_vxlan_exit();
128 0 : ret = vr_dpdk_n3k_offload_vxlan_init(router->vr_max_nexthops);
129 0 : if (ret)
130 0 : return ret;
131 :
132 0 : vr_dpdk_n3k_offload_mpls_exit();
133 0 : ret = vr_dpdk_n3k_offload_mpls_init(router->vr_max_nexthops);
134 0 : if (ret)
135 0 : return ret;
136 :
137 0 : vr_dpdk_n3k_offload_missing_mirror_exit_all();
138 0 : ret = vr_dpdk_n3k_offload_missing_mirror_init_all();
139 0 : if (ret)
140 0 : return ret;
141 :
142 : /* We don't need to reset offload_hold, as it's cleared by
143 : * vr_dpdk_n3k_offload_flow_reset_unlocked */
144 :
145 0 : vr_dpdk_n3k_packet_metadata_reset();
146 :
147 0 : vr_dpdk_n3k_offload_lock();
148 0 : vr_dpdk_n3k_offload_flow_reset_unlocked();
149 0 : vr_dpdk_n3k_offload_unlock();
150 :
151 0 : return 0;
152 : }
153 :
154 : static int
155 0 : vr_dpdk_n3k_offload_flow_set_threadsafe(
156 : struct vr_flow_entry *fe, uint32_t fe_index, struct vr_flow_entry *rfe)
157 : {
158 0 : int ret = 0;
159 0 : vr_dpdk_n3k_offload_lock();
160 0 : ret = vr_dpdk_n3k_offload_flow_set_unlocked(fe, fe_index, rfe);
161 0 : vr_dpdk_n3k_offload_unlock();
162 0 : return ret;
163 : }
164 :
165 : static int
166 0 : vr_dpdk_n3k_offload_flow_del_threadsafe(struct vr_flow_entry *fe)
167 : {
168 0 : vr_dpdk_n3k_offload_lock();
169 0 : int ret = vr_dpdk_n3k_offload_flow_del_unlocked(fe);
170 0 : vr_dpdk_n3k_offload_unlock();
171 0 : return ret;
172 : }
173 :
174 : static int
175 0 : vr_dpdk_n3k_offload_flow_stats_update_threadsafe(struct vr_flow_entry *fe)
176 : {
177 0 : vr_dpdk_n3k_offload_lock();
178 0 : int ret = vr_dpdk_n3k_offload_flow_stats_update_unlocked(fe);
179 0 : vr_dpdk_n3k_offload_unlock();
180 0 : return ret;
181 : }
182 :
183 : static int
184 0 : vr_dpdk_n3k_offload_mirror_add_threadsafe(
185 : struct vr_mirror_entry *mirror, unsigned int index)
186 : {
187 0 : vr_dpdk_n3k_offload_lock();
188 0 : if (mirror->mir_rid == 0) {
189 0 : vr_dpdk_n3k_offload_missing_mirror_flows_unlocked(index);
190 : }
191 0 : vr_dpdk_n3k_offload_unlock();
192 0 : return 0;
193 : }
194 :
195 : static int
196 0 : vr_dpdk_n3k_offload_nexthop_add_threadsafe(struct vr_nexthop *nh)
197 : {
198 0 : vr_dpdk_n3k_offload_lock();
199 0 : if (vr_dpdk_n3k_offload_nexthop_validate(nh) == 0) {
200 0 : vr_dpdk_n3k_offload_missing_nexthop_flows_unlocked(nh->nh_id);
201 : }
202 0 : vr_dpdk_n3k_offload_unlock();
203 0 : return 0;
204 : }
205 :
206 : static char n3k_voo_handler_id[] = "N3K offloads";
207 :
208 : static const struct vr_offload_ops vr_dpdk_n3k_offload_ops = {
209 : .voo_handler_id = n3k_voo_handler_id,
210 :
211 : .voo_soft_reset = vr_dpdk_n3k_offload_soft_reset,
212 :
213 : .voo_packet_parse = vr_dpdk_n3k_offload_packet_parse,
214 :
215 : .voo_flow_set = vr_dpdk_n3k_offload_flow_set_threadsafe,
216 : .voo_flow_del = vr_dpdk_n3k_offload_flow_del_threadsafe,
217 : .voo_flow_stats_update = vr_dpdk_n3k_offload_flow_stats_update_threadsafe,
218 :
219 : .voo_interface_add = vr_dpdk_n3k_offload_interface_add,
220 : .voo_interface_del = vr_dpdk_n3k_offload_interface_del,
221 :
222 : .voo_mpls_add = vr_dpdk_n3k_offload_mpls_add,
223 : .voo_mpls_del = vr_dpdk_n3k_offload_mpls_del,
224 :
225 : .voo_vxlan_add = vr_dpdk_n3k_offload_vxlan_add,
226 : .voo_vxlan_del = vr_dpdk_n3k_offload_vxlan_del,
227 :
228 : .voo_mirror_add = vr_dpdk_n3k_offload_mirror_add_threadsafe,
229 :
230 : .voo_nexthop_add = vr_dpdk_n3k_offload_nexthop_add_threadsafe,
231 : };
232 :
233 : static const struct vr_offload_ops *n3k_offload_ops = NULL;
234 :
235 : static void
236 0 : vr_dpdk_n3k_offload_ops_exit(void)
237 : {
238 0 : n3k_offload_ops = NULL;
239 :
240 0 : vr_dpdk_n3k_offload_lock();
241 :
242 0 : vr_dpdk_n3k_offload_missing_mirror_exit_all();
243 0 : vr_dpdk_n3k_offload_flow_exit();
244 0 : vr_dpdk_n3k_offload_mpls_exit();
245 0 : vr_dpdk_n3k_offload_vxlan_exit();
246 0 : vr_dpdk_n3k_offload_interface_exit();
247 0 : vr_dpdk_n3k_packet_metadata_exit();
248 0 : vr_dpdk_n3k_offload_hold_exit();
249 0 : vr_dpdk_n3k_offload_unlock();
250 0 : }
251 :
252 : static int
253 0 : vr_dpdk_n3k_offload_ops_init(struct vrouter *router)
254 : {
255 0 : int ret = 0;
256 :
257 0 : vr_compute_size_oflow_table();
258 0 : const unsigned int flow_entries = vr_flow_entries + vr_oflow_entries;
259 :
260 0 : rte_spinlock_init(&vr_dpdk_n3k_offload_spinlock);
261 :
262 0 : ret = vr_dpdk_n3k_offload_interface_init(router->vr_max_interfaces);
263 0 : if (ret)
264 0 : goto error;
265 :
266 0 : ret = vr_dpdk_n3k_offload_vxlan_init(router->vr_max_nexthops);
267 0 : if (ret)
268 0 : goto error;
269 :
270 0 : ret = vr_dpdk_n3k_offload_mpls_init(router->vr_max_nexthops);
271 0 : if (ret)
272 0 : goto error;
273 :
274 0 : ret = vr_dpdk_n3k_offload_flow_init(flow_entries);
275 0 : if (ret)
276 0 : goto error;
277 :
278 0 : ret = vr_dpdk_n3k_offload_missing_mirror_init_all();
279 0 : if (ret)
280 0 : goto error;
281 :
282 0 : ret = vr_dpdk_n3k_packet_metadata_init(2 * flow_entries);
283 0 : if (ret)
284 0 : goto error;
285 :
286 0 : ret = vr_dpdk_n3k_offload_hold_init(flow_entries);
287 0 : if (ret)
288 0 : goto error;
289 :
290 0 : n3k_offload_ops = &vr_dpdk_n3k_offload_ops;
291 :
292 0 : return 0;
293 :
294 0 : error:
295 0 : vr_dpdk_n3k_offload_ops_exit();
296 0 : return ret;
297 : }
298 :
299 : void
300 0 : vr_dpdk_n3k_offload_exit(void)
301 : {
302 0 : if (!datapath_offloads) {
303 0 : return;
304 : }
305 :
306 0 : vr_offload_unregister();
307 0 : vr_dpdk_n3k_offload_ops_exit();
308 : }
309 :
310 : int
311 0 : vr_dpdk_n3k_offload_init(void)
312 : {
313 0 : if (!datapath_offloads) {
314 0 : return 0;
315 : }
316 :
317 : /* TODO(n3k): Handle multiple vrouters */
318 0 : int ret = vr_dpdk_n3k_offload_ops_init(vrouter_get(0));
319 0 : if (ret != 0) {
320 0 : RTE_LOG(ERR, VROUTER, "Initialization of N3K vr_offload_ops failed; ret = %s\n",
321 : rte_strerror(ret));
322 0 : return ret;
323 : }
324 :
325 0 : vr_offload_unregister();
326 0 : ret = vr_offload_register(n3k_offload_ops);
327 0 : if (ret != 0) {
328 0 : RTE_LOG(ERR, VROUTER, "vr_offload_register() failed; ret = %s\n",
329 : rte_strerror(ret));
330 :
331 0 : vr_dpdk_n3k_offload_ops_exit();
332 :
333 0 : return ret;
334 : }
335 :
336 0 : return 0;
337 : }
|