This is the mail archive of the
ecos-discuss@sources.redhat.com
mailing list for the eCos project.
Problem with IP Stack ...
- From: Thomas BINDER <Thomas dot Binder at frequentis dot com>
- To: ecos-discuss at sources dot redhat dot com
- Date: Fri, 06 Sep 2002 12:41:23 +0200
- Subject: [ECOS] Problem with IP Stack ...
- Organization: Frequentis
I have a serious problem with the IP Stack of ecos. Whenever UDP packets are
sent to an open socket and nobody cares to read the packets, ecos crashes after
a while. The problem seems to be related to the long known `out of MBUFs'
problem. At least one occasionally reads this message before the crash happens.
As I understand, however, running out of MBUFs should not actually crash the
system.
The attached code will reproduce the problem.
target code:
mbuf.cpp
host code (linux):
client.cpp
To reproduce the problem first load and start mbuf. It will open an udp socket
and then print mbuf statistics.
Then start the client tool:
./client 10.16.2.238 9001 100000
The last argument determines an interval (realized as a for loop) between two
consecutive transmissions of data. A smaller value results in faster
transmissions.
With an interval value of 0 (up to 100000 on my machine) ecos crashes
immediately.
The problem is not restricted to UDP sockets. It also happens after return from
accept of a TCP socket. Note, however, that the problem does not occur *before*
accept returns.
I use ecos version 2.0 (from June or Juli).
Any ideas on what is going on here or where I could start searching?
Thx,
Tom
#include <cyg/infra/diag.h>
#include <pkgconf/kernel.h>
#include <cyg/kernel/sched.hxx>
#include <cyg/infra/cyg_type.h>
#include <cyg/kernel/kapi.h>
#include <cyg/kernel/thread.hxx>
#include <cyg/kernel/thread.inl>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <sys/types.h> // socket
#include <sys/socket.h> // socket
#include <netinet/in.h> // IPPROTO_TCP
#include <netinet/ip.h> // IPTOS_....
#include <arpa/inet.h> // inet_addr / inet_aton
static cyg_uint8 threadStack[ CYGNUM_HAL_STACK_SIZE_TYPICAL ];
static char threadName[] = "Network Test Thread";
static cyg_handle_t threadHandle;
static cyg_thread thread;
static void UdpThreadFunction( cyg_addrword_t threadObject );
externC void cyg_kmem_print_stats();
externC void cyg_user_start()
{
cyg_thread_create( 5, // prio
UdpThreadFunction, // entry
0, // data
threadName,
threadStack,
sizeof( threadStack ),
&threadHandle,
&thread );
cyg_thread_resume( threadHandle );
Cyg_Scheduler::start();
}
struct SockAddrIn: public sockaddr_in
{
SockAddrIn();
SockAddrIn(const char* aAddr, const unsigned short aPort);
struct sockaddr* ToSockAddr();
};
SockAddrIn::SockAddrIn()
{
memset(static_cast<struct sockaddr_in*>(this), 0,
sizeof(struct sockaddr_in));
}
SockAddrIn::SockAddrIn(const char* aAddr, const unsigned short aPort)
{
memset(static_cast<struct sockaddr_in*>(this), 0,
sizeof(struct sockaddr_in));
struct in_addr ia;
(void) inet_aton( aAddr, &ia );
sin_family = AF_INET;
sin_port = htons(aPort);
sin_addr.s_addr = ia.s_addr;
}
struct sockaddr* SockAddrIn::ToSockAddr()
{
return reinterpret_cast< struct sockaddr* >( this );
}
class MyUdpSocket
{
public:
MyUdpSocket( const char ip_addr[], unsigned short port );
~MyUdpSocket();
protected:
int itsFd;
};
MyUdpSocket::MyUdpSocket( const char ip_addr[], unsigned short port )
{
if ( (itsFd = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP ) ) < 0 )
{
diag_printf("socket failed: \"%s\"\n", strerror(errno));
return;
}
SockAddrIn sin(ip_addr, 9001);
if ( bind( itsFd, sin.ToSockAddr(), sizeof(sin) ) < 0 )
{
diag_printf("bind failed: \"%s\"\n", strerror( errno ) );
close( itsFd );
itsFd = -1;
}
}
MyUdpSocket::~MyUdpSocket()
{
diag_printf("in MyUdpSocket::~MyUdpSocket\n");
if ( itsFd != -1 )
{
diag_printf("in MyUdpSocket::~MyUdpSocket closing socket: %u\n",
itsFd);
if ( close( itsFd ) < 0 )
{
diag_printf("close: \"%s\"\n", strerror(errno));
}
}
}
static void UdpThreadFunction( cyg_addrword_t data )
{
diag_printf("in UDP thread ...\n");
void init_eth0( char my_ip_string[] );
char my_ip_string[16]; // template for "uuu.vvv.www.xxx"
init_eth0( my_ip_string );
MyUdpSocket sock( my_ip_string, 9001 );
diag_printf("return from socket, now printing stats\n");
for ( ;; )
{
cyg_kmem_print_stats();
Cyg_Thread::self()->delay( 10 );
}
}
#include <network.h>
#include <cyg/hal/hal_if.h>
#ifndef CONFIG_IP
#define CONFIG_IP 5
#endif
// offset added to the ip address of RedBoot, used
// for the ip address of the application
#define IP_ADDR_OFFSET 8
extern cyg_bool_t eth0_up;
extern struct bootp eth0_bootp_data;
// local ip address mapping
extern cyg_bool_t eth0_up;
typedef unsigned char ip_addr_t[4];
void init_eth0( char my_ip_string[] )
{
bool ip_ok;
ip_addr_t my_ip;
const char *eth0_name = "eth0";
// get the ip address of RedBoot out of flash
ip_ok = CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET,
const_cast< char* >("bootp_my_ip"),
&my_ip, CONFIG_IP);
// diag_printf("ip: %d %d %d %d\n", my_ip[0], my_ip[1], my_ip[2], my_ip[3]);
CYG_ASSERT( my_ip[3] + IP_ADDR_OFFSET <= 255, "IP address exceeds 255");
// add offset to it
my_ip[3] += IP_ADDR_OFFSET;
// my_ip[3] = 232; // ssgtest1ec.ssg.frequentis.frq
sprintf(my_ip_string, "%d.%d.%d.%d", my_ip[0], my_ip[1], my_ip[2], my_ip[3]);
diag_printf("IP: %s\n", my_ip_string );
eth0_up = true;
build_bootp_record(ð0_bootp_data,
"Hollaro",
(const char *)my_ip_string, // IP address
"255.255.254.0", // net mask
"10.16.3.255", // broadcast address
"10.16.2.1", // gateway address
"10.16.2.20"); // server address
// call "the" init function
if (!init_net(eth0_name, ð0_bootp_data)) {
diag_printf("Network initialization failed for eth0\n");
eth0_up = false;
return;
}
show_bootp(eth0_name, ð0_bootp_data);
}
#include <sys/types.h> // socket
#include <sys/socket.h> // socket
#include <netinet/in.h> // IPPROTO_TCP
#include <netinet/ip.h> // IPTOS_....
#include <arpa/inet.h> // inet_addr / inet_aton
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <iostream>
using namespace std;
#define REDBOOT_CONSOLE 1
#define LOG_LEVEL 1000
struct SockAddrIn: public sockaddr_in
{
SockAddrIn();
SockAddrIn(const char* aAddr, const unsigned short aPort);
struct sockaddr* ToSockAddr();
};
SockAddrIn::SockAddrIn()
{
memset(static_cast<struct sockaddr_in*>(this), 0,
sizeof(struct sockaddr_in));
}
SockAddrIn::SockAddrIn(const char* aAddr, const unsigned short aPort)
{
memset(static_cast<struct sockaddr_in*>(this), 0,
sizeof(struct sockaddr_in));
struct in_addr ia;
(void) inet_aton( aAddr, &ia );
sin_family = AF_INET;
sin_port = htons(aPort);
sin_addr.s_addr = ia.s_addr;
}
struct sockaddr* SockAddrIn::ToSockAddr()
{
return reinterpret_cast< struct sockaddr* >( this );
}
int main( int argc, char** argv )
{
if ( argc != 4 )
{
cerr << "Usage: " << argv[0] << " ip-addr port delay" << endl;
exit ( 1 );
}
unsigned short port;
if ( sscanf( argv[2], "%hd", &port ) != 1 )
{
cerr << "illegal port argument received: \"" << argv[2] << "\"" << endl;
cerr << "Usage: " << argv[0] << " ip-addr port delay" << endl;
exit ( 1 );
}
unsigned int delay;
if ( sscanf( argv[3], "%d", &delay ) != 1 )
{
cerr << "illegal delay argument received: \"" << argv[3] << "\""
<< endl;
cerr << "Usage: " << argv[0] << " ip-addr port delay" << endl;
exit ( 1 );
}
int itsFd;
if ( (itsFd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
{
if ( REDBOOT_CONSOLE && ( LOG_LEVEL > 0 ) )
{
printf("socket failed: \"%s\"\n", strerror(errno));
}
return false;
}
SockAddrIn addr(argv[1], port);
cout << "connecting to " << inet_ntoa(addr.sin_addr)
<< " " << ntohs(addr.sin_port) << endl;
if ( connect( itsFd, addr.ToSockAddr(), sizeof( addr ) ) < 0 )
{
perror("connect");
return 1;
}
const unsigned int dataLen( 256 );
char data[ dataLen ];
for ( ;; )
{
cout << "writing " << dataLen << " bytes to socket" << endl;
write( itsFd, data, dataLen );
for (unsigned int i (0); i < delay; ++i);
}
return true;
}
--
Before posting, please read the FAQ: http://sources.redhat.com/fom/ecos
and search the list archive: http://sources.redhat.com/ml/ecos-discuss