SDOCM00113322: kernel RX UDP/TCP checksum offload to NETCP breaks user space tranport...
[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     return NULL;
82 }
84 /********************************************************************
85  * FUNCTION PURPOSE:  Netapi internal function to free a transaction id
86  ********************************************************************
87  * DESCRIPTION:  Netapi internal function to free a transaction id
88  ********************************************************************/
89 void netapip_freeTransInfo(NetapiNwalTransInfo_t *pTransInfo)
90 {
91     pTransInfo->inUse = nwal_FALSE;
92     pTransInfo->state = NETAPI_NWAL_HANDLE_STATE_IDLE;
93     pTransInfo->transType = NETAPI_NWAL_HANDLE_TRANS_NONE;
94 }
95 /********************************************************************
96  * FUNCTION PURPOSE:  Netapi internal function to build a route
97  ********************************************************************
98  * DESCRIPTION:  Netapi internal function to build a route
99  ********************************************************************/
100 void netapip_netcpCfgBuildRoute(NETCP_CFG_ROUTE_T * p_route,
101                                 int16_t *p_flow,
102                                 Qmss_QueueHnd *p_q,
103                                 nwalRouteType_t *p_type)
105     if (!p_route) return;
106     if (p_route->p_flow)  *p_flow= p_route->p_flow->flowid;
107     else *p_flow = CPPI_PARAM_NOT_SPECIFIED;
109     if (p_route->p_dest_q) *p_q = netapi_pktioGetQ(p_route->p_dest_q);
110     else *p_q=QMSS_PARAM_NOT_SPECIFIED;
112     *p_type = p_route->routeType;
116 /******************************************************/
117 /*----------------database management stuff           */
118 /******************************************************/
120 /*=====================POLICIES=============================*/
122 /********************************************************************
123  * FUNCTION PURPOSE:  Netapi internal function to find a free slot for an SA
124  ********************************************************************
125  * DESCRIPTION:  Netapi internal function to find a free slot for an SA
126  ********************************************************************/
127 int netapip_netcpCfgFindPolicySlot(NETAPI_HANDLE_T *p_handle,
128                                    NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
129                                    int tunnel)
131     int i;
132     if ((tunnel <0 ) || (tunnel >=TUNE_NETAPI_MAX_SA))
133         return -1;
135     p_handle->spinLock.lock(&pnetapiShm->netapi_netcp_cfg_lock);
136     //find a free entry
137     for(i=0;i<TUNE_NETAPI_MAX_POLICY;i++)
138     {
139         if (!p->policy[i].in_use)
140         {
141             p->policy[i].in_use = 2; //pending
142             p->policy[i].tunnel= tunnel; //save tunnel this is linked to
143             p_handle->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_lock);
144             return i;
145         }
146     }
147     p_handle->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_lock);
148     return -1;
151 /********************************************************************
152  * FUNCTION PURPOSE:  Netapi internal function to delete a policy from policy list
153  ********************************************************************
154  * DESCRIPTION:  Netapi internal function to delete a policy from policy list
155  ********************************************************************/
156 void netapip_netcpCfgDeletePolicy(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
157                                   int policy_slot)
159     if ((policy_slot <0 ) || (policy_slot >= TUNE_NETAPI_MAX_POLICY))
160     {
161         return ;
162     }
163     p->policy[policy_slot].in_use=0;
164     return;
167 /********************************************************************
168  * FUNCTION PURPOSE:  Netapi internal function to insert a policy to the policy list
169  ********************************************************************
170  * DESCRIPTION:  Netapi internal function to insert a policy to the policy list
171  ********************************************************************/
172 void netapip_netcpCfgInsertPolicy(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
173                                   int policy_slot,
174                                   void * handle,
175                                   void * user_data)
177     p->policy[policy_slot].in_use=1;
178     p->policy[policy_slot].nwal_handle = handle;
179     p->policy[policy_slot].user_data = user_data;
180     return;
183 /************************************************************************
184  * FUNCTION PURPOSE:  Netapi internal function which returns NWAL handle for a policy
185  ************************************************************************
186  * DESCRIPTION:  Netapi internal function which returns NWAL handle for a policy
187  ************************************************************************/
188 void *netapip_netcpCfgGetPolicy(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
189                                 int policy_slot)
191     if ((policy_slot <0 ) || (policy_slot >= TUNE_NETAPI_MAX_POLICY))
192         return NULL;
193     if (!p->policy[policy_slot].in_use)
194         return NULL;
195     return p->policy[policy_slot].nwal_handle;
198 /********************************************************************
199  * FUNCTION PURPOSE:  Netapi internal function to find a free slot in SA list for a SA
200  ********************************************************************
201  * DESCRIPTION:  Netapi internal function to find a free slot in SA list for an SA
202  ********************************************************************/
203 int netapip_netcpCfgFindSaSlot(NETAPI_HANDLE_T *p_handle,
204                                NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
205                                int iface)
206 {                                    
207    int i;
208    if (iface != NETCP_CFG_NO_INTERFACE)
209    {
210    if ((iface <0 ) || (iface >=TUNE_NETAPI_MAX_NUM_MAC)) return -1;
211    }
212    p_handle->spinLock.lock(&pnetapiShm->netapi_netcp_cfg_lock);
213    //find a free entry
214    for(i=0;i<TUNE_NETAPI_MAX_SA;i++)
215    {                       
216        if (!p->tunnel[i].in_use)
217        {
218            p->tunnel[i].in_use = 2; //pending
219            p->tunnel[i].iface= iface; //save iface
220            p_handle->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_lock);
221            return i;
222        }
223    }
224    p_handle->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_lock);
225    return -1;
228 /********************************************************************
229  * FUNCTION PURPOSE:  Netapi internal function to delete an SA from SA list
230  ********************************************************************
231  * DESCRIPTION: Netapi internal function to delete an SA from SA list 
232  ********************************************************************/
233 void netapip_netcpCfgDeleteSa(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
234                               int sa_slot)
236     if ((sa_slot <0 ) || (sa_slot >= TUNE_NETAPI_MAX_SA))
237     {
238         return ;
239     }
240     p->tunnel[sa_slot].in_use=0;
241     return;
245 /****************************************************************************
246  * FUNCTION PURPOSE:  Internal function to retrieve SB command info template
247  **************************************************************************
248  * DESCRIPTION:  Internal function to retrieve SB command info template
249  ***************************************************************************/
250 nwalTxDmPSCmdInfo_t* netapip_netcpCfgGetSaSBInfo(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
251                                                  NETCP_CFG_SA_T    sa_app_id)
253      int sa_slot = netapi_cfgGetMatchId(sa_app_id);
254     if ((sa_slot <0 ) || (sa_slot >= TUNE_NETAPI_MAX_SA))
255     {
256         return NULL;
257     }
258     return (&p->tunnel[sa_slot].dmPSCmdInfo);
261 /****************************************************************************
262  * FUNCTION PURPOSE:  Internal function to retrieve Inflow mode 
263  *                    software information required to transmit packet
264  **************************************************************************
265  * DESCRIPTION:  Internal function to retrieve Inflow mode 
266  *                    software information required to transmit packet
267  ***************************************************************************/
268 int netapip_netcpCfgGetSaInflowInfo(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
269                                     NETCP_CFG_SA_T    sa_app_id,
270                                     uint32_t *swInfo0,
271                                     uint32_t *swInfo1)
273     int sa_slot = netapi_cfgGetMatchId(sa_app_id);
274     if ((sa_slot <0 ) || (sa_slot >= TUNE_NETAPI_MAX_SA))
275     {
276         return 0;
277     }
278     *swInfo0 = p->tunnel[sa_slot].swInfo0;
279     *swInfo1 = p->tunnel[sa_slot].swInfo1;
280     return 1;
283 /********************************************************************
284  * FUNCTION PURPOSE:  Netapi internal function to insert an SA to the SA list
285  ********************************************************************
286  * DESCRIPTION: Netapi internal function to insert an SA to the SA list 
287  ********************************************************************/
288 void netapip_netcpCfgInsertSa(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
289                               int sa_slot,
290                               int dir,
291                               int mode,
292                               void * temp1,
293                               void * temp2,
294                               void * handle_inflow,
295                               void * handle_sideband,
296                               nwalTxDmPSCmdInfo_t *dmPSCmdInfo,
297                               uint32_t swInfo0,
298                               uint32_t swInfo1,
299                               void* user_data)
301     p->tunnel[sa_slot].in_use=1;
302     p->tunnel[sa_slot].inbound = dir;
303     p->tunnel[sa_slot].sa_mode = mode;
304     p->tunnel[sa_slot].sa_handle_inflow = handle_inflow;
305     p->tunnel[sa_slot].sa_handle_sideband = handle_sideband;
306     p->tunnel[sa_slot].swInfo0 = swInfo0;
307     p->tunnel[sa_slot].swInfo1 = swInfo1;
308     p->tunnel[sa_slot].user_data = user_data;
310     if (dmPSCmdInfo)
311     {
312         memcpy(&p->tunnel[sa_slot].dmPSCmdInfo, dmPSCmdInfo, sizeof(nwalTxDmPSCmdInfo_t));
313     }
314     return;
317 /********************************************************************
318  * FUNCTION PURPOSE:  Netapi internal function to return NWAL handles for an SA
319  ********************************************************************
320  * DESCRIPTION: Netapi internal function to return NWAL handles for an SA
321  ********************************************************************/
322  void *netapip_netcpCfgGetSaHandles(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
323                                     int sa_slot,
324                                     void ** p_sideband)
326     if ((sa_slot <0 ) || (sa_slot >= TUNE_NETAPI_MAX_SA))
327         return NULL;
328     if (!p->tunnel[sa_slot].in_use)
329         return NULL;
330     *p_sideband = p->tunnel[sa_slot].sa_handle_sideband;
331     return p->tunnel[sa_slot].sa_handle_inflow;
335 /*==============================FLOWS=============================*/
337 /********************************************************************
338  * FUNCTION PURPOSE:  Netapi internal function to find a free slot for a flow
339  ********************************************************************
340  * DESCRIPTION: Netapi internal function to find a free slot for a flow
341  ********************************************************************/
342 static int netapip_netcpCfgFindFlowSlot(NETAPI_HANDLE_T *p_handle,
343                                         NETAPI_NWAL_GLOBAL_CONTEXT_T *p)
345     int i;
346     //find a free entry
347     p_handle->spinLock.lock(&pnetapiShm->netapi_netcp_cfg_lock);
348     for(i=0;i<TUNE_NETAPI_MAX_FLOWS;i++)
349     {
350         if (!p->flows[i].in_use)
351         {
352             p->flows[i].in_use = 2; /* pending */
353             p_handle->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_lock);
354             return i;
355         }
356     }
357    p_handle->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_lock);
358     return -1;
361 /********************************************************************
362  * FUNCTION PURPOSE:  Netapi internal function to find delete a flow from flow list
363  ********************************************************************
364  * DESCRIPTION: Netapi internal function to find delete a flow from flow list
365  ********************************************************************/
366 static void netapip_netcpCfgDeleteFlow(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
367                                        int slot)
369     if ((slot >=0 ) && (slot < TUNE_NETAPI_MAX_FLOWS))
370     {
371         p->flows[slot].in_use = 0;
372     }
375 /********************************************************************
376  * FUNCTION PURPOSE:  Netapi internal function to  insert a flow to the  flow list
377  ********************************************************************
378  * DESCRIPTION: Netapi internal function to  delete a flow from flow list
379  ********************************************************************/
380 static NETCP_CFG_FLOW_HANDLE_T netapip_netcpCfgInsertFlow(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
381                                                           int slot,
382                                                           int dma_engine,
383                                                           void * handle)
385     p->flows[slot].in_use=1;
386     p->flows[slot].handle = handle;
387     p->flows[slot].flow.flowid  = Cppi_getFlowId(handle);
388     p->flows[slot].flow.dma_engine  = dma_engine;
389         return (NETCP_CFG_FLOW_HANDLE_T) &p->flows[slot].flow;
392 /********************************************************************
393  * FUNCTION PURPOSE:  Netapi internal function to find entry matching the flowid
394  ********************************************************************
395  * DESCRIPTION: Netapi internal function to find entry matching the flowid. Returns
396  * the slot number and the cPPI handle.
397  ********************************************************************/
398 static int netapip_netcpCfgFindFlow(NETAPI_HANDLE_T *p_handle,
399                                     NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
400                                     int flowid,  
401                                     int dma_engine,
402                                     void ** handle) 
404     int i;
405     *handle=NULL;
406     p_handle->spinLock.lock(&pnetapiShm->netapi_netcp_cfg_lock);
407     for(i=0;i<TUNE_NETAPI_MAX_FLOWS;i++)
408     {
409        if ((p->flows[i].in_use)&&
410            (p->flows[i].flow.flowid == flowid)&&
411            (p->flows[i].flow.dma_engine == dma_engine))
412         {
413             *handle = p->flows[i].handle;
414              p_handle->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_lock);
415             return i;
416         }
417     }
418     p_handle->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_lock);
419     return -1;
424 /*============================IP ADDRESSES==========================*/
426 /***************************************************************************
427  * FUNCTION PURPOSE:  Netapi internal function to find a free slot for IP rule in IP slot list
428  ***************************************************************************
429  * DESCRIPTION: NNetapi internal function to find a free slot for IP rule in IP slot list
430  ***************************************************************************/
431 static int netapip_netcpCfgFindIpSlot(NETAPI_HANDLE_T *p_handle,
432                                       NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
433                                       int iface_no)
435     int i;
437     //find a free entry
438     p_handle->spinLock.lock(&pnetapiShm->netapi_netcp_cfg_lock);
439     for(i=0;i<TUNE_NETAPI_MAX_NUM_IP;i++)
440     {
441         if (!p->ips[i].in_use)
442         {
443             p->ips[i].in_use = 2; //pending
444             p_handle->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_lock);
445             return i;
446         }
447     }
448     p_handle->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_lock);
449     return -1;
452 /***************************************************************************
453  * FUNCTION PURPOSE:  Netapi internal function to insert an IP address into interface
454  ***************************************************************************
455  * DESCRIPTION: Netapi internal function to insert an IP address into interface
456  ***************************************************************************/
457 static void netapip_netcpCfgInsertIp(NETAPI_NWAL_GLOBAL_CONTEXT_T *p, 
458                                      nwal_IpType ipType,
459                                      nwalIpAddr_t *ip_addr, 
460                                      nwalIpOpt_t *ip_qualifiers, 
461                                      int iface_no,
462                                      int ip_slot,
463                                      void * handle,
464                                      void * user_data)
466     p->ips[ip_slot].in_use=1;
467     memcpy(&p->ips[ip_slot].ip_addr, ip_addr, sizeof(nwalIpAddr_t));
468     if(ip_qualifiers)
469     {
470         memcpy(&p->ips[ip_slot].ip_qualifiers, ip_qualifiers, sizeof(nwalIpOpt_t));
471     }
472     else
473     {
474         memset(&p->ips[ip_slot].ip_qualifiers, 0, sizeof(nwalIpOpt_t));
475     }
476     p->ips[ip_slot].ip_type = ipType;
477     p->ips[ip_slot].nwal_handle = handle;
478     p->ips[ip_slot].user_data = user_data;
481 /***************************************************************************
482  * FUNCTION PURPOSE:  Netapi internal function to free IP slot associated with IP address
483  ***************************************************************************
484  * DESCRIPTION: Netapi internal function to free IP slot associated with IP address
485  ***************************************************************************/
486 static void netapip_netcpCfgDeleteIp(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
487                                      int iface_no,
488                                      int ip_slot)
490     if ((ip_slot >=0) &&(ip_slot < TUNE_NETAPI_MAX_NUM_IP))
491     {
492         p->ips[ip_slot].in_use=0;
493     }
496 /***************************************************************************
497  * FUNCTION PURPOSE:  Netapi internal function to get IP handle associated with IP address
498  ***************************************************************************
499  * DESCRIPTION: Netapi internal function to get IP handle associated with IP address
500  ***************************************************************************/
501 static void *netapip_netcpCfgGetIpHandle(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
502                                          int iface_no,
503                                          int ip_slot)
505     if ((ip_slot <0)||(ip_slot>=TUNE_NETAPI_MAX_NUM_IP))
506         return NULL;
507     if (!p->ips[ip_slot].in_use)
508         return NULL;
509     return (void *) p->ips[ip_slot].nwal_handle;
512 /*==========================MAC INTERFACES======================*/
516 /*******************************************************************************
517  * FUNCTION PURPOSE:  Netapi internal function to insert an interface to the interface list
518  *******************************************************************************
519  * DESCRIPTION:  Netapi internal function to insert an interface to the interface list
520  *******************************************************************************/
521 static void netapip_netcpCfgInsertMac(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
522                                       unsigned char * p_mac,
523                                       int iface_no, 
524                                       int state, NETCP_CFG_VLAN_T vlan, 
525                                       void * handle)
527     if ((iface_no >=0 ) && (iface_no < TUNE_NETAPI_MAX_NUM_MAC))
528     {
529         memset(&p->interfaces[iface_no],0,sizeof(NETCP_INTERFACE_T));
530         p->interfaces[iface_no].in_use = 1;
531         memcpy(&p->interfaces[iface_no].mac[0], p_mac,6);
532         p->interfaces[iface_no].state = state;
533         //todo p->interfaces[iface_no].vlan = vlan;
534         p->interfaces[iface_no].nwal_handle = handle; //save handle assoicated with this rule
536     }
539 /*******************************************************************************
540  * FUNCTION PURPOSE:  Netapi internal function to get handle associated with interface
541  *******************************************************************************
542  * DESCRIPTION:  Netapi internal function to get handle associated with interface
543  *******************************************************************************/
544 void* netapip_netcpCfgGetMacHandle(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
545                                    int iface_no)
547     if (iface_no == NETCP_CFG_NO_INTERFACE)
548     {
549         return NULL;
550     }
551     if ((iface_no <0 ) || (iface_no >= TUNE_NETAPI_MAX_NUM_MAC))
552     {
553         return NULL;
554     }
555     else if ( p->interfaces[iface_no].in_use)
556     {
557       return (void *) p->interfaces[iface_no].nwal_handle;
558     }
559     //no valid entry in slot
560     return NULL;
562 /*******************************************************************************
563  * FUNCTION PURPOSE:  Netapi internal function to delete interface from interface list
564  *******************************************************************************
565  * DESCRIPTION:  Netapi internal function to delete interface from interface list
566  *******************************************************************************/
567 static void netapip_netcpCfgDeleteMac(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
568                                       int iface_no)
570     if ((iface_no >=0 ) && (iface_no < TUNE_NETAPI_MAX_NUM_MAC))
571     {
572         p->interfaces[iface_no].in_use = 0;
573     }
576 /*========================CLASSIFIERS==========================*/
578 /*******************************************************************************
579  * FUNCTION PURPOSE:  Netapi internal function to find a free slot for classifier rule
580  *******************************************************************************
581  * DESCRIPTION:  Netapi internal function to find a free slot for classifier rule
582  *******************************************************************************/
583 static int netapip_netcpCfgFindClassSlot(NETAPI_HANDLE_T *p_handle,
584                                          NETAPI_NWAL_GLOBAL_CONTEXT_T *p)
586     int i;
587     p_handle->spinLock.lock(&pnetapiShm->netapi_netcp_cfg_lock);
588     for(i=0;i<TUNE_NETAPI_MAX_CLASSIFIERS;i++)
589     {
590         if (!p->classi[i].in_use)
591         {
592             p->classi[i].in_use = 2; //pending
593             p_handle->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_lock);
594             return i;
595         }
596     }
597     p_handle->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_lock);
598     return -1;
600 /*******************************************************************************
601  * FUNCTION PURPOSE:  Netapi internal function to find a delete a classifer from classifer list
602  *******************************************************************************
603  * DESCRIPTION:  Netapi internal function to find a delete a classifer from classifer list
604  *******************************************************************************/
605 static void netapip_netcpCfgDeleteClass(
606          NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
607          int class_slot )
609     if ((class_slot <0 ) || (class_slot >= TUNE_NETAPI_MAX_CLASSIFIERS))
610     {
611         return;
612     }
613     p->classi[class_slot].in_use=0;
616 /*******************************************************************************
617  * FUNCTION PURPOSE:  Netapi internal function to find a insert a classifer to classifer list
618  *******************************************************************************
619  * DESCRIPTION:  Netapi internal function to find a insert a classifer to classifer list
620  *******************************************************************************/
621 static void netapip_netcpCfgInsertClass(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
622                                         int class_slot,
623                                         int class_type,
624                                         void * L2_handle,
625                                         void * L3_handle,
626                                         void * L4_handle,
627                                         void * user_data)
629     if ((class_slot >=0 ) && (class_slot < TUNE_NETAPI_MAX_CLASSIFIERS))
630     {
631         p->classi[class_slot].in_use=1;
632         p->classi[class_slot].nwal_L2_handle = L2_handle;
633         p->classi[class_slot].nwal_L3_handle = L3_handle;
634         p->classi[class_slot].nwal_L4_handle = L4_handle;
635         p->classi[class_slot].class_type = class_type;
636         p->classi[class_slot].user_data = user_data;
637     }
640 /*******************************************************************************
641  * FUNCTION PURPOSE:  Netapi internal function to get L4 nwal handle for classifier
642  *******************************************************************************
643  * DESCRIPTION:  Netapi internal function to get L4 nwal handle for classifier
644  *******************************************************************************/
645 static void *netapip_netcpCfgGetL4Handle(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
646                                          int class_slot)
648     if ((class_slot <0 ) || (class_slot >= TUNE_NETAPI_MAX_CLASSIFIERS))
649     {
650         return NULL;
651     }
652     if (!p->classi[class_slot].in_use)
653     {
654         return NULL;
655     }
656     return p->classi[class_slot].nwal_L4_handle;
661 /*******************************************************************************
662  * FUNCTION PURPOSE:  Netapi internal function to get L3 nwal handle for classifier
663  *******************************************************************************
664  * DESCRIPTION:  Netapi internal function to get L3 nwal handle for classifier
665  *******************************************************************************/
666 static int cfgOkToDeleteL3ClassiHandle(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
667                                          void*  l3_handle)
669     int i;
670     int count=0;
672     if(l3_handle == NULL)
673         return NETAPI_FALSE;
674     for(i=0; i< TUNE_NETAPI_MAX_CLASSIFIERS;i++)
675     {
676         if (!p->classi[i].in_use)
677         {
678             continue;
679         }
680         if (l3_handle == p->classi[i].nwal_L3_handle)
681         {
682             count++;
683         }
684     }
685     if (count > 0)
686         return NETAPI_FALSE;
688     return NETAPI_TRUE;
691 /*******************************************************************************
692  * FUNCTION PURPOSE:  Netapi internal function to get L3 nwal handle for classifier
693  *******************************************************************************
694  * DESCRIPTION:  Netapi internal function to get L3 nwal handle for classifier
695  *******************************************************************************/
696 static void *netapip_netcpCfgGetL3Handle(NETAPI_NWAL_GLOBAL_CONTEXT_T *p,
697                                          int class_slot)
699     if ((class_slot <0 ) || (class_slot >= TUNE_NETAPI_MAX_CLASSIFIERS))
700     {
701         return NULL;
702     }
703     if (!p->classi[class_slot].in_use)
704     {
705         return NULL;
706     }
707     return p->classi[class_slot].nwal_L3_handle;
711 /***********************************************************************************/
712 /****************************************API****************************************/
713 /***********************************************************************************/
716 /********************************************************************
717  * FUNCTION PURPOSE:  API to request statistics from NETCP
718  ********************************************************************
719  * DESCRIPTION:  API to request statistics from NETCP
720  ********************************************************************/
721 void netapi_netcpCfgReqStats(NETAPI_T  h, 
722                              NETCP_CFG_STATS_CB cb,
723                              int doClear,
724                              int *err)
726     nwal_RetValue ret;
727     NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
728     NetapiNwalTransInfo_t *pTransInfo;
729     nwal_TransID_t     transId;
731     paSysStats_t netcp_stats;
732     if ((!n) || (!cb))
733     {
734         *err = NETAPI_ERR_BAD_INPUT;
735         return ;
736     }
737     *err =0;
739     pTransInfo = netapip_getFreeTransInfo(n,
740                                           (NETAPI_PROC_GLOBAL_T *) n->proc_global,
741                                           &transId);
742     if (!pTransInfo) { *err =  NETAPI_ERR_BUSY; return ;}
743     pTransInfo->transType = NETAPI_NWAL_HANDLE_STAT_REQUEST;
744     pTransInfo->netapi_handle = h;
745     n->nwal_local.stats_cb = cb;
747     memset(&netcp_stats, 0, sizeof(paSysStats_t));
748     ret = nwal_getPAStats( ((NETAPI_GLOBAL_T *) n->global)->nwal_context.nwalInstHandle,
749                               transId,
750                               &netcp_stats,
751                               doClear);
752     if(ret !=  nwal_OK)
753     {
754         *err = NETAPI_ERR_BUSY;  //no resources??
755         netapip_freeTransInfo(pTransInfo);
756         return;
757     }
758 #if defined(DEVICE_K2E) || defined(DEVICE_K2L)
759     if (cb)
760     {
761         cb(h, &netcp_stats);
762     }
763 #endif
764     netapip_freeTransInfo(pTransInfo);
766 /********************************************************************
767  * FUNCTION PURPOSE:  API to create a MAC interface
768  ********************************************************************
769  * DESCRIPTION:  API to create a MAC interface
770  ********************************************************************/
771 NETCP_CFG_MACIF_T  netapi_netcpCfgCreateMacInterface(NETAPI_T  h,
772                                                      uint8_t *p_mac,
773                                                      uint8_t *p_mac_remote,
774                                                      int  iface_no, /* index, from 0 to n */
775                                                      int switch_port,
776                                                      NETCP_CFG_ROUTE_HANDLE_T  route,
777                                                      NETCP_CFG_VLAN_T  vlan,  //future
778                                                      uint16_t etherType,
779                                                      int state,  //0=down, 1=up  //ignored
780                                                      int * err)
782     NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
783     nwalMacParam_t   macInfo=
784     {
785         0,      /* validParams */
786         0,      /* ifNum */
787         0,      /* vlanId      */
788         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },      /* Local mac */
789         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },      /* Remote mac */
790         NWAL_MATCH_ACTION_CONTINUE_NEXT_ROUTE,       /* Continue parsing to next route for match */
791         NWAL_NEXT_ROUTE_FAIL_ACTION_HOST,            /* For next route fail action by default is route to host */
792         CPPI_PARAM_NOT_SPECIFIED,                    /* Use default flow configured to NWAL  if packet is routed to host */
793         QMSS_PARAM_NOT_SPECIFIED,                     /* Use default queue configured to NWAL if packet is routed to host */
794         0,
795         0,
796         0
797     };
799     nwal_RetValue       retValue;
800     NetapiNwalTransInfo_t *pTransInfo;
801     nwal_TransID_t     trans_id;
802     nwal_AppId         appId;
803     if ((!n) || (!p_mac)) {*err = NETAPI_ERR_BAD_INPUT; return -1;}
804     *err =0;
806     pTransInfo = netapip_getFreeTransInfo(n,
807                                           (NETAPI_PROC_GLOBAL_T *) n->proc_global,
808                                           &trans_id);
809     if (!pTransInfo)
810     {
811         *err =  NETAPI_ERR_BUSY;
812         return -1;
813     }
814     pTransInfo->transType = NETAPI_NWAL_HANDLE_TRANS_MAC;
815     pTransInfo->state = NETAPI_NWAL_HANDLE_STATE_OPEN_PENDING;
816     pTransInfo->inUse = nwal_TRUE;
817     pTransInfo->netapi_handle = h;
819     /* set up MacInfo */
820     memcpy(&macInfo.macAddr,p_mac,6);
822     if(p_mac_remote)
823     {
824         macInfo.validParams |=  NWAL_SET_MAC_VALID_PARAM_REMOTE_MAC;
825         memcpy(&macInfo.remMacAddr,p_mac_remote,6);
826     }
827     /* todo: vlan */
828     if (switch_port)
829     {
830         macInfo.validParams |= NWAL_SET_MAC_VALID_PARAM_IFNUM ;
831         macInfo.ifNum = switch_port;
832     }
834     if(etherType)
835     {
836         macInfo.validParams |= NWAL_SET_MAC_VALID_PARAM_ETHER_TYPE;
837         macInfo.etherType = etherType;
838     }
840     if (route != NULL)
841     {
842         if((route->valid_params & NETCP_CFG_VALID_PARAM_ROUTE_TYPE) ==
843             NETCP_CFG_VALID_PARAM_ROUTE_TYPE)
844         {
845            macInfo.validParams |= 
846                     NWAL_SET_MAC_VALID_PARAM_ROUTE_TYPE;
848            if(route->routeType == NWAL_ROUTE_PKTTYPE_EQOS)
849            {
850                 macInfo.egress_switch_port = route->egress_swith_port;
851                 macInfo.routeType = NWAL_ROUTE_PKTTYPE_EQOS;
852                 macInfo.matchAction = NWAL_MATCH_ACTION_HOST;
853            }
854         }
855         if((route->valid_params & NETCP_CFG_VALID_PARAM_MATCH_ACTION_DEST) ==
856             NETCP_CFG_VALID_PARAM_MATCH_ACTION_DEST)
857         {
858             macInfo.matchAction = route->match_destination;
859         }
860         if((route->valid_params & NETCP_CFG_VALID_PARAM_FAIL_ACTION_DEST) ==
861             NETCP_CFG_VALID_PARAM_FAIL_ACTION_DEST)
862         {
863             macInfo.failAction = route->fail_destination;
864         }
866         netapip_netcpCfgBuildRoute(route,
867                                    &macInfo.appRxPktFlowId,
868                                    &macInfo.appRxPktQueue,
869                                    &macInfo.routeType);
870     }
873     appId = (nwal_AppId) (NETAPI_NETCP_MATCH_GENERIC_MAC | iface_no);
875     retValue = nwal_setMacIface( ((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,
876                                   trans_id,
877                                   appId,
878                                   &macInfo,
879                                   &pTransInfo->handle);
880     if(retValue !=  nwal_OK)
881     {
882         *err = NETAPI_ERR_NWAL_ERR0;
883         netapip_freeTransInfo(pTransInfo);
884         return -1;
885     }
887     //wait here until its done since scheduler isn't running yet most likely..
888     // todo:  make this handled by scheduler poll later ??
889     if(trans_id != NWAL_TRANSID_SPIN_WAIT)
890     {
891         n->nwal_local.numPendingCfg++;
892         while ((pTransInfo->state  !=NETAPI_NWAL_HANDLE_STATE_ERR) &&
893                 (pTransInfo->state !=NETAPI_NWAL_HANDLE_STATE_OPEN))
894         {
895             // if response is there, then this poll squirts out in the CTl poll callback, 
896             // which handles the rest (including decrmenting #pending!!
897             nwal_pollCtl(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,NULL,NULL);
898         }
899         if (pTransInfo->state == NETAPI_NWAL_HANDLE_STATE_ERR)
900         {
901             netapip_freeTransInfo(pTransInfo);
902             *err = NETAPI_ERR_PA_FW;
903             return -1;
904         }
906     }
907     netapip_netcpCfgInsertMac(&netapi_get_global()->nwal_context, 
908                           p_mac, iface_no, state,vlan,
909                           (void *) pTransInfo->handle);
910     netapip_freeTransInfo(pTransInfo);
911     return (NETCP_CFG_MACIF_T)appId;
914 /********************************************************************
915  * FUNCTION PURPOSE:  API to delete MAC  interface
916  ********************************************************************
917  * DESCRIPTION:  API to delete MAC  interface
918  ********************************************************************/
919 void netapi_netcpCfgDelMac(NETAPI_T h,
920                            int iface_no,
921                            int *err)
923     nwal_RetValue ret;
924     NetapiNwalTransInfo_t *pTransInfo;
925     nwal_TransID_t     trans_id;
926     NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
927     void * ifHandle;
929     //get the nwal handle assoicated with this iface
930     ifHandle = netapip_netcpCfgGetMacHandle(&netapi_get_global()->nwal_context, iface_no );
931     if(!ifHandle) 
932     {
933         *err = NETAPI_ERR_BAD_INPUT; return ;
934     }
935     *err =0;
937     //get a transaction id
938     pTransInfo = netapip_getFreeTransInfo(n,
939                                           (NETAPI_PROC_GLOBAL_T *) n->proc_global,
940                                           &trans_id);
941     if (!pTransInfo)
942     {
943         *err =  NETAPI_ERR_BUSY;
944         return ;
945     }
946     pTransInfo->transType = NETAPI_NWAL_HANDLE_TRANS_MAC;
947     pTransInfo->state = NETAPI_NWAL_HANDLE_STATE_CLOSE_PENDING;
948     pTransInfo->inUse = nwal_TRUE;
949     pTransInfo->netapi_handle = h;
951     //issue request
952     ret = nwal_delMacIface(
953                 ((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,
954                 trans_id,
955                 ifHandle);
956     if(ret !=  nwal_OK)
957     {
958         *err = NETAPI_ERR_NWAL_ERR0;
959         netapip_freeTransInfo(pTransInfo);
960         return;
961     }
962     //wait here until its done since scheduler isn't running yet most likely..
963     // todo:  make this handled by scheduler poll later ??
964     if(trans_id != NWAL_TRANSID_SPIN_WAIT)
965     {
966         n->nwal_local.numPendingCfg++;
967         while ((pTransInfo->state  !=NETAPI_NWAL_HANDLE_STATE_ERR) &&
968                 (pTransInfo->state !=NETAPI_NWAL_HANDLE_STATE_IDLE))
969         {
970             // if response is there, then this poll squirts out in the CTl poll callback, 
971             // which handles the rest (including decrmenting #pending!!
972             nwal_pollCtl(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,NULL,NULL);
973         }
974         if (pTransInfo->state == NETAPI_NWAL_HANDLE_STATE_ERR)
975         {
976             netapip_freeTransInfo(pTransInfo);
977             *err = NETAPI_ERR_PA_FW;
978             netapip_netcpCfgDeleteMac(&netapi_get_global()->nwal_context,  iface_no);
979             return;
980         }
981     }
982     netapip_freeTransInfo(pTransInfo);
983     //zap the entry
984     netapip_netcpCfgDeleteMac(&netapi_get_global()->nwal_context,  iface_no);
985     return ;
989 /********************************************************************
990  * FUNCTION PURPOSE:  NETAPi internal function to Add IP to MAC interface
991  ********************************************************************
992  * DESCRIPTION:  NETAPi internal function to Add IP to MAC interface
993  ********************************************************************/
994 static NETCP_CFG_IP_T  netapip_netcpCfgAddIpInternal(NETAPI_T  h,
995                                                      int  iface_no,
996                                                      nwal_IpType ipType,
997                                                      nwalIpAddr_t  * ip_addr,
998                                                      nwalIpAddr_t  *ip_rem_addr,
999                                                      nwalIpOpt_t * ip_qualifiers,
1000                                                      NETCP_CFG_ROUTE_HANDLE_T  route,/*NULL for default*/
1001                                                      void * user_data,
1002                                                      int * err,
1003                                                      int  flag) /*TRUE: add IP to iface,
1004                                                      FALSE: add IP as part of classifier */
1006     static unsigned char zeroIP6[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
1007     NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
1008     void * n_handle=NULL;
1009     nwalIpParam_t    nwalIpParam= {
1010     0,
1011     pa_IPV4,      /* IP Type */
1012     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },  /* Dest IP */
1013     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },  /* Source IP */
1014     { 0x0,0,0,0},/* IP Options */
1015     NWAL_MATCH_ACTION_CONTINUE_NEXT_ROUTE,       /* Continue parsing to next route for match */
1016     NWAL_NEXT_ROUTE_FAIL_ACTION_HOST,            /* For next route fail action by default is route to host */
1017     CPPI_PARAM_NOT_SPECIFIED,                    /* Use default flow configured to NWAL  if packet is routed to host */
1018     QMSS_PARAM_NOT_SPECIFIED,                     /* Use default queue configured to NWAL if packet is routed to host */
1019     0
1020 };
1021     nwal_RetValue       retValue;
1022     NetapiNwalTransInfo_t *pTransInfo;
1023     nwal_TransID_t     trans_id;
1024     int ip_slot=-1;
1025     NETCP_CFG_IP_T ip_rule_id;
1026     NETCP_CFG_IP_T temp;
1028     //verify that iface has been configured 
1029     if (iface_no != NETCP_CFG_NO_INTERFACE)
1030     {
1031         if ((iface_no<0) || (iface_no>= TUNE_NETAPI_MAX_NUM_MAC)) {*err = NETAPI_ERR_BAD_INPUT; return -1;}
1032     }
1034     if (iface_no != NETCP_CFG_NO_INTERFACE)
1035     {
1036         if(netapi_get_global()->nwal_context.interfaces[iface_no].in_use)
1037         {
1038             n_handle =  netapi_get_global()->nwal_context.interfaces[iface_no].nwal_handle;
1039         }
1040         else
1041         {
1042             *err = NETAPI_ERR_BAD_INPUT;
1043             return -1;
1044         }
1045     }
1046     if (flag) //if adding IP to MAC then reserve a slot to save info
1047     {
1048         //find free slot for IP & reserve
1049          ip_slot= netapip_netcpCfgFindIpSlot(n,
1050                                              &netapi_get_global()->nwal_context, 
1051                                              iface_no);
1052         if (ip_slot <0) 
1053         {
1054             *err= NETAPI_ERR_NOMEM;  //no room 
1055             return -1;
1056         }
1057     }
1059     //get a transaction object for config action
1060     pTransInfo = netapip_getFreeTransInfo(n, 
1061                                           (NETAPI_PROC_GLOBAL_T *) n->proc_global,
1062                                           &trans_id);
1063     if (!pTransInfo)
1064     {
1065         *err =  NETAPI_ERR_BUSY;
1066         if (flag)
1067         {
1068             netapip_netcpCfgDeleteIp(&netapi_get_global()->nwal_context,
1069                          iface_no,
1070                          ip_slot);
1071         }
1072         return -1;
1073     }
1074     pTransInfo->transType = NETAPI_NWAL_HANDLE_TRANS_IP;
1075     pTransInfo->state = NETAPI_NWAL_HANDLE_STATE_OPEN_PENDING;
1076     pTransInfo->inUse = nwal_TRUE;
1077     pTransInfo->netapi_handle = h;
1079     //build nwalIpParam
1080     memcpy(&nwalIpParam.locIpAddr,ip_addr, sizeof(nwalIpAddr_t));
1081     if (ip_rem_addr)
1082     {
1083         if (ipType == nwal_IPV4)
1084         {
1085             if(memcmp(ip_rem_addr, zeroIP6, sizeof(nwalIpv4Addr_t)))
1086             {
1087                 nwalIpParam.validParams |= NWAL_SET_IP_VALID_PARAM_REMOTE_IP;
1088                 memcpy(&nwalIpParam.remIpAddr,ip_rem_addr, sizeof(nwalIpAddr_t));
1089             }
1090         }
1091         else
1092         {
1093             if(memcmp(ip_rem_addr, zeroIP6, sizeof(nwalIpv6Addr_t)))
1094             {
1095                 nwalIpParam.validParams |= NWAL_SET_IP_VALID_PARAM_REMOTE_IP;
1096                 memcpy(&nwalIpParam.remIpAddr,ip_rem_addr, sizeof(nwalIpAddr_t));
1097             }
1098         }
1099     }
1100     nwalIpParam.ipType=ipType;
1101     if(route)
1102     {
1103         if((route->valid_params & NETCP_CFG_VALID_PARAM_ROUTE_TYPE) ==
1104             NETCP_CFG_VALID_PARAM_ROUTE_TYPE)
1105         {
1106            nwalIpParam.validParams |= 
1107                     NWAL_SET_IP_VALID_PARAM_ROUTE_TYPE;
1108         }
1109         netapip_netcpCfgBuildRoute(route,
1110                                    &nwalIpParam.appRxPktFlowId,
1111                                    &nwalIpParam.appRxPktQueue,
1112                                    &nwalIpParam.routeType);
1113     }
1114     else{} //use nwal defaults
1116     if (ip_qualifiers)
1117         memcpy(&nwalIpParam.ipOpt,ip_qualifiers, sizeof(nwalIpOpt_t)); 
1118     else
1119         memset(&nwalIpParam.ipOpt,0, sizeof(nwalIpOpt_t));
1121     //build the rule id that will be returned when a packet matches 
1122     if (flag)
1123         ip_rule_id = NETAPI_NETCP_MATCH_GENERIC_IP | iface_no | ((ip_slot&& NETAPI_NETCP_MATCH_ID_MASK) << NETAPI_NETCP_MATCH_ID_SHIFT);
1124     else
1125         ip_rule_id = (NETAPI_NETCP_MATCH_CLASS_L3 | iface_no);
1127     retValue = nwal_setIPAddr(   netapi_get_global()->nwal_context.nwalInstHandle,
1128                                   trans_id,
1129                                   (nwal_AppId) (ip_rule_id),
1130                                   n_handle,
1131                                   &nwalIpParam,
1132                                   &pTransInfo->handle);
1134     if(retValue !=  nwal_OK)
1135     {
1136         *err = NETAPI_ERR_NWAL_ERR0;
1137         netapip_freeTransInfo(pTransInfo);
1138         //zap the entry
1139         if (flag)
1140         {
1141             netapip_netcpCfgDeleteIp(&netapi_get_global()->nwal_context,
1142                          iface_no,
1143                          ip_slot);
1144         }
1145         return -1;
1146     }
1147     //wait here until its done since scheduler isn't running yet most likely..
1148     // todo:  make this handled by scheduler poll later ??
1149     if(trans_id != NWAL_TRANSID_SPIN_WAIT)
1150     {
1151         n->nwal_local.numPendingCfg++;
1152         while ((pTransInfo->state  !=NETAPI_NWAL_HANDLE_STATE_ERR) &&
1153         (pTransInfo->state !=NETAPI_NWAL_HANDLE_STATE_OPEN))
1154         {
1155             // if response is there, then this poll squirts out in the CTl poll callback, 
1156             // which handles the rest (including decrmenting #pending!!
1157             nwal_pollCtl(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,NULL,NULL);
1158         }
1159         if (pTransInfo->state == NETAPI_NWAL_HANDLE_STATE_ERR)
1160         {
1161             netapip_freeTransInfo(pTransInfo);
1162             *err = NETAPI_ERR_PA_FW;
1163             return -1;
1164         }
1165     }
1166     if (flag)
1167     {
1168         netapip_netcpCfgInsertIp(&netapi_get_global()->nwal_context,
1169                                  ipType, 
1170                                  ip_addr,
1171                                  ip_qualifiers,
1172                                  iface_no,
1173                                  ip_slot,
1174                                  pTransInfo->handle,
1175                                  user_data);
1176     }
1178     temp = (NETCP_CFG_IP_T) pTransInfo->handle;
1179     netapip_freeTransInfo(pTransInfo);
1180     return  (flag ? ip_rule_id:  temp);
1183 /********************************************************************
1184  * FUNCTION PURPOSE:  API to Add IP to MAC interface
1185  ********************************************************************
1186  * DESCRIPTION:  API to Add IP to MAC interface
1187  ********************************************************************/
1188 NETCP_CFG_IP_T  netapi_netcpCfgAddIp(NETAPI_T                  h,
1189                                      int                       iface_no,
1190                                      nwal_IpType               ipType,
1191                                      nwalIpAddr_t*             ip_addr,
1192                                      nwalIpAddr_t*             ip_rem_addr,
1193                                      nwalIpOpt_t*              ip_qualifiers,
1194                                      NETCP_CFG_ROUTE_HANDLE_T  route,  //NULL for default
1195                                      void*                     user_data,
1196                                      int*                      err)
1198     return netapip_netcpCfgAddIpInternal(h,
1199                                          iface_no,
1200                                          ipType,
1201                                          ip_addr,
1202                                          ip_rem_addr,
1203                                          ip_qualifiers, 
1204                                          route, 
1205                                          user_data,
1206                                          err,
1207                                          1);
1211 /********************************************************************
1212  * FUNCTION PURPOSE:  NETAPI internal function to detach IP from MAC interface
1213  ********************************************************************
1214  * DESCRIPTION:  NETAPI internal function to detach IP from MAC interface
1215  ********************************************************************/
1216 static void netapip_netcpCfgDelIpInternal(NETAPI_T h, 
1217                                           int iface_no,
1218                                           nwal_IpType ipType,
1219                                           nwalIpAddr_t  * ip_addr,
1220                                           nwalIpOpt_t * ip_qualifiers, 
1221                                           NETCP_CFG_IP_T  ip_rule_id,
1222                                           int *err, 
1223                                           void * handle,   /* if flag==0, handle must be valid */
1224                                           int flag)        /* flag==0 => delete IP rule that was part of classifier, not interface */
1226     nwal_RetValue ret;
1227     NetapiNwalTransInfo_t *pTransInfo;
1228     nwal_TransID_t     trans_id;
1229     NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
1230     void * ifHandle;
1231     int ip_slot = netapi_cfgGetMatchId(ip_rule_id);
1232     /* get the nwal handle assoicated with this ip */
1233     if (flag)
1234     {
1235         ifHandle = netapip_netcpCfgGetIpHandle(&netapi_get_global()->nwal_context,
1236                                                 iface_no,
1237                                                 ip_slot);
1238     }
1239     else 
1240     {
1241         ifHandle = handle;
1242     }
1243     if(!ifHandle)
1244     {
1245         *err = NETAPI_ERR_BAD_INPUT;
1246         return ;
1247     }
1248     *err =0;
1250     //get a transaction id
1251     pTransInfo = netapip_getFreeTransInfo(n,
1252                                           (NETAPI_PROC_GLOBAL_T *) n->proc_global,
1253                                           &trans_id);
1254     if (!pTransInfo)
1255     {
1256         *err =  NETAPI_ERR_BUSY;
1257         return;
1258     }
1259     pTransInfo->transType = NETAPI_NWAL_HANDLE_TRANS_IP;
1260     pTransInfo->state = NETAPI_NWAL_HANDLE_STATE_CLOSE_PENDING;
1261     pTransInfo->inUse = nwal_TRUE;
1262     pTransInfo->netapi_handle = h;
1263     //issue request
1264     ret = nwal_delIPAddr(
1265                 ((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,
1266                 trans_id,
1267                 ifHandle);
1268     if(ret !=  nwal_OK)
1269     {
1270         *err = NETAPI_ERR_NWAL_ERR0;
1271         netapip_freeTransInfo(pTransInfo);
1272         return ;
1273     }
1274     //wait here until its done since scheduler isn't running yet most likely..
1275     // todo:  make this handled by scheduler poll later ??
1276     if(trans_id != NWAL_TRANSID_SPIN_WAIT)
1277     {
1278         n->nwal_local.numPendingCfg++;
1279         while ((pTransInfo->state  !=NETAPI_NWAL_HANDLE_STATE_ERR) &&
1280                 (pTransInfo->state !=NETAPI_NWAL_HANDLE_STATE_IDLE))
1281         {
1282             // if response is there, then this poll squirts out in the CTl poll callback, 
1283             // which handles the rest (including decrmenting #pending!!
1284             nwal_pollCtl(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,NULL,NULL);
1285         }
1286         if (pTransInfo->state == NETAPI_NWAL_HANDLE_STATE_ERR)
1287         {
1288             netapip_freeTransInfo(pTransInfo);
1289             *err = NETAPI_ERR_PA_FW;
1290             return;
1291         }
1292     }
1294     netapip_freeTransInfo(pTransInfo);
1296     //zap the entry
1297     if (flag)
1298         netapip_netcpCfgDeleteIp(&netapi_get_global()->nwal_context,  
1299                          iface_no,
1300                          ip_slot);
1301     return ;
1304 /********************************************************************
1305  * FUNCTION PURPOSE:  API to detach IP from MAC interface
1306  ********************************************************************
1307  * DESCRIPTION:  API  to detach IP from MAC interface
1308  ********************************************************************/
1309 void netapi_netcpCfgDelIp(NETAPI_T              h,
1310                           int                   iface_no,
1311                           nwal_IpType           ipType,
1312                           nwalIpAddr_t*         ip_addr,
1313                           nwalIpOpt_t*          ip_qualifiers,
1314                           NETCP_CFG_IP_T        ip_rule_id,
1315                           int*                  err)
1317     netapip_netcpCfgDelIpInternal( h, iface_no, ipType,
1318                   ip_addr, ip_qualifiers, ip_rule_id,
1319                   err, NULL, 1);
1320     return;
1324 /********************************************************************
1325  * FUNCTION PURPOSE:  API to attach a classifier rule to NETCP
1326  ********************************************************************
1327  * DESCRIPTION:  API to attach a classifier rule to NETCP
1328  ********************************************************************/
1329 NETCP_CFG_CLASS_T netapi_netcpCfgAddClass(NETAPI_T                  h,
1330                                           NETCP_CFG_CLASSIFIER_T*   p_class,
1331                                           NETCP_CFG_ROUTE_HANDLE_T  route,
1332                                           int                       action, 
1333                                           void*                     user_data, 
1334                                           int*                      err)
1336     NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
1337     void * l3_handle=NULL;  //ip handle
1338     nwal_RetValue       retValue;
1339     NetapiNwalTransInfo_t *pTransInfo;
1340     nwal_TransID_t     trans_id;
1341     int class_slot=-1;
1342     int iface_no;
1343     int ip_slot=-1;
1344     NETCP_CFG_CLASS_T  classHandle;  //returned by us
1345     nwal_appProtoType_t proto;
1346     nwalRxConnCfg_t tempCfg=
1347     {
1348         0,  //nwal_handle: to be filled in
1349         0, // l4 ports: to be filled in
1350         0,  //core id (NA)
1351         0, //action
1352         CPPI_PARAM_NOT_SPECIFIED, //flow id
1353         QMSS_PARAM_NOT_SPECIFIED, //dest queue
1354         0,
1355         0, // l4 ports: to be filled in
1356     };
1358     *err = NETAPI_ERR_OK;
1360     if(!p_class)
1361     {
1362         *err=NETAPI_ERR_BAD_INPUT;
1363         return -1;
1364     }
1365     switch(p_class->classType)
1366     {
1367         default:
1368             break;
1369         case(NETCP_CFG_CLASS_TYPE_L3_L4):
1370             n->spinLock.lock(&pnetapiShm->netapi_netcp_cfg_l3_classi_lock);
1371         case(NETCP_CFG_CLASS_TYPE_L4):
1372             //assume just type l4 only (L2, L3 defined by iface, l3 id )
1373             iface_no = p_class->u.c_l4.iface;
1374             if (p_class->classType== NETCP_CFG_CLASS_TYPE_L4)
1375             {
1376                 ip_slot = netapi_cfgGetMatchId(p_class->u.c_l4.ip);
1377             }
1379             //verify that iface has been configured 
1380             if (iface_no != NETCP_CFG_NO_INTERFACE)
1381             {
1382                 if(!netapi_get_global()->nwal_context.interfaces[iface_no].in_use)
1383                 {
1384                     *err = NETAPI_ERR_BAD_INPUT;
1385                     if(p_class->classType== NETCP_CFG_CLASS_TYPE_L3_L4)
1386                         n->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_l3_classi_lock);
1387                     return -1;
1388                 }
1389             }
1391             if (p_class->classType== NETCP_CFG_CLASS_TYPE_L4)
1392             {
1393                 //verify that ip has been configured and get its handle
1394                 l3_handle = netapip_netcpCfgGetIpHandle(
1395                       &netapi_get_global()->nwal_context, iface_no,
1396                       ip_slot );
1397             }
1398             else
1399             {
1400                 nwalIpParam_t tempParam=
1401                 {
1402                     0,
1403                     pa_IPV4,      /* IP Type */
1404                     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },  /* Dest IP */
1405                     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },  /* Source IP */
1406                     { 0x0,0,0,0},/* IP Options */
1407                     NWAL_MATCH_ACTION_CONTINUE_NEXT_ROUTE,       /* Continue parsing to next route for match */
1408                     NWAL_NEXT_ROUTE_FAIL_ACTION_HOST,            /* For next route fail action by default is route to host */
1409                     CPPI_PARAM_NOT_SPECIFIED,                    /* Use default flow configured to NWAL  if packet is routed to host */
1410                     QMSS_PARAM_NOT_SPECIFIED,                    /* Use default queue configured to NWAL if packet is routed to host */
1411                     0
1412                 };
1413                 //build nwalIpParam
1414                 memcpy(&tempParam.locIpAddr,p_class->u.c_l3_l4.ip_addr, sizeof(nwalIpAddr_t));
1415                 tempParam.ipType=p_class->u.c_l3_l4.ipType;
1416                 //use nwal defauls for route
1417                 if (p_class->u.c_l3_l4.ip_qualifiers)
1418                     memcpy(&tempParam.ipOpt,p_class->u.c_l3_l4.ip_qualifiers, sizeof(nwalIpOpt_t));
1419                 else
1420                     memset(&tempParam.ipOpt,0, sizeof(nwalIpOpt_t));
1422                 //find if we have a matching L3 handle for IP classifier; if not create it
1423                 retValue =  nwal_getIPAddr (((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,
1424                             &tempParam,
1425                             netapip_netcpCfgGetMacHandle(&netapi_get_global()->nwal_context, iface_no ),
1426                             &l3_handle); 
1427                 if (retValue != nwal_TRUE) 
1428                 {
1429                     int ret;
1430                     //**NEW IP RULE  
1431                     //need to attach this IP RULE to the MAC
1432                     l3_handle= (void *) netapip_netcpCfgAddIpInternal(
1433                                       h, iface_no, 
1434                                       p_class->u.c_l3_l4.ipType,
1435                                       p_class->u.c_l3_l4.ip_addr,
1436                                       NULL,
1437                                       p_class->u.c_l3_l4.ip_qualifiers,
1438                                       p_class->u.c_l3_l4.p_fail_route,
1439                                       user_data,
1440                                       &ret,
1441                                       NETAPI_FALSE);
1442                     if(!ret)
1443                     {
1444                         l3_handle=NULL;
1445                     }
1446                 }
1447             }
1448             if(!l3_handle)
1449             {
1450                 *err = NETAPI_ERR_BAD_INPUT; 
1451                 if(p_class->classType == NETCP_CFG_CLASS_TYPE_L3_L4)
1452                         n->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_l3_classi_lock);
1453                 return -1 ;
1454             }
1456             //find free slot for CLASS & reserve
1457             class_slot= netapip_netcpCfgFindClassSlot(n,
1458                                                       &netapi_get_global()->nwal_context);
1459             if(class_slot<0) 
1460             {
1461                 *err = NETAPI_ERR_NOMEM;
1462                 if(p_class->classType == NETCP_CFG_CLASS_TYPE_L3_L4)
1463                         n->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_l3_classi_lock);
1464                 return -1;
1465                 }
1466             classHandle = NETAPI_NETCP_MATCH_CLASS |
1467                           (class_slot << NETAPI_NETCP_MATCH_ID_SHIFT) | 
1468                           (iface_no & NETAPI_NETCP_MATCH_LOGICAL_MAC_IFACE_MASK);
1469             //build request from template
1470             tempCfg.inHandle=l3_handle;
1471             if (p_class->classType== NETCP_CFG_CLASS_TYPE_L4)
1472             {
1473                 memcpy(&tempCfg.appProto,&p_class->u.c_l4.appProto,sizeof(nwalAppProto_t));
1474                 proto = p_class->u.c_l4.proto;
1475             }
1476             else
1477             {
1478                 memcpy(&tempCfg.appProto,&p_class->u.c_l3_l4.appProto,sizeof(nwalAppProto_t));
1479                 proto = p_class->u.c_l3_l4.proto;
1480             }
1482             tempCfg.matchAction = (action==NETCP_CFG_ACTION_TO_SW)  ? NWAL_MATCH_ACTION_HOST : NWAL_MATCH_ACTION_DISCARD;
1483             if (route)
1484             {
1485                 if((route->valid_params & NETCP_CFG_VALID_PARAM_ROUTE_TYPE) ==
1486                     NETCP_CFG_VALID_PARAM_ROUTE_TYPE)
1487                 {
1488                     tempCfg.validParams |= 
1489                         NWAL_SET_CONN_VALID_PARAM_ROUTE_TYPE;
1490                 }
1491                 netapip_netcpCfgBuildRoute(route,
1492                                            &tempCfg.appRxPktFlowId,
1493                                            &tempCfg.appRxPktQueue,
1494                                            &tempCfg.routeType);
1495             }
1498             //get a transaction id
1499             pTransInfo = netapip_getFreeTransInfo(n,
1500                                                   (NETAPI_PROC_GLOBAL_T *) n->proc_global,
1501                                                   &trans_id);
1502             if (!pTransInfo)
1503             {
1504                 *err =  NETAPI_ERR_BUSY;
1505                 if(p_class->classType == NETCP_CFG_CLASS_TYPE_L3_L4)
1506                     n->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_l3_classi_lock);
1507                 return -1;
1508             }
1509             pTransInfo->transType = NETAPI_NWAL_HANDLE_TRANS_PORT;
1510             pTransInfo->state = NETAPI_NWAL_HANDLE_STATE_OPEN_PENDING;
1511             pTransInfo->inUse = nwal_TRUE;
1512             pTransInfo->netapi_handle = h;
1513                 //issue request
1514             retValue = nwal_addConn(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,
1515                             trans_id,
1516                             (nwal_AppId) classHandle,
1517                             proto,
1518                             &tempCfg,
1519                             NULL,
1520                             &pTransInfo->handle);
1521             if(retValue !=  nwal_OK)
1522             {
1523                 *err = NETAPI_ERR_NWAL_ERR0;
1524                 netapip_freeTransInfo(pTransInfo);
1525                 netapip_netcpCfgDeleteClass(&netapi_get_global()->nwal_context, class_slot);
1526                 if(p_class->classType== NETCP_CFG_CLASS_TYPE_L3_L4)
1527                     n->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_l3_classi_lock);
1528                 return -1;
1529             }
1530             //wait here until its done since scheduler isn't running yet most likely..
1531            // todo:  make this handled by scheduler poll later ??
1532             if(trans_id != NWAL_TRANSID_SPIN_WAIT)
1533             {
1534                 n->nwal_local.numPendingCfg++;
1535                 while ((pTransInfo->state  !=NETAPI_NWAL_HANDLE_STATE_ERR) &&
1536                     (pTransInfo->state !=NETAPI_NWAL_HANDLE_STATE_OPEN))
1537                 {
1538                     // if response is there, then this poll squirts out in the CTl poll callback, 
1539                     // which handles the rest (including decrmenting #pending!!
1540                     nwal_pollCtl(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,NULL,NULL);
1541                 }
1542                 if (pTransInfo->state == NETAPI_NWAL_HANDLE_STATE_ERR)
1543                 {
1544                     netapip_freeTransInfo(pTransInfo);
1545                     *err = NETAPI_ERR_PA_FW;
1546                     netapip_netcpCfgDeleteClass(&netapi_get_global()->nwal_context, class_slot);
1547                     if(p_class->classType== NETCP_CFG_CLASS_TYPE_L3_L4)
1548                         n->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_l3_classi_lock);
1549                     return -1;
1550                 }
1551             }
1552             netapip_netcpCfgInsertClass(&netapi_get_global()->nwal_context, 
1553                                    class_slot,
1554                                  p_class->classType, 
1555                                 NULL,  //L2 we have
1556                                 (p_class->classType== NETCP_CFG_CLASS_TYPE_L3_L4? l3_handle : NULL),
1557                                   pTransInfo->handle,
1558                                   user_data);
1560             netapip_freeTransInfo(pTransInfo);
1561             if(p_class->classType== NETCP_CFG_CLASS_TYPE_L3_L4)
1562                 n->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_l3_classi_lock);
1563             return classHandle;
1564     } //end switch
1566 return -1;
1569 /********************************************************************
1570  * FUNCTION PURPOSE:  API to delete a preconfigured classifier
1571  ********************************************************************
1572  * DESCRIPTION:  API to delete a preconfigured classifier
1573  ********************************************************************/
1574 void netapi_netcpCfgDelClass(NETAPI_T           h,
1575                              NETCP_CFG_CLASS_T  classId,
1576                              int*               err)
1578     NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
1579     void *L4_handle = NULL;  //class handle -> L4
1580     void *L3_handle = NULL;  //class handle -> L3
1581     nwal_RetValue       retValue;
1582     NetapiNwalTransInfo_t *pTransInfo;
1583     nwal_TransID_t     trans_id;
1584     int class_slot=-1;
1586     class_slot = netapi_cfgGetMatchId(classId);
1587     L4_handle=netapip_netcpCfgGetL4Handle(&netapi_get_global()->nwal_context, class_slot);
1588     if(!L4_handle)
1589     {
1590         *err = NETAPI_ERR_BAD_INPUT; 
1591         goto ERR_netapi_netcpCfgDelClass;
1592     }
1593     L3_handle = netapip_netcpCfgGetL3Handle( &netapi_get_global()->nwal_context,
1594                                             class_slot);
1595     /* l3 handle might be NULL, depending on type of classifier */
1597     if(L3_handle)
1598     {
1599         // grab l3 lock
1600         n->spinLock.lock(&pnetapiShm->netapi_netcp_cfg_l3_classi_lock);
1601     }
1602     netapip_netcpCfgDeleteClass(
1603                         &netapi_get_global()->nwal_context,
1604                         class_slot );
1605     //get a transaction id
1606     pTransInfo = netapip_getFreeTransInfo(n,
1607                                           (NETAPI_PROC_GLOBAL_T *) n->proc_global,
1608                                           &trans_id);
1609     if (!pTransInfo)
1610     {
1611         *err =  NETAPI_ERR_BUSY; 
1612         goto ERR_netapi_netcpCfgDelClass;
1613     }
1614     pTransInfo->transType = NETAPI_NWAL_HANDLE_TRANS_PORT;
1615     pTransInfo->state = NETAPI_NWAL_HANDLE_STATE_CLOSE_PENDING;
1616     pTransInfo->inUse = nwal_TRUE;
1617     pTransInfo->netapi_handle = h;
1618     //issue request for L4
1619     retValue = nwal_delConn(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,
1620                                                  trans_id,
1621                                                  L4_handle);
1622     if(retValue !=  nwal_OK)
1623     {
1624         *err = NETAPI_ERR_NWAL_ERR0;
1625          netapip_freeTransInfo(pTransInfo);
1626          goto ERR_netapi_netcpCfgDelClass;  /* todo: what about the L3? */
1627     }
1628     //wait here until its done since scheduler isn't running yet most likely..
1629     // todo:  make this handled by scheduler poll later ??
1630     if(trans_id != NWAL_TRANSID_SPIN_WAIT)
1631     {
1632         n->nwal_local.numPendingCfg++;
1633         while ((pTransInfo->state  !=NETAPI_NWAL_HANDLE_STATE_ERR) &&
1634                 (pTransInfo->state !=NETAPI_NWAL_HANDLE_STATE_IDLE))
1635         {
1636             // if response is there, then this poll squirts out in the CTl poll callback, 
1637             // which handles the rest (including decrmenting #pending!!
1638             nwal_pollCtl(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,NULL,NULL);
1639         }
1640     }
1641     if (pTransInfo->state == NETAPI_NWAL_HANDLE_STATE_ERR)
1642     {
1643         netapip_freeTransInfo(pTransInfo);
1644         *err = NETAPI_ERR_PA_FW;
1645          goto ERR_netapi_netcpCfgDelClass;
1646     }
1647     pTransInfo->state =  NETAPI_NWAL_HANDLE_STATE_IDLE;
1648     pTransInfo->inUse = nwal_FALSE;
1650     /* delete L3 if we have to */
1651     if (cfgOkToDeleteL3ClassiHandle(h, L3_handle))
1652     {
1653         netapip_netcpCfgDelIpInternal(h,
1654                                       0,
1655                                       0,
1656                                       NULL,
1657                                       NULL,
1658                                       0,
1659                                       err,
1660                                       L3_handle,
1661                                       0);
1662     }
1663     netapip_freeTransInfo(pTransInfo);
1665 ERR_netapi_netcpCfgDelClass:
1666     if(L3_handle)
1667         n->spinLock.unlock(&pnetapiShm->netapi_netcp_cfg_l3_classi_lock);
1669     return;
1672 /********************************************************************
1673  * FUNCTION PURPOSE:  API to add a flow
1674  ********************************************************************
1675  * DESCRIPTION:  API to add a flow
1676  ********************************************************************/
1677 /*--------------flow management--------*/
1678 // ADD A Flow
1679 NETCP_CFG_FLOW_HANDLE_T netapi_netcpCfgAddFlow(NETAPI_T                 h,
1680                                                int                      n,
1681                                                Pktlib_HeapHandle        handles[],
1682                                                int                      sizes[],
1683                                                NETCP_CFG_FLOW_CONFIG_T* p_cfg,
1684                                                int*                     err )
1686     Cppi_RxFlowCfg  rxFlowCfg;
1687     Uint8           isAlloc;
1688     Qmss_QueueHnd   rxBufQ[TUNE_NETAPI_MAX_BUF_POOLS_IN_FLOW];
1689     Uint32          rxBufSize[TUNE_NETAPI_MAX_BUF_POOLS_IN_FLOW];
1690     int             i;
1691     Cppi_FlowHnd FlowHnd;
1692     int  slot;
1693     NETCP_CFG_FLOW_HANDLE_T retVal;
1694     NETAPI_HANDLE_T * pHandle = (NETAPI_HANDLE_T *) h;
1695     *err= 0;  /* ok */
1696     if (!p_cfg)
1697     {
1698         *err= NETAPI_ERR_BAD_INPUT;
1699         return NULL;
1700     }
1701     //get a slot to save new flow
1702     slot = netapip_netcpCfgFindFlowSlot(pHandle,
1703                                         &netapi_get_global()->nwal_context);
1705     if (slot<0) { *err= NETAPI_ERR_NOMEM;  return NULL; }
1707     //configure flow
1708     memset(&rxFlowCfg,0,sizeof(Cppi_RxFlowCfg));
1709     for (i = 0; i < TUNE_NETAPI_MAX_BUF_POOLS_IN_FLOW; i++)
1710     {
1711         if (i >= n)
1712         {
1713             rxBufQ[i] = 0;
1714             rxBufSize[i] = 0;
1715         }
1716         else
1717         {
1718             rxBufQ[i] =   Pktlib_getInternalHeapQueue(handles[i]);
1719             //todo: verity sizes< heapsize
1720             //todo: verify order
1721             rxBufSize[i]= sizes[i];
1722         }
1723        if (i && (rxBufQ[i] <= 0))
1724        {
1725             rxBufQ[i] = rxBufQ[i-1];
1726             rxBufSize[i] = 0;
1727        }
1728     }
1730     /* Configure Rx flow */
1731     rxFlowCfg.flowIdNum      = p_cfg->flow_index;/*CPPI_PARAM_NOT_SPECIFIED*/;
1732     rxFlowCfg.rx_dest_qnum   = netapi_pktioGetQ(p_cfg->p_dest_q);
1733     rxFlowCfg.rx_dest_qmgr   = Qmss_getQueueNumber(rxFlowCfg.rx_dest_qnum).qMgr; 
1734     rxFlowCfg.rx_sop_offset  = p_cfg->recv_offset;
1735     rxFlowCfg.rx_ps_location = Cppi_PSLoc_PS_IN_DESC;
1736     rxFlowCfg.rx_desc_type   = Cppi_DescType_HOST;
1737     rxFlowCfg.rx_error_handling = p_cfg->block;
1739     rxFlowCfg.rx_psinfo_present = 1;
1740     rxFlowCfg.rx_einfo_present  = 1;
1742     rxFlowCfg.rx_dest_tag_lo = 0;
1743     rxFlowCfg.rx_dest_tag_hi = 0;
1744     rxFlowCfg.rx_src_tag_lo  = 0;
1745     rxFlowCfg.rx_src_tag_hi  = 0;
1747     rxFlowCfg.rx_size_thresh0_en = rxBufSize[1] ? 1 : 0;
1748     rxFlowCfg.rx_size_thresh1_en = rxBufSize[2] ? 1 : 0;
1749     rxFlowCfg.rx_size_thresh2_en = rxBufSize[3] ? 1 : 0;
1751   if (p_cfg->dma_index==NETAPI_DMA_NETCP )
1752     rxFlowCfg.rx_dest_tag_lo_sel =0;
1753   else
1754     rxFlowCfg.rx_dest_tag_lo_sel = 0x4;
1755     rxFlowCfg.rx_dest_tag_hi_sel = 0;
1756     rxFlowCfg.rx_src_tag_lo_sel  = 0;
1757     rxFlowCfg.rx_src_tag_hi_sel  = 0;
1759     rxFlowCfg.rx_fdq1_qnum = rxBufQ[1];
1760     rxFlowCfg.rx_fdq1_qmgr = (rxBufQ[1] ? Qmss_getQueueNumber(rxBufQ[1]).qMgr: 0);
1761     rxFlowCfg.rx_fdq2_qnum = rxBufQ[2];
1762     rxFlowCfg.rx_fdq2_qmgr = (rxBufQ[2] ? Qmss_getQueueNumber(rxBufQ[2]).qMgr: 0);
1763     rxFlowCfg.rx_fdq3_qnum = rxBufQ[3];
1764     rxFlowCfg.rx_fdq3_qmgr = (rxBufQ[3] ? Qmss_getQueueNumber(rxBufQ[3]).qMgr: 0);
1766     rxFlowCfg.rx_size_thresh0 = rxBufSize[1] ? rxBufSize[0] : 0;
1767     rxFlowCfg.rx_size_thresh1 = rxBufSize[2] ? rxBufSize[1] : 0;
1768     rxFlowCfg.rx_size_thresh2 = rxBufSize[3] ? rxBufSize[2] : 0;
1770     rxFlowCfg.rx_fdq0_sz0_qnum = rxBufQ[0];
1771     rxFlowCfg.rx_fdq0_sz0_qmgr =  (rxBufQ[0] ? Qmss_getQueueNumber(rxBufQ[0]).qMgr: 0);
1772     rxFlowCfg.rx_fdq0_sz1_qnum = rxBufQ[1];
1773     rxFlowCfg.rx_fdq0_sz1_qmgr =  (rxBufQ[1] ? Qmss_getQueueNumber(rxBufQ[1]).qMgr:0);
1774     rxFlowCfg.rx_fdq0_sz2_qnum = rxBufQ[2];
1775     rxFlowCfg.rx_fdq0_sz2_qmgr =  (rxBufQ[2] ? Qmss_getQueueNumber(rxBufQ[2]).qMgr:0);
1776     rxFlowCfg.rx_fdq0_sz3_qnum = rxBufQ[3];
1777     rxFlowCfg.rx_fdq0_sz3_qmgr =  (rxBufQ[3] ? Qmss_getQueueNumber(rxBufQ[3]).qMgr:0);
1778     {
1779         //todo: replace this with a nwal call to get global cntx info
1780         Cppi_CpDmaInitCfg cpdmaCfg;
1781         Cppi_Handle cppiHnd;
1782         memset(&cpdmaCfg,0,sizeof(Cppi_CpDmaInitCfg));
1783         cpdmaCfg.dmaNum   = (p_cfg->dma_index==NETAPI_DMA_NETCP ) ?Cppi_CpDma_PASS_CPDMA: Cppi_CpDma_QMSS_CPDMA;
1784         cppiHnd= Cppi_open (&cpdmaCfg);
1785         if (cppiHnd == NULL)
1786         {
1787               netapip_netcpCfgDeleteFlow(&netapi_get_global()->nwal_context, slot);
1788               *err= NETAPI_ERR_NORES;
1789               return NULL;
1790         }
1791         FlowHnd = Cppi_configureRxFlow (cppiHnd, &rxFlowCfg, &isAlloc);
1792     }
1793     if (FlowHnd == NULL)
1794     {
1795         *err= NETAPI_ERR_NORES;
1796         netapip_netcpCfgDeleteFlow(&netapi_get_global()->nwal_context, slot);
1797         return (NULL);
1798     }
1800     //update slot
1801     retVal = netapip_netcpCfgInsertFlow(&netapi_get_global()->nwal_context,
1802                                         slot,
1803                                         p_cfg->dma_index,
1804                                         (void*) FlowHnd);
1805     return (retVal);
1808 /********************************************************************
1809  * FUNCTION PURPOSE:  API to delete a flow
1810  ********************************************************************
1811  * DESCRIPTION:  API to delete a flow
1812  ********************************************************************/
1813 void netapi_netcpCfgDelFlow(NETAPI_T                h,
1814                             NETCP_CFG_FLOW_HANDLE_T f,
1815                             int*                    err)
1817     int slot;
1818     void * handle;
1819     *err=0;
1820     NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
1821     /* find entry */
1822         slot = netapip_netcpCfgFindFlow(n,
1823                                         &netapi_get_global()->nwal_context,
1824                                         ((NETCP_CFG_FLOW_T *) f) ->flowid,
1825                                         ((NETCP_CFG_FLOW_T *) f) ->dma_engine,
1826                                         &handle);
1827     if (slot<0)
1828     {
1829         *err = NETAPI_ERR_BAD_INPUT;
1830         return;
1831     }
1832     if ((Cppi_closeRxFlow( (Cppi_FlowHnd) handle)) == 0)
1833     {
1834         netapip_netcpCfgDeleteFlow(&netapi_get_global()->nwal_context,
1835                                slot);
1836     }
1837     return;
1840 /******************************************************************************
1841  * FUNCTION PURPOSE:  API to configure NETCP with global rules for exception packet handling
1842  ******************************************************************************
1843  * DESCRIPTION:  API to configure NETCP with global rules for exception packet handling
1844  *****************************************************************************/
1845 NETCP_CFG_EXCEPTION_PKT_T netapi_netcpCfgExceptions(NETAPI_T                    h,
1846                                                     int                         exception_id,
1847                                                     nwal_matchAction_t          action,
1848                                                     NETCP_CFG_ROUTE_HANDLE_T    p_route)
1850     nwalCtlInfo_t   ctrl;
1851     NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
1852     nwal_RetValue retVal = 0;
1853     memset(&ctrl, 0, sizeof(nwalCtlInfo_t));
1855     if (p_route != NULL)
1856     {
1857         if((p_route->valid_params & NETCP_CFG_VALID_PARAM_ROUTE_TYPE) ==
1858             NETCP_CFG_VALID_PARAM_ROUTE_TYPE)
1859         {
1860            ctrl.validParams |= 
1861                     NWAL_CONTROL_VALID_PARAM_ROUTE_TYPE;
1862            ctrl.routeType = p_route->routeType;
1863         }
1864         netapip_netcpCfgBuildRoute(p_route,
1865                                    &ctrl.appRxPktFlowId,
1866                                    &ctrl.appRxPktQueue,
1867                                    &ctrl.routeType);
1868     }
1869     else
1870     {
1871         ctrl.appRxPktFlowId = NWAL_FLOW_NOT_SPECIFIED;
1872         ctrl.appRxPktQueue = NWAL_QUEUE_NOT_SPECIFIED;
1873     }
1875     ctrl.appId = (void*)(NETAPI_NETCP_CFG_MATCH_EXCEPTION | exception_id);
1877     ctrl.matchAction = action;
1879     if (exception_id == NETCP_CFG_ALL_EXCEPTIONS)
1880     {
1881         ctrl.pktCtl = NWAL_CTRL_CFG_ALL_EXCEPTIONS;
1882     }
1883     else
1884     {
1885             ctrl.pa_EROUTE_Id = exception_id;
1886             ctrl.pktCtl = NWAL_CTRL_CFG_SINGLE_EXCEPTION;
1887     }
1889     retVal = nwal_control(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle, &ctrl);
1892     return (NETCP_CFG_EXCEPTION_PKT_T) ctrl.appId;
1895 /*************************************************************************/
1896 /*********************************INTERNAL*******************************/
1897 /************************************************************************/
1899 /********************************************************************
1900  * FUNCTION PURPOSE:  NETAPI internal function, NETCP command reply callback
1901  ********************************************************************
1902  * DESCRIPTION:  NETAPI internal function, NETCP command reply callback
1903  ********************************************************************/
1904 void netapip_netcpCfgNWALCmdCallBack(nwal_AppId        appHandle,
1905                             uint16_t            trans_id,
1906                             nwal_RetValue     ret)
1908     NetapiNwalTransInfo_t * p_trans;
1909     NETAPI_NWAL_LOCAL_CONTEXT_T *p_local=NULL;
1911     if(trans_id == NWAL_TRANSID_SPIN_WAIT)
1912     {
1913         netapi_get_proc_global()->nwal_context.numBogusTransIds++;
1914         return;
1915     }
1917     p_trans= &netapi_get_proc_global()->nwal_context.transInfos[trans_id];
1918     p_local =&((NETAPI_HANDLE_T*) (p_trans->netapi_handle))->nwal_local;
1920     if(ret != nwal_OK)
1921     {
1922         // update error code that is fialed  in p_trans */
1923         //todo: atomic inc
1924         p_trans->state = NETAPI_NWAL_HANDLE_STATE_ERR;
1925         netapi_get_proc_global()->nwal_context.numCmdFail++;
1926     }
1927     else
1928     {
1929         //todo: atomic inc
1930         netapi_get_proc_global()->nwal_context.numCmdPass++;
1931         switch(p_trans->transType)
1932         {
1933             case NETAPI_NWAL_HANDLE_TRANS_MAC:
1934             {
1935                 if(p_trans->state == NETAPI_NWAL_HANDLE_STATE_OPEN_PENDING)
1936                 {
1937                     p_trans->state =NETAPI_NWAL_HANDLE_STATE_OPEN;
1938                 }
1939                 else if(p_trans->state == NETAPI_NWAL_HANDLE_STATE_CLOSE_PENDING)
1940                 {
1941                     p_trans->state =NETAPI_NWAL_HANDLE_STATE_IDLE;
1942                 }
1943                 break;
1944             }
1945             case NETAPI_NWAL_HANDLE_TRANS_IP:
1946             {
1947                  if(p_trans->state == NETAPI_NWAL_HANDLE_STATE_OPEN_PENDING)
1948                 {
1949                     p_trans->state = NETAPI_NWAL_HANDLE_STATE_OPEN;
1950                 }
1951                 else if(p_trans->state == NETAPI_NWAL_HANDLE_STATE_CLOSE_PENDING)
1952                 {
1953                     p_trans->state =NETAPI_NWAL_HANDLE_STATE_IDLE;
1954                 }
1955                 break;
1956             }
1957             case NETAPI_NWAL_HANDLE_TRANS_PORT:
1958             {
1959                 if(p_trans->state == NETAPI_NWAL_HANDLE_STATE_OPEN_PENDING)
1960                 {
1961                     p_trans->state =NETAPI_NWAL_HANDLE_STATE_OPEN;
1962                 }
1963                 else if(p_trans->state == NETAPI_NWAL_HANDLE_STATE_CLOSE_PENDING)
1964                 {
1965                     p_trans->state =NETAPI_NWAL_HANDLE_STATE_IDLE;
1966                 }
1967                 break;
1968             }
1969             case NETAPI_NWAL_HANDLE_TRANS_SA:
1970             {
1971                 if(p_trans->state == NETAPI_NWAL_HANDLE_STATE_OPEN_PENDING)
1972                 {
1973                     p_trans->state =NETAPI_NWAL_HANDLE_STATE_OPEN;
1974                 }
1975                 else if(p_trans->state == NETAPI_NWAL_HANDLE_STATE_CLOSE_PENDING)
1976                 {
1977                     p_trans->state =NETAPI_NWAL_HANDLE_STATE_IDLE;
1978                 }
1979                 break;
1980             }
1981             case NETAPI_NWAL_HANDLE_TRANS_SA_POLICY:
1982             {
1983                 if(p_trans->state == NETAPI_NWAL_HANDLE_STATE_OPEN_PENDING)
1984                 {
1985                     p_trans->state =NETAPI_NWAL_HANDLE_STATE_OPEN;
1986                 }
1987                 else if(p_trans->state == NETAPI_NWAL_HANDLE_STATE_CLOSE_PENDING)
1988                 {
1989                     p_trans->state =NETAPI_NWAL_HANDLE_STATE_IDLE;
1990                 }
1991                 break;
1992             }
1993             default:
1994             {
1995                 break;
1996             }
1997         }
1998     }
2000     p_local->numPendingCfg--;
2002     if(p_trans->state == NETAPI_NWAL_HANDLE_STATE_IDLE)
2003     {
2004         p_trans->inUse = nwal_FALSE;
2005     }
2009 /********************************************************************
2010  * FUNCTION PURPOSE:  NETAPI internal function, PA stats reply callback
2011  ********************************************************************
2012  * DESCRIPTION:  NETAPI internal function, PA stats reply callback
2013  ********************************************************************/
2014 void netapip_netcpCfgNWALCmdPaStatsReply(nwal_AppId        appHandle,
2015                                 nwal_TransID_t    trans_id,
2016                                 paSysStats_t      *stats)
2018     NetapiNwalTransInfo_t * p_trans;
2019     NETAPI_NWAL_LOCAL_CONTEXT_T *p_local=NULL;
2021     if(trans_id == NWAL_TRANSID_SPIN_WAIT)
2022     {
2023         netapi_get_proc_global()->nwal_context.numBogusTransIds++;
2024         return;
2025     }
2027     p_trans= &netapi_get_proc_global()->nwal_context.transInfos[trans_id];
2028     p_trans->inUse = nwal_FALSE;
2029     p_local =&((NETAPI_HANDLE_T*) (p_trans->netapi_handle))->nwal_local;
2031     //save a local copy  of some stuff*/
2032     p_local->numL2PktsRecvd=stats->classify1.nPackets;
2033     p_local->numL3PktsRecvd=stats->classify1.nIpv4Packets;
2035     //callout result to application !!
2036     if (p_local->stats_cb)
2037     {
2038         (*p_local->stats_cb)(p_trans->netapi_handle,stats);
2039     }