[keystone-rtos/netapi.git] / ti / runtime / netapi / applications / ipsec_offload / ipsecmgr / src / netapilib_interface.c
1 /*
2 * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
3 *
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the
15 * distribution.
16 *
17 * Neither the name of Texas Instruments Incorporated nor the names of
18 * its contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 */
35 /* Standard includes */
36 #include <stdio.h>
37 #include <arpa/inet.h>
38 #include <inttypes.h>
40 /* ipsecmgr includes */
41 #include <ipsecmgr_snoop.h>
42 #include <ipsecmgr_syslog.h>
44 #include "netapilib_interface.h"
47 extern ipsecMgrMcb_t globalDB;
48 extern NETAPI_T netapi_handle;
51 /**************************************************************************
52 * FUNCTION PURPOSE: Internal function to find a free slot to store APPID
53 * in list
54 **************************************************************************
55 * DESCRIPTION: Internal internal function to find a free slot in SA list for an SA
56 ********************************************************************/
57 int findFreeAppIdSlot(ipsecMgrAppId_T *pList)
58 {
59 int i;
60 for(i=0;i<64;i++)
61 {
62 if (!pList[i].in_use)
63 {
64 if (free)
65 pList[i].in_use = 1; //pending
66 return i;
67 }
68 }
69 return -1;
70 }
72 /********************************************************************
73 * FUNCTION PURPOSE: Internal function to find a SA app id in SA list
74 * and free SA Slot entry if specified
75 ********************************************************************
76 * DESCRIPTION: Internal function to find a SA app id in SA list
77 * and free SA Slot entry if specified
78 ********************************************************************/
79 int findAppIdSlot(ipsecMgrAppId_T *pList, uint32_t saAppId, int free)
80 {
81 int i;
82 for(i=0;i<64;i++)
83 {
84 if ((pList[i].in_use) && (pList[i].saAppId == saAppId))
85 {
86 if(free)
87 pList[i].in_use = 0;
88 return i;
89 }
90 }
91 return -1;
92 }
94 /**************************************************************************
95 * FUNCTION PURPOSE: The function is used to translate the SA configuration
96 * parameters received from the IPSec Snopper and call the NETAPI function
97 * to create a security association
98 ********************************************************************/
99 int netapilib_ifAddSA
100 (
101 ipsecmgr_af_t af,
102 ipsecmgr_sa_id_t *sa_id,
103 ipsecmgr_sa_info_t *sa_info,
104 ipsecmgr_sa_dscp_map_cfg_t *dscp_map_cfg,
105 ipsecmgr_ifname_t *if_name,
106 ipsecmgr_sa_encap_tmpl_t *encap,
107 ipsecmgr_fp_handle_t *sa_handle
108 )
109 {
110 uint8_t auth_key[36];
111 uint8_t encr_key[36];
112 int error, index,slot;
113 NETAPI_SEC_SA_INFO_T saInfo;
114 nwalSecKeyParams_t keyParams;
115 void * p_rx_inflow_mode_handle;
116 void * p_tx_inflow_mode_handle;
117 NETCP_CFG_ROUTE_T route;
118 NETCP_CFG_FLOW_T flow;
119 NETCP_CFG_SA_HANDLE_T pSaHandle;
122 ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO,
123 "netapilib_ifAddSA:, DEBUG: Translating SA\n");
125 memset((void *)&saInfo, 0, sizeof (NETAPI_SEC_SA_INFO_T));
126 memset((void *)&keyParams, 0, sizeof (nwalSecKeyParams_t));
127 memset((void *)&route, 0, sizeof (NETCP_CFG_ROUTE_T));
128 memset((void *)&flow, 0, sizeof (NETCP_CFG_FLOW_T));
130 flow.dma_engine= 1;
131 flow.flowid = globalDB.flowId;
132 route.p_flow = &flow;
133 route.p_dest_q = globalDB.pktio_channel;
136 /* Initialize the SA Config structure. */
137 /* Get the IP protocol version. */
138 if (af == IPSECMGR_AF_IPV4)
139 {
140 saInfo.ipType = nwal_IPV4;
141 /* Populate the source and destination IP addresses. */
142 for (index = 0; index < 4; index++)
143 {
144 saInfo.dst.ipv4[index] = sa_id->daddr.ipv4[index];
145 saInfo.src.ipv4[index] = sa_info->saddr.ipv4[index];
146 }
147 }
148 else if (af == IPSECMGR_AF_IPV6)
149 {
150 saInfo.ipType = nwal_IPV6;
152 /* Populate the source and destination IP addresses. */
153 for (index = 0; index < 16; index++)
154 {
155 saInfo.dst.ipv6[index] = sa_id->daddr.ipv6[index];
156 saInfo.src.ipv6[index] = sa_info->saddr.ipv6[index];
157 }
158 }
159 else
160 {
161 ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR,
162 "netapilib_ifAddSA: Address family (%d) is invalid\n", af);
163 return -1;
164 }
165 /* Get the SPI. */
166 saInfo.spi = sa_id->spi;
168 /* Get the SA direction. */
169 if (sa_info->dir == DIR_INBOUND)
170 {
171 slot = findFreeAppIdSlot(&globalDB.rx_sa[0]);
172 if (slot == -1)
173 {
174 ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR,
175 "netapilib_ifAddSA:, Too many INBOUND SAs already offloaded\n");
176 return -1;
177 }
178 saInfo.dir = NWAL_SA_DIR_INBOUND;
179 }
180 else if (sa_info->dir == DIR_OUTBOUND)
181 {
182 slot = findFreeAppIdSlot(&globalDB.tx_sa[0]);
183 if (slot == -1)
184 {
185 ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR,
186 "netapilib_ifAddSA:, Too many OUTBOUND SAs already offloaded\n");
187 return -1;
188 }
189 saInfo.dir = NWAL_SA_DIR_OUTBOUND;
190 }
191 else
192 {
193 ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR,
194 "netapilib_ifAddSA: IPSec direction (%d) is invalid\n", sa_info->dir);
195 return -1;
196 }
199 /* Get the replay Window */
200 saInfo.replayWindow = sa_info->replay_window;
202 /* Get the IPSec protocol. */
203 if (sa_id->proto == SA_PROTO_AH)
204 saInfo.proto = nwal_IpSecProtoAH;
205 else if (sa_id->proto == SA_PROTO_ESP)
206 saInfo.proto = nwal_IpSecProtoESP;
207 else
208 {
209 ipsecmgr_syslog_msg(SYSLOG_LEVEL_INFO,
210 "netapilib_ifAddSA: IPSec protocol (%d) is invalid.\n", sa_id->proto);
211 return -1;
212 }
213 /* Get the IPSec mode. */
214 if (sa_info->mode == SA_MODE_TRANSPORT)
215 saInfo.saMode = nwal_SA_MODE_TRANSPORT;
216 else if (sa_info->mode == SA_MODE_TUNNEL)
217 saInfo.saMode = nwal_SA_MODE_TUNNEL;
218 else
219 {
220 ipsecmgr_syslog_msg(SYSLOG_LEVEL_INFO,
221 "netapilib_ifAddSA: IPSec mode (%d) is invalid.\n", sa_info->mode);
222 return -1;
223 }
224 /* Get the authentication mode algorithm. */
225 if (sa_info->auth.algo == SA_AALG_HMAC_SHA1)
226 saInfo.authMode = NWAL_SA_AALG_HMAC_SHA1;
227 else if (sa_info->auth.algo == SA_AALG_HMAC_MD5)
228 saInfo.authMode = NWAL_SA_AALG_HMAC_MD5;
229 else if (sa_info->auth.algo == SA_AALG_NONE || sa_info->auth.algo == SA_AALG_NULL)
230 saInfo.authMode = NWAL_SA_AALG_NULL;
231 else
232 {
233 ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO,
234 "netapilib_ifAddSA: Authentication algorithm (%d) is invalid\n", sa_info->auth.algo);
235 return -1;
236 }
238 /* Get the encryption mode algorithm. */
239 if (sa_info->enc.algo == SA_EALG_NULL)
240 saInfo.cipherMode = NWAL_SA_EALG_NULL;
241 else if (sa_info->enc.algo == SA_EALG_AES_CTR)
242 saInfo.cipherMode = NWAL_SA_EALG_AES_CTR;
243 else if (sa_info->enc.algo == SA_EALG_AES_CBC)
244 saInfo.cipherMode = NWAL_SA_EALG_AES_CBC;
245 else if (sa_info->enc.algo == SA_EALG_3DES_CBC)
246 saInfo.cipherMode = NWAL_SA_EALG_3DES_CBC;
247 else if (sa_info->enc.algo == SA_EALG_DES_CBC)
248 saInfo.cipherMode = NWAL_SA_EALG_DES_CBC;
249 else
250 {
251 ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR,
252 "netapilib_ifAddSA: Encryption algorithm (%d) is invalid\n", sa_info->enc.algo);
253 return -1;
254 }
255 /* Validate the key lengths. */
256 if ((keyParams.macKeySize = sa_info->auth_key_len) > 32)
257 {
258 ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR,
259 "netapilib_ifAddSA: Authentication key size (%d) is invalid.\n", sa_info->auth_key_len);
260 return -1;
261 }
262 if ((keyParams.encKeySize = sa_info->enc_key_len) > 32)
263 {
264 ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR,
265 "netapilib_ifAddSA: Encryption key size (%d) is invalid.\n", sa_info->enc_key_len);
266 return -1;
267 }
269 /* Get the authentication/encryption keys. */
270 keyParams.pAuthKey = &sa_info->auth_key[0];
271 keyParams.pEncKey = &sa_info->enc_key[0];
273 if (saInfo.dir == NWAL_SA_DIR_INBOUND)
274 {
275 /* Inbound == RX */
276 globalDB.rx_sa[slot].saAppId = netapi_secAddSA(netapi_handle,
277 NETCP_CFG_NO_INTERFACE,
278 &saInfo,
279 &keyParams,
280 NETAPI_SEC_SA_INFLOW,
281 (NETCP_CFG_ROUTE_HANDLE_T)&route,
282 &p_rx_inflow_mode_handle,
283 &p_tx_inflow_mode_handle,
284 NULL, &error);
286 if (error == NETAPI_ERR_OK)
287 {
288 *sa_handle = globalDB.rx_sa[slot].saAppId;
289 }
290 else
291 {
292 ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR,
293 "netapilib_ifAddSA: netapi_secAddSA returned error: %d.\n",
294 error);
295 return -1;
296 }
297 }
298 else
299 {
300 /* OUTBOUND == TX */
301 globalDB.tx_sa[slot].saAppId = netapi_secAddSA(netapi_handle,
302 NETCP_CFG_NO_INTERFACE,
303 &saInfo,
304 &keyParams,
305 NETAPI_SEC_SA_INFLOW,
306 (NETCP_CFG_ROUTE_HANDLE_T)NULL,
307 &p_rx_inflow_mode_handle,
308 &p_tx_inflow_mode_handle,
309 NULL, &error);
310 if (error == NETAPI_ERR_OK)
311 {
312 *sa_handle = globalDB.tx_sa[slot].saAppId;
313 printf("netapilib_ifAddSA: using slot: %d\n", slot);
314 #if 0
315 netapi_secGetChanHandles(netapi_handle,
316 saAppIdOut,
317 NULL,
318 &pSaHandle);
319 #endif
320 }
321 else
322 {
323 ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR,
324 "netapilib_ifAddSA: netapi_secAddSA returned error: %d.\n",
325 error);
326 return -1;
327 }
328 }
330 ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO,
331 "netapilib_ifAddSA: Translation of SA successful, app_id: 0x%x\n", *sa_handle);
333 /* SA was created successfully. */
334 return 0;
335 }
336 /**************************************************************************
337 * FUNCTION PURPOSE: The function is used to translate the SA configuration
338 * parameters received from the IPSec Snopper and call the NETAPI function
339 * to delete a security association
340 ********************************************************************/
341 int netapilib_ifDeleteSA (ipsecmgr_fp_handle_t sa_handle)
342 {
343 int error, slot;
345 slot = findAppIdSlot(&globalDB.rx_sa[0],sa_handle, 1);
347 /* Determine if rx_sa or tx_sa is being deleted */
348 if (slot != -1)
349 {
350 /* found rx SA, see if there is policy assoicated with rx SA
351 if so, then delete it first*/
352 if (globalDB.rx_sa[slot].spAppId)
353 {
354 netapi_secDelRxPolicy(netapi_handle,
355 (NETCP_CFG_IPSEC_POLICY_T) globalDB.rx_sa[slot].spAppId,
356 &error);
357 ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO,
358 "netapilib_ifDeleteSA: SP deleted: sp_app_id: 0x%x, slot: %d, error: %d\n",
359 globalDB.rx_sa[slot].spAppId, slot, error);
360 netapi_secDelSA(netapi_handle,
361 NETCP_CFG_NO_INTERFACE,
362 (NETCP_CFG_SA_T) sa_handle,
363 &error);
364 ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO,
365 "netapilib_ifDeleteSA: SA deleted: sa_app_id: 0x%x, slot: %d, error: %d\n",
366 sa_handle, slot, error);
368 }
369 }
370 else
371 {
372 /* not rx SA, check for tx_sa */
373 slot = findAppIdSlot(&globalDB.tx_sa[0], sa_handle, 1);
375 if (slot != -1)
376 {
377 /* found tx SA, delete it now */
378 netapi_secDelSA(netapi_handle,
379 NETCP_CFG_NO_INTERFACE,
380 (NETCP_CFG_SA_T) sa_handle,
381 &error);
382 ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO,
383 "netapilib_ifDeleteSA: SA deleted: sa_app_id: 0x%x, slot: %d, error: %d\n",
384 sa_handle, slot, error);
385 }
386 else
387 {
388 ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR,
389 "netapilib_ifDeleteSA: sa_app_id 0x%x not found in internal list\n",
390 sa_handle);
391 return -1;
392 }
393 }
395 return error;
396 }
398 /**************************************************************************
399 * FUNCTION PURPOSE: The function is used to translate the SP configuration
400 * parameters received from the IPSec Snopper and call the NETAPI function
401 * to create a security policy
402 ********************************************************************/
403 int32_t netapilib_ifAddSP
404 (
405 ipsecmgr_af_t af,
406 ipsecmgr_selector_t *sel,
407 ipsecmgr_dir_t dir,
408 uint32_t reqid,
409 ipsecmgr_fp_handle_t sa_handle,
410 ipsecmgr_policy_id_t policy_id,
411 ipsecmgr_fp_handle_t *sp_handle
412 )
413 {
414 #ifdef ENABLE_ADD_POLICY
415 NETCP_CFG_IPSEC_POLICY_T spAppIdIn;
416 int error, index, slot;
417 nwal_IpType ipType;
418 nwalIpAddr_t src_ip_addr;
419 nwalIpAddr_t dst_ip_addr;
420 nwalIpOpt_t ip_qualifiers;
421 NETCP_CFG_SA_T sa =(NETCP_CFG_SA_T)sa_handle;
422 NETCP_CFG_ROUTE_T route;
423 NETCP_CFG_FLOW_T flow;
424 NETCP_CFG_PA_HANDLE_T pPaHandleOuterIP;
425 NETCP_CFG_PA_HANDLE_T pPaHandleInnerIP;
426 NETCP_CFG_SA_HANDLE_T pSaHandle;
427 ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO,"netapilib_ifAddSP: called\n");
430 if (dir == DIR_OUTBOUND)
431 {
432 ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO,
433 "netapilib_ifAddSP: called for outbound SA, no RX policy required\n");
434 return 0;
435 }
436 slot = findAppIdSlot(&globalDB.rx_sa[0],sa_handle, 0);
437 if (slot == -1)
438 {
439 ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR,
440 "netapilib_ifAddSA:, Too many OUTBOUND SAs already offloaded\n");
441 return -1;
442 }
445 flow.dma_engine= 1;
446 flow.flowid = globalDB.flowId;
447 route.p_flow = &flow;
448 route.p_dest_q = globalDB.pktio_channel;
450 /* Get the IP protocol version. */
451 if (af == IPSECMGR_AF_IPV4)
452 {
453 ipType = nwal_IPV4;
454 /* Populate the source and destination IP addresses. */
455 for (index = 0; index < 4; index++)
456 {
457 dst_ip_addr.ipv4[index] = sel->daddr.ipv4[index];
458 src_ip_addr.ipv4[index] = sel->saddr.ipv4[index];
459 }
460 }
461 else if (af == IPSECMGR_AF_IPV6)
462 {
463 ipType = nwal_IPV6;
464 /* Populate the source and destination IP addresses. */
465 for (index = 0; index < 16; index++)
466 {
467 dst_ip_addr.ipv6[index] = sel->daddr.ipv6[index];
468 src_ip_addr.ipv6[index] = sel->saddr.ipv6[index];
469 }
470 }
471 else
472 {
473 ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR,
474 "netapilib_ifAddSP: Address family (%d) is invalid\n", af);
475 return -1;
476 }
478 globalDB.rx_sa[slot].spAppId = netapi_secAddRxPolicy(netapi_handle,
479 (NETCP_CFG_SA_T) sa_handle,
480 ipType,
481 &src_ip_addr,
482 &dst_ip_addr,
483 NULL,
484 (NETCP_CFG_ROUTE_HANDLE_T)&route,
485 NULL,
486 &error);
488 if (error == NETAPI_ERR_OK)
489 {
490 *sp_handle = globalDB.rx_sa[slot].spAppId;
491 }
492 else
493 {
494 ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR,
495 "netapilib_ifAddSA: netapi_secAddRxPolicy returned error: %d.\n",
496 error);
497 return -1;
498 }
499 ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO,
500 "netapilib_ifAddSA: Translation of SP successful, app_id: 0x%x\n", *sp_handle);
502 #if 0
503 netapi_secGetChanHandles(netapi_handle,
504 (NETCP_CFG_SA_T)sa_handle,
505 globalDB.rx_sa[slot].spAppId,
506 &pPaHandleOuterIP,
507 &pPaHandleInnerIP,
508 &pSaHandle);
509 #endif
510 #endif
511 return 0;
512 }
514 /**************************************************************************
515 * FUNCTION PURPOSE: The function is used to translate the SP configuration
516 * parameters received from the IPSec Snopper and call the NETAPI function
517 * to delete a security association
518 ********************************************************************/
519 int32_t netapilib_ifDeleteSP
520 (
521 ipsecmgr_fp_handle_t sp_handle,
522 ipsecmgr_policy_id_t policy_id,
523 ipsecmgr_dir_t dir
524 )
525 {
526 /* Security Policy is deleted as part of deleting SA */
527 return 0;
528 #if 0
529 int error =0;
530 ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO,"netapilib_ifDeleteSP: called\n");
532 if (dir == DIR_OUTBOUND)
533 {
534 ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO,
535 "netapilib_ifDeleteSP: called for outbound SA, no RX policy to delete\n");
536 return 0;
537 }
538 netapi_secDelRxPolicy(netapi_handle,
539 (NETCP_CFG_IPSEC_POLICY_T) sp_handle,
540 &error);
542 return 0;
543 #endif
544 }
546 /**************************************************************************
547 * FUNCTION PURPOSE: The function is used to translate the SA configuration
548 * parameters received from the IPSec Snopper and retrieve SA context
549 * information for SA.
550 *************************************************************************/
551 int netapilib_ifGetSACtx
552 (
553 ipsecmgr_fp_handle_t sa_handle,
554 ipsecmgr_sa_hw_ctx_t* hw_ctx
555 )
556 {
557 uint32_t swInfo0 = 0;
558 uint32_t swInfo1 = 0;
559 nwalGlobCxtInfo_t info;
560 nwal_RetValue retVal;
562 memset(&info, 0, sizeof(nwalGlobCxtInfo_t));
563 NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) netapi_handle;
564 ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO,"netapilib_ifGetSACtx: called\n");
567 netapip_netcpCfgGetSaInflowInfo(&netapi_get_global()->nwal_context,
568 (NETCP_CFG_SA_T) sa_handle,
569 &swInfo0,
570 &swInfo1);
572 hw_ctx->swinfo_sz = 2;
573 hw_ctx->swinfo[0] = swInfo0;
574 hw_ctx->swinfo[1] = swInfo1;
576 retVal = nwal_getGlobCxtInfo(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,
577 &info);
578 if (retVal != nwal_OK)
579 {
580 ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR,
581 "netapilib_ifGetSACtx: nwal_getGlobCxtInfo returned error: 0x%x\n", retVal);
582 return -1;
583 }
584 hw_ctx->flow_id = info.rxSaPaFlowId;
586 ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO,
587 "netapilib_ifGetSACtx: rxPaSaFlowId: 0x%x, rxSaPaFlowId: 0x%x\n",
588 info.rxPaSaFlowId,
589 info.rxSaPaFlowId);
590 ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO,
591 "netapilib_ifGetSACtx: swInfo0: 0x%x, swInfo1: 0x%x, flowId: 0x%x\n",
592 hw_ctx->swinfo[0],
593 hw_ctx->swinfo[1],
594 hw_ctx->flow_id);
596 /* return success */
597 return 0;
598 }