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.

How to make GBE as DHCP server using NDK?

Expert 2985 points
Other Parts Discussed in Thread: TMS320C6670

Hi all,

Software environment: C6670, CCSv5.3, MCSDK 2.1.2.6, MCSDK PDK TMS320C6670 1.1.2.6, NDK 2.21.1.38.

On my custom board, the C6670 is connected to two PHYs(88E1111) using SGMII0 and SGMII1 ports respectively. The followed figure shows some details of my board.

What I want to implement is that using the C6670 as a DHCP server and when I connect two PCs these two PCs can achieve their own IP address and DSP Core0 works as another DHCP client.

I mean three parts are connected to the GbE switch. One is DSP Core0 and the other two are PCs. GbE switch is used as a router which has a DHCP server can assign IP addresses to the DSP Core0 and the two PCs.

How can I implement this using NDK?

I had changed the codes like this attached file 

#include <stdio.h>
#include <ti/ndk/inc/netmain.h>
#include <ti/sysbios/BIOS.h>
#include <xdc/runtime/System.h>
#include "ti/platform/platform.h"
#include "ti/platform/resource_mgr.h"

char *VerStr = "\nWavepop K7_C6670 Board TCP/IP Stack Test Application\n\n";

// Our NETCTRL callback functions
static void   NetworkOpen();
static void   NetworkClose();
static void   NetworkIPAddr( IPN IPAddr, uint IfIdx, uint fAdd );

// Fun reporting function
static void   ServiceReport( uint Item, uint Status, uint Report, HANDLE hCfgEntry );

// External references
extern int dtask_udp_hello();

//---------------------------------------------------------------------------
// Configuration
//
char *HostName    = "tidsp";
char *LocalIPAddr = "192.168.1.100";
char *LocalIPMask = "255.255.255.0";    // Not used when using DHCP
char *GatewayIP   = "192.168.2.101";    // Not used when using DHCP
char *DomainName  = "demo.net";         // Not used when using DHCP
char *DNSServer   = "0.0.0.0";          // Used when set to anything but zero

// Simulator EMAC Switch does not handle ALE_LEARN mode, so please configure the
// MAC address of the PC where you want to launch the webpages and initiate PING to NDK */

Uint8 clientMACAddress [6] = {0x5C, 0x26, 0x0A, 0x69, 0x44, 0x0B}; /* MAC address for my PC */
void EVM_init()
{
	platform_init_flags   sFlags;
	platform_init_config  sConfig;

	memset( (void *) &sFlags,  0, sizeof(platform_init_flags));
	memset( (void *) &sConfig, 0, sizeof(platform_init_config));

    sFlags.pll  = 0; /* PLLs for clocking    */
    sFlags.ddr  = 0;     /* External memory    */
    sFlags.tcsl = 1; /* Time stamp counter   */
    sFlags.phy  = 1; /* Ethernet       */
    sFlags.ecc  = 0; /* Memory ECC       */
    sConfig.pllm = 0;  /* Use libraries default clock divisor */

    platform_init(&sFlags, &sConfig);
}

//---------------------------------------------------------------------
// Main Entry Point
//---------------------------------------------------------------------
int main()
{
 /* Start the BIOS 6 Scheduler */
 BIOS_start ();
}

// Main Thread
int StackTest()
{
    int             rc;
    int        i;
    HANDLE          hCfg;
    QMSS_CFG_T      qmss_cfg;
    CPPI_CFG_T      cppi_cfg;

    /* Initialize the components required to run this application:
     *  (1) QMSS
     *  (2) CPPI
     *  (3) Packet Accelerator
     */
    /* Initialize QMSS */
    if (platform_get_coreid() == 0)
    {
        qmss_cfg.master_core        = 1;
    }
    else
    {
        qmss_cfg.master_core        = 0;
    }
    qmss_cfg.max_num_desc       = MAX_NUM_DESC;
    qmss_cfg.desc_size          = MAX_DESC_SIZE;
    qmss_cfg.mem_region         = Qmss_MemRegion_MEMORY_REGION0;
    if (res_mgr_init_qmss (&qmss_cfg) != 0)
    {
        System_printf ("Failed to initialize the QMSS subsystem \n");
        goto main_exit;
    }
    else
    {
     System_printf ("QMSS successfully initialized \n");
    }

    /* Initialize CPPI */
    if (platform_get_coreid() == 0)
    {
        cppi_cfg.master_core        = 1;
    }
    else
    {
        cppi_cfg.master_core        = 0;
    }
    cppi_cfg.dma_num            = Cppi_CpDma_PASS_CPDMA;
    cppi_cfg.num_tx_queues      = NUM_PA_TX_QUEUES;
    cppi_cfg.num_rx_channels    = NUM_PA_RX_CHANNELS;
    if (res_mgr_init_cppi (&cppi_cfg) != 0)
    {
        System_printf ("Failed to initialize CPPI subsystem \n");
        goto main_exit;
    }
    else
    {
    	System_printf ("CPPI successfully initialized \n");
    }


    if (res_mgr_init_pass()!= 0) {
        System_printf ("Failed to initialize the Packet Accelerator \n");
        goto main_exit;
    }
    else
    {
    	System_printf ("PA successfully initialized \n");
    }

    //
    // THIS MUST BE THE ABSOLUTE FIRST THING DONE IN AN APPLICATION!!
    //
    rc = NC_SystemOpen( NC_PRIORITY_LOW, NC_OPMODE_INTERRUPT );
    if( rc )
    {
        System_printf("NC_SystemOpen Failed (%d)\n",rc);
        for(;;);
    }

    // Print out our banner
    System_printf(VerStr);

    //
    // Create and build the system configuration from scratch.
    //

    // Create a new configuration
    hCfg = CfgNew();
    if( !hCfg )
    {
        System_printf("Unable to create configuration\n");
        goto main_exit;
    }

    // We better validate the length of the supplied names
    if( strlen( DomainName ) >= CFG_DOMAIN_MAX ||
        strlen( HostName ) >= CFG_HOSTNAME_MAX )
    {
        System_printf("Names too long\n");
        goto main_exit;
    }

    // Add our global hostname to hCfg (to be claimed in all connected domains)
    CfgAddEntry( hCfg, CFGTAG_SYSINFO, CFGITEM_DHCP_HOSTNAME, 0,
                 strlen(HostName), (UINT8 *)HostName, 0 );

    // If the IP address is specified, manually configure IP and Gateway
    if (0)
    {
        CI_IPNET NA;
        CI_ROUTE RT;
        IPN      IPTmp;
        int		return_value = 0;

        // Setup manual IP address
        bzero( &NA, sizeof(NA) );
        NA.IPAddr  = inet_addr(LocalIPAddr);
        NA.IPMask  = inet_addr(LocalIPMask);
        strcpy( NA.Domain, DomainName );
        NA.NetType = 0;

        // Add the address to interface 1
        return_value = CfgAddEntry( hCfg, CFGTAG_IPNET, 1, 0,
                           sizeof(CI_IPNET), (UINT8 *)&NA, 0 );

        // Add the default gateway. Since it is the default, the
        // destination address and mask are both zero (we go ahead
        // and show the assignment for clarity).
        bzero( &RT, sizeof(RT) );
        RT.IPDestAddr = 0;
        RT.IPDestMask = 0;
        RT.IPGateAddr = inet_addr(GatewayIP);

        // Add the route
        CfgAddEntry( hCfg, CFGTAG_ROUTE, 0, 0,
                           sizeof(CI_ROUTE), (UINT8 *)&RT, 0 );

        // Manually add the DNS server when specified
        IPTmp = inet_addr(DNSServer);
        if( IPTmp )
            CfgAddEntry( hCfg, CFGTAG_SYSINFO, CFGITEM_DHCP_DOMAINNAMESERVER,
                         0, sizeof(IPTmp), (UINT8 *)&IPTmp, 0 );
    }
    // Else we specify DHCP
    else if(0)
    {
        CI_SERVICE_DHCPC dhcpc;

        // Specify DHCP Service on IF-1
        bzero( &dhcpc, sizeof(dhcpc) );
        dhcpc.cisargs.Mode   = CIS_FLG_IFIDXVALID;
        dhcpc.cisargs.IfIdx  = 1;
        dhcpc.cisargs.pCbSrv = &ServiceReport;
        CfgAddEntry( hCfg, CFGTAG_SERVICE, CFGITEM_SERVICE_DHCPCLIENT, 0,
                     sizeof(dhcpc), (UINT8 *)&dhcpc, 0 );
    }
    else
    {
    	printf("DHCP Server start...\n");

    	CI_SERVICE_DHCPS dhcps;
    	CI_ROUTE RT;

        // Specify DHCP Server Service on IF-1
        bzero( &dhcps, sizeof(dhcps) );
        dhcps.cisargs.Mode   	= CIS_FLG_IFIDXVALID;
        dhcps.cisargs.IfIdx  	= 1;
        dhcps.cisargs.pCbSrv 	= &ServiceReport;
        dhcps.param.Flags		= DHCPS_FLG_LOCALDNS;
        dhcps.param.PoolBase	= inet_addr("192.168.1.100");
        dhcps.param.PoolCount	= 10;
        CfgAddEntry( hCfg, CFGTAG_SERVICE, CFGITEM_SERVICE_DHCPSERVER, 0,
                     sizeof(dhcps), (UINT8 *)&dhcps, 0 );

        bzero( &RT, sizeof(RT) );
        RT.IPDestAddr = inet_addr("192.168.1.1");;
        RT.IPDestMask = inet_addr(LocalIPMask);
        // Add the route
        CfgAddEntry( hCfg, CFGTAG_ROUTE, 0, 0,
                           sizeof(CI_ROUTE), (UINT8 *)&RT, 0 );
    }

    //
    // Configure IPStack/OS Options
    //

    // We don't want to see debug messages less than WARNINGS
    rc = DBG_WARN;
    CfgAddEntry( hCfg, CFGTAG_OS, CFGITEM_OS_DBGPRINTLEVEL,
                 CFG_ADDMODE_UNIQUE, sizeof(uint), (UINT8 *)&rc, 0 );

    //
    // This code sets up the TCP and UDP buffer sizes
    // (Note 8192 is actually the default. This code is here to
    // illustrate how the buffer and limit sizes are configured.)
    //

    // UDP Receive limit
    rc = 8192;
    CfgAddEntry( hCfg, CFGTAG_IP, CFGITEM_IP_SOCKUDPRXLIMIT,
                 CFG_ADDMODE_UNIQUE, sizeof(uint), (UINT8 *)&rc, 0 );

    //
    // Boot the system using this configuration
    //
    // We keep booting until the function returns 0. This allows
    // us to have a "reboot" command.
    //
    do
    {
        rc = NC_NetStart( hCfg, NetworkOpen, NetworkClose, NetworkIPAddr );
    } while( rc > 0 );

    // Delete Configuration
    CfgFree( hCfg );

    // Close the OS
main_exit:
    NC_SystemClose();
    return(0);
}


//
// System Task Code [ Server Daemon Servers ]
//
static HANDLE hHello=0;

//
// NetworkOpen
//
// This function is called after the configuration has booted
//
static void NetworkOpen()
{
    // Create our local server
    hHello = DaemonNew( SOCK_DGRAM, 0, 7, dtask_udp_hello,
                       OS_TASKPRINORM, OS_TASKSTKNORM, 0, 1 );
}

//
// NetworkClose
//
// This function is called when the network is shutting down,
// or when it no longer has any IP addresses assigned to it.
//
static void NetworkClose()
{
    DaemonFree( hHello );
}


//
// NetworkIPAddr
//
// This function is called whenever an IP address binding is
// added or removed from the system.
//
static void NetworkIPAddr( IPN IPAddr, uint IfIdx, uint fAdd )
{
    IPN IPTmp;

    if( fAdd )
        System_printf("Network Added: ");
    else
        System_printf("Network Removed: ");

    // Print a message
    IPTmp = ntohl( IPAddr );
    System_printf("If-%d:%d.%d.%d.%d\n", IfIdx,
            (UINT8)(IPTmp>>24)&0xFF, (UINT8)(IPTmp>>16)&0xFF,
            (UINT8)(IPTmp>>8)&0xFF, (UINT8)IPTmp&0xFF );
}

//
// Service Status Reports
//
// Here's a quick example of using service status updates
//
static char *TaskName[]  = { "Telnet","HTTP","NAT","DHCPS","DHCPC","DNS" };
static char *ReportStr[] = { "","Running","Updated","Complete","Fault" };
static char *StatusStr[] = { "Disabled","Waiting","IPTerm","Failed","Enabled" };
static void ServiceReport( uint Item, uint Status, uint Report, HANDLE h )
{
    System_printf( "Service Status: %-9s: %-9s: %-9s: %03d\n",
            TaskName[Item-1], StatusStr[Status],
            ReportStr[Report/256], Report&0xFF );

    //
    // Example of adding to the DHCP configuration space
    //
    // When using the DHCP client, the client has full control over access
    // to the first 256 entries in the CFGTAG_SYSINFO space.
    //
    // Note that the DHCP client will erase all CFGTAG_SYSINFO tags except
    // CFGITEM_DHCP_HOSTNAME. If the application needs to keep manual
    // entries in the DHCP tag range, then the code to maintain them should
    // be placed here.
    //
    // Here, we want to manually add a DNS server to the configuration, but
    // we can only do it once DHCP has finished its programming.
    //
    if( Item == CFGITEM_SERVICE_DHCPCLIENT &&
        Status == CIS_SRV_STATUS_ENABLED &&
        (Report == (NETTOOLS_STAT_RUNNING|DHCPCODE_IPADD) ||
         Report == (NETTOOLS_STAT_RUNNING|DHCPCODE_IPRENEW)) )
    {
        IPN IPTmp;

        // Manually add the DNS server when specified
        IPTmp = inet_addr(DNSServer);
        if( IPTmp )
            CfgAddEntry( 0, CFGTAG_SYSINFO, CFGITEM_DHCP_DOMAINNAMESERVER,
                         0, sizeof(IPTmp), (UINT8 *)&IPTmp, 0 );
    }
}


.

The DHCP server configuration codes are like these

CI_SERVICE_DHCPS dhcps;
CI_ROUTE RT;

// Specify DHCP Server Service on IF-1
bzero( &dhcps, sizeof(dhcps) );
dhcps.cisargs.Mode   	= CIS_FLG_IFIDXVALID;
dhcps.cisargs.IfIdx  	= 1;
dhcps.cisargs.pCbSrv 	= &ServiceReport;
dhcps.param.Flags	= DHCPS_FLG_LOCALDNS;
dhcps.param.PoolBase	= inet_addr("192.168.1.100");
dhcps.param.PoolCount	= 10;
CfgAddEntry( hCfg, CFGTAG_SERVICE, CFGITEM_SERVICE_DHCPSERVER, 0,
                     sizeof(dhcps), (UINT8 *)&dhcps, 0 );

bzero( &RT, sizeof(RT) );
RT.IPDestAddr = inet_addr("192.168.1.1");;
RT.IPDestMask = inet_addr(LocalIPMask);
// Add the route
CfgAddEntry( hCfg, CFGTAG_ROUTE, 0, 0,
            sizeof(CI_ROUTE), (UINT8 *)&RT, 0 );

When I ran this codes as DHCP server, the console printed the results as below

QMSS successfully initialized 
CPPI successfully initialized 
PA successfully initialized 

Wavepop K7_C6670 Board TCP/IP Stack Test Application

DHCP Server start...
Service Status: DHCPS    : Failed   :          : 000

Can anyone give me some hints to resolve this problem?

Regards,

Feng

  • Did you check section 6.3 of spru524, NDK reference guide?

    Regards, Eric
  • Hi Eric,

    I had referred to the section G.3.2.4.2 in the NDK API Reference Guide(spru524i). And I modified my codes like below

    CI_SERVICE_DHCPS dhcps;
    CI_ROUTE RT;
    
    // Specify DHCP Server Service on IF-1
    bzero( &dhcps, sizeof(dhcps) );
    dhcps.cisargs.Mode   	= CIS_FLG_IFIDXVALID;
    dhcps.cisargs.IfIdx  	= 1;
    dhcps.cisargs.pCbSrv 	= &ServiceReport;
    dhcps.param.Flags	= DHCPS_FLG_LOCALDNS | DHCPS_FLG_LOCALDOMAIN;
    dhcps.param.PoolBase	= inet_addr("192.168.1.100");
    dhcps.param.PoolCount	= 10;
    CfgAddEntry( hCfg, CFGTAG_SERVICE, CFGITEM_SERVICE_DHCPSERVER, 0,
                sizeof(dhcps), (UINT8 *)&dhcps, 0 );

    And the problems remained.

    And as you suggestion, I had referred section 6.3 also. And I modified my codes like these 

    NTARGS *pNTA;
    NTPARAM_DHCPS *pNTP;
    bzero( &pNTA, sizeof(pNTA) );
    pNTA->CallMode  = CIS_FLG_IFIDXVALID;
    pNTA->IPAddr	= inet_addr("192.168.1.1");
    pNTA->IfIdx 	= 1;
    pNTA->hCallback	= &ServiceReport;
    //pNTA->pCb	= &ServiceReport;
    
    bzero( &pNTP, sizeof(pNTP) );
    pNTP->Flags	= DHCPS_FLG_LOCALDNS;
    pNTP->PoolBase	= inet_addr("192.168.1.100");
    pNTP->PoolCount	= 10;
    DHCPSOpen(pNTA, pNTP);

    And DHCP server can not work also.

    I see that the G3.2.4.2 is legacy configuration API. 

    So what the difference between G3.4.2 and section 6.3?

    Where can I find some examples using the codes on section 6.3?

    What I get from the PDK C6670 1.1.2.6 are using the codes on G3.4.2.

    Regards,

    Feng

  • Feng,

    There is a https://e2e.ti.com/support/embedded/tirtos/f/355/t/444448 for NDK DHCP server on a different device. The forum linked to a TI wiki page with lab slides and example package. Can you check if that help?

    Regards, Eric