This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

GTPU header parsing in PA L4 classifier (C6670 Keystone I)

Hi,

Im trying to do GTPU header parsing using PA L4 classifier engine. I referred to PA unit test sample project. In this test5.c is doing the UPD and GTPU related parsing functionality.

In example code for both UDP and GTPU port config destination route info is specified "PA_DEST_HOST". I used the same configuration in my project too, and sending received packets from network to PA TX 0 queue (L2 classifier engine). As per the route info after successfull match of UPD port PA is posting the packet to HOST. GTPU parsing is not done. Then i changed route info as "pa_DEST_CONTINUE_PARSE_LUT2" for UDP port config. Then application did not receive any packet from PA.

I want to know how i can use L4 classifier for GTPU parsing after UDP header parsing. Can network packet classification done in single step i.e., continuous L2, L3 and L4 calssiffication (like Ethernet header next IP header next UPD header and final GTPU header)?

  • Hi Divya, 

    The Packet Accelerator (PA) is able to do multiple classifications of a packet, L2, L3, and L4. What happens is the packet is send to different PDSPs, and each one is assigned a different level of classification. For example, PDSP0 receives a packet, and classifies it based on L2, then sends its it to the packet streaming switch. It then goes to the next PDSP that fits it requirements (for example L3 if it has that classification). 

    So, in short, the packet should be able to do L4 , L3, and L2. I would suggest looking at the user guide example and setup in more detail. It might answer some more of your questions. (http://www.ti.com/lit/ug/sprugs4a/sprugs4a.pdf, page 11,17, 20). 

    I hope this answers your question!

    Kat Kelsch 

  •  

    Hi Kat Kelsch,

    Thanks for your reply..

    I have gone through the PA userguide, only UDP header level classiffication is give in the receive classification example on Page 20.

    And i dont have any issue till UDP header classification..

    Im receiving a network packet with Ethernet, IP(IPv4), UDP and GTPU header and want to classify GTP-U header using L4 classifier (where L4 classifier is used for TCP/UDP and GTP-U header parsing).

    Classification sequenece:

    1. Destination MAC
    2. Destination IP address
    3. Destination UDP port
    4. Destination GTPU port.

    I have few queries regarding the implementation of the above receive classification prototype.

    1) What i should specify in the route info for UDP port configureation i.e., either pa_DEST_HOST (where it routes the packet to the host) or

    pa_DEST_CONTINUE_PARSE_LUT2 (where it should route the packet to the next classifier for LTU2 parsing, but i hope this option is ruled out because L4 is the last classification engine). Is my understanding correct?

    2) If I specify destination as host for UDP port configuration, after successful calssification of UDP header, packet is forwarded to the "HOST". I want to know how Packet accelerator is aware of GTPU header of the incoming packet?

    3) Link field for both UDP and GTPU port configuration is specified as L3 handle and destination is "HOST", How a ingress packet with UPD and GTPU header is classified in L4 classifier?

    4) Is it really possible classifying UDP and GTPU header of the same packet using L4 classifier?

    Im completely stuck with the GTPU header parsing implementation using PA.

     

     

     

     

     

  • HI Divya,

    The example was meant to show you that there can be more than one classification. However, let's answer your questions:

     

    1. pa_DEST_HOST is where you will specifiy the route information if you just want to do UDP

    2. Every time a packet is receive it will go through every PDSP to check the classification to see if it fits for that PDSP's job. So, it automatically checks for you.

    3. I don't know the answer to this one, but I will get back to you and see.

    4. The GTP-U classification work should probably be forawarded to the DSP. From my understanding the PDSP isn't really able to classify it fully.

     

    I also found a forum question that may interest you, where they talk more about this issue: http://e2e.ti.com/support/dsp/c6000_multi-core_dsps/f/639/t/135555.aspx?pi24527=1

  • Hi Ti Folks,

                      Further to points by Divya, i wanted to know answers to the following

    1. If i understand, there is no L4 Handles required to fill LUT2 with L4 handles for udp ports.

    2. setting PORT_SIZE_32 and appropriate 32 bit TED-ID in pa_addPort, i quickly checked for parsing GTPU packets, i was not able to get the packets parsed by PA.

    3. Here is my configuration

    MAC rule <--> IP rule [proto is put as 0, instead of UDP,TCP] <--> GTPU rule [PORT_SIZE_32 and appropriate 32 bit TED-ID in pa_addPort] in L4

    4. please note i am using command set as null.

    5. i used the pasimpleExample_example project and modified it.

    6. project is changed to receive packets from PC/laptop.

    7.I verfied the project, with udp packet generated from pc/laptop and it worked fine [in the sense, i was able to receive the packet in the dsp (sent from external world/pc/laptop)]

    8. I modifed the code as put below

    Int ipLink[] = CONFIG_ADDPORT_IP_HANDLE_IDX;
    UInt32 ports[] = 0x11111111;//CONFIG_ADDPORT_PORTS;
    paRouteInfo_t routeInfo[] = CONFIG_ADDPORT_ROUTE;
    paCmdReply_t reply = CONFIG_PACOM_REPLY;

    Uint32 myswinfo[] = { 0x11112222, 0x33334444 };

    paReturn_t paret;
    paEntryHandle_t retHandle;
    Int htype;
    Int cmdDest;

    UInt32 psCmd = ((UInt32)(4 << 5) << 24); /* Command word - will be moved to common pa/sa file */

    for (i = 0; i < CONFIG_N_ADDPORTS; i++) {

    /* Pop a descriptor with linked buffer off the packet receive queue and use it
    * to form the command. After use it will be returned to the recycle queue */
    hd = (Cppi_HostDesc *)(((UInt32)Qmss_queuePop (gvRxBufQ)) & ~0xf);
    q.qMgr = 0;
    q.qNum = gvPaTxRecycleQ;
    Cppi_setReturnQueue (Cppi_DescType_HOST, (Cppi_Desc *)hd, q);

    csize = hd->buffLen;
    reply.replyId = CONFIG_PA_CMD_REPLY_ID + i; /* unique for each add port command */

    paret = Pa_addPort ((Pa_Handle)paInst,
    pa_LUT2_PORT_SIZE_32,
    ports[i],
    gvPaL3Handles[ipLink[i]],
    FALSE, /* New Entry required */
    pa_PARAMS_NOT_SPECIFIED, /* No queue diversion */
    &routeInfo[i],
    gvPaL4Handles[i],
    (paCmd_t)hd->buffPtr,
    &csize,
    &reply,
    &cmdDest);

    9. I generated the GTP packet with TED = 0x11111111 from pc/laptop and i was expecting it to get received at DSP [same as case of point 7 with udp packet]. however i did not receive the packet.  Let me know what things need to be taken care.

    Thanks

    RC Reddy

  • Hi, RC:

    Please refer to PA unit test test5.c for GTPU test examples. It will be much better to use local generated or canned packets to debug initial configuration problems for new use case. You can always compare your configuration with the working example at PA unit test. If you want us to check your configuration please send us the actual configuration and the input packet,

    Please see my answers in line!

    Hi Ti Folks,

                      Further to points by Divya, i wanted to know answers to the following

    1. If i understand, there is no L4 Handles required to fill LUT2 with L4 handles for udp ports.

    [Eric] The L4 Handle will be filled by the LLD. You just need to use the L4 handle to delete LUT2 entry.

    2. setting PORT_SIZE_32 and appropriate 32 bit TED-ID in pa_addPort, i quickly checked for parsing GTPU packets, i was not able to get the packets parsed by PA.

    3. Here is my configuration

    MAC rule <--> IP rule [proto is put as 0, instead of UDP,TCP] <--> GTPU rule [PORT_SIZE_32 and appropriate 32 bit TED-ID in pa_addPort] in L4

    [Eric] It looks good. There is only one LUT2 entry right?

    4. please note i am using command set as null.

    5. i used the pasimpleExample_example project and modified it.

    6. project is changed to receive packets from PC/laptop.

    7.I verfied the project, with udp packet generated from pc/laptop and it worked fine [in the sense, i was able to receive the packet in the dsp (sent from external world/pc/laptop)]

    8. I modifed the code as put below

    Int ipLink[] = CONFIG_ADDPORT_IP_HANDLE_IDX;
    UInt32 ports[] = 0x11111111;//CONFIG_ADDPORT_PORTS;
    paRouteInfo_t routeInfo[] = CONFIG_ADDPORT_ROUTE;
    paCmdReply_t reply = CONFIG_PACOM_REPLY;

    Uint32 myswinfo[] = { 0x11112222, 0x33334444 };

    paReturn_t paret;
    paEntryHandle_t retHandle;
    Int htype;
    Int cmdDest;

    UInt32 psCmd = ((UInt32)(4 << 5) << 24); /* Command word - will be moved to common pa/sa file */

    for (i = 0; i < CONFIG_N_ADDPORTS; i++) {

    /* Pop a descriptor with linked buffer off the packet receive queue and use it
    * to form the command. After use it will be returned to the recycle queue */
    hd = (Cppi_HostDesc *)(((UInt32)Qmss_queuePop (gvRxBufQ)) & ~0xf);
    q.qMgr = 0;
    q.qNum = gvPaTxRecycleQ;
    Cppi_setReturnQueue (Cppi_DescType_HOST, (Cppi_Desc *)hd, q);

    csize = hd->buffLen;
    reply.replyId = CONFIG_PA_CMD_REPLY_ID + i; /* unique for each add port command */

    paret = Pa_addPort ((Pa_Handle)paInst,
    pa_LUT2_PORT_SIZE_32,
    ports[i],
    gvPaL3Handles[ipLink[i]],
    FALSE, /* New Entry required */
    pa_PARAMS_NOT_SPECIFIED, /* No queue diversion */
    &routeInfo[i],
    gvPaL4Handles[i],
    (paCmd_t)hd->buffPtr,
    &csize,
    &reply,
    &cmdDest);

    [Eric] It looks fine!

    9. I generated the GTP packet with TED = 0x11111111 from pc/laptop and i was expecting it to get received at DSP [same as case of point 7 with udp packet]. however i did not receive the packet.  Let me know what things need to be taken care.

    [Eric] We need to see the packet. Please see whether you can receive the GTPU packet by adding a UDP entry with port number = 2152 instead.

    Thanks

    RC Reddy

  • Hi Eric,

               Thanks for your reply. I am able to receive UDP packet with port entry 2152 [i.e GTP packet i.e. port_size_16 + 2152 combination] [but this turns out to be UDP based classification], but my aim is to classify based on GTP Tunnel ID. Please let me know further. I am attaching the following with this this post

    1. the GTP packet which works with pasimple_example project. I am using a open-source packet generator tool called ostinato to generate packets and i have constructed packet which satisfies pasimple_example project and GTPU requirements. 

    0000   10 11 12 13 14 15 00 e0 a6 66 57 04 08 00 45 00  .........fW...E.
    0010   00 72 04 d2 00 00 7f 11 26 bf 9e da 6d 0a 01 02  .r......&...m...
    0020   03 04 08 68 08 68 00 5e c4 73 32 11 00 4e 00 00  ...h.h.^.s2..N..
    0030   00 01 50 01 00 00 01 80 08 00 0e 01 10 00 00 00  ..P.............
    0040   01 11 00 00 00 01 7f 00 00 00 01 80 00 06 f1 21  ...............!
    0050   c0 a8 06 02 84 00 14 80 80 21 10 02 00 00 10 81  .........!......
    0060   06 00 00 00 00 83 06 00 00 00 00 85 00 04 c0 a8  ................
    0070   06 65 85 00 04 c0 a8 06 65 87 00 04 00 0b 92 1f  .e......e.......

    also attaching .c files which i changed to make paSimpleExample project receive packet from external world. Test was run on 6678 board.

    /*
     *
     * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ 
     * 
     * 
     *  Redistribution and use in source and binary forms, with or without 
     *  modification, are permitted provided that the following conditions 
     *  are met:
     *
     *    Redistributions of source code must retain the above copyright 
     *    notice, this list of conditions and the following disclaimer.
     *
     *    Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the 
     *    documentation and/or other materials provided with the   
     *    distribution.
     *
     *    Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
     *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
     *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
     *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
     *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
     *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
     *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
     *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
    */
    
    
    
    /*  pa1.c
     *
     *  A simple example of using the PA/QM/SGMII 
     *
     *
     *  The overall system setup is shown in the following figure:                             /------------------\
     *                                                                                         | Q899             |
     *                                                                                         | Teardown         |
     *                                            /------------------\                         |------------------|
     *                                            |                  |<------------------------| Q900             |
     *                                            |  Packet Created  |-----\                   | Free descriptor  |
     *                                            |  by GEM          |     |                   |------------------|
     *                                            |                  |     |                   | Q901             |
     *                                            \------------------/     |  /------------\   | Free buffer      |-\
     *                                                                     |  |            |   |------------------| | Flow 0
     *                                                                     |  |            |   | Q902             |_|
     *                                                                     |  |            |   | PA cmd reply     | |
     *                                                                    \|/ |            |   |------------------| |
     *  /-----------------------------------------------------------------------\          |   | Q903             | |
     *  | Q640  | Q641  | Q642  | Q643  | Q644  | Q645  | Q646  | Q647  | Q648  |          |   | Pkt Send recycle | |  
     *  | PaTx0 | PaTx1 | PaTx2 | PaTx3 | PaTx4 | PaTx5 | SaTx0 | SaTx1 | SwTx0 |          |   |------------------| |   
     *  \-----------------------------------------------------------------------/          \-->| Q904             |<-  
     *                                                                     |                   | Pkt Receive      |<--\     
     *                                                                     |                   \------------------/   |      
     *                                                                     |                                          |
     *                                                                     |                                          |
     *           /------------\    /------------\    /----------------\    |                                          |
     *           |            |    |            |    |         Port 0 |    |                                          |
     *           |         /--|<---|------------|<---|----------------|<---/                                          |
     *           |  SGMII  |  |    |   EMAC     |    |  Switch        |                                               |
     *           |         \--|--->|------------|--->|-\              |                                               |
     *           |            |    |            |    | |Port 2 Port 1 |                                               |
     *           \------------/    \------------/    \----------------/                                               |
     *                                                 |                                                              |
     *                      /--------------------------/                                                              |
     *                      |                                                                                         |
     *               /------------\                                                                                   |
     *               |            |                                                                                   |
     *               |     PA     |-----------------------------------------------------------------------------------/
     *               |            |
     *               \------------/
     *
     *
     *
     *
     *  The example is meant to be the simplest possible example which demonstrates configuration of the QM, CDMA, flows
     *  PA, and switch/emac/SGMII.
     *
     *
     *  One manual entry is made in the switch tables to forward route mac address 00:01:02:03:04:aa to ports 0 and 1.
     *
     *  The PA is configured to forward packets with headers:
     *
     *          dest mac  = 10:11:12:13:14:15, ethertype = 0x0800 (ipv4)
     *          dest IP   = 1.2.3.4, protocol = any
     *          dest port = 0x0555
     *
     *      To queue 902 using flow 0.
     *
     *
     *  Flow 0 is configured to use Q901 as the free buffer queue. No size selection of source queues is made.
     *
     *
     *  See file pa1config.h for build time configuration.
     *
     */
     
    #include <xdc/runtime/System.h>
    #include <ti/drv/pa/pa.h>
    #include <ti/csl/cslr_device.h>
    #include <ti/csl/csl_psc.h>
    #include <ti/csl/csl_pscAux.h>
     
    #include "pa1.h"
    
    /*
     * Default test configuration for the silicon
     *
     * To run test at the CCS simulator
     *    cpswSimTest = 0
     *    cpswLpbkMode = CPSW_LOOPBACK_PA
     */
    #ifdef SIMULATOR_SUPPORT
    Int cpswLpbkMode = CPSW_LOOPBACK_PA;
    Int cpswSimTest = 1;
    #else 
    Int cpswLpbkMode = CPSW_LOOPBACK_NONE;//CPSW_LOOPBACK_PA;
    Int cpswSimTest = 0;
    #endif
    
    /***************************************************************************************
     * FUNCTION PURPOSE: Power up PA subsystem
     ***************************************************************************************
     * DESCRIPTION: this function powers up the PA subsystem domains
     ***************************************************************************************/
    void passPowerUp (void)
    {
    
        /* PASS power domain is turned OFF by default. It needs to be turned on before doing any 
         * PASS device register access. This not required for the simulator. */
    
        /* Set PASS Power domain to ON */        
        CSL_PSC_enablePowerDomain (CSL_PSC_PD_PASS);
    
        /* Enable the clocks for PASS modules */
        CSL_PSC_setModuleNextState (CSL_PSC_LPSC_PKTPROC, PSC_MODSTATE_ENABLE);
        CSL_PSC_setModuleNextState (CSL_PSC_LPSC_CPGMAC,  PSC_MODSTATE_ENABLE);
        CSL_PSC_setModuleNextState (CSL_PSC_LPSC_Crypto,  PSC_MODSTATE_ENABLE);
    
        /* Start the state transition */
        CSL_PSC_startStateTransition (CSL_PSC_PD_PASS);
    
        /* Wait until the state transition process is completed. */
        while (!CSL_PSC_isStateTransitionDone (CSL_PSC_PD_PASS));
    }
    
    void main (void)
    {
      TSCL = 1;  /* Init internal cycle counter */
    
      /* Power up PA sub-systems */
      if (!cpswSimTest)
      {
        passPowerUp();
      }
    
      if (setupQmCdma ())  {
        System_printf ("Function setupQmCdma failed\n");
        return;
      }
    
      if (Init_Cpsw())  {
        System_printf ("Function Init_Cpsw failed\n");
        tearDownQmCdma ();
        return;
      }
      
      if (setupPa ())  {
        System_printf ("Function setupPa failed\n");
        tearDownQmCdma ();
        return;
      }
    
    #if 0
      if (sendPacket ())  {
        System_printf ("Function sendPacket failed\n");
        tearDownQmCdma ();
        return;
      }
    #endif
    
      /* Look for the return packet */
      if (findPacket ())  {
      	getPaStats ();
        System_printf ("Function findPacket failed\n");
        return;
      }
    
      if (getPaStats ())  {
      	System_printf ("Function getPaStats failed\n");
      	return;
      }
      	
      tearDownQmCdma ();
    
      System_printf ("Test Completed successfully\n");
    
    }
    
    
    

    /*
     *
     * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ 
     * 
     * 
     *  Redistribution and use in source and binary forms, with or without 
     *  modification, are permitted provided that the following conditions 
     *  are met:
     *
     *    Redistributions of source code must retain the above copyright 
     *    notice, this list of conditions and the following disclaimer.
     *
     *    Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the 
     *    documentation and/or other materials provided with the   
     *    distribution.
     *
     *    Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
     *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
     *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
     *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
     *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
     *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
     *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
     *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
    */
    
    
    
    /* expa.c
     *
     * Example PA setup
     */
    
    #include <xdc/runtime/System.h>
    #include "pa1.h"
    #include <ti/drv/pa/pa.h>
    
    /* Firmware images */
    #include <ti/drv/pa/fw/pafw.h>
    
    #include <ti/csl/cslr_device.h>
    #include <ti/drv/cppi/cppi_drv.h>
    #include <ti/drv/cppi/cppi_desc.h>
    #include <ti/drv/qmss/qmss_drv.h>
    
    Int paDownloadFirmware (void)
    {
      Int i;
    
      Pa_resetControl (paInst, pa_STATE_RESET);
    
      /* PDPSs 0-2 use image c1 */
      for (i = 0; i < 3; i++)
        Pa_downloadImage (paInst, i, (Ptr)c1, c1Size);
    
      /* PDSP 3 uses image c2 */
      Pa_downloadImage (paInst, 3, (Ptr)c2, c2Size);
    
      /* PDSPs 4-5 use image m */
      for (i = 4; i < 6; i++)
        Pa_downloadImage (paInst, i, (Ptr)m, mSize);
    
      Pa_resetControl (paInst, pa_STATE_ENABLE);
    
      return (0);
    
    }
    
    Int setMacs (void)
    {
      Int     i, j;
      UInt16  csize;
    
      Cppi_HostDesc *hd;
      Qmss_Queue     q;
    
      paEthInfo_t   ethInfo[]   = CONFIG_ADDMAC_ETH_INFO;
      paRouteInfo_t routeInfo[] = CONFIG_ADDMAC_ROUTE;
      paRouteInfo_t nfailInfo[] = CONFIG_ADDMAC_NFAIL;
      paCmdReply_t  reply       = CONFIG_PACOM_REPLY;
      
      Uint32 myswinfo[] = { 0x11112222, 0x33334444 };
      
    
      paReturn_t       paret;
      paEntryHandle_t  retHandle;
      Int              htype;
      Int              cmdDest;
    
      UInt32      psCmd = ((UInt32)(4 << 5) << 24);  /* Command word - will be moved to common pa/sa file */
    
    
      for (i = 0; i < CONFIG_N_ADDMACS; i++)  {
    
        /* Pop a descriptor with linked buffer off the packet receive queue and use it
         * to form the command. After use it will be returned to the recycle queue */
        hd     = (Cppi_HostDesc *)(((UInt32)Qmss_queuePop (gvRxBufQ)) & ~0xf);
        q.qMgr = 0;
        q.qNum = gvPaTxRecycleQ;
        Cppi_setReturnQueue (Cppi_DescType_HOST, (Cppi_Desc *)hd, q);
    
        csize = hd->buffLen;
        reply.replyId = CONFIG_PA_CMD_REPLY_ID + i;  /* unique for each add mac command */
    
        paret = Pa_addMac  ((Pa_Handle)paInst,
                            pa_LUT1_INDEX_NOT_SPECIFIED,
                            &ethInfo[i],
                            &routeInfo[i],
                            &nfailInfo[i],
                            &gvPaL2Handles[i],
                            (paCmd_t) hd->buffPtr,
                            &csize,
                            &reply,
                            &cmdDest);
        
        /* This sets the extended info for descriptors, and this is required so PS info
         * goes to the right spot */                   
        Cppi_setSoftwareInfo (Cppi_DescType_HOST, (Cppi_Desc *)hd, (UInt8 *)myswinfo);
    
        /* Set the buffer length to the size used. It will be restored when the descriptor
         * is returned */
        Cppi_setPacketLen (Cppi_DescType_HOST, (Cppi_Desc *)hd, csize);
        hd->buffLen = csize;
        
        Cppi_linkNextBD (Cppi_DescType_HOST, (Cppi_Desc *)hd, NULL);
        
    
        /* Mark the packet as a configuration packet */
        Cppi_setPSData (Cppi_DescType_HOST, (Cppi_Desc *)hd, (UInt8 *)&psCmd, 4);
           
    
        if (paret != pa_OK)  {
          System_printf ("function setMacs: call to Pa_addMac returned error code %d\n", paret);
          return (-1);
        }
        
        /* Send the command to the PA and wait for the return */
        Qmss_queuePush (gvTxQ[cmdDest - pa_CMD_TX_DEST_0], (Uint32 *)gAddr((UInt32)hd), hd->buffLen, CONFIG_SIZE_DESC, Qmss_Location_TAIL);
    
        /* wait for return buffer */
        for (j = 0; j < 100; j++)  {
          CycleDelay (1000);
    
          if (Qmss_getQueueEntryCount (gvPaTxRecycleQ) > 0)   {
            hd = (Cppi_HostDesc *)(((UInt32)Qmss_queuePop (gvPaTxRecycleQ)) & ~0xf);
            /* Reset the buffer lenght and put the descriptor back on the free queue */      
            hd->buffLen = hd->origBufferLen;
            Qmss_queuePush (gvRxBufQ, hd, hd->buffLen, CONFIG_SIZE_DESC, Qmss_Location_TAIL);
            break;
          }  
        }      
        
        if (j == 100)  {
          System_printf ("function setMacs: Timeout waiting for return buffer from complete queue to Pa_addMac command\n");
          return (-1);
        }
        
        /* Wait for the PA to return a response */
        for (j = 0; j < 100; j++)  {
          CycleDelay (1000);
    
          if (Qmss_getQueueEntryCount (gvPaRespQ) > 0)   {
            hd = (Cppi_HostDesc *)(((UInt32)Qmss_queuePop (gvPaRespQ)) & ~0xf);
            if (hd->softwareInfo0 != reply.replyId)  {
              System_printf ("function setMacs: Found an entry in PA reply queue with swinfo0 = 0x%08x, expected 0x%08x\n", 
                       hd->softwareInfo0, reply.replyId);
              hd->buffLen = hd->origBufferLen;
              Qmss_queuePush (gvRxBufQ, hd, hd->buffLen, CONFIG_SIZE_DESC, Qmss_Location_TAIL);
              
              return (-1);
            }
    
            paret = Pa_forwardResult ((Pa_Handle)paInst, (void *)hd->buffPtr, &retHandle, &htype, &cmdDest);
            
            /* Reset the buffer lenght and put the descriptor back on the free queue */
            hd->buffLen = hd->origBufferLen;
            Qmss_queuePush (gvRxBufQ, hd, hd->buffLen, CONFIG_SIZE_DESC, Qmss_Location_TAIL);
    
            if (paret != pa_OK)  {
              System_printf ("function setMacs: PA sub-system rejected Pa_addMac command\n");
              return (-1);
            }
    
            break;
          }
        }
    
        if (j == 100)  {
          System_printf ("function setMacs: Timeout waiting for reply from PA to Pa_addMac command\n");
          return (-1);
        }
    
      }
    
      return (0);
    
    }
            
    /* Configure IP addresses */
    Int setIps (void)
    {
      Int     i, j;
      Uint16  csize;
    
      Cppi_HostDesc *hd;
      Qmss_Queue     q;
     
      paIpInfo_t    ipInfo[]    = CONFIG_ADDIP_IP_INFO;
      Int           macLink[]   = CONFIG_ADDIP_MAC_HANDLE_IDX;
      paRouteInfo_t routeInfo[] = CONFIG_ADDIP_ROUTE;
      paRouteInfo_t nfailInfo[] = CONFIG_ADDIP_NFAIL;
      paCmdReply_t  reply       = CONFIG_PACOM_REPLY;
    
      paReturn_t      paret;
      paEntryHandle_t retHandle;
      Int             htype;
      Int             cmdDest;
      
      
      Uint32 myswinfo[] = { 0x11112222, 0x33334444 };
    
      UInt32      psCmd = ((UInt32)(4 << 5) << 24);  /* Command word - will be moved to common pa/sa file */
    
      for (i = 0; i < CONFIG_N_ADDIPS; i++)  {
    
        /* Pop a descriptor with linked buffer off the packet receive queue and use it
         * to form the command. After use it will be returned to the recycle queue */
        hd     = (Cppi_HostDesc *)(((UInt32)Qmss_queuePop (gvRxBufQ)) & ~0xf);
        q.qMgr = 0;
        q.qNum = gvPaTxRecycleQ;
        Cppi_setReturnQueue (Cppi_DescType_HOST, (Cppi_Desc *)hd, q);
    
        csize = hd->buffLen;
        reply.replyId = CONFIG_PA_CMD_REPLY_ID + i;  /* unique for each add ip command */
    
        paret = Pa_addIp ((Pa_Handle)paInst,
                          pa_LUT_INST_NOT_SPECIFIED,
                          pa_LUT1_INDEX_NOT_SPECIFIED,
                          &ipInfo[i],
                          gvPaL2Handles[macLink[i]],
                          &routeInfo[i],
                          &nfailInfo[i],
                          &gvPaL3Handles[i],
                          (paCmd_t)hd->buffPtr,
                          &csize,
                          &reply,
                          &cmdDest);
    
        /* Set the buffer length to the size used. It will be restored when the descriptor
         * is returned */
        Cppi_setPacketLen (Cppi_DescType_HOST, (Cppi_Desc *)hd, csize);
        hd->buffLen = csize;
        
        /* This sets the extended info for descriptors, and this is required so PS info
         * goes to the right spot */                   
        Cppi_setSoftwareInfo (Cppi_DescType_HOST, (Cppi_Desc *)hd, (UInt8 *)myswinfo);
        
    
        /* Mark the packet as a configuration packet */
        Cppi_setPSData (Cppi_DescType_HOST, (Cppi_Desc *)hd, (UInt8 *)&psCmd, sizeof(psCmd));
        
        Cppi_linkNextBD (Cppi_DescType_HOST, (Cppi_Desc *)hd, NULL);
    
        if (paret != pa_OK)  {
          System_printf ("function setIps: Pa_addIp returned with error code %d\n", paret);
          return (-1);
        }
    
        /* Send the command to the PA and wait for the return */
        Qmss_queuePush (gvTxQ[cmdDest - pa_CMD_TX_DEST_0], (Uint32 *)gAddr((UInt32)hd), hd->buffLen, CONFIG_SIZE_DESC, Qmss_Location_TAIL);
        
        
        /* wait for return buffer */
        for (j = 0; j < 100; j++)  {
          CycleDelay (1000);
    
          if (Qmss_getQueueEntryCount (gvPaTxRecycleQ) > 0)   {
            hd = (Cppi_HostDesc *)(((UInt32)Qmss_queuePop (gvPaTxRecycleQ)) & ~0xf);
            /* Reset the buffer lenght and put the descriptor back on the free queue */      
            hd->buffLen = hd->origBufferLen;
            Qmss_queuePush (gvRxBufQ, hd, hd->buffLen, CONFIG_SIZE_DESC, Qmss_Location_TAIL);
            break;
          }  
        }      
        
        if (j == 100)  {
          System_printf ("function setIps: Timeout waiting for return buffer from complete queue to Pa_addIp command\n");
          return (-1);
        }
        
       
        /* Wait for the PA to return a response */
        for (j = 0; j < 100; j++)  {
          CycleDelay (1000);
    
          if (Qmss_getQueueEntryCount (gvPaRespQ) > 0)   {
            hd = (Cppi_HostDesc *)(((UInt32)Qmss_queuePop (gvPaRespQ)) & ~0xf);
    
            if (hd->softwareInfo0 != reply.replyId)  {
              System_printf ("function setIps: Found an entry in PA reply queue with swinfo0 = 0x%08x, expected 0x%08x\n", 
                       hd->softwareInfo0, reply.replyId);
              hd->buffLen = hd->origBufferLen;
              Qmss_queuePush (gvRxBufQ, hd, hd->buffLen, CONFIG_SIZE_DESC, Qmss_Location_TAIL);
              return (-1);
            }
    
            paret = Pa_forwardResult ((Pa_Handle)paInst, (void *)hd->buffPtr, &retHandle, &htype, &cmdDest);
            
            /* Reset the buffer lenght and put the descriptor back on the free queue */      
            hd->buffLen = hd->origBufferLen;
            Qmss_queuePush (gvRxBufQ, hd, hd->buffLen, CONFIG_SIZE_DESC, Qmss_Location_TAIL);
    
            if (paret != pa_OK)  {
              System_printf ("function setIps: PA sub-system rejected Pa_addIp command\n");
              return (-1);
            }
    
            break;
          }
        }
    
        if (j == 100)  {
          System_printf ("function setIps: Timeout waiting for reply from PA to Pa_addIp command\n");
          return (-1);
        }
    
      }
    
      return (0);
    
    }
    
    
    Int setPorts (void)
    {
      Int     i, j;
      Uint16  csize;
    
      Cppi_HostDesc *hd;
      Qmss_Queue     q;
    
      Int           ipLink[]    = CONFIG_ADDPORT_IP_HANDLE_IDX;
      UInt32        ports[]     = 0x11111111;//CONFIG_ADDPORT_PORTS;
      paRouteInfo_t routeInfo[] = CONFIG_ADDPORT_ROUTE;
      paCmdReply_t  reply       = CONFIG_PACOM_REPLY;
      
      Uint32 myswinfo[] = { 0x11112222, 0x33334444 };
    
      paReturn_t       paret;
      paEntryHandle_t  retHandle;
      Int              htype;
      Int              cmdDest;
    
      UInt32      psCmd = ((UInt32)(4 << 5) << 24);  /* Command word - will be moved to common pa/sa file */
    
      for (i = 0; i < CONFIG_N_ADDPORTS; i++)  {
    
        /* Pop a descriptor with linked buffer off the packet receive queue and use it
         * to form the command. After use it will be returned to the recycle queue */
        hd     = (Cppi_HostDesc *)(((UInt32)Qmss_queuePop (gvRxBufQ)) & ~0xf);
        q.qMgr = 0;
        q.qNum = gvPaTxRecycleQ;
        Cppi_setReturnQueue (Cppi_DescType_HOST, (Cppi_Desc *)hd, q);
    
        csize = hd->buffLen;
        reply.replyId = CONFIG_PA_CMD_REPLY_ID + i;  /* unique for each add port command */
    
        paret = Pa_addPort ((Pa_Handle)paInst,
                            pa_LUT2_PORT_SIZE_32,
                            ports[i],
                            gvPaL3Handles[ipLink[i]],
                            FALSE,                      /* New Entry required */
                            pa_PARAMS_NOT_SPECIFIED,    /* No queue diversion */
                            &routeInfo[i],
                            gvPaL4Handles[i],
                            (paCmd_t)hd->buffPtr,
                            &csize,
                            &reply,
                            &cmdDest);
    
        /* Set the buffer length to the size used. It will be restored when the descriptor
         * is returned */
        Cppi_setPacketLen (Cppi_DescType_HOST, (Cppi_Desc *)hd, csize);
        hd->buffLen = csize;
        
        /* This sets the extended info for descriptors, and this is required so PS info
         * goes to the right spot */                   
        Cppi_setSoftwareInfo (Cppi_DescType_HOST, (Cppi_Desc *)hd, (UInt8 *)myswinfo);
     
    
        /* Mark the packet as a configuration packet */
        Cppi_setPSData (Cppi_DescType_HOST, (Cppi_Desc *)hd, (UInt8 *)&psCmd, sizeof(psCmd));
        
        Cppi_linkNextBD (Cppi_DescType_HOST, (Cppi_Desc *)hd, NULL);
    
        if (paret != pa_OK)  {
          System_printf ("function setPorts: Pa_addPort returned with error code %d\n", paret);
          return (-1);
        }
        
    
        /* Send the command to the PA and wait for the return */
        Qmss_queuePush (gvTxQ[cmdDest - pa_CMD_TX_DEST_0], (UInt32 *)gAddr((UInt32)hd), hd->buffLen, CONFIG_SIZE_DESC, Qmss_Location_TAIL);
    
        /* wait for return buffer */
        for (j = 0; j < 100; j++)  {
          CycleDelay (1000);
    
          if (Qmss_getQueueEntryCount (gvPaTxRecycleQ) > 0)   {
            hd = (Cppi_HostDesc *)(((UInt32)Qmss_queuePop (gvPaTxRecycleQ)) & ~0xf);
            /* Reset the buffer lenght and put the descriptor back on the free queue */      
            hd->buffLen = hd->origBufferLen;
            Qmss_queuePush (gvRxBufQ, hd, hd->buffLen, CONFIG_SIZE_DESC, Qmss_Location_TAIL);
            break;
          }  
        }      
        
        if (j == 100)  {
          System_printf ("function setPorts: Timeout waiting for return buffer from complete queue to Pa_addIp command\n");
          return (-1);
        }
        
        /* Wait for the PA to return a response */
        for (j = 0; j < 100; j++)  {
          CycleDelay (1000);
    
          if (Qmss_getQueueEntryCount (gvPaRespQ) > 0)   {
            hd = (Cppi_HostDesc *)(((UInt32)Qmss_queuePop (gvPaRespQ)) & ~0xf);
    
            if (hd->softwareInfo0 != reply.replyId)  {
              System_printf ("function setIps: Found an entry in PA reply queue with swinfo0 = 0x%08x, expected 0x%08x\n", 
                       hd->softwareInfo0, reply.replyId);
              hd->buffLen = hd->origBufferLen;
              Qmss_queuePush (gvRxBufQ, hd, hd->buffLen, CONFIG_SIZE_DESC, Qmss_Location_TAIL);
              
              return (-1);
            }
    
            paret = Pa_forwardResult ((Pa_Handle)paInst, (void *)hd->buffPtr, &retHandle, &htype, &cmdDest);
            
            /* Reset the buffer lenght and put the descriptor back on the free queue */      
            hd->buffLen = hd->origBufferLen;
            Qmss_queuePush (gvRxBufQ, hd, hd->buffLen, CONFIG_SIZE_DESC, Qmss_Location_TAIL);
            
    
            if (paret != pa_OK)  {
              System_printf ("function setPorts: PA sub-system rejected Pa_addPort command\n");
              return (-1);
            }
    
            break;
          }
        }
    
        if (j == 100)  {
          System_printf ("function setPorts: Timeout waiting for reply from PA to Pa_addPort command\n");
          return (-1);
        }
    
      }
    
      return (0);
    
    }
                           
    
    
    Int setupPa (void)
    {
      paSizeInfo_t  paSize;
      paConfig_t    paCfg;
      int           ret;
      int           sizes[pa_N_BUFS];
      int           aligns[pa_N_BUFS];
      void*         bases[pa_N_BUFS];
      
      memset(&paSize, 0, sizeof(paSizeInfo_t));
      memset(&paCfg, 0, sizeof(paConfig_t));
    
      paSize.nMaxL2 = CONFIG_MAX_L2_HANDLES;
      paSize.nMaxL3 = CONFIG_MAX_L3_HANDLES;
      paSize.nUsrStats = 0;
      
      
      ret = Pa_getBufferReq(&paSize, sizes, aligns);
    
      if (ret != pa_OK)  {
        System_printf ("setupPa: Pa_getBufferReq() return with error code %d\n", ret);
        return (-1);
      }
      
      /* The first buffer is used as the instance buffer */
      if ((Uint32)paInstBuf & (aligns[0] - 1))  {
        System_printf ("setupPa: Pa_getBufferReq requires %d alignment for instance buffer, but address is 0x%08x\n", aligns[0], (Uint32)paInstBuf);
        return (-1);
      }
    
      if (sizeof(paInstBuf) < sizes[0])  {
        System_printf ("setupPa: Pa_getBufferReq requires size %d for instance buffer, have only %d\n", sizes[0], sizeof(paInstBuf));
        return (-1);
      }
    
      bases[0] = (void *)paInstBuf;
    
      /* The second buffer is the L2 table */
      if ((Uint32)memL2Ram & (aligns[1] - 1))  {
        System_printf ("setupPa: Pa_getBufferReq requires %d alignment for buffer 1, but address is 0x%08x\n", aligns[1], (Uint32)memL2Ram);
        return (-1);
      }
    
      if (sizeof(memL2Ram) <  sizes[1])  {
        System_printf ("setupPa: Pa_getBufferReq requires %d bytes for buffer 1, have only %d\n", sizes[1], sizeof(memL2Ram));
        return (-1);
      }
    
      bases[1] = (void *)memL2Ram;
    
      /* The third buffer is the L3 table */
      if ((Uint32)memL3Ram & (aligns[2] - 1))  {
        System_printf ("setupPa: Pa_getBufferReq requires %d alignment for buffer 1, but address is 0x%08x\n", aligns[2], (Uint32)memL3Ram);
        return (-1);
      }
    
      if (sizeof(memL3Ram) <  sizes[2])  {
        System_printf ("setupPa: Pa_getBufferReq requires %d bytes for buffer 1, have only %d\n", sizes[2], sizeof(memL3Ram));
        return (-1);
      }
    
      bases[2] = (void *)memL3Ram;
      
      /* There is no User-defined statistics */
      bases[3] = 0;
      
      paCfg.initTable = TRUE;
      paCfg.initDefaultRoute = TRUE;
      paCfg.baseAddr = CSL_PA_SS_CFG_REGS;
      paCfg.sizeCfg = &paSize;
      
      ret = Pa_create (&paCfg, bases, &paInst);
      if (ret != pa_OK)  {
        System_printf ("setupPa: Pa_create returned with error code %d\n", ret);
        return (-1);
      }
      
      /* Download the firmware */
      if (paDownloadFirmware ())
        return (-1);
    
    
      /* Add the MAC addresses */
      if (setMacs ())
        return (-1);
    
      /* Add the IP addresses */
      if (setIps())
        return (-1);
    
      /* Add the ports (TCP/UDP) */
      if (setPorts())
        return (-1);
    
      return (0);
    
    }
    
    
    
    
    
    
    
    
    
    
    
    
    

    This packet works with paSimpleExample project if 

    1. UDP port entry is created with PORT_SIZE_16 and udp port as 2152.

    I looked at the example [test 5] and following it, i see it no different from what i am doing. one step i might be missing is for every GTP entry should there be a corresponding UDP [2152] entry ?. Let me re-visit the example [test 5] and put back my output. 

    Thanks

    RC Reddy

  • Hi, RC:

    The PASS will perform GTP-U (message type = 0xff = 255) classification based on Tunnel-ID and it also detect the following message type and route the packets through excpetion routes:

    /**
     *  @def pa_EROUTE_GTPU_MESSAGE_TYPE_1
     *       GTP-U PING Request packet
     */
    #define pa_EROUTE_GTPU_MESSAGE_TYPE_1      16

    /**
     *  @def pa_EROUTE_GTPU_MESSAGE_TYPE_2
     *       GTP-U PING Response packet
     */
    #define pa_EROUTE_GTPU_MESSAGE_TYPE_2      17

    /**
     *  @def pa_EROUTE_GTPU_MESSAGE_TYPE_26
     *       GTP-U Error Indication packet
     */
    #define pa_EROUTE_GTPU_MESSAGE_TYPE_26     18

    /**
     *  @def pa_EROUTE_GTPU_MESSAGE_TYPE_31
     *       GTP-U Supported Header Notification packet
     */
    #define pa_EROUTE_GTPU_MESSAGE_TYPE_31     19

    /**
     *  @def pa_EROUTE_GTPU_MESSAGE_TYPE_254
     *       GTP-U End Markr packet
     */
    #define pa_EROUTE_GTPU_MESSAGE_TYPE_254    20

    /**
     *  @def pa_EROUTE_GTPU_FAIL
     *       Packet failed due to GTPU parsing error or unsupporte dmessage types
     */
    #define pa_EROUTE_GTPU_FAIL                21

     All other GTP packets will be considered as error and be routed through pa_EROUTE_GTPU_FAIL.

    The GTP packet that you sent is with message type = 0x11 = 17.

    I ask you to add UDP port = 2152 just to verify whether the GTP packet contains correct UDP header.  The PA LLD will disable GTPU parsing if LUT2 entry with port number 2152 is added. In this case, the application intends to receive and process GTP packets.

    Best regards,

    Eric

     

     

     

     

  • Hi ,

               Thanks for quick answer. That change of 0xff worked and PASS did classify the gtp packet. I learnt it hardway [ i debugged it, but could not pick the issue] [you identified the issue in the packet][i was only thining of GTP packet as udp packet with destination port of 2152] of GTP classification. Thanks again.

    Regards

    RC Reddy

  • Hi Eric/RC,

    I read the conversation and I've gone through the code you shared. I have small doubt regarding the GTP packet type.

    During the PA configuration we no where mentioned anything regarding the GTPU packet type. If my understanding is correct,

    L4 classifier will get the packet type info from the received packet and at given point of time L4 classifier should have only one entry (either UPD

    port or GTPU port). Am I correct?

    If this is the case, how did PA L4 calssifier routed the GTPU packet of type 0xff and not for 0x11?

    Please help me in understanding what exactly needs to be tacken for enabling GTPU parsing at L4 classifier..

    Regards,

    R. Divya.

  • want to add one more point to my previous post..

    what do you mean exactly by expectional route?

    Regards,

    R. Divya.

  • Hi, Divya:

    The PASS will parse the protocol headers of the incoming packet in order to classify that packet based on the protocol specific parameters such as IP address or UDP destination port. For LUT1 (L2/L3), PASS supports MAC/IP/IPSEC, for LUT2 (L4), PASS supports UDP/TCP only. It also support limited GTP (L5) parsing in order to support the fully-offloaded 3GPP Air-Ciphering GTP-U traffic.

    For GTP-U parsing, the PASS will recognize that there is a GTP header when it processes the UDP header and find out the destination port is equal to 2152 and then it will continue pasring operation to process the GTP header, the GTP parsing is based on its message type, as I mentioned in the other thread. Please note that PASS only supports GTP V1.
    If the message type is 255, the PASS will perform LUT2 lookup based on the 32-bit tunnel ID, other wise, it will route the packet through the various exception routes.

    Please refer to PA LLD doxygen or pa.h for more information regarding exception route. Here is a short summary.

     *  @details  The exception route defines the global routing information when the exception condition such
     *            as LUT1 lookup failure, packet parsing failure, broadcast packet detection and etc. Multiple
     *            exception routes can be configured through @ref Pa_configExceptionRoute. All the exception
     *            routes are disabled by default.

    Best regards,

    Eric

     

  •  

    Hi Eric,

    Thanks for your reply. And one small clarification. Is my below understanding correct w.r.t GTPU classification?

    • LUT2 L4 classifier should be configured for both UDP port (16 bit) and GTPU port (32 bit).
    • Right now GTPU parsing can only be done for GTPU v1 (Type 255) message.
    • If the above two steps are taken care, PASS should be able to route the successfully classified packets to the configured destination queue.

    Regards,

    R. Divya.

  • Hi, Diyya:

    Please see my answers below:

    • LUT2 L4 classifier should be configured for both UDP port (16 bit) and GTPU port (32 bit).

            I am not sure what you really mean, but let me try to answer your question in two different ways.
            To enable GTP-U parsing, you do  not need to add UDP port 2152 as an entry, The PASS will perform GTP-U parsing and classification when UDP destination port 2152 is detected. If L4 16-bit port (2152) entry is added, then PASS will disable GTP-U operation until all those entries are deleted.

             The LUT2 L4 classifier can handle both 16-bit and 32-bit entries simultaneously, however, you need to make sure the most significant 8-bit 0f GTP-U tunnel ID is not zero so that the 32-bit entry will not collide with 16-bit entry with link.

    • Right now GTPU parsing can only be done for GTPU v1 (Type 255) message.

            The GTP parsing can be done for GTP v1, the tunnel ID based classification will be done for message type 255,  the exception routes are applicable to some other message types.

    • If the above two steps are taken care, PASS should be able to route the successfully classified packets to the configured destination queue.

            Yes.

    Best regards,

    Eric