Ethernet initialization

Hello out there, I try to build an application to start a simple TCP connection between 2 boads with a QorlQ processor. To achive this I filled the rtems_bsdnet_ifconfig:

struct rtems_bsdnet_ifconfig client_interface = {
    "tsec0",                             /* name of the interface */
    tsec_driver_attach_detach,          /* driver attach function */
    NULL,                               /* next interface */
    "192.168.0.1",                     /* IP address (or NULL for DHCP) */
    "255.255.255.0",                   /* Netmask */
    NULL,                   /* Hardware address (or NULL) */
    0,                      /* Driver specific field 1 */
};

and with this, I filled the rtems_bsdnet_config:

struct rtems_bsdnet_config rtems_bsdnet_config = {
    &client_interface,          /* pointer to first interface */
    NULL,  /* Use BOOTP/DHCP or NULL for static IP */
    0,                      /* Default network task priority */
    256 * 1024,                      /* Default buffer size */
    256 * 1024,                      /* Default mbuf cluster count */
    NULL,             /* Hostname */
    NULL,           /* Domain name */
    NULL,          /* Gateway */
    NULL,          /* Loghost */
    {NULL},            /* Name server(s) */
    {NULL}
};

with this I initialized the TCP/IP Stack within the network task:

printf("Initialize libBSD\n");
sc = rtems_bsd_initialize();
if (sc != RTEMS_SUCCESFUL)
    printf("libbsd init failed: %s\n", rtems_status_text(sc));

printf("libBSD initialized!\n");

but instead the ethernet driver comes up with a MAC Address, no configuration. But rtems_bsd_initialize() works without complains:

tsec0: mem 0x26000-0x26fff irq 15,16,17 on simplebus0
info: tsec0: Ethernet address: 00:a0:1e:a0:a1:a4

libBSD initialized!

what’s my fault?

Thanks in advance

Chris

Hello Chris,

I think the rtems_bsdnet_config is a leftover from the legacy stack. It isn’t parsed in the LibBSD.

In LibBSD, you have two possibilities to initialize the system:

  1. Via an /etc/rc.conf file that is quite similar to the one in FreeBSD.
  2. Via function calls for the commands like ifconfig and similar.

I usually use the second option because rc.conf pulls in more code. For example, a config could look like follows:

	sc = rtems_bsd_initialize();
	assert(sc == RTEMS_SUCCESSFUL);

	rv = rtems_bsd_ifconfig_lo0();
	assert(rv == 0);

#ifdef FIXED_IP
	sc = rtems_bsd_ifconfig("ffec0", "172.24.0.24", "255.255.0.0",
	    "172.24.0.255");
	assert(sc == RTEMS_SUCCESSFUL);
#else  /* !FIXED_IP */
	sc = rtems_dhcpcd_start(NULL);
	assert(sc == RTEMS_SUCCESSFUL);
#endif /* FIXED_IP */

Best regards

Christian

Edit: PS: Of course you have to use tsec0 instead of my ffec0. I copied that from an application on a different board.

Hello Christian, thank you for your help. I tried the 2nd possibility you showed up.

sc = rtems_bsd_initialize(); 

if (sc != RTEMS_SUCCESSFUL)
    printf("libbsd init failed: %s\n", rtems_status_text(sc));

sc = rtems_bsd_ifconfig_lo();
if(sc != RTEMS_SUCCESSFUL)
    printf("ifconfig_lo failed: %s\n", rtems_status_text(sc));

sc = rtems_bsd_ifconfig("tsec0", "192.168.0.2", "255.255.255.0", "192.168.0.255");
if(sc != RTEMS_SUCCESSFUL)
    printf("ifconfig failed: %s\n", rtems_status_text(sc));

But what now happens is really strange because the whole system crahes already in the init process after creating the first task:

sc = rtems_semaphore_create(
    rtems_build_name( 'S', 'E', 'M', 'C'),
    0,
    RTEMS_COUNTING_SEMAPHORE,
    0,
    &semc_done,
);
ASSERT_SUCCESS(sc);

sc = rtems_message_queue_construct( &msg_queue_conf, &msg_queue);
ASSERT_SUCCESS(sc);

sc = rtems_task_construct( &msg_task_config, &id);
ASSERT_SUCCESS(sc);

and it breaks within the rtems_task_construct function with return code (sc) RTEMS_INVALID_SIZE.

So the only thing I changed in my code was putting rtems_bsd_config into the tcpip task and that seems to disturb the memory order of my system completly, so that it breaks in a different place right at the beginning. Before that these task was created without a problem, but of course without a working TCP/IP connection. So there has to be something else changed?

rtems_bsd_ifconfig_lo makes no trouble at all, btw.

the full dump is:

(warning) PciE to region 2 failed, 0x0
*** EXIT STATUS NOT ZERO ***
exit source: 5 (RTEMS_FATAL_SOURCE_EXIT)
CPU: 0
exit code: 507 (0x000001fb)
RTEMS version: 6.0.0.c69a…
RTEMS tools: 9.5.0
executing thread ID: 0x0a010001
executing thread name: UT1

Thanks in advance /Chris

PS: it there an updated documentation on how to setup a TCP/IP stack, how to do it with the latest version? Or an example?

Unfortunately, LibBSD has very few documentation.

If rtems_task_construct returns RTEMS_INVALID_SIZE, it is most likely a problem with the thread local storage (at least according to the documentation; I didn’t check the source yet). How did you configure your application? Do you try to configure just the necessary objects or do you use something like UNIFIED_WORK_AREAS and similar options? LibBSD uses quite a lot of different objects and storage depending on what parts you use.

Regarding examples: I’m not sure whether there is an official one. But I can offer a few simple demo applications written by me. But note that I didn’t update these for quite some time now:

Hi Christian, I rearrange the whole code and put all the network code into the Init() function. Now it only to consider that we have one init function for the client and one for the server.
This is the client:

static void Init( rtems_task_argument arg)
{
    rtems_status_code sc;
    int exit_code = 0;
    rtems_task_priority oldprio;
    int sockFd;
    int serverSocket;
    int len = 0;
    struct sockaddr_in remoteAddr = {0};
    struct sockaddr_in localAddr     = {0};
    size_t seconds = 0;
    (void) arg;
     
    sc = rtems_task_set_priority(RTEMS_SELF,
      (rtems_task_priority)PRIO_INIT_TASK, &oldprio);
    ASSERT_SUCCESS(sc);

    sc = rtems_bsd_initialize();
    ASSERT_SUCCESS(sc);

    exit_code = rtems_bsd_ifconfig_lo0();
    ASSERT_SUCCESS(sc);

    exit_code = rtems_bsd_ifconfig("tsec0", "192.168.0.2",
      "255.255.255.0", "192.168.0.255");

    while (true) {
        bool link_active = false;
        exit_code = rtems_bsd_iface_link_state("tsec0", &link_active );
        ASSERT_SUCCESS(exit_code);
        if (link_active) 
            break;
        sleep( 1 );
        ++seconds;
        if (seconds > 10)
            printf("error: tsec0 no active link\n");
    }

    if ((sockFd = socket (AF_INET, SOCK_STREAM, 0)) < 0) {
        printf("open socket failed: %d\n", sockFd);
        return;
    }

    localAddr.sin_addr.s_addr_addr = inet_addr("192.168.0.2");
    localAddr.sin_family = AF_INET;

    exit_code = bind(sockFd, (struct sockaddr*) &localAddr, sizeof(localAddr));
    printf("BIND returns: %d\n", exit_code);

    remoteAddr.sin_addr.s_addr_addr = inet_addr("192.168.0.1");
    remoteAddr.sin_family = AF_INET;
    remoteAddr.sin_port    = 4242;

    while(1)  {
        if ((serverSocket = connect(sockFd, (struct sockaddr*) &remoteAddr, sizeof(remoteAddr))) == -1) {
            perror("no connection established\n");
            continue;
        }
    }
}

and the output is:

info: lo0: linke state changed to UP
info: tsec0: link state changed to DOWN
info: tsec0: link state changed to UP
BIND returns: 0
err: tsec0: DAD detected duplicate IPv6 address fe80:1::2a0:1eff:fea0:a1a4: NS in/out/loopback=0/1/0, NA in=1
err: tsec0: DAD complete for fe80:1::2a0:1eff:fea0:a1a4 - duplicate found
err: tsec0: manual intervention required
err: tsec0: possible hardware address duplication detected, disable IPv6
no connection established
: Connection refused

where does this IPv6 error come from? This error remained even when I disable the bind function. I added bind just to determin which IP address is bound to which interface. The “connection refused” error also comes up, when there is no other system in the network, so this is no server which refuses the connection :thinking:

Hope someone can help me out :wink:

Thanks in advance

BR /Chris

The fe80:... address is a link local IPv6 address. That one is generated from a MAC address. That’s one of the standard methods. Basically it’s fe80:1::XXYY:ZZff:feUU:VVWW for a MAC address XX-YY-ZZ-UU-VV-WW. If you get a message about a duplicate detected, I assume that you have two systems in the same network with one MAC address. That’s most likely also the reason for your Connection refused: Your connection request is sent to your own MAC.

It seems that the tsec uses the following function to get it’s MAC:

void
tsec_get_hwaddr(struct tsec_softc *sc, uint8_t *addr)
{
	rtems_bsd_get_mac_address(device_get_name(sc->dev),
	    device_get_unit(sc->dev), addr);
}

The rtems_bsd_get_mac_address returns some default address. Usually it should be something like 0e-b0-ba-5e-ba-11. So either you or your BSP already overwrote the function. Please make sure that you return a unique address per board.

Best regards

Christian