Nios® II Embedded Design Suite (EDS)
Support for Embedded Development Tools, Processors (SoCs and Nios® II processor), Embedded Development Suites (EDSs), Boot and Configuration, Operating Systems, C and C++
12485 Discussions

Help Getting goAhead Web Server Working

Altera_Forum
Honored Contributor II
1,106 Views

Hello: 

 

Has anyone got the goAhead web serve running? 

 

I have built the web server and got it to run with one issue. 

 

When I request a simple web page, about.htm, the page is never displayed.  

Analyzing with Ethereal shows multiple packets with incorrect checksums. In  

addition, two lines do not have the terminating \n's; Content-length: 4353\r  

and \r. Stepping through the code indicates that in both cases, the \n are  

being written into the buffer. 

 

To verify the function of the server, I built it under windows and used  

ethereal to generate a correct sequence for packets to and from the server. 

 

Any thoughts would be appreciated.
0 Kudos
7 Replies
Altera_Forum
Honored Contributor II
142 Views

I saw the same thing; however, I never got around to debugging it. Unfortunately web is low on the dev priority now. If I get around to it and figure it out I will post details. If you figure it out please post details of the fix/workaround/config as I would be interested. 

 

Good luck. 

 

Tuck
Altera_Forum
Honored Contributor II
142 Views

 

--- Quote Start ---  

originally posted by tuck@Feb 16 2006, 01:39 PM 

i saw the same thing; however, i never got around to debugging it. unfortunately web is low on the dev priority now. if i get around to it and figure it out i will post details. if you figure it out please post details of the fix/workaround/config as i would be interested. 

 

good luck. 

 

tuck 

<div align='right'><{post_snapback}> (index.php?act=findpost&pid=12749) 

--- quote end ---  

 

--- Quote End ---  

 

 

 

Tuck: 

 

Here is what I have so far..... 

 

I turned on the eCos asserts and tracing: 

 

 

Anyway...enabling asserts in eCos unmasks the following assert: 

 

ASSERT FAIL: <3> if_lan91cxx(868)lan91cxx_send() odd length 

 

Breaking and examining the code shows that there are four buffers in the  

driver that contains the packet. Their lengths are 54, 71, 63, and 27.  

Accorfing to the assert, only the last one can be of an odd length. 

 

Because the device interface is 16 bits, the driver load two bytes at a time  

and increments the counter by two. If the packet is of an odd length, a  

flag is set and the odd byte is written to complete the packet. At each of  

the odd buffers, the last (odd) character is my missing &#39;\n&#39; and explains  

why the server is not delivering my pages as I would expect. 

 

Now that I know the source of the failure, I will determine the root cause  

and propose a solution. I think by writing even chunks from the ring buffer to the device is the solution. Perhaps a new routine to only write an odd length at the end of a packet. Right now I am developing under windows to get XML-RPC and XMLHttpResponse support up and running. I will port more as I learn more. 

 

Thanks for your reply. 

 

Graham....
Altera_Forum
Honored Contributor II
142 Views

 

--- Quote Start ---  

originally posted by graham615+feb 22 2006, 12:16 pm--><div class='quotetop'>quote (graham615 @ feb 22 2006, 12:16 pm)</div> 

--- quote start ---  

<!--quotebegin-tuck@Feb 16 2006, 01:39 PM 

i saw the same thing; however, i never got around to debugging it. unfortunately web is low on the dev priority now. if i get around to it and figure it out i will post details. if you figure it out please post details of the fix/workaround/config as i would be interested. 

 

good luck. 

 

tuck 

<div align='right'><{post_snapback}> (index.php?act=findpost&pid=12749) 

--- quote end ---  

 

--- Quote End ---  

 

 

 

Tuck: 

 

Here is what I have so far..... 

 

I turned on the eCos asserts and tracing: 

 

 

Anyway...enabling asserts in eCos unmasks the following assert: 

 

ASSERT FAIL: <3> if_lan91cxx(868)lan91cxx_send() odd length 

 

Breaking and examining the code shows that there are four buffers in the  

driver that contains the packet. Their lengths are 54, 71, 63, and 27.  

Accorfing to the assert, only the last one can be of an odd length. 

 

Because the device interface is 16 bits, the driver load two bytes at a time  

and increments the counter by two. If the packet is of an odd length, a  

flag is set and the odd byte is written to complete the packet. At each of  

the odd buffers, the last (odd) character is my missing &#39;\n&#39; and explains  

why the server is not delivering my pages as I would expect. 

 

Now that I know the source of the failure, I will determine the root cause  

and propose a solution. I think by writing even chunks from the ring buffer to the device is the solution. Perhaps a new routine to only write an odd length at the end of a packet. Right now I am developing under windows to get XML-RPC and XMLHttpResponse support up and running. I will port more as I learn more. 

 

Thanks for your reply. 

 

Graham.... 

<div align='right'><{post_snapback}> (index.php?act=findpost&pid=12883)</div> 

[/b] 

--- Quote End ---  

 

Excellent! 

I would go for a modification in the driver code. If you patch up the ring buffer in X 

network stack then there are still other network stacks that could have issues. Seems to me like the driver doesn&#39;t properly handle the scatter gather list if it can only reassemble very specific types of SG lists (ones where the individual nodes can only be even length except for the last). 

I would do a look behind like this: 

@@ line 869 if(i && sg_list.len & 1) { //correct my len for next iter sg_list.len++; //correct my current pointer. sdata = (unsigned short *)sg_list.buf+1; //Get the last byte of the last buffer and shift it one byte left. short data = *sg_list.buf.len -1]; data = data << 8; //Add in the first byte from my buffer. data |= *sg_list.buf; //Send this off. put_data(sc, *sdata); len--; } 

I don&#39;t have time to really check this code over, but you can probably get the gist if I have errors. The only other thing I would be concerned about is modifying the sg_list[i].len in which case you could maintain a boolean indicating weather the last iteration handled a odd item 

bool oddHandled = false; for(... ... if(i && sg_list.len & 1 && !oddHandled) { oddHandled = true; ... } else oddHandled = false; 

 

That way the sg list wouldn&#39;t be tampered with (incase it is inspected/used after the call). 

 

Tuck 

 

--Edit 

Oh and after that first if block you would need to handle if the current len is odd 

if(i != (sg_len - 1) && (len & 1)) len--;
Altera_Forum
Honored Contributor II
142 Views

Ok I think I fixed the odd buffer size issue, but the checksum issue remains. 

 

Since this is calculated further up the stack, and my cursory glance didn&#39;t reveal any areas in the driver that may be corrupting the header I think there is another issue. 

 

When I went in the debugger and manually corrected the CRC in the header the remaining data looked fine, so hopefully this can help! 

 

Unfortunately I can&#39;t spend more time on this since I won&#39;t be using this driver once our boards arrive, and the issue isn&#39;t affecting me right this instant. I went ahead and put a patch together. It&#39;s not well tested, but the tests I have done indicate that it is working as designed. 

 

If you take the following text save it to a file and execute patch -p0 < patchFile from your nios2 shell in the ecos-current dirctory (probably /cygdrive/c/altera/kits/nios2_51/components/ecos/ecos-current). It should resolve the buffer issue (I think http://forum.niosforum.com/work2/style_emoticons/<#EMO_DIR#>/smile.gif ). 

diff -Naru packagesOrig/devs/eth/smsc/lan91cxx/current/src/if_lan91cxx.c packages/devs/eth/smsc/lan91cxx/current/src/if_lan91cxx.c --- packagesOrig/devs/eth/smsc/lan91cxx/current/src/if_lan91cxx.c    2005-01-07 12:50:34.000000000 -0500 +++ packages/devs/eth/smsc/lan91cxx/current/src/if_lan91cxx.c    2006-02-24 11:30:49.525340400 -0500 @@ -860,13 +860,53 @@     // packet length (includes status, byte-count and control shorts)     put_data(sc, CYG_CPU_TO_LE16(0x7FE & (plen + 6)) ); // Always even, always < 15xx(dec) +    //Since this driver transfers 2 bytes at a time buffers in the beginning of +    //the scatter gather list with odd lengths must be combined with their +    //next neighbor to create 2 byte sets. The oddHandled variable tracks if +    //the PRIOR iteration handled one of these conditions +    bool oddHandled = false;     // Put data into buffer     for (i = 0;  i < sg_len;  i++) { -        sdata = (unsigned short *)sg_list.buf; -        len = sg_list.len; +    // 2006.02.24 - THW - Odd lengths now handled. +    //CYG_ASSERT(0 == (len & 1) || (i == (sg_len-1)), "odd length"); -        CYG_ASSERT(0 == (len & 1) || (i == (sg_len-1)), "odd length"); -        CYG_ASSERT( sdata, "No sg data pointer here" ); +    //If this is the first buffer then just process as normal +    //If this is a middle buffer then inspect the previous buffer: +    // - If previous length was odd and the last iteration didn&#39;t handle an +    //     odd buffer then we need to combine. +    // - If the previous iteration did handle an odd buffer and it&#39;s length +    //     is even it total transfer was odd and I need to combine. +    bool lastLenOdd = sg_list.len & 1; +    if(i && (lastLenOdd ^ oddHandled)){ +     //Notify the next iteration that this iteration handled an odd +     //buffer. +     oddHandled = true; + +     //Get the last byte of the last buffer and shift it into MSB. +     short data = ((char*)sg_list.buf).len - 1)]; +     data = data << 8; + +     //Add in the first byte from my buffer to the LSB. +     data |= ((char*)sg_list.buf); +     //correct my current pointer (since I just sent one of my bytes). +     sdata = (unsigned short *)(sg_list.buf + 1); + +     //Send this off. +     put_data(sc, *sdata); +     len = sg_list.len - 1; +    } +    else { +     oddHandled = false; +     sdata = (unsigned short *)sg_list.buf; +     len = sg_list.len; +    } +    CYG_ASSERT( sdata, "No sg data pointer here" ); + +    //If this isn&#39;t the last buffer and my len is odd then don&#39;t transfer +    //the last byte (the next iteration will handle it). +    if(i != (sg_len - 1) && (len & 1)) +     len--; +             while(len >= sizeof(*sdata)) {             put_data(sc, *sdata++);             len -= sizeof(*sdata);
Altera_Forum
Honored Contributor II
142 Views

 

--- Quote Start ---  

originally posted by tuck@Feb 24 2006, 02:01 PM 

ok i think i fixed the odd buffer size issue, but the checksum issue remains. 

 

since this is calculated further up the stack, and my cursory glance didn&#39;t reveal any areas in the driver that may be corrupting the header i think there is another issue. 

 

when i went in the debugger and manually corrected the crc in the header the remaining data looked fine, so hopefully this can help! 

 

unfortunately i can&#39;t spend more time on this since i won&#39;t be using this driver once our boards arrive, and the issue isn&#39;t affecting me right this instant. i went ahead and put a patch together. it&#39;s not well tested, but the tests i have done indicate that it is working as designed. 

 

if you take the following text save it to a file and execute patch -p0 < patchfile from your nios2 shell in the ecos-current dirctory (probably /cygdrive/c/altera/kits/nios2_51/components/ecos/ecos-current). it should resolve the buffer issue (i think http://forum.niosforum.com/work2/style_emoticons/<#emo_dir#>/smile.gif ). 

diff -naru packagesorig/devs/eth/smsc/lan91cxx/current/src/if_lan91cxx.c packages/devs/eth/smsc/lan91cxx/current/src/if_lan91cxx.c --- packagesorig/devs/eth/smsc/lan91cxx/current/src/if_lan91cxx.c    2005-01-07 12:50:34.000000000 -0500 +++ packages/devs/eth/smsc/lan91cxx/current/src/if_lan91cxx.c    2006-02-24 11:30:49.525340400 -0500 @@ -860,13 +860,53 @@     // packet length (includes status, byte-count and control shorts)     put_data(sc, cyg_cpu_to_le16(0x7fe & (plen + 6)) ); // always even, always < 15xx(dec) +    //since this driver transfers 2 bytes at a time buffers in the beginning of +    //the scatter gather list with odd lengths must be combined with their +    //next neighbor to create 2 byte sets. the oddhandled variable tracks if +    //the prior iteration handled one of these conditions +    bool oddhandled = false;     // put data into buffer     for (i = 0;  i < sg_len;  i++) { -        sdata = (unsigned short *)sg_list.buf; -        len = sg_list.len; +    // 2006.02.24 - thw - odd lengths now handled. +    //cyg_assert(0 == (len & 1) || (i == (sg_len-1)), "odd length"); -        cyg_assert(0 == (len & 1) || (i == (sg_len-1)), "odd length"); -        cyg_assert( sdata, "no sg data pointer here" ); +    //if this is the first buffer then just process as normal +    //if this is a middle buffer then inspect the previous buffer: +    // - if previous length was odd and the last iteration didn&#39;t handle an +    //     odd buffer then we need to combine. +    // - if the previous iteration did handle an odd buffer and it&#39;s length +    //     is even it total transfer was odd and i need to combine. +    bool lastlenodd = sg_list.len & 1; +    if(i && (lastlenodd ^ oddhandled)){ +     //notify the next iteration that this iteration handled an odd +     //buffer. +     oddhandled = true; + +     //get the last byte of the last buffer and shift it into msb. +     short data = ((char*)sg_list.buf).len - 1)]; +     data = data << 8; + +     //add in the first byte from my buffer to the lsb. +     data |= ((char*)sg_list.buf); +     //correct my current pointer (since i just sent one of my bytes). +     sdata = (unsigned short *)(sg_list.buf + 1); + +     //send this off. +     put_data(sc, *sdata); +     len = sg_list.len - 1; +    } +    else { +     oddhandled = false; +     sdata = (unsigned short *)sg_list.buf; +     len = sg_list.len; +    } +    cyg_assert( sdata, "no sg data pointer here" ); + +    //if this isn&#39;t the last buffer and my len is odd then don&#39;t transfer +    //the last byte (the next iteration will handle it). +    if(i != (sg_len - 1) && (len & 1)) +     len--; +             while(len >= sizeof(*sdata)) {             put_data(sc, *sdata++);             len -= sizeof(*sdata); 

<div align='right'><{post_snapback}> (index.php?act=findpost&pid=12954)</div> 

--- Quote End ---  

Altera_Forum
Honored Contributor II
142 Views

 

--- Quote Start ---  

originally posted by graham615+mar 9 2006, 03:41 pm--><div class='quotetop'>quote (graham615 @ mar 9 2006, 03:41 pm)</div> 

--- quote start ---  

<!--quotebegin-tuck@Feb 24 2006, 02:01 PM 

ok i think i fixed the odd buffer size issue, but the checksum issue remains. 

 

since this is calculated further up the stack, and my cursory glance didn&#39;t reveal any areas in the driver that may be corrupting the header i think there is another issue. 

 

when i went in the debugger and manually corrected the crc in the header the remaining data looked fine, so hopefully this can help! 

 

unfortunately i can&#39;t spend more time on this since i won&#39;t be using this driver once our boards arrive, and the issue isn&#39;t affecting me right this instant. i went ahead and put a patch together. it&#39;s not well tested, but the tests i have done indicate that it is working as designed. 

 

if you take the following text save it to a file and execute patch -p0 < patchfile from your nios2 shell in the ecos-current dirctory (probably /cygdrive/c/altera/kits/nios2_51/components/ecos/ecos-current). it should resolve the buffer issue (i think http://forum.niosforum.com/work2/style_emoticons/<#emo_dir#>/smile.gif ). 

diff -naru packagesorig/devs/eth/smsc/lan91cxx/current/src/if_lan91cxx.c packages/devs/eth/smsc/lan91cxx/current/src/if_lan91cxx.c --- packagesorig/devs/eth/smsc/lan91cxx/current/src/if_lan91cxx.c    2005-01-07 12:50:34.000000000 -0500 +++ packages/devs/eth/smsc/lan91cxx/current/src/if_lan91cxx.c    2006-02-24 11:30:49.525340400 -0500 @@ -860,13 +860,53 @@     // packet length (includes status, byte-count and control shorts)     put_data(sc, cyg_cpu_to_le16(0x7fe & (plen + 6)) ); // always even, always < 15xx(dec) +    //since this driver transfers 2 bytes at a time buffers in the beginning of +    //the scatter gather list with odd lengths must be combined with their +    //next neighbor to create 2 byte sets. the oddhandled variable tracks if +    //the prior iteration handled one of these conditions +    bool oddhandled = false;     // put data into buffer     for (i = 0;  i < sg_len;  i++) { -        sdata = (unsigned short *)sg_list.buf; -        len = sg_list.len; +    // 2006.02.24 - thw - odd lengths now handled. +    //cyg_assert(0 == (len & 1) || (i == (sg_len-1)), "odd length"); -        cyg_assert(0 == (len & 1) || (i == (sg_len-1)), "odd length"); -        cyg_assert( sdata, "no sg data pointer here" ); +    //if this is the first buffer then just process as normal +    //if this is a middle buffer then inspect the previous buffer: +    // - if previous length was odd and the last iteration didn&#39;t handle an +    //     odd buffer then we need to combine. +    // - if the previous iteration did handle an odd buffer and it&#39;s length +    //     is even it total transfer was odd and i need to combine. +    bool lastlenodd = sg_list.len & 1; +    if(i && (lastlenodd ^ oddhandled)){ +     //notify the next iteration that this iteration handled an odd +     //buffer. +     oddhandled = true; + +     //get the last byte of the last buffer and shift it into msb. +     short data = ((char*)sg_list.buf).len - 1)]; +     data = data << 8; + +     //add in the first byte from my buffer to the lsb. +     data |= ((char*)sg_list.buf); +     //correct my current pointer (since i just sent one of my bytes). +     sdata = (unsigned short *)(sg_list.buf + 1); + +     //send this off. +     put_data(sc, *sdata); +     len = sg_list.len - 1; +    } +    else { +     oddhandled = false; +     sdata = (unsigned short *)sg_list.buf; +     len = sg_list.len; +    } +    cyg_assert( sdata, "no sg data pointer here" ); + +    //if this isn&#39;t the last buffer and my len is odd then don&#39;t transfer +    //the last byte (the next iteration will handle it). +    if(i != (sg_len - 1) && (len & 1)) +     len--; +             while(len >= sizeof(*sdata)) {             put_data(sc, *sdata++);             len -= sizeof(*sdata); 

<div align='right'><{post_snapback}> (index.php?act=findpost&pid=12954)</div> 

--- Quote End ---  

 

<div align='right'><{post_snapback}> (index.php?act=findpost&pid=13264)</div> 

[/b] 

--- Quote End ---  

 

Tuck: 

 

Ok......thanks for your reply and directing me to the solution to this problem. Basically we only need to look at whether or not we have a byte left over from the last transmission. In that case, we need to output output the remain byte plus the first byte of the next buffer. This results in odd data alignment. To fix this, there are two while loops; one for even alignment and one for odd alignment. The following code works with no asserts and no checksum errors. 

 

// modified 03/09/2006 to handle odd lenght segment buffers 

 

bool byteRemaining = false; // indicates byte remaining from last buffer 

short data; // data to be sent to device 

char * pCData; // temp pointer to char array 

 

for (i = 0; i < sg_len; i++) 

// get the data length and the pointer to the data 

sdata = (unsigned short *)sg_list.buf; 

len = sg_list.len; 

 

CYG_ASSERT( sdata, "No sg data pointer here" ); 

 

// is there a byte remaining from the last buffer ? 

if( byteRemaining) 

// yes - send the remaining byte with the first byte of this segment 

data = ((char*)sg_list[i-1].buf)[(sg_list[i-1].len - 1)]; 

 

//Add in the first byte from my buffer to the LSB. 

data |= ((char*)sg_list.buf)[0] << 8; 

 

//send this off. 

put_data(sc, data); 

 

//correct my current pointer (since i just sent one of my bytes). 

pcdata = ((char *)sg_list.buf) + 1; 

 

// adjust the length 

len--; 

 

// output data aligned to short 

while(len >= sizeof(*sdata)) 

data = *pCData++; 

data |= *pCData++ << 8; 

 

put_data(sc, data); 

 

len -= sizeof( short); 

else 

// output 

while(len >= sizeof(*sdata)) 

put_data(sc, *sdata++); 

len -= sizeof(*sdata); 

 

byteRemaining = len; 

 

 

CYG_ASSERT( sdata, "No sg data pointer outside" );
Altera_Forum
Honored Contributor II
142 Views

Version 2.5 of the Goahead-Webserver has been posted now at embedthis.com

Reply