SDOCM00090624:Delete Classifer API will try and delete the same ad hoc IP rule if...
[keystone-rtos/netapi.git] / ti / runtime / netapi / src / netcp_cfg.c
1 /**********************************************************
2  * file: netcp_cfg.c
3  * purpose: netcp configurations routines
4  **************************************************************
5  * FILE: netcp_cfg.c
6  * 
7  * DESCRIPTION:  netcp configuration main source file for user space transport
8  *               library
9  * 
10  * REVISION HISTORY:
11  *
12  *  Copyright (c) Texas Instruments Incorporated 2013
13  * 
14  *  Redistribution and use in source and binary forms, with or without 
15  *  modification, are permitted provided that the following conditions 
16  *  are met:
17  *
18  *    Redistributions of source code must retain the above copyright 
19  *    notice, this list of conditions and the following disclaimer.
20  *
21  *    Redistributions in binary form must reproduce the above copyright
22  *    notice, this list of conditions and the following disclaimer in the 
23  *    documentation and/or other materials provided with the   
24  *    distribution.
25  *
26  *    Neither the name of Texas Instruments Incorporated nor the names of
27  *    its contributors may be used to endorse or promote products derived
28  *    from this software without specific prior written permission.
29  *
30  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
31  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
32  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
33  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
34  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
35  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
36  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
37  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
38  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
39  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
40  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42  ******************************************************/
44 #include "netapi.h"
46 extern NETAPI_SHM_T* pnetapiShm;
48 /******************************************************************
49  ********************Netapi internal*************************************
50 *******************************************************************/
53 /********************************************************************
54  * FUNCTION PURPOSE:  Netapi internal function to get a free transaction id
55  ********************************************************************
56  * DESCRIPTION:  Netapi internal function to get a free transaction id.
57  ********************************************************************/
58 NetapiNwalTransInfo_t * netapip_getFreeTransInfo(NETAPI_HANDLE_T *p_handle,
59                                                  NETAPI_PROC_GLOBAL_T *p_proc_global,
60                                                  nwal_TransID_t *pTransId)
61 {
62     uint16_t    count=0;
64     count=0;
65     p_handle->spinLock.lock(&pnetapiShm->netapi_netcp_cfg_lock);
66     while(count < TUNE_NETAPI_MAX_NUM_TRANS)
67     {
68         if((p_proc_global->nwal_context.transInfos[count].inUse) != nwal_TRUE)
69         {
70             p_proc_global->nwal_context.transInfos[count].inUse = nwal_TRUE;
71             *pTransId = count;
72             p_handle->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_lock);
73             return(&p_proc_global->nwal_context.transInfos[count]);
74         }
75         count++;
76     }
77     p_handle->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_lock);
78     /* trouble.  need to wait for one to free up*/
79     /* to do: handle this by forcing a poll of cntrl queue*/
80     netapi_Log(">netcp_cfg: trying to get free transaction slot but all full!!\n");
81     return NULL;
83 }
85 /********************************************************************
86  * FUNCTION PURPOSE:  Netapi internal function to free a transaction id
87  ********************************************************************
88  * DESCRIPTION:  Netapi internal function to free a transaction id
89  ********************************************************************/
90 void netapip_freeTransInfo(NetapiNwalTransInfo_t *pTransInfo)
91 {
92     pTransInfo->inUse = nwal_FALSE;
93     pTransInfo->state = NETAPI_NWAL_HANDLE_STATE_IDLE;
94     pTransInfo->transType = NETAPI_NWAL_HANDLE_TRANS_NONE;
95 }
96 /********************************************************************
97  * FUNCTION PURPOSE:  Netapi internal function to build a route
98  ********************************************************************
99  * DESCRIPTION:  Netapi internal function to build a route
100  ********************************************************************/
101 void netapip_netcpCfgBuildRoute(NETCP_CFG_ROUTE_T * p_route,
102                                 int16_t *p_flow,
103                                 Qmss_QueueHnd *p_q,
104                                 nwalRouteType_t *p_type)
106     if (!p_route) return;
107     if (p_route->p_flow)  *p_flow= p_route->p_flow->flowid;
108     else *p_flow = CPPI_PARAM_NOT_SPECIFIED;
110     if (p_route->p_dest_q) *p_q = netapi_pktioGetQ(p_route->p_dest_q);
111     else *p_q=QMSS_PARAM_NOT_SPECIFIED;
113     *p_type = p_route->routeType;
117 /******************************************************/
118 /*----------------database management stuff           */
119 /******************************************************/
121 /*=====================POLICIES=============================*/
123 /********************************************************************
124  * FUNCTION PURPOSE:  Netapi internal function to find a free slot for an SA
125  ********************************************************************
126  * DESCRIPTION:  Netapi internal function to find a free slot for an SA
127  ********************************************************************/
128 int netapip_netcpCfgFindPolicySlot(NETAPI_HANDLE_T *p_handle,
129                                    NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
130                                    int tunnel)
132     int i;
133     if ((tunnel <0 ) || (tunnel >=TUNE_NETAPI_MAX_SA))
134         return -1;
136     p_handle->spinLock.lock(&pnetapiShm->netapi_netcp_cfg_lock);
137     //find a free entry
138     for(i=0;i<TUNE_NETAPI_MAX_POLICY;i++)
139     {
140         if (!p->policy[i].in_use)
141         {
142             p->policy[i].in_use = 2; //pending
143             p->policy[i].tunnel= tunnel; //save tunnel this is linked to
144             p_handle->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_lock);
145             return i;
146         }
147     }
148     p_handle->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_lock);
149     return -1;
152 /********************************************************************
153  * FUNCTION PURPOSE:  Netapi internal function to delete a policy from policy list
154  ********************************************************************
155  * DESCRIPTION:  Netapi internal function to delete a policy from policy list
156  ********************************************************************/
157 void netapip_netcpCfgDeletePolicy(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
158                                   int policy_slot)
160     if ((policy_slot <0 ) || (policy_slot >= TUNE_NETAPI_MAX_POLICY))
161     {
162         return ;
163     }
164     p->policy[policy_slot].in_use=0;
165     return;
168 /********************************************************************
169  * FUNCTION PURPOSE:  Netapi internal function to insert a policy to the policy list
170  ********************************************************************
171  * DESCRIPTION:  Netapi internal function to insert a policy to the policy list
172  ********************************************************************/
173 void netapip_netcpCfgInsertPolicy(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
174                                   int policy_slot,
175                                   void * handle,
176                                   void * user_data)
178     p->policy[policy_slot].in_use=1;
179     p->policy[policy_slot].nwal_handle = handle;
180     p->policy[policy_slot].user_data = user_data;
181     return;
184 /************************************************************************
185  * FUNCTION PURPOSE:  Netapi internal function which returns NWAL handle for a policy
186  ************************************************************************
187  * DESCRIPTION:  Netapi internal function which returns NWAL handle for a policy
188  ************************************************************************/
189 void *netapip_netcpCfgGetPolicy(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
190                                 int policy_slot)
192     if ((policy_slot <0 ) || (policy_slot >= TUNE_NETAPI_MAX_POLICY))
193         return NULL;
194     if (!p->policy[policy_slot].in_use)
195         return NULL;
196     return p->policy[policy_slot].nwal_handle;
199 /********************************************************************
200  * FUNCTION PURPOSE:  Netapi internal function to find a free slot in SA list for a SA
201  ********************************************************************
202  * DESCRIPTION:  Netapi internal function to find a free slot in SA list for an SA
203  ********************************************************************/
204 int netapip_netcpCfgFindSaSlot(NETAPI_HANDLE_T *p_handle,
205                                NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
206                                int iface)
207 {                                    
208    int i;
209    if (iface != NETCP_CFG_NO_INTERFACE)
210    {
211    if ((iface <0 ) || (iface >=TUNE_NETAPI_MAX_NUM_MAC)) return -1;
212    }
213    p_handle->spinLock.lock(&pnetapiShm->netapi_netcp_cfg_lock);
214    //find a free entry
215    for(i=0;i<TUNE_NETAPI_MAX_SA;i++)
216    {                       
217        if (!p->tunnel[i].in_use)
218        {
219            p->tunnel[i].in_use = 2; //pending
220            p->tunnel[i].iface= iface; //save iface
221            p_handle->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_lock);
222            return i;
223        }
224    }
225    p_handle->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_lock);
226    return -1;
229 /********************************************************************
230  * FUNCTION PURPOSE:  Netapi internal function to delete an SA from SA list
231  ********************************************************************
232  * DESCRIPTION: Netapi internal function to delete an SA from SA list 
233  ********************************************************************/
234 void netapip_netcpCfgDeleteSa(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
235                               int sa_slot)
237     if ((sa_slot <0 ) || (sa_slot >= TUNE_NETAPI_MAX_SA))
238     {
239         return ;
240     }
241     p->tunnel[sa_slot].in_use=0;
242     return;
246 /****************************************************************************
247  * FUNCTION PURPOSE:  Internal function to retrieve SB command info template
248  **************************************************************************
249  * DESCRIPTION:  Internal function to retrieve SB command info template
250  ***************************************************************************/
251 nwalTxDmPSCmdInfo_t* netapip_netcpCfgGetSaSBInfo(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
252                                                  NETCP_CFG_SA_T    sa_app_id)
254      int sa_slot = netapi_cfgGetMatchId(sa_app_id);
255     if ((sa_slot <0 ) || (sa_slot >= TUNE_NETAPI_MAX_SA))
256     {
257         return NULL;
258     }
259     return (&p->tunnel[sa_slot].dmPSCmdInfo);
262 /****************************************************************************
263  * FUNCTION PURPOSE:  Internal function to retrieve Inflow mode 
264  *                    software information required to transmit packet
265  **************************************************************************
266  * DESCRIPTION:  Internal function to retrieve Inflow mode 
267  *                    software information required to transmit packet
268  ***************************************************************************/
269 int netapip_netcpCfgGetSaInflowInfo(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
270                                     NETCP_CFG_SA_T    sa_app_id,
271                                     uint32_t *swInfo0,
272                                     uint32_t *swInfo1)
274     int sa_slot = netapi_cfgGetMatchId(sa_app_id);
275     if ((sa_slot <0 ) || (sa_slot >= TUNE_NETAPI_MAX_SA))
276     {
277         return 0;
278     }
279     *swInfo0 = p->tunnel[sa_slot].swInfo0;
280     *swInfo1 = p->tunnel[sa_slot].swInfo1;
281     return 1;
284 /********************************************************************
285  * FUNCTION PURPOSE:  Netapi internal function to insert an SA to the SA list
286  ********************************************************************
287  * DESCRIPTION: Netapi internal function to insert an SA to the SA list 
288  ********************************************************************/
289 void netapip_netcpCfgInsertSa(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
290                               int sa_slot,
291                               int dir,
292                               int mode,
293                               void * temp1,
294                               void * temp2,
295                               void * handle_inflow,
296                               void * handle_sideband,
297                               nwalTxDmPSCmdInfo_t *dmPSCmdInfo,
298                               uint32_t swInfo0,
299                               uint32_t swInfo1,
300                               void* user_data)
302     p->tunnel[sa_slot].in_use=1;
303     p->tunnel[sa_slot].inbound = dir;
304     p->tunnel[sa_slot].sa_mode = mode;
305     p->tunnel[sa_slot].sa_handle_inflow = handle_inflow;
306     p->tunnel[sa_slot].sa_handle_sideband = handle_sideband;
307     p->tunnel[sa_slot].swInfo0 = swInfo0;
308     p->tunnel[sa_slot].swInfo1 = swInfo1;
309     p->tunnel[sa_slot].user_data = user_data;
310     //netapi_Log("netapip_netcpCfgInsertSa: swInfo0 0x%x, swInfo1: 0x%x, user data: %d\n",
311 //        p->tunnel[sa_slot].swInfo0, p->tunnel[sa_slot].swInfo1, (uint32_t)p->tunnel[sa_slot].user_data);
313     if (dmPSCmdInfo)
314     {
315         memcpy(&p->tunnel[sa_slot].dmPSCmdInfo, dmPSCmdInfo, sizeof(nwalTxDmPSCmdInfo_t));
316     }
317     return;
320 /********************************************************************
321  * FUNCTION PURPOSE:  Netapi internal function to return NWAL handles for an SA
322  ********************************************************************
323  * DESCRIPTION: Netapi internal function to return NWAL handles for an SA
324  ********************************************************************/
325  void *netapip_netcpCfgGetSaHandles(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
326                                     int sa_slot,
327                                     void ** p_sideband)
329     if ((sa_slot <0 ) || (sa_slot >= TUNE_NETAPI_MAX_SA))
330         return NULL;
331     if (!p->tunnel[sa_slot].in_use)
332         return NULL;
333     *p_sideband = p->tunnel[sa_slot].sa_handle_sideband;
334     return p->tunnel[sa_slot].sa_handle_inflow;
338 /*==============================FLOWS=============================*/
340 /********************************************************************
341  * FUNCTION PURPOSE:  Netapi internal function to find a free slot for a flow
342  ********************************************************************
343  * DESCRIPTION: Netapi internal function to find a free slot for a flow
344  ********************************************************************/
345 static int netapip_netcpCfgFindFlowSlot(NETAPI_HANDLE_T *p_handle,
346                                         NETAPI_NWAL_GLOBAL_CONTEXT_T *p)
348     int i;
349     //find a free entry
350     p_handle->spinLock.lock(&pnetapiShm->netapi_netcp_cfg_lock);
351     for(i=0;i<TUNE_NETAPI_MAX_FLOWS;i++)
352     {
353         if (!p->flows[i].in_use)
354         {
355             p->flows[i].in_use = 2; /* pending */
356             p_handle->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_lock);
357             return i;
358         }
359     }
360    p_handle->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_lock);
361     return -1;
364 /********************************************************************
365  * FUNCTION PURPOSE:  Netapi internal function to find delete a flow from flow list
366  ********************************************************************
367  * DESCRIPTION: Netapi internal function to find delete a flow from flow list
368  ********************************************************************/
369 static void netapip_netcpCfgDeleteFlow(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
370                                        int slot)
372     if ((slot >=0 ) && (slot < TUNE_NETAPI_MAX_FLOWS))
373     {
374         p->flows[slot].in_use = 0;
375     }
378 /********************************************************************
379  * FUNCTION PURPOSE:  Netapi internal function to  insert a flow to the  flow list
380  ********************************************************************
381  * DESCRIPTION: Netapi internal function to  delete a flow from flow list
382  ********************************************************************/
383 static NETCP_CFG_FLOW_HANDLE_T netapip_netcpCfgInsertFlow(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
384                                                           int slot,
385                                                           int dma_engine,
386                                                           void * handle)
388     p->flows[slot].in_use=1;
389     p->flows[slot].handle = handle;
390     p->flows[slot].flow.flowid  = Cppi_getFlowId(handle);
391     p->flows[slot].flow.dma_engine  = dma_engine;
392         return (NETCP_CFG_FLOW_HANDLE_T) &p->flows[slot].flow;
395 /********************************************************************
396  * FUNCTION PURPOSE:  Netapi internal function to find entry matching the flowid
397  ********************************************************************
398  * DESCRIPTION: Netapi internal function to find entry matching the flowid. Returns
399  * the slot number and the cPPI handle.
400  ********************************************************************/
401 static int netapip_netcpCfgFindFlow(NETAPI_HANDLE_T *p_handle,
402                                     NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
403                                     int flowid,  
404                                     int dma_engine,
405                                     void ** handle) 
407     int i;
408     *handle=NULL;
409     p_handle->spinLock.lock(&pnetapiShm->netapi_netcp_cfg_lock);
410     for(i=0;i<TUNE_NETAPI_MAX_FLOWS;i++)
411     {
412        if ((p->flows[i].in_use)&&
413            (p->flows[i].flow.flowid == flowid)&&
414            (p->flows[i].flow.dma_engine == dma_engine))
415         {
416             *handle = p->flows[i].handle;
417              p_handle->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_lock);
418             return i;
419         }
420     }
421     p_handle->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_lock);
422     return -1;
427 /*============================IP ADDRESSES==========================*/
429 /***************************************************************************
430  * FUNCTION PURPOSE:  Netapi internal function to find a free slot for IP rule in IP slot list
431  ***************************************************************************
432  * DESCRIPTION: NNetapi internal function to find a free slot for IP rule in IP slot list
433  ***************************************************************************/
434 static int netapip_netcpCfgFindIpSlot(NETAPI_HANDLE_T *p_handle,
435                                       NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
436                                       int iface_no)
438     int i;
440     //find a free entry
441     p_handle->spinLock.lock(&pnetapiShm->netapi_netcp_cfg_lock);
442     for(i=0;i<TUNE_NETAPI_MAX_NUM_IP;i++)
443     {
444         if (!p->ips[i].in_use)
445         {
446             p->ips[i].in_use = 2; //pending
447             p_handle->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_lock);
448             return i;
449         }
450     }
451     p_handle->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_lock);
452     return -1;
455 /***************************************************************************
456  * FUNCTION PURPOSE:  Netapi internal function to insert an IP address into interface
457  ***************************************************************************
458  * DESCRIPTION: Netapi internal function to insert an IP address into interface
459  ***************************************************************************/
460 static void netapip_netcpCfgInsertIp(NETAPI_NWAL_GLOBAL_CONTEXT_T *p, 
461                                      nwal_IpType ipType,
462                                      nwalIpAddr_t *ip_addr, 
463                                      nwalIpOpt_t *ip_qualifiers, 
464                                      int iface_no,
465                                      int ip_slot,
466                                      void * handle,
467                                      void * user_data)
469     p->ips[ip_slot].in_use=1;
470     memcpy(&p->ips[ip_slot].ip_addr, ip_addr, sizeof(nwalIpAddr_t));
471     if(ip_qualifiers)
472     {
473         memcpy(&p->ips[ip_slot].ip_qualifiers, ip_qualifiers, sizeof(nwalIpOpt_t));
474     }
475     else
476     {
477         memset(&p->ips[ip_slot].ip_qualifiers, 0, sizeof(nwalIpOpt_t));
478     }
479     p->ips[ip_slot].ip_type = ipType;
480     p->ips[ip_slot].nwal_handle = handle;
481     p->ips[ip_slot].user_data = user_data;
482     p->ips[ip_slot].ref_count++;
483     
486 /***************************************************************************
487  * FUNCTION PURPOSE:  Netapi internal function to free IP slot associated with IP address
488  ***************************************************************************
489  * DESCRIPTION: Netapi internal function to free IP slot associated with IP address
490  ***************************************************************************/
491 static void netapip_netcpCfgDeleteIp(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
492                                      int iface_no,
493                                      int ip_slot)
495     if ((ip_slot >=0) &&(ip_slot <=TUNE_NETAPI_MAX_NUM_IP))
496     {
497         p->ips[ip_slot].in_use=0;
498         p->ips[ip_slot].ref_count = 0;
499     }
502 /***************************************************************************
503  * FUNCTION PURPOSE:  Netapi internal function to get IP handle associated with IP address
504  ***************************************************************************
505  * DESCRIPTION: Netapi internal function to get IP handle associated with IP address
506  ***************************************************************************/
507 static void *netapip_netcpCfgGetIpHandle(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
508                                          int iface_no,
509                                          int ip_slot)
511     if ((ip_slot <0)||(ip_slot>=TUNE_NETAPI_MAX_NUM_IP))
512         return NULL;
513     if (!p->ips[ip_slot].in_use)
514         return NULL;
515     return (void *) p->ips[ip_slot].nwal_handle;
518 /*==========================MAC INTERFACES======================*/
522 /*******************************************************************************
523  * FUNCTION PURPOSE:  Netapi internal function to insert an interface to the interface list
524  *******************************************************************************
525  * DESCRIPTION:  Netapi internal function to insert an interface to the interface list
526  *******************************************************************************/
527 static void netapip_netcpCfgInsertMac(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
528                                       unsigned char * p_mac,
529                                       int iface_no, 
530                                       int state, NETCP_CFG_VLAN_T vlan, 
531                                       void * handle)
533     if ((iface_no >=0 ) && (iface_no < TUNE_NETAPI_MAX_NUM_MAC))
534     {
535         memset(&p->interfaces[iface_no],0,sizeof(NETCP_INTERFACE_T));
536         p->interfaces[iface_no].in_use = 1;
537         memcpy(&p->interfaces[iface_no].mac[0], p_mac,6);
538         p->interfaces[iface_no].state = state;
539         //todo p->interfaces[iface_no].vlan = vlan;
540         p->interfaces[iface_no].nwal_handle = handle; //save handle assoicated with this rule
541         netapi_Log("netapip_netcpCfgInsertMac, global context 0x%x\n", p);
542     }
543     else 
544         netapi_Log(">netapip_netcpCfgInsertMac insert interface # out of range %d\n",iface_no);
548 /*******************************************************************************
549  * FUNCTION PURPOSE:  Netapi internal function to get handle associated with interface
550  *******************************************************************************
551  * DESCRIPTION:  Netapi internal function to get handle associated with interface
552  *******************************************************************************/
553 void* netapip_netcpCfgGetMacHandle(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
554                                    int iface_no)
556     if (iface_no == NETCP_CFG_NO_INTERFACE)
557     {
558         return NULL;
559     }
560     if ((iface_no <0 ) || (iface_no >= TUNE_NETAPI_MAX_NUM_MAC))
561     {
562         return NULL;
563     }
564     else if ( p->interfaces[iface_no].in_use)
565     {
566       return (void *) p->interfaces[iface_no].nwal_handle;
567     }
568     //no valid entry in slot
569     return NULL;
571 /*******************************************************************************
572  * FUNCTION PURPOSE:  Netapi internal function to delete interface from interface list
573  *******************************************************************************
574  * DESCRIPTION:  Netapi internal function to delete interface from interface list
575  *******************************************************************************/
576 static void netapip_netcpCfgDeleteMac(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
577                                       int iface_no)
579     if ((iface_no >=0 ) && (iface_no < TUNE_NETAPI_MAX_NUM_MAC))
580     {
581         p->interfaces[iface_no].in_use = 0;
582     }
585 /*========================CLASSIFIERS==========================*/
587 /*******************************************************************************
588  * FUNCTION PURPOSE:  Netapi internal function to find a free slot for classifier rule
589  *******************************************************************************
590  * DESCRIPTION:  Netapi internal function to find a free slot for classifier rule
591  *******************************************************************************/
592 static int netapip_netcpCfgFindClassSlot(NETAPI_HANDLE_T *p_handle,
593                                          NETAPI_NWAL_GLOBAL_CONTEXT_T *p)
595     int i;
596     p_handle->spinLock.lock(&pnetapiShm->netapi_netcp_cfg_lock);
597     for(i=0;i<TUNE_NETAPI_MAX_CLASSIFIERS;i++)
598     {
599         if (!p->classi[i].in_use)
600         {
601             p->classi[i].in_use = 2; //pending
602             p_handle->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_lock);
603             return i;
604         }
605     }
606     p_handle->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_lock);
607     return -1;
609 /*******************************************************************************
610  * FUNCTION PURPOSE:  Netapi internal function to find a delete a classifer from classifer list
611  *******************************************************************************
612  * DESCRIPTION:  Netapi internal function to find a delete a classifer from classifer list
613  *******************************************************************************/
614 static void netapip_netcpCfgDeleteClass(
615          NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
616          int class_slot )
618     if ((class_slot <0 ) || (class_slot >= TUNE_NETAPI_MAX_CLASSIFIERS))
619     {
620         return;
621     }
622     p->classi[class_slot].in_use=0;
625 /*******************************************************************************
626  * FUNCTION PURPOSE:  Netapi internal function to find a insert a classifer to classifer list
627  *******************************************************************************
628  * DESCRIPTION:  Netapi internal function to find a insert a classifer to classifer list
629  *******************************************************************************/
630 static void netapip_netcpCfgInsertClass(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
631                                         int class_slot,
632                                         int class_type,
633                                         void * L2_handle,
634                                         void * L3_handle,
635                                         void * L4_handle,
636                                         void * user_data)
638     if ((class_slot >=0 ) && (class_slot < TUNE_NETAPI_MAX_CLASSIFIERS))
639     {
640         p->classi[class_slot].in_use=1;
641         p->classi[class_slot].nwal_L2_handle = L2_handle;
642         p->classi[class_slot].nwal_L3_handle = L3_handle;
643         p->classi[class_slot].nwal_L4_handle = L4_handle;
644         p->classi[class_slot].class_type = class_type;
645         p->classi[class_slot].user_data = user_data;
646     }
649 /*******************************************************************************
650  * FUNCTION PURPOSE:  Netapi internal function to get L4 nwal handle for classifier
651  *******************************************************************************
652  * DESCRIPTION:  Netapi internal function to get L4 nwal handle for classifier
653  *******************************************************************************/
654 static void *netapip_netcpCfgGetL4Handle(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
655                                          int class_slot)
657     if ((class_slot <0 ) || (class_slot >= TUNE_NETAPI_MAX_CLASSIFIERS))
658     {
659         return NULL;
660     }
661     if (!p->classi[class_slot].in_use)
662     {
663         return NULL;
664     }
665     return p->classi[class_slot].nwal_L4_handle;
668 /*******************************************************************************
669  * FUNCTION PURPOSE:  Netapi internal function to get L3 nwal handle for classifier
670  *******************************************************************************
671  * DESCRIPTION:  Netapi internal function to get L3 nwal handle for classifier
672  *******************************************************************************/
673 static void *netapip_netcpCfgGetL3Handle(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
674                                          int class_slot)
676     if ((class_slot <0 ) || (class_slot >= TUNE_NETAPI_MAX_CLASSIFIERS))
677     {
678         return NULL;
679     }
680     if (!p->classi[class_slot].in_use)
681     {
682         return NULL;
683     }
684     return p->classi[class_slot].nwal_L3_handle;
688 /***********************************************************************************/
689 /****************************************API****************************************/
690 /***********************************************************************************/
693 /********************************************************************
694  * FUNCTION PURPOSE:  API to request statistics from NETCP
695  ********************************************************************
696  * DESCRIPTION:  API to request statistics from NETCP
697  ********************************************************************/
698 void netapi_netcpCfgReqStats(NETAPI_T  h, 
699                              NETCP_CFG_STATS_CB cb,
700                              int doClear,
701                              int *err) 
703     nwal_RetValue ret;
704     NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
705     NetapiNwalTransInfo_t *pTransInfo;
706     nwal_TransID_t     transId;
707     if ((!n) || (!cb))
708     {
709         *err = NETAPI_ERR_BAD_INPUT;
710         return ;
711     }
712     *err =0;
714     pTransInfo = netapip_getFreeTransInfo(n,
715                                           (NETAPI_PROC_GLOBAL_T *) n->proc_global,
716                                           &transId);
717     if (!pTransInfo) { *err =  NETAPI_ERR_BUSY; return ;}
718     pTransInfo->transType = NETAPI_NWAL_HANDLE_STAT_REQUEST;
719     pTransInfo->netapi_handle = h;
720     n->nwal_local.stats_cb = cb;
721     ret = nwal_getPAStats( ((NETAPI_GLOBAL_T *) n->global)->nwal_context.nwalInstHandle,
722                               transId,
723                               NULL,
724                               doClear);
725     if(ret !=  nwal_OK)
726     {
727         //pTransInfo->inUse = nwal_FALSE;
728         *err = NETAPI_ERR_BUSY;  //no resources??
729         netapi_Log("> netapi_netcpCfg reqStats failed, err=%d\n",ret);
730     }
731     netapip_freeTransInfo(pTransInfo);
733 /********************************************************************
734  * FUNCTION PURPOSE:  API to create a MAC interface
735  ********************************************************************
736  * DESCRIPTION:  API to create a MAC interface
737  ********************************************************************/
738 NETCP_CFG_MACIF_T  netapi_netcpCfgCreateMacInterface(NETAPI_T  h,
739                                                      uint8_t *p_mac,
740                                                      int  iface_no, 
741                                                      int switch_port, 
742                                                      NETCP_CFG_ROUTE_HANDLE_T  route,
743                                                      NETCP_CFG_VLAN_T  vlan,  //future
744                                                      int state,  //0=down, 1=up  //ignored
745                                                      int * err)
747     NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
748     nwalMacParam_t   macInfo=
749     {
750         0,      /* validParams */
751         0,      /* ifNum */
752         0,      /* vlanId      */
753         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },      /* Local mac */
754         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },      /* Remote mac */
755         NWAL_MATCH_ACTION_CONTINUE_NEXT_ROUTE,       /* Continue parsing to next route for match */
756         NWAL_NEXT_ROUTE_FAIL_ACTION_HOST,            /* For next route fail action by default is route to host */
757         CPPI_PARAM_NOT_SPECIFIED,                    /* Use default flow configured to NWAL  if packet is routed to host */
758         QMSS_PARAM_NOT_SPECIFIED,                     /* Use default queue configured to NWAL if packet is routed to host */
759         0
760     };
762     nwal_RetValue       retValue;
763     NetapiNwalTransInfo_t *pTransInfo;
764     nwal_TransID_t     trans_id;
766     if ((!n) || (!p_mac)) {*err = NETAPI_ERR_BAD_INPUT; return -1;}
767     *err =0;
769     pTransInfo = netapip_getFreeTransInfo(n,
770                                           (NETAPI_PROC_GLOBAL_T *) n->proc_global,
771                                           &trans_id);
772     if (!pTransInfo)
773     {
774         *err =  NETAPI_ERR_BUSY;
775         return -1;
776     }
777     pTransInfo->transType = NETAPI_NWAL_HANDLE_TRANS_MAC;
778     pTransInfo->state = NETAPI_NWAL_HANDLE_STATE_OPEN_PENDING;
779     pTransInfo->inUse = nwal_TRUE;
780     pTransInfo->netapi_handle = h;
782     /* set up MacInfo */
783     memcpy(&macInfo.macAddr,p_mac,6); 
784     /* todo: vlan */
785     if (switch_port)
786     {
787         macInfo.validParams |= NWAL_SET_MAC_VALID_PARAM_IFNUM ;
788         macInfo.ifNum = switch_port;  /* */
789     }
791     if (route != NULL)
792     {
793         if((route->valid_params & NETCP_CFG_VALID_PARAM_ROUTE_TYPE) ==
794             NETCP_CFG_VALID_PARAM_ROUTE_TYPE)
795         {
796            macInfo.validParams |= 
797                     NWAL_SET_MAC_VALID_PARAM_ROUTE_TYPE;
798         }
799         netapip_netcpCfgBuildRoute(route,
800                                    &macInfo.appRxPktFlowId,
801                                    &macInfo.appRxPktQueue,
802                                    &macInfo.routeType);
803     }
804     retValue = nwal_setMacIface( ((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,
805                                   trans_id,
806                                   (nwal_AppId) (NETAPI_NETCP_MATCH_GENERIC_MAC | iface_no),
807                                   &macInfo,
808                                   &pTransInfo->handle);
809     if(retValue !=  nwal_OK)
810     {
811         *err = NETAPI_ERR_NWAL_ERR0;
812         netapi_Log ("netapi_netcpCfg - ERROR: nwal_setMacIface returned Error Code %d\n",
813                     retValue);
814         netapip_freeTransInfo(pTransInfo);
815         return -1;
816     }
818     //wait here until its done since scheduler isn't running yet most likely..
819     // todo:  make this handled by scheduler poll later ??
820     if(trans_id != NWAL_TRANSID_SPIN_WAIT)
821     {
822         n->nwal_local.numPendingCfg++;
823         while ((pTransInfo->state  !=NETAPI_NWAL_HANDLE_STATE_ERR) &&
824                 (pTransInfo->state !=NETAPI_NWAL_HANDLE_STATE_OPEN))
825         {
826             // if response is there, then this poll squirts out in the CTl poll callback, 
827             // which handles the rest (including decrmenting #pending!!
828             nwal_pollCtl(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,NULL,NULL);
829         }
830         if (pTransInfo->state == NETAPI_NWAL_HANDLE_STATE_ERR)
831         {
832             netapip_freeTransInfo(pTransInfo);
833             *err = NETAPI_ERR_PA_FW;
834             netapi_Log (">netapi_netcpCfgCreateMacInterface - ERROR returned by NETCP PA firmware %d\n",
835                     *err);
836             return -1;
837         }
839     }
840     netapi_Log ("netapi_netcpCfg: MAC i/f %d added\n", iface_no);
841     netapip_netcpCfgInsertMac(&netapi_get_global()->nwal_context, 
842                           p_mac, iface_no, state,vlan,
843                           (void *) pTransInfo->handle);
844     netapip_freeTransInfo(pTransInfo);
845     return  (NETAPI_NETCP_MATCH_GENERIC_MAC | iface_no);
848 /********************************************************************
849  * FUNCTION PURPOSE:  API to delete MAC  interface
850  ********************************************************************
851  * DESCRIPTION:  API to delete MAC  interface
852  ********************************************************************/
853 void netapi_netcpCfgDelMac(NETAPI_T h,
854                            int iface_no,
855                            int *err)
857     nwal_RetValue ret;
858     NetapiNwalTransInfo_t *pTransInfo;
859     nwal_TransID_t     trans_id;
860     NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
861     void * ifHandle;
863     //get the nwal handle assoicated with this iface
864     ifHandle = netapip_netcpCfgGetMacHandle(&netapi_get_global()->nwal_context, iface_no );
865     if(!ifHandle) 
866     {
867         *err = NETAPI_ERR_BAD_INPUT; return ;
868     }
869     *err =0;
871     //get a transaction id
872     pTransInfo = netapip_getFreeTransInfo(n,
873                                           (NETAPI_PROC_GLOBAL_T *) n->proc_global,
874                                           &trans_id);
875     if (!pTransInfo)
876     {
877         *err =  NETAPI_ERR_BUSY;
878         return ;
879     }
880     pTransInfo->transType = NETAPI_NWAL_HANDLE_TRANS_MAC;
881     pTransInfo->state = NETAPI_NWAL_HANDLE_STATE_CLOSE_PENDING;
882     pTransInfo->inUse = nwal_TRUE;
883     pTransInfo->netapi_handle = h;
885     //issue request
886     ret = nwal_delMacIface(
887                 ((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,
888                 trans_id,
889                 ifHandle);
890     if(ret !=  nwal_OK)
891     {
892         *err = NETAPI_ERR_NWAL_ERR0;
893         netapi_Log ("netapi_netcpCfg - ERROR: nwal_delMacIface returned Error Code %d\n",
894                     ret);
895         netapip_freeTransInfo(pTransInfo);
896         return;
897     }
898     //wait here until its done since scheduler isn't running yet most likely..
899     // todo:  make this handled by scheduler poll later ??
900     if(trans_id != NWAL_TRANSID_SPIN_WAIT)
901     {
902         n->nwal_local.numPendingCfg++;
903         while ((pTransInfo->state  !=NETAPI_NWAL_HANDLE_STATE_ERR) &&
904                 (pTransInfo->state !=NETAPI_NWAL_HANDLE_STATE_IDLE))
905         {
906             // if response is there, then this poll squirts out in the CTl poll callback, 
907             // which handles the rest (including decrmenting #pending!!
908             nwal_pollCtl(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,NULL,NULL);
909         }
910         if (pTransInfo->state == NETAPI_NWAL_HANDLE_STATE_ERR)
911         {
912             netapip_freeTransInfo(pTransInfo);
913             *err = NETAPI_ERR_PA_FW;
914             netapi_Log (">netapi_netcpCfgCreateMacInterface - ERROR returned by NETCP PA firmware %d\n",
915                     *err);
916             netapip_netcpCfgDeleteMac(&netapi_get_global()->nwal_context,  iface_no);
917             return;
918         }
919     }
920     netapi_Log ("netapi_netcpCfg: MAC i/f %d deleted\n",iface_no);
921     netapip_freeTransInfo(pTransInfo);
922     //zap the entry
923     netapip_netcpCfgDeleteMac(&netapi_get_global()->nwal_context,  iface_no);
924     return ;
928 /********************************************************************
929  * FUNCTION PURPOSE:  NETAPi internal function to Add IP to MAC interface
930  ********************************************************************
931  * DESCRIPTION:  NETAPi internal function to Add IP to MAC interface
932  ********************************************************************/
933 static NETCP_CFG_IP_T  netapip_netcpCfgAddIpInternal(NETAPI_T  h,
934                                                      int  iface_no,
935                                                      nwal_IpType ipType,
936                                                      nwalIpAddr_t  * ip_addr,
937                                                      nwalIpAddr_t  *ip_rem_addr,
938                                                      nwalIpOpt_t * ip_qualifiers,
939                                                      NETCP_CFG_ROUTE_HANDLE_T  route,/*NULL for default*/
940                                                      void * user_data,
941                                                      int * err,
942                                                      int  flag) /*TRUE: add IP to iface,
943                                                      FALSE: add IP as part of classifier */
945     static unsigned char zeroIP4[]={0,0,0,0};
946     static unsigned char zeroIP6[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
947     NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
948     void * n_handle=NULL;
949     nwalIpParam_t    nwalIpParam= {
950     0,
951     pa_IPV4,      /* IP Type */
952     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },  /* Dest IP */
953     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },  /* Source IP */
954     { 0x0,0,0,0},/* IP Options */
955     NWAL_MATCH_ACTION_CONTINUE_NEXT_ROUTE,       /* Continue parsing to next route for match */
956     NWAL_NEXT_ROUTE_FAIL_ACTION_HOST,            /* For next route fail action by default is route to host */
957     CPPI_PARAM_NOT_SPECIFIED,                    /* Use default flow configured to NWAL  if packet is routed to host */
958     QMSS_PARAM_NOT_SPECIFIED,                     /* Use default queue configured to NWAL if packet is routed to host */
959     0
960 };
961     nwal_RetValue       retValue;
962     NetapiNwalTransInfo_t *pTransInfo;
963     nwal_TransID_t     trans_id;
964     int ip_slot=-1;
965     NETCP_CFG_IP_T ip_rule_id;
966     NETCP_CFG_IP_T temp;
968     //verify that iface has been configured 
969     if (iface_no != NETCP_CFG_NO_INTERFACE)
970     {
971         if ((iface_no<0) || (iface_no>= TUNE_NETAPI_MAX_NUM_MAC)) {*err = NETAPI_ERR_BAD_INPUT; return -1;}
972     }
974     if (iface_no != NETCP_CFG_NO_INTERFACE)
975     {
976         netapi_Log("netapip_netcpCfgAddIpInternal, in_use %d\n", netapi_get_global()->nwal_context.interfaces[iface_no].in_use);
977         netapi_Log("netapip_netcpCfgAddIpInternal, p 0x%x\n", &netapi_get_global()->nwal_context);
978         if(netapi_get_global()->nwal_context.interfaces[iface_no].in_use)
979         {
980             n_handle =  netapi_get_global()->nwal_context.interfaces[iface_no].nwal_handle;
981         }
982         else
983         {
984             *err = NETAPI_ERR_BAD_INPUT;
985             return -1;
986         }
987     }
988     if (flag) //if adding IP to MAC then reserve a slot to save info
989     {
990         //find free slot for IP & reserve
991          ip_slot= netapip_netcpCfgFindIpSlot(n,
992                                              &netapi_get_global()->nwal_context, 
993                                              iface_no);
994         if (ip_slot <0) 
995         {
996             *err= NETAPI_ERR_NOMEM;  //no room 
997             return -1;
998         }
999     }
1001     //get a transaction object for config action
1002     pTransInfo = netapip_getFreeTransInfo(n, 
1003                                           (NETAPI_PROC_GLOBAL_T *) n->proc_global,
1004                                           &trans_id);
1005     if (!pTransInfo)
1006     {
1007         *err =  NETAPI_ERR_BUSY;
1008         if (flag)
1009         {
1010             netapip_netcpCfgDeleteIp(&netapi_get_global()->nwal_context,
1011                          iface_no,
1012                          ip_slot);
1013         }
1014         return -1;
1015     }
1016     pTransInfo->transType = NETAPI_NWAL_HANDLE_TRANS_IP;
1017     pTransInfo->state = NETAPI_NWAL_HANDLE_STATE_OPEN_PENDING;
1018     pTransInfo->inUse = nwal_TRUE;
1019     pTransInfo->netapi_handle = h;
1021     //build nwalIpParam
1022     memcpy(&nwalIpParam.locIpAddr,ip_addr, sizeof(nwalIpAddr_t));
1023     if (ip_rem_addr)
1024     {
1025         if (ipType == nwal_IPV4)
1026         {
1027             if(memcmp(ip_rem_addr, zeroIP4, sizeof(nwalIpv4Addr_t)))
1028             {
1029                 nwalIpParam.validParams |= NWAL_SET_IP_VALID_PARAM_REMOTE_IP;
1030                 memcpy(&nwalIpParam.remIpAddr,ip_rem_addr, sizeof(nwalIpAddr_t));
1031             }
1032         }
1033         else
1034         {
1035             if(memcmp(ip_rem_addr, zeroIP6, sizeof(nwalIpv6Addr_t)))
1036             {
1037                 nwalIpParam.validParams |= NWAL_SET_IP_VALID_PARAM_REMOTE_IP;
1038                 memcpy(&nwalIpParam.remIpAddr,ip_rem_addr, sizeof(nwalIpAddr_t));
1039             }
1040         }
1041     }
1042     nwalIpParam.ipType=ipType;
1043     if(route)
1044     {
1045         if((route->valid_params & NETCP_CFG_VALID_PARAM_ROUTE_TYPE) ==
1046             NETCP_CFG_VALID_PARAM_ROUTE_TYPE)
1047         {
1048            nwalIpParam.validParams |= 
1049                     NWAL_SET_IP_VALID_PARAM_ROUTE_TYPE;
1050         }
1051         netapip_netcpCfgBuildRoute(route,
1052                                    &nwalIpParam.appRxPktFlowId,
1053                                    &nwalIpParam.appRxPktQueue,
1054                                    &nwalIpParam.routeType);
1055     }
1056     else{} //use nwal defaults
1058     if (ip_qualifiers)
1059         memcpy(&nwalIpParam.ipOpt,ip_qualifiers, sizeof(nwalIpOpt_t)); 
1060     else
1061         memset(&nwalIpParam.ipOpt,0, sizeof(nwalIpOpt_t));
1063     //build the rule id that will be returned when a packet matches 
1064     if (flag)
1065         ip_rule_id = NETAPI_NETCP_MATCH_GENERIC_IP | iface_no | ((ip_slot&& NETAPI_NETCP_MATCH_ID_MASK) << NETAPI_NETCP_MATCH_ID_SHIFT);
1066     else
1067         ip_rule_id = (NETAPI_NETCP_MATCH_CLASS_L3 | iface_no);
1069     retValue = nwal_setIPAddr(   netapi_get_global()->nwal_context.nwalInstHandle,
1070                                   trans_id,
1071                                   (nwal_AppId) (ip_rule_id),
1072                                   n_handle,
1073                                   &nwalIpParam,
1074                                   &pTransInfo->handle);
1076     if(retValue !=  nwal_OK)
1077     {
1078         *err = NETAPI_ERR_NWAL_ERR0;
1079         netapi_Log ("netcp_cfg: nwal_setIP returned Error Code %d\n",
1080                     retValue);
1081         netapip_freeTransInfo(pTransInfo);
1082         //zap the entry
1083         if (flag)
1084         {
1085             netapip_netcpCfgDeleteIp(&netapi_get_global()->nwal_context,
1086                          iface_no,
1087                          ip_slot);
1088         }
1089         return -1;
1090     }
1091     //wait here until its done since scheduler isn't running yet most likely..
1092     // todo:  make this handled by scheduler poll later ??
1093     if(trans_id != NWAL_TRANSID_SPIN_WAIT)
1094     {
1095         n->nwal_local.numPendingCfg++;
1096         while ((pTransInfo->state  !=NETAPI_NWAL_HANDLE_STATE_ERR) &&
1097         (pTransInfo->state !=NETAPI_NWAL_HANDLE_STATE_OPEN))
1098         {
1099             // if response is there, then this poll squirts out in the CTl poll callback, 
1100             // which handles the rest (including decrmenting #pending!!
1101             nwal_pollCtl(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,NULL,NULL);
1102         }
1103         if (pTransInfo->state == NETAPI_NWAL_HANDLE_STATE_ERR)
1104         {
1105             netapip_freeTransInfo(pTransInfo);
1106             *err = NETAPI_ERR_PA_FW;
1107             netapi_Log ("netapip_netcpCfgAddIpInternal - ERROR returned by NETCP PA firmware %d\n", *err);
1108             return -1;
1109         }
1110     }
1111     if (flag)
1112     {
1113         netapi_Log ("netcp_cfg: IP added to interface %d (slot%d)\n", iface_no, ip_slot);
1114         netapip_netcpCfgInsertIp(&netapi_get_global()->nwal_context,
1115                                  ipType, 
1116                                  ip_addr,
1117                                  ip_qualifiers,
1118                                  iface_no,
1119                                  ip_slot,
1120                                  pTransInfo->handle,
1121                                  user_data);
1122     }
1124     temp = (NETCP_CFG_IP_T) pTransInfo->handle;
1125     netapip_freeTransInfo(pTransInfo);
1126     return  (flag ? ip_rule_id:  temp);
1129 /********************************************************************
1130  * FUNCTION PURPOSE:  API to Add IP to MAC interface
1131  ********************************************************************
1132  * DESCRIPTION:  API to Add IP to MAC interface
1133  ********************************************************************/
1134 NETCP_CFG_IP_T  netapi_netcpCfgAddIp(NETAPI_T                  h,
1135                                      int                       iface_no,
1136                                      nwal_IpType               ipType,
1137                                      nwalIpAddr_t*             ip_addr,
1138                                      nwalIpAddr_t*             ip_rem_addr,
1139                                      nwalIpOpt_t*              ip_qualifiers,
1140                                      NETCP_CFG_ROUTE_HANDLE_T  route,  //NULL for default
1141                                      void*                     user_data,
1142                                      int*                      err)
1144     return netapip_netcpCfgAddIpInternal(h,
1145                                          iface_no,
1146                                          ipType,
1147                                          ip_addr,
1148                                          ip_rem_addr,
1149                                          ip_qualifiers, 
1150                                          route, 
1151                                          user_data,
1152                                          err,
1153                                          1);
1155 /***************************************************************************
1156 * DESCRIPTION:Netapi internal function to check reference count of IP
1157 ***************************************************************************/
1158 static Bool netapip_netcpCfgCheckIpRefCount(NETAPI_HANDLE_T *p_handle,
1159                                             NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
1160                                             int ip_slot)
1163     if ((ip_slot >=0) &&(ip_slot <=TUNE_NETAPI_MAX_NUM_IP))
1164     {
1165              p_handle->spinLock.lock(&pnetapiShm->netapi_netcp_cfg_lock);
1166             /* IS IP is associated with alteast 2 rules, if yes, then dont delete IP */
1167             if(p->ips[ip_slot].ref_count)
1168                 p->ips[ip_slot].ref_count--;
1169             if (p->ips[ip_slot].ref_count)
1170             {
1171                  p_handle->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_lock);
1172                 return FALSE;
1173             }
1174             else
1175             {
1176                 p_handle->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_lock);
1177                 return TRUE;
1178             }
1179     }
1180     else
1181         return FALSE;
1184 /********************************************************************
1185  * FUNCTION PURPOSE:  NETAPI internal function to detach IP from MAC interface
1186  ********************************************************************
1187  * DESCRIPTION:  NETAPI internal function to detach IP from MAC interface
1188  ********************************************************************/
1189 static void netapip_netcpCfgDelIpInternal(NETAPI_T h, 
1190                                           int iface_no,
1191                                           nwal_IpType ipType,
1192                                           nwalIpAddr_t  * ip_addr,
1193                                           nwalIpOpt_t * ip_qualifiers, 
1194                                           NETCP_CFG_IP_T  ip_rule_id,
1195                                           int *err, 
1196                                           void * handle,   /* if flag==0, handle must be valid */
1197                                           int flag)        /* flag==0 => delete IP rule that was part of classifier, not interface */
1199     nwal_RetValue ret;
1200     NetapiNwalTransInfo_t *pTransInfo;
1201     nwal_TransID_t     trans_id;
1202     NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
1203     void * ifHandle;
1204     int ip_slot = netapi_cfgGetMatchId(ip_rule_id);
1205     //get the nwal handle assoicated with this ip   
1206     if (flag)
1207     {
1208         ifHandle = netapip_netcpCfgGetIpHandle(
1209                                         &netapi_get_global()->nwal_context, iface_no,
1210                                         ip_slot );
1211     }
1212     else 
1213     {
1214         ifHandle = handle;
1215     }
1216     if(!ifHandle)
1217     {
1218         *err = NETAPI_ERR_BAD_INPUT;
1219         return ;
1220     }
1221     *err =0;
1223     /* need to check to see if this IP is attached to a classifier(s)
1224        and only delete if this is last classifier */
1225     if (!netapip_netcpCfgCheckIpRefCount(n,
1226                                          &netapi_get_global()->nwal_context,
1227                                          ip_slot))
1228     {
1229         return;
1230     }
1232     //get a transaction id
1233     pTransInfo = netapip_getFreeTransInfo(n,
1234                                           (NETAPI_PROC_GLOBAL_T *) n->proc_global,
1235                                           &trans_id);
1236     if (!pTransInfo)
1237     {
1238         *err =  NETAPI_ERR_BUSY;
1239         return;
1240     }
1241     pTransInfo->transType = NETAPI_NWAL_HANDLE_TRANS_IP;
1242     pTransInfo->state = NETAPI_NWAL_HANDLE_STATE_CLOSE_PENDING;
1243     pTransInfo->inUse = nwal_TRUE;
1244     pTransInfo->netapi_handle = h;
1245     //issue request
1246     ret = nwal_delIPAddr(
1247                 ((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,
1248                 trans_id,
1249                 ifHandle);
1250     if(ret !=  nwal_OK)
1251     {
1252         *err = NETAPI_ERR_NWAL_ERR0;
1253         netapi_Log ("netcp_cfg - ERROR: nwal_delMacIface returned Error Code %d\n",
1254                     ret);
1255         netapip_freeTransInfo(pTransInfo);
1256         return ;
1257     }
1258     //wait here until its done since scheduler isn't running yet most likely..
1259     // todo:  make this handled by scheduler poll later ??
1260     if(trans_id != NWAL_TRANSID_SPIN_WAIT)
1261     {
1262         n->nwal_local.numPendingCfg++;
1263         while ((pTransInfo->state  !=NETAPI_NWAL_HANDLE_STATE_ERR) &&
1264                 (pTransInfo->state !=NETAPI_NWAL_HANDLE_STATE_IDLE))
1265         {
1266             // if response is there, then this poll squirts out in the CTl poll callback, 
1267             // which handles the rest (including decrmenting #pending!!
1268             nwal_pollCtl(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,NULL,NULL);
1269         }
1270         if (pTransInfo->state == NETAPI_NWAL_HANDLE_STATE_ERR)
1271         {
1272             netapip_freeTransInfo(pTransInfo);
1273             *err = NETAPI_ERR_PA_FW;
1274             netapi_Log (">netapip_netcpCfgDelIpInternal - ERROR returned by NETCP PA firmware %d\n", *err);
1275             return;
1276         }
1277     }
1279     netapip_freeTransInfo(pTransInfo);
1281     //zap the entry
1282     if (flag)
1283         netapip_netcpCfgDeleteIp(&netapi_get_global()->nwal_context,  
1284                          iface_no,
1285                          ip_slot);
1286     return ;
1289 /********************************************************************
1290  * FUNCTION PURPOSE:  API to detach IP from MAC interface
1291  ********************************************************************
1292  * DESCRIPTION:  API  to detach IP from MAC interface
1293  ********************************************************************/
1294 void netapi_netcpCfgDelIp(NETAPI_T              h,
1295                           int                   iface_no,
1296                           nwal_IpType           ipType,
1297                           nwalIpAddr_t*         ip_addr,
1298                           nwalIpOpt_t*          ip_qualifiers,
1299                           NETCP_CFG_IP_T        ip_rule_id,
1300                           int*                  err)
1302     netapip_netcpCfgDelIpInternal( h, iface_no, ipType,
1303                   ip_addr, ip_qualifiers, ip_rule_id,
1304                   err, NULL, 1);
1305     return;
1309 /********************************************************************
1310  * FUNCTION PURPOSE:  API to attach a classifier rule to NETCP
1311  ********************************************************************
1312  * DESCRIPTION:  API to attach a classifier rule to NETCP
1313  ********************************************************************/
1314 NETCP_CFG_CLASS_T netapi_netcpCfgAddClass(NETAPI_T                  h,
1315                                           NETCP_CFG_CLASSIFIER_T*   p_class,
1316                                           NETCP_CFG_ROUTE_HANDLE_T  route,
1317                                           int                       action, 
1318                                           void*                     user_data, 
1319                                           int*                      err)
1321     NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
1322     void * l3_handle=NULL;  //ip handle
1323     nwal_RetValue       retValue;
1324     NetapiNwalTransInfo_t *pTransInfo;
1325     nwal_TransID_t     trans_id;
1326     int class_slot=-1;
1327     int iface_no;
1328     int ip_slot=-1;
1329     NETCP_CFG_CLASS_T  classHandle;  //returned by us
1330     nwal_appProtoType_t proto;
1331     nwalRxConnCfg_t tempCfg=
1332     {
1333         0,  //nwal_handle: to be filled in
1334         0, // l4 ports: to be filled in
1335         0,  //core id (NA)
1336         0, //action
1337         CPPI_PARAM_NOT_SPECIFIED, //flow id
1338         QMSS_PARAM_NOT_SPECIFIED, //dest queue
1339         0,
1340         0, // l4 ports: to be filled in
1341     };
1343     *err = NETAPI_ERR_OK;
1345     if(!p_class)
1346     {
1347         *err=NETAPI_ERR_BAD_INPUT;
1348         return -1;
1349     }
1350     switch(p_class->classType)
1351     {
1352         default:
1353             netapi_Log(">netapi_netcpCfg : classifier type %d not supported\n",p_class->classType);
1354             break;
1355         case(NETCP_CFG_CLASS_TYPE_L3_L4):
1356         case(NETCP_CFG_CLASS_TYPE_L4):
1357             //assume just type l4 only (L2, L3 defined by iface, l3 id )
1358             iface_no = p_class->u.c_l4.iface;
1359             if (p_class->classType== NETCP_CFG_CLASS_TYPE_L4)
1360             {
1361                 ip_slot = netapi_cfgGetMatchId(p_class->u.c_l4.ip);
1362             }
1364             //verify that iface has been configured 
1365             if (iface_no != NETCP_CFG_NO_INTERFACE)
1366             {
1367                 if(!netapi_get_global()->nwal_context.interfaces[iface_no].in_use)
1368                 {
1369                     *err = NETAPI_ERR_BAD_INPUT;
1370                     return -1;
1371                 }
1372             }
1374             if (p_class->classType== NETCP_CFG_CLASS_TYPE_L4)
1375             {
1376                 //verify that ip has been configured and get its handle
1377                 l3_handle = netapip_netcpCfgGetIpHandle(
1378                       &netapi_get_global()->nwal_context, iface_no,
1379                       ip_slot );
1380             }
1381             else
1382             {
1383                 nwalIpParam_t tempParam=
1384                 {
1385                     0,
1386                     pa_IPV4,      /* IP Type */
1387                     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },  /* Dest IP */
1388                     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },  /* Source IP */
1389                     { 0x0,0,0,0},/* IP Options */
1390                     NWAL_MATCH_ACTION_CONTINUE_NEXT_ROUTE,       /* Continue parsing to next route for match */
1391                     NWAL_NEXT_ROUTE_FAIL_ACTION_HOST,            /* For next route fail action by default is route to host */
1392                     CPPI_PARAM_NOT_SPECIFIED,                    /* Use default flow configured to NWAL  if packet is routed to host */
1393                     QMSS_PARAM_NOT_SPECIFIED,                    /* Use default queue configured to NWAL if packet is routed to host */
1394                     0
1395                 };
1396                 //build nwalIpParam
1397                 memcpy(&tempParam.locIpAddr,p_class->u.c_l3_l4.ip_addr, sizeof(nwalIpAddr_t));
1398                 tempParam.ipType=p_class->u.c_l3_l4.ipType;
1399                 //use nwal defauls for route
1400                 if (p_class->u.c_l3_l4.ip_qualifiers)
1401                     memcpy(&tempParam.ipOpt,p_class->u.c_l3_l4.ip_qualifiers, sizeof(nwalIpOpt_t));
1402                 else
1403                     memset(&tempParam.ipOpt,0, sizeof(nwalIpOpt_t));
1405                 //find if we have a matching L3 handle for IP classifier; if not create it
1406                 retValue =  nwal_getIPAddr (((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,
1407                             &tempParam,
1408                             netapip_netcpCfgGetMacHandle(&netapi_get_global()->nwal_context, iface_no ),
1409                             &l3_handle); 
1410                 if (retValue != nwal_TRUE) 
1411                 {
1412                     int ret;
1413                     //**NEW IP RULE  
1414                     //need to attach this IP RULE to the MAC
1415                     l3_handle= (void *) netapip_netcpCfgAddIpInternal(
1416                                       h, iface_no, 
1417                                       p_class->u.c_l3_l4.ipType,
1418                                       p_class->u.c_l3_l4.ip_addr,
1419                                       NULL,
1420                                       p_class->u.c_l3_l4.ip_qualifiers,
1421                                       p_class->u.c_l3_l4.p_fail_route,
1422                                       user_data,
1423                                       &ret,
1424                                       FALSE);
1425                     if(!ret)
1426                     {
1427                         l3_handle=NULL;
1428                     }
1429                 }
1430             }
1431             if(!l3_handle)
1432             {
1433                 *err = NETAPI_ERR_BAD_INPUT; 
1434                 return -1 ;
1435             }
1438             //find free slot for CLASS & reserve
1439             class_slot= netapip_netcpCfgFindClassSlot(n,
1440                                                       &netapi_get_global()->nwal_context);
1441             if(class_slot<0) {*err = NETAPI_ERR_NOMEM; return -1;}
1442             classHandle = NETAPI_NETCP_MATCH_CLASS |
1443                           (class_slot << NETAPI_NETCP_MATCH_ID_SHIFT) | 
1444                           (iface_no & NETAPI_NETCP_MATCH_LOGICAL_MAC_IFACE_MASK);
1445             //build request from template
1446             tempCfg.inHandle=l3_handle;
1447             if (p_class->classType== NETCP_CFG_CLASS_TYPE_L4)
1448             {
1449                 memcpy(&tempCfg.appProto,&p_class->u.c_l4.appProto,sizeof(nwalAppProto_t));
1450                 proto = p_class->u.c_l4.proto;
1451             }
1452             else
1453             {
1454                 memcpy(&tempCfg.appProto,&p_class->u.c_l3_l4.appProto,sizeof(nwalAppProto_t));
1455                 proto = p_class->u.c_l3_l4.proto;
1456             }
1458             tempCfg.matchAction = (action==NETCP_CFG_ACTION_TO_SW)  ? NWAL_MATCH_ACTION_HOST : NWAL_MATCH_ACTION_DISCARD;
1459             if (route)
1460             {
1461                 if((route->valid_params & NETCP_CFG_VALID_PARAM_ROUTE_TYPE) ==
1462                     NETCP_CFG_VALID_PARAM_ROUTE_TYPE)
1463                 {
1464                     tempCfg.validParams |= 
1465                         NWAL_SET_CONN_VALID_PARAM_ROUTE_TYPE;
1466                 }
1467                 netapip_netcpCfgBuildRoute(route,
1468                                            &tempCfg.appRxPktFlowId,
1469                                            &tempCfg.appRxPktQueue,
1470                                            &tempCfg.routeType);
1471             }
1474             //get a transaction id
1475             pTransInfo = netapip_getFreeTransInfo(n,
1476                                                   (NETAPI_PROC_GLOBAL_T *) n->proc_global,
1477                                                   &trans_id);
1478             if (!pTransInfo)
1479             {
1480                 *err =  NETAPI_ERR_BUSY; 
1481                 return -1;
1482             }
1483             pTransInfo->transType = NETAPI_NWAL_HANDLE_TRANS_PORT;
1484             pTransInfo->state = NETAPI_NWAL_HANDLE_STATE_OPEN_PENDING;
1485             pTransInfo->inUse = nwal_TRUE;
1486             pTransInfo->netapi_handle = h;
1487                 //issue request
1488             retValue = nwal_addConn(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,
1489                             trans_id,
1490                             (nwal_AppId) classHandle,
1491                             proto,
1492                             &tempCfg,
1493                             NULL,
1494                             &pTransInfo->handle);
1495             if(retValue !=  nwal_OK)
1496             {
1497                 *err = NETAPI_ERR_NWAL_ERR0;
1498                 netapi_Log ("netcp_cfg - ERROR: nwal_delMacIface returned Error Code %d\n",
1499                         retValue);
1500                 netapip_freeTransInfo(pTransInfo);
1501                 netapip_netcpCfgDeleteClass(&netapi_get_global()->nwal_context, class_slot);
1502                 return -1;
1503             }
1504             //wait here until its done since scheduler isn't running yet most likely..
1505            // todo:  make this handled by scheduler poll later ??
1506             if(trans_id != NWAL_TRANSID_SPIN_WAIT)
1507             {
1508                 n->nwal_local.numPendingCfg++;
1509                 while ((pTransInfo->state  !=NETAPI_NWAL_HANDLE_STATE_ERR) &&
1510                     (pTransInfo->state !=NETAPI_NWAL_HANDLE_STATE_OPEN))
1511                 {
1512                     // if response is there, then this poll squirts out in the CTl poll callback, 
1513                     // which handles the rest (including decrmenting #pending!!
1514                     nwal_pollCtl(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,NULL,NULL);
1515                 }
1516                 if (pTransInfo->state == NETAPI_NWAL_HANDLE_STATE_ERR)
1517                 {
1518                     netapip_freeTransInfo(pTransInfo);
1519                     *err = NETAPI_ERR_PA_FW;
1520                     netapip_netcpCfgDeleteClass(&netapi_get_global()->nwal_context, class_slot);
1521                     netapi_Log (">netcp_cfgAddClass - ERROR returned by NETCP PA firmware %d\n", *err);
1522                     return -1;
1523                 }
1524             }
1525             netapi_Log ("netcp_cfg: L4 Classifer added to interface %d ip %d (slot%d)\n", iface_no, ip_slot, class_slot);
1526             netapip_netcpCfgInsertClass(&netapi_get_global()->nwal_context, 
1527                                    class_slot,
1528                                  p_class->classType, 
1529                                 NULL,  //L2 we have
1530                                 (p_class->classType== NETCP_CFG_CLASS_TYPE_L3_L4? l3_handle : NULL),
1531                                   pTransInfo->handle,
1532                                   user_data);
1534             netapip_freeTransInfo(pTransInfo);
1535             return classHandle;
1536     } //end switch
1538 return -1;
1541 /********************************************************************
1542  * FUNCTION PURPOSE:  API to delete a preconfigured classifier
1543  ********************************************************************
1544  * DESCRIPTION:  API to delete a preconfigured classifier
1545  ********************************************************************/
1546 void netapi_netcpCfgDelClass(NETAPI_T           h,
1547                              NETCP_CFG_CLASS_T  classId,
1548                              int*               err)
1550     NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
1551     void * L4_handle;  //class handle -> L4
1552     void * L3_handle;  //class handle -> L3
1553     nwal_RetValue       retValue;
1554     NetapiNwalTransInfo_t *pTransInfo;
1555     nwal_TransID_t     trans_id;
1556     int class_slot=-1;
1558     class_slot = netapi_cfgGetMatchId(classId);
1559     L4_handle=netapip_netcpCfgGetL4Handle(&netapi_get_global()->nwal_context, class_slot);
1560     if(!L4_handle)
1561     {
1562         *err = NETAPI_ERR_BAD_INPUT; 
1563         goto ERR_netapi_netcpCfgDelClass;
1564     }
1565     L3_handle = netapip_netcpCfgGetL3Handle( &netapi_get_global()->nwal_context, class_slot );
1566     /* l3 handle might be NULL,, depending on type of classifier */
1568     netapip_netcpCfgDeleteClass(
1569                         &netapi_get_global()->nwal_context,
1570                         class_slot );
1571     //get a transaction id
1572     pTransInfo = netapip_getFreeTransInfo(n,
1573                                           (NETAPI_PROC_GLOBAL_T *) n->proc_global,
1574                                           &trans_id);
1575     if (!pTransInfo)
1576     {
1577         *err =  NETAPI_ERR_BUSY; 
1578         goto ERR_netapi_netcpCfgDelClass;
1579     }
1580     pTransInfo->transType = NETAPI_NWAL_HANDLE_TRANS_PORT;
1581     pTransInfo->state = NETAPI_NWAL_HANDLE_STATE_CLOSE_PENDING;
1582     pTransInfo->inUse = nwal_TRUE;
1583     pTransInfo->netapi_handle = h;
1584     //issue request for L4
1585     retValue = nwal_delConn(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,
1586                                                   trans_id,
1587                                                 L4_handle);
1588     if(retValue !=  nwal_OK)
1589     {
1590         *err = NETAPI_ERR_NWAL_ERR0;
1591          netapi_Log ("netcp_cfg - ERROR: nwal_delMacIface returned Error Code %d\n", retValue);
1592          netapip_freeTransInfo(pTransInfo);
1593          goto ERR_netapi_netcpCfgDelClass;  /* todo: what about the L3? */
1594     }
1595     //wait here until its done since scheduler isn't running yet most likely..
1596     // todo:  make this handled by scheduler poll later ??
1597     if(trans_id != NWAL_TRANSID_SPIN_WAIT)
1598     {
1599         n->nwal_local.numPendingCfg++;
1600         while ((pTransInfo->state  !=NETAPI_NWAL_HANDLE_STATE_ERR) &&
1601                 (pTransInfo->state !=NETAPI_NWAL_HANDLE_STATE_IDLE))
1602         {
1603             // if response is there, then this poll squirts out in the CTl poll callback, 
1604             // which handles the rest (including decrmenting #pending!!
1605             nwal_pollCtl(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,NULL,NULL);
1606         }
1607     }
1608     if (pTransInfo->state == NETAPI_NWAL_HANDLE_STATE_ERR)
1609     {
1610         netapip_freeTransInfo(pTransInfo);
1611         *err = NETAPI_ERR_PA_FW;
1612          netapi_Log (">netapi_netcpCfgDelClass - ERROR returned by NETCP PA firmware %d\n", *err);
1613          goto ERR_netapi_netcpCfgDelClass;
1614     }
1615     netapi_Log ("netcp_cfg: Classifer deleted\n");
1616     pTransInfo->state =  NETAPI_NWAL_HANDLE_STATE_IDLE;
1617     pTransInfo->inUse = nwal_FALSE;
1619     /* delete L3 if we have to */
1620     if (L3_handle)
1621     {
1622         netapip_netcpCfgDelIpInternal( h, 0, 0,
1623                   NULL, NULL, 0,
1624                   err, L3_handle,  0);
1625     }
1626     netapip_freeTransInfo(pTransInfo);
1628 ERR_netapi_netcpCfgDelClass:
1629     return;
1632 /********************************************************************
1633  * FUNCTION PURPOSE:  API to add a flow
1634  ********************************************************************
1635  * DESCRIPTION:  API to add a flow
1636  ********************************************************************/
1637 /*--------------flow management--------*/
1638 // ADD A Flow
1639 NETCP_CFG_FLOW_HANDLE_T netapi_netcpCfgAddFlow(NETAPI_T                 h,
1640                                                int                      n,
1641                                                Pktlib_HeapHandle        handles[],
1642                                                int                      sizes[],
1643                                                NETCP_CFG_FLOW_CONFIG_T* p_cfg,
1644                                                int*                     err )
1646     Cppi_RxFlowCfg  rxFlowCfg;
1647     Uint8           isAlloc;
1648     Qmss_QueueHnd   rxBufQ[TUNE_NETAPI_MAX_BUF_POOLS_IN_FLOW];
1649     Uint32          rxBufSize[TUNE_NETAPI_MAX_BUF_POOLS_IN_FLOW];
1650     int             i;
1651     Cppi_FlowHnd FlowHnd;
1652     int  slot;
1653     NETCP_CFG_FLOW_HANDLE_T retVal;
1654     NETAPI_HANDLE_T * pHandle = (NETAPI_HANDLE_T *) h;
1655     *err= 0;  /* ok */
1656     if (!p_cfg)
1657     {
1658         *err= NETAPI_ERR_BAD_INPUT;
1659         return NULL;
1660     }
1661     //get a slot to save new flow
1662     slot = netapip_netcpCfgFindFlowSlot(pHandle,
1663                                         &netapi_get_global()->nwal_context);
1665     if (slot<0) { *err= NETAPI_ERR_NOMEM;  return NULL; }
1667     //configure flow
1668     memset(&rxFlowCfg,0,sizeof(Cppi_RxFlowCfg));
1669     for (i = 0; i < TUNE_NETAPI_MAX_BUF_POOLS_IN_FLOW; i++)
1670     {
1671         if (i >= n)
1672         {
1673             rxBufQ[i] = 0;
1674             rxBufSize[i] = 0;
1675         }
1676         else
1677         {
1678             rxBufQ[i] =   Pktlib_getInternalHeapQueue(handles[i]);
1679             //todo: verity sizes< heapsize
1680             //todo: verify order
1681             rxBufSize[i]= sizes[i];
1682         }
1683        if (i && (rxBufQ[i] <= 0))
1684        {
1685             rxBufQ[i] = rxBufQ[i-1];
1686             rxBufSize[i] = 0;
1687        }
1688     }
1690     /* Configure Rx flow */
1691     rxFlowCfg.flowIdNum      = p_cfg->flow_index;/*CPPI_PARAM_NOT_SPECIFIED*/;
1692     rxFlowCfg.rx_dest_qnum   = netapi_pktioGetQ(p_cfg->p_dest_q);
1693     rxFlowCfg.rx_dest_qmgr   = Qmss_getQueueNumber(rxFlowCfg.rx_dest_qnum).qMgr; 
1694     rxFlowCfg.rx_sop_offset  = p_cfg->recv_offset;
1695     rxFlowCfg.rx_ps_location = Cppi_PSLoc_PS_IN_DESC;
1696     rxFlowCfg.rx_desc_type   = Cppi_DescType_HOST;
1697     rxFlowCfg.rx_error_handling = p_cfg->block;
1699     rxFlowCfg.rx_psinfo_present = 1;
1700     rxFlowCfg.rx_einfo_present  = 1;
1702     rxFlowCfg.rx_dest_tag_lo = 0;
1703     rxFlowCfg.rx_dest_tag_hi = 0;
1704     rxFlowCfg.rx_src_tag_lo  = 0;
1705     rxFlowCfg.rx_src_tag_hi  = 0;
1707     rxFlowCfg.rx_size_thresh0_en = rxBufSize[1] ? 1 : 0;
1708     rxFlowCfg.rx_size_thresh1_en = rxBufSize[2] ? 1 : 0;
1709     rxFlowCfg.rx_size_thresh2_en = rxBufSize[3] ? 1 : 0;
1711   if (p_cfg->dma_index==NETAPI_DMA_NETCP )
1712     rxFlowCfg.rx_dest_tag_lo_sel =0;
1713   else
1714     rxFlowCfg.rx_dest_tag_lo_sel = 0x4;
1715     rxFlowCfg.rx_dest_tag_hi_sel = 0;
1716     rxFlowCfg.rx_src_tag_lo_sel  = 0;
1717     rxFlowCfg.rx_src_tag_hi_sel  = 0;
1719     rxFlowCfg.rx_fdq1_qnum = rxBufQ[1];
1720     rxFlowCfg.rx_fdq1_qmgr = (rxBufQ[1] ? Qmss_getQueueNumber(rxBufQ[1]).qMgr: 0);
1721     rxFlowCfg.rx_fdq2_qnum = rxBufQ[2];
1722     rxFlowCfg.rx_fdq2_qmgr = (rxBufQ[2] ? Qmss_getQueueNumber(rxBufQ[2]).qMgr: 0);
1723     rxFlowCfg.rx_fdq3_qnum = rxBufQ[3];
1724     rxFlowCfg.rx_fdq3_qmgr = (rxBufQ[3] ? Qmss_getQueueNumber(rxBufQ[3]).qMgr: 0);
1726     rxFlowCfg.rx_size_thresh0 = rxBufSize[1] ? rxBufSize[0] : 0;
1727     rxFlowCfg.rx_size_thresh1 = rxBufSize[2] ? rxBufSize[1] : 0;
1728     rxFlowCfg.rx_size_thresh2 = rxBufSize[3] ? rxBufSize[2] : 0;
1730     rxFlowCfg.rx_fdq0_sz0_qnum = rxBufQ[0];
1731     rxFlowCfg.rx_fdq0_sz0_qmgr =  (rxBufQ[0] ? Qmss_getQueueNumber(rxBufQ[0]).qMgr: 0);
1732     rxFlowCfg.rx_fdq0_sz1_qnum = rxBufQ[1];
1733     rxFlowCfg.rx_fdq0_sz1_qmgr =  (rxBufQ[1] ? Qmss_getQueueNumber(rxBufQ[1]).qMgr:0);
1734     rxFlowCfg.rx_fdq0_sz2_qnum = rxBufQ[2];
1735     rxFlowCfg.rx_fdq0_sz2_qmgr =  (rxBufQ[2] ? Qmss_getQueueNumber(rxBufQ[2]).qMgr:0);
1736     rxFlowCfg.rx_fdq0_sz3_qnum = rxBufQ[3];
1737     rxFlowCfg.rx_fdq0_sz3_qmgr =  (rxBufQ[3] ? Qmss_getQueueNumber(rxBufQ[3]).qMgr:0);
1738     {
1739         //todo: replace this with a nwal call to get global cntx info
1740         Cppi_CpDmaInitCfg cpdmaCfg;
1741         Cppi_Handle cppiHnd;
1742         memset(&cpdmaCfg,0,sizeof(Cppi_CpDmaInitCfg));
1743         cpdmaCfg.dmaNum   = (p_cfg->dma_index==NETAPI_DMA_NETCP ) ?Cppi_CpDma_PASS_CPDMA: Cppi_CpDma_QMSS_CPDMA;
1744         cppiHnd= Cppi_open (&cpdmaCfg);
1745         if (cppiHnd == NULL)
1746         {
1747               netapip_netcpCfgDeleteFlow(&netapi_get_global()->nwal_context, slot);
1748               *err= NETAPI_ERR_NORES;
1749               return NULL;
1750         }
1751         FlowHnd = Cppi_configureRxFlow (cppiHnd, &rxFlowCfg, &isAlloc);
1752     }
1753     if (FlowHnd == NULL)
1754     {
1755         *err= NETAPI_ERR_NORES;
1756         netapip_netcpCfgDeleteFlow(&netapi_get_global()->nwal_context, slot);
1757         return (NULL);
1758     }
1760     //update slot
1761     retVal = netapip_netcpCfgInsertFlow(&netapi_get_global()->nwal_context,
1762                                         slot,
1763                                         p_cfg->dma_index,
1764                                         (void*) FlowHnd);
1765     netapi_Log(">netcp cfg:  flow %d created in dma index %d\n",
1766         ((NETCP_CFG_FLOW_T *) retVal)->flowid, p_cfg->dma_index);
1767     return (retVal);
1770 /********************************************************************
1771  * FUNCTION PURPOSE:  API to delete a flow
1772  ********************************************************************
1773  * DESCRIPTION:  API to delete a flow
1774  ********************************************************************/
1775 void netapi_netcpCfgDelFlow(NETAPI_T                h,
1776                             NETCP_CFG_FLOW_HANDLE_T f,
1777                             int*                    err)
1779     int slot;
1780     void * handle;
1781     *err=0;
1782     NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
1783     /* find entry */
1784         slot = netapip_netcpCfgFindFlow(n,
1785                                         &netapi_get_global()->nwal_context,
1786                                         ((NETCP_CFG_FLOW_T *) f) ->flowid,
1787                                         ((NETCP_CFG_FLOW_T *) f) ->dma_engine,
1788                                         &handle);
1789     if (slot<0)
1790     {
1791         *err = NETAPI_ERR_BAD_INPUT;
1792         return;
1793     }
1795     Cppi_closeRxFlow( (Cppi_FlowHnd) handle);
1796     netapip_netcpCfgDeleteFlow(&netapi_get_global()->nwal_context,
1797                                slot);
1798     netapi_Log(">netcp cfg:  flow %d (dma index %d) deleted\n",
1799                 ((NETCP_CFG_FLOW_T *) f)->flowid,
1800                 ((NETCP_CFG_FLOW_T *) f)->dma_engine);
1801     return;
1804 /******************************************************************************
1805  * FUNCTION PURPOSE:  API to configure NETCP with global rules for exception packet handling
1806  ******************************************************************************
1807  * DESCRIPTION:  API to configure NETCP with global rules for exception packet handling
1808  *****************************************************************************/
1809 NETCP_CFG_EXCEPTION_PKT_T netapi_netcpCfgExceptions(NETAPI_T                    h,
1810                                                     int                         exception_id,
1811                                                     nwal_matchAction_t          action,
1812                                                     NETCP_CFG_ROUTE_HANDLE_T    p_route)
1814     nwalCtlInfo_t   ctrl;
1815     NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
1816     nwal_RetValue retVal = 0;
1817     memset(&ctrl, 0, sizeof(nwalCtlInfo_t));
1820     if (p_route != NULL)
1821     {
1822         if((p_route->valid_params & NETCP_CFG_VALID_PARAM_ROUTE_TYPE) ==
1823             NETCP_CFG_VALID_PARAM_ROUTE_TYPE)
1824         {
1825            ctrl.validParams |= 
1826                     NWAL_CONTROL_VALID_PARAM_ROUTE_TYPE;
1827            ctrl.routeType = p_route->routeType;
1828         }
1829         netapip_netcpCfgBuildRoute(p_route,
1830                                    &ctrl.appRxPktFlowId,
1831                                    &ctrl.appRxPktQueue,
1832                                    &ctrl.routeType);
1833     }
1834     else
1835     {
1836         ctrl.appRxPktFlowId = NWAL_FLOW_NOT_SPECIFIED;
1837         ctrl.appRxPktQueue = NWAL_QUEUE_NOT_SPECIFIED;
1838     }
1840     ctrl.appId = (void*)(NETAPI_NETCP_CFG_MATCH_EXCEPTION | exception_id);
1842     ctrl.matchAction = action;
1844     if (exception_id == NETCP_CFG_ALL_EXCEPTIONS)
1845     {
1846         ctrl.pktCtl = NWAL_CTRL_CFG_ALL_EXCEPTIONS;
1847     }
1848     else
1849     {
1850             ctrl.pa_EROUTE_Id = exception_id;
1851             ctrl.pktCtl = NWAL_CTRL_CFG_SINGLE_EXCEPTION;
1852     }
1854     retVal = nwal_control(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle, &ctrl);
1856     return (NETCP_CFG_EXCEPTION_PKT_T) ctrl.appId;
1860 /*************************************************************************/
1861 /*********************************INTERNAL*******************************/
1862 /************************************************************************/
1864 /********************************************************************
1865  * FUNCTION PURPOSE:  NETAPI internal function, NETCP command reply callback
1866  ********************************************************************
1867  * DESCRIPTION:  NETAPI internal function, NETCP command reply callback
1868  ********************************************************************/
1869 void netapip_netcpCfgNWALCmdCallBack(nwal_AppId        appHandle,
1870                             uint16_t            trans_id,
1871                             nwal_RetValue     ret)
1873     NetapiNwalTransInfo_t * p_trans;
1874     NETAPI_NWAL_LOCAL_CONTEXT_T *p_local=NULL;
1876     if(trans_id == NWAL_TRANSID_SPIN_WAIT)
1877     {
1878         netapi_get_proc_global()->nwal_context.numBogusTransIds++;
1879         return;
1880     }
1882     p_trans= &netapi_get_proc_global()->nwal_context.transInfos[trans_id];
1883     p_local =&((NETAPI_HANDLE_T*) (p_trans->netapi_handle))->nwal_local;
1885     if(ret != nwal_OK)
1886     {
1887         netapi_Log ("netcp_cfg : netapip_netcpCfgNWALCmdCallBack returned Error Code %d for trans_id %d\n",
1888                     ret, trans_id);
1889         // update error code that is fialed  in p_trans */
1890         //todo: atomic inc
1891         p_trans->state = NETAPI_NWAL_HANDLE_STATE_ERR;
1892         netapi_get_proc_global()->nwal_context.numCmdFail++;
1893     }
1894     else
1895     {
1896         //todo: atomic inc
1897         netapi_get_proc_global()->nwal_context.numCmdPass++;
1898         switch(p_trans->transType)
1899         {
1900             case NETAPI_NWAL_HANDLE_TRANS_MAC:
1901             {
1902                 if(p_trans->state == NETAPI_NWAL_HANDLE_STATE_OPEN_PENDING)
1903                 {
1904                     p_trans->state =NETAPI_NWAL_HANDLE_STATE_OPEN;
1905                 }
1906                 else if(p_trans->state == NETAPI_NWAL_HANDLE_STATE_CLOSE_PENDING)
1907                 {
1908                     p_trans->state =NETAPI_NWAL_HANDLE_STATE_IDLE;
1909                 }
1910                 break;
1911             }
1912             case NETAPI_NWAL_HANDLE_TRANS_IP:
1913             {
1914                  if(p_trans->state == NETAPI_NWAL_HANDLE_STATE_OPEN_PENDING)
1915                 {
1916                     p_trans->state = NETAPI_NWAL_HANDLE_STATE_OPEN;
1917                 }
1918                 else if(p_trans->state == NETAPI_NWAL_HANDLE_STATE_CLOSE_PENDING)
1919                 {
1920                     p_trans->state =NETAPI_NWAL_HANDLE_STATE_IDLE;
1921                 }
1922                 break;
1923             }
1924             case NETAPI_NWAL_HANDLE_TRANS_PORT:
1925             {
1926                 if(p_trans->state == NETAPI_NWAL_HANDLE_STATE_OPEN_PENDING)
1927                 {
1928                     p_trans->state =NETAPI_NWAL_HANDLE_STATE_OPEN;
1929                 }
1930                 else if(p_trans->state == NETAPI_NWAL_HANDLE_STATE_CLOSE_PENDING)
1931                 {
1932                     p_trans->state =NETAPI_NWAL_HANDLE_STATE_IDLE;
1933                 }
1934                 break;
1935             }
1936             case NETAPI_NWAL_HANDLE_TRANS_SA:
1937             {
1938                 if(p_trans->state == NETAPI_NWAL_HANDLE_STATE_OPEN_PENDING)
1939                 {
1940                     p_trans->state =NETAPI_NWAL_HANDLE_STATE_OPEN;
1941                 }
1942                 else if(p_trans->state == NETAPI_NWAL_HANDLE_STATE_CLOSE_PENDING)
1943                 {
1944                     p_trans->state =NETAPI_NWAL_HANDLE_STATE_IDLE;
1945                 }
1946                 break;
1947             }
1948             case NETAPI_NWAL_HANDLE_TRANS_SA_POLICY:
1949             {
1950                 if(p_trans->state == NETAPI_NWAL_HANDLE_STATE_OPEN_PENDING)
1951                 {
1952                     p_trans->state =NETAPI_NWAL_HANDLE_STATE_OPEN;
1953                 }
1954                 else if(p_trans->state == NETAPI_NWAL_HANDLE_STATE_CLOSE_PENDING)
1955                 {
1956                     p_trans->state =NETAPI_NWAL_HANDLE_STATE_IDLE;
1957                 }
1958                 break;
1959             }
1960             default:
1961             {
1962                 netapi_Log ("netcp cfg> Invalid transaction type %d for trans_id: %d\n",
1963                     p_trans->transType,trans_id);
1964                 break;
1965             }
1966         }
1967     }
1969     p_local->numPendingCfg--;
1971     if(p_trans->state == NETAPI_NWAL_HANDLE_STATE_IDLE)
1972     {
1973         p_trans->inUse = nwal_FALSE;
1974     }
1978 /********************************************************************
1979  * FUNCTION PURPOSE:  NETAPI internal function, PA stats reply callback
1980  ********************************************************************
1981  * DESCRIPTION:  NETAPI internal function, PA stats reply callback
1982  ********************************************************************/
1983 void netapip_netcpCfgNWALCmdPaStatsReply(nwal_AppId        appHandle,
1984                                 nwal_TransID_t    trans_id,
1985                                 paSysStats_t      *stats)
1987     NetapiNwalTransInfo_t * p_trans;
1988     NETAPI_NWAL_LOCAL_CONTEXT_T *p_local=NULL;
1990     if(trans_id == NWAL_TRANSID_SPIN_WAIT)
1991     {
1992         netapi_get_proc_global()->nwal_context.numBogusTransIds++;
1993         return;
1994     }
1996     p_trans= &netapi_get_proc_global()->nwal_context.transInfos[trans_id];
1997     p_trans->inUse = nwal_FALSE;
1998     p_local =&((NETAPI_HANDLE_T*) (p_trans->netapi_handle))->nwal_local;
2000     //save a local copy  of some stuff*/
2001     p_local->numL2PktsRecvd=stats->classify1.nPackets;
2002     p_local->numL3PktsRecvd=stats->classify1.nIpv4Packets;
2004     //callout result to application !!
2005     if (p_local->stats_cb)
2006     {
2007         (*p_local->stats_cb)(p_trans->netapi_handle,stats);
2008     }