genodelabs / genode

Genode OS Framework
https://genode.org/
Other
1.05k stars 250 forks source link

lwip with static IP does not work #349

Closed chelmuth closed 11 years ago

chelmuth commented 12 years ago

EunSeok Kim reported on the mailing list:

I wanna setting the network card with static IP address in the Panda-Board environment. My Program is using lwip_nic_init() function of lwip library for network communication on the Panda-Board. We have been applied static IP address when we using the funtion. However it seems the function causes any problem in terms of network setting with usb_drv. ( It's only well done when we set loopback address to bind on server, with QEMU. It's put following message, when it's in other environment. "Could not connect!" )

Following is Server and Client source code of the my test program. Could you please know why this program is failed on Panda_Board.

Server Code

/* Genode includes */
#include <base/printf.h>
#include <base/thread.h>
#include <util/string.h>

/* LwIP includes */
extern "C" {
#include <lwip/sockets.h>
#include <lwip/api.h>
}

#include <lwip/genode.h>
#define SERVER_PORTNUM 10000

const static char http_html_hdr[] =
"HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n"; /* HTTP response header */

const static char http_index_html[] =
"<html><head><title>Congrats!</title></head><body><h1>Welcome to our lwIP HTTP server!</h1><p>This is a small test page.</body></html>"; /* HTML page */

/**
* Handle a single client's request.
*
* \param conn socket connected to the client
*/
void http_server_serve(int conn) {
char buf[1024];
ssize_t buflen;

/* Read the data from the port, blocking if nothing yet there.
We assume the request (the part we care about) is in one packet */
buflen = lwip_recv(conn, buf, 1024, 0);

if( buflen > 0 )
{
PLOG("Packet received!");
PDBG("MSG : %s \n", buf );
}

/* Ignore all receive errors */
if (buflen > 0) {

/* Is this an HTTP GET command? (only check the first 5 chars, since
there are other formats for GET, and we're keeping it very simple)*/
if (buflen >= 5 &&
buf[0] == 'G' &&
buf[1] == 'E' &&
buf[2] == 'T' &&
buf[3] == ' ' &&
buf[4] == '/' ) {

PLOG("Will send response");

/* Send http header */
lwip_send(conn, http_html_hdr, Genode::strlen(http_html_hdr), 0);

/* Send our HTML page */
lwip_send(conn, http_index_html, Genode::strlen(http_index_html), 0);
}
}
}

int main()
{
int s;

lwip_tcpip_init();

/* Initialize network stack and do DHCP */
if (lwip_nic_init( inet_addr("10.89.8.1"), inet_addr("255.255.255.0"), inet_addr("10.89.8.1") )) {
// if (lwip_nic_init(0, 0, 0 )) {
PERR("We got no IP address!");
return -1;
}

PLOG("Create new socket ...");
if((s = lwip_socket(AF_INET, SOCK_STREAM, 0/*IPPROTO_TCP*/)) < 0) {
PERR("No socket available!");
return -1;
}

PLOG("Now, I will bind ...");
struct sockaddr_in in_addr;
in_addr.sin_family = AF_INET;
in_addr.sin_port = htons( SERVER_PORTNUM );
in_addr.sin_addr.s_addr = inet_addr("10.89.8.1");
if(lwip_bind(s, (struct sockaddr*)&in_addr, sizeof(in_addr))) {
PERR("bind failed!");
return -1;
}

PLOG("Now, I will listen ...");
if(lwip_listen(s, 5)) {
PERR("listen failed!");
return -1;
}

PLOG("Start the server loop ...");

// Client cli;
// cli.start();

while(true) {
PDBG(" loop is alived. --- \n");
struct sockaddr addr;
socklen_t len = sizeof(addr);
int client = lwip_accept(s, &addr, &len);
if(client < 0) {
PWRN("Invalid socket from accept!");
continue;
}
http_server_serve(client);
PDBG(" yahoo~~! client communication success!!!^^ client= 0x%p \n", client);
lwip_close(client);
}
return 0;
}

Client Code

/* Genode includes */
#include <base/printf.h>
#include <base/thread.h>
#include <util/string.h>

//#include <unistd.h>
//#include <sys/types.h>

extern "C" {
#include <lwip/sockets.h>
#include <lwip/api.h>
}

//#include <arpa/inet.h>
//#include <netinet/in.h>

#include <lwip/genode.h>

static const char *http_get_request =
"GET / HTTP/1.0\r\nHost: localhost:80\r\n\r\n"; /* simple HTTP request header */

/**
* The client thread simply loops endless,
* and sends as much 'http get' requests as possible,
* printing out the response.
*/

int main()
{
lwip_tcpip_init();

if( lwip_nic_init( inet_addr("10.89.8.2"), inet_addr("255.255.255.0"), inet_addr("10.89.8.1") ))
//if( lwip_nic_init(0, 0, 0))
{
PERR("We got no IP address!");
return 0;
}

while(true) {

PDBG("Create new socket ...");
int s = lwip_socket(AF_INET, SOCK_STREAM, 0 ); //IPPROTO_TCP);
if (s < 0) {
PERR("No socket available!");
continue;
}

PDBG("Connect to server ...");
struct sockaddr_in addr;
addr.sin_port = htons(10000);
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("10.89.8.1");

if((lwip_connect(s, (struct sockaddr *)&addr, sizeof(addr))) < 0) {
PERR("Could not connect!");
lwip_close(s);
continue;
}

PDBG("Send request...");
unsigned long bytes = lwip_send(s, (char*)http_get_request,
Genode::strlen(http_get_request), 0);
if ( bytes < 0 ) {
PERR("Couldn't send request ...");
lwip_close(s);
continue;
}

/* Receive http header and content independently in 2 packets */
for(int i=0; i<2; i++) {
char buf[1024];
ssize_t buflen;
buflen = lwip_recv(s, buf, 1024, 0);
if(buflen > 0) {
buf[buflen] = 0;
PDBG("Packet received!");
PDBG("Packet content:\n%s", buf);
} else
break;
}

/* Close socket */
lwip_close(s);
}

PDBG("Modifyed test program ----\n");
return 0;
}

run script of Server

if {[have_spec linux]} {
puts "Run script does not support Linux."; exit 0 }

#
# Build
#

build {
core init
drivers/pci drivers/timer drivers/usb
test/lwip/ESserver
}

create_boot_directory

#
# Generate config
#

set config {
<config verbose="yes">
<parent-provides>
<service name="ROM"/>
<service name="RAM"/>
<service name="IRQ"/>
<service name="IO_MEM"/>
<service name="IO_PORT"/>
<service name="CAP"/>
<service name="PD"/>
<service name="RM"/>
<service name="CPU"/>
<service name="LOG"/>
<service name="SIGNAL"/>
</parent-provides>
<default-route>
<any-service> <parent/> <any-child/> </any-service>
</default-route>
<start name="timer">
<resource name="RAM" quantum="568K"/>
<provides> <service name="Timer"/> </provides>
</start>
<start name="usb_drv">
<resource name="RAM" quantum="20M"/>
<provides>
<service name="Nic"/>
<service name="Input"/>
</provides>
<config>
<nic mac="2e:60:90:0c:4e:01" />
<hid/>
</config>
</start>
<start name="lwip_ESserver">
<resource name="RAM" quantum="2M"/>
<route>
<service name="Nic"> <child name="usb_drv"/> </service>
<any-service> <parent/> <any-child/> </any-service>
</route>
</start> }

append_if [have_spec pci] config {
<start name="pci_drv">
<resource name="RAM" quantum="1M"/>
<provides> <service name="PCI"/> </provides>
</start> }

append config {
</config>
}

install_config $config

#
# Boot modules
#

# generic modules
set boot_modules {
core init timer
usb_drv
ld.lib.so libc.lib.so libc_log.lib.so lwip.lib.so lwip_ESserver
}

# platform-specific modules
lappend_if [have_spec pci] boot_modules pci_drv

build_boot_image $boot_modules

#
# Execute test case
#

run_genode_until {.*\/ #.*} 3000

run script of Client

if {[have_spec linux]} {
puts "Run script does not support Linux."; exit 0 }

#
# Build
#

build {
core init
drivers/pci drivers/timer drivers/usb
test/lwip/ESclient
}

create_boot_directory

#
# Generate config
#

set config {
<config verbose="yes">
<parent-provides>
<service name="ROM"/>
<service name="RAM"/>
<service name="IRQ"/>
<service name="IO_MEM"/>
<service name="IO_PORT"/>
<service name="CAP"/>
<service name="PD"/>
<service name="RM"/>
<service name="CPU"/>
<service name="LOG"/>
<service name="SIGNAL"/>
</parent-provides>
<default-route>
<any-service> <parent/> <any-child/> </any-service>
</default-route>
<start name="timer">
<resource name="RAM" quantum="568K"/>
<provides> <service name="Timer"/> </provides>
</start>
<start name="usb_drv">
<resource name="RAM" quantum="20M"/>
<provides>
<service name="Nic"/>
<service name="Input"/>
</provides>
<config>
<nic mac="2e:60:90:0c:4e:02" />
<hid/>
</config>
</start>
<start name="lwip_ESclient">
<resource name="RAM" quantum="2M"/>
<route>
<service name="Nic"> <child name="usb_drv"/> </service>
<any-service> <parent/> <any-child/> </any-service>
</route>
</start> }

append_if [have_spec pci] config {
<start name="pci_drv">
<resource name="RAM" quantum="1M"/>
<provides> <service name="PCI"/> </provides>
</start> }

append config {
</config>
}

install_config $config

#
# Boot modules
#

# generic modules
set boot_modules {
core init timer
usb_drv
ld.lib.so libc.lib.so libc_log.lib.so lwip.lib.so lwip_ESclient
}

# platform-specific modules
lappend_if [have_spec pci] boot_modules pci_drv

build_boot_image $boot_modules

#
# Execute test case
#

run_genode_until {.*\/ #.*} 3000
chelmuth commented 12 years ago

i.ismagilov responded with

diff --git a/libports/src/lib/lwip/platform/sys_arch.cc b/libports/src/lib/lwip/platform/sys_arch.cc
index 8127e37..0b79d0c 100644
--- a/libports/src/lib/lwip/platform/sys_arch.cc
+++ b/libports/src/lib/lwip/platform/sys_arch.cc
@@ -192,6 +192,8 @@ extern "C" {
                return 1;
 #endif /* LWIP_DHCP */
            }
+           else
+               netif_set_up(&netif);
        } catch (Nic_not_availble) {
            PWRN("NIC not available, set loopback as default");
            netif_set_default(loopif);
nfeske commented 12 years ago

@cnuke, @cproc, could you please review the fix? If you agree, I would like to include it into staging.

chelmuth commented 11 years ago

Any news here?

chelmuth commented 11 years ago

Can we close this bug?