Changeset 683 for trunk/kernel/devices


Ignore:
Timestamp:
Jan 13, 2021, 12:36:17 AM (4 years ago)
Author:
alain
Message:

All modifications required to support the <tcp_chat> application
including error recovery in case of packet loss.A

Location:
trunk/kernel/devices
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/kernel/devices/dev_fbf.c

    r674 r683  
    159159                                intptr_t * user_buffer )
    160160{
    161     kmem_req_t     req;
    162161    fbf_window_t * window;      // window descriptor (created in local cluster)
    163162    vseg_t       * vseg;        // vseg descriptor (created in reference cluster)
     
    202201 
    203202    // allocate memory for the window descriptor in local cluster
    204     req.type   = KMEM_KCM;
    205     req.order  = bits_log2( sizeof(fbf_window_t) );
    206     req.flags  = AF_ZERO | AF_KERNEL;
    207     window     = kmem_alloc( &req );
     203    window  = kmem_alloc( bits_log2(sizeof(fbf_window_t)) , AF_ZERO );
    208204
    209205    if( window == NULL )
     
    256252        printk("\n[ERROR] in %s / thread[%x,%x] cannot create vseg in reference cluster\n",
    257253        __FUNCTION__, process->pid, this->trdid );
    258         req.ptr = (void *)window;
    259         kmem_free( &req );
     254        kmem_free( window , bits_log2(sizeof(fbf_window_t)) );
    260255        return -1;
    261256    }
     
    281276        printk("\n[ERROR] in %s / thread[%x,%x] cannot allocate buffer for window\n",
    282277        __FUNCTION__, process->pid, this->trdid );
    283         req.ptr = (void *)window;
    284         kmem_free( &req );
     278        kmem_free( window , bits_log2(sizeof(fbf_window_t)) );
    285279        vmm_remove_vseg( process , vseg );
    286280        return -1;
     
    521515error_t dev_fbf_delete_window( uint32_t  wid )
    522516{
    523     kmem_req_t     req;
    524 
    525517    thread_t  * this    = CURRENT_THREAD;
    526518    process_t * process = this->process;
     
    581573 
    582574    // 8. release memory allocated for window descriptor
    583     req.type = KMEM_KCM;
    584     req.ptr  = window_ptr;
    585     kmem_remote_free( window_cxy , &req );
     575    kmem_remote_free( window_cxy , window_ptr , bits_log2(sizeof(fbf_window_t)) );
    586576
    587577    // 9. release the associated vseg
  • trunk/kernel/devices/dev_nic.c

    r674 r683  
    1 
    21/*
    32 * dev_nic.c - NIC (Network Controler) generic device API implementation.
     
    4645void dev_nic_init( chdev_t * chdev )
    4746{
     47
     48assert( __FUNCTION__ , (chdev->func == DEV_FUNC_NIC) ,
     49"bad func value");
     50
    4851    thread_t * new_thread;
    4952    error_t    error;
     
    7477
    7578    // build pointer on server function
    76     void * func = is_rx ? &dev_nic_rx_server : &dev_nic_tx_server;
     79    void * server_func = is_rx ? &dev_nic_rx_server : &dev_nic_tx_server;
    7780
    7881    // create server thread
    7982    error = thread_kernel_create( &new_thread,
    8083                                  THREAD_DEV,
    81                                   func,
     84                                  server_func,
    8285                                  chdev,
    8386                                  lid );
     
    120123    thread_t * this = CURRENT_THREAD;
    121124   
    122     xptr_t dev_xp = chdev_dir.nic_tx[0];
     125    // get cluster and local pointer fo the nic_tx[0] chdev
     126    xptr_t    dev_xp  = chdev_dir.nic_tx[0];
    123127    chdev_t * dev_ptr = GET_PTR( dev_xp );
    124 
    125     if( dev_xp == XPTR_NULL ) return -1;
     128    cxy_t     dev_cxy = GET_CXY( dev_xp );
     129
     130    if( dev_xp == XPTR_NULL )
     131    {
     132
     133#if DEBUG_DEV_NIC_ERROR
     134printk("\n[ERROR] in %s : nic_tx[0] chdev undefined in chdev_dir of cluster %x\n",
     135__FUNCTION__, local_cxy );
     136#endif
     137        return -1;
     138    }
    126139   
    127140    // set command arguments in client thread descriptor
     
    131144    this->nic_cmd.type   = NIC_CMD_GET_KEY;
    132145
     146    // get cmd function pointer from nic_tx[0] chdev descriptor
     147    dev_cmd_t * cmd = hal_remote_lpt( XPTR( dev_cxy , &dev_ptr->cmd ));
     148   
    133149    // call driver
    134     dev_ptr->cmd( XPTR( local_cxy , this ) );
    135 
    136     // get "status"
     150    cmd( XPTR( local_cxy , this ) );
     151
     152    // return command status
    137153    return this->nic_cmd.status;
    138 }
     154
     155}  // end dev_nic_get_key()
    139156
    140157//////////////////////////////////////////
     
    146163    if( channel >= LOCAL_CLUSTER->nb_nic_channels ) return -1;
    147164
    148     xptr_t    dev_xp  = chdev_dir.nic_tx[0];
     165    // get cluster and local pointer fo the nic_tx[channel] chdev
     166    xptr_t    dev_xp  = chdev_dir.nic_tx[channel];
    149167    chdev_t * dev_ptr = GET_PTR( dev_xp );
    150 
    151     if( dev_xp == XPTR_NULL ) return -1;
     168    cxy_t     dev_cxy = GET_CXY( dev_xp );
     169
     170    if( dev_xp == XPTR_NULL )
     171    {
     172
     173#if DEBUG_DEV_NIC_ERROR
     174printk("\n[ERROR] in %s : nic_tx[%d] chdev undefined in chdev_dir of cluster %x\n",
     175__FUNCTION__, channel, local_cxy );
     176#endif
     177        return -1;
     178    }
    152179   
    153180    // set command arguments in client thread descriptor
     
    157184    this->nic_cmd.status = run;
    158185
     186    // get cmd function pointer from nic_tx[channel] chdev descriptor
     187    dev_cmd_t * cmd = hal_remote_lpt( XPTR( dev_cxy , &dev_ptr->cmd ));
     188   
    159189    // call driver
    160     dev_ptr->cmd( XPTR( local_cxy , this ) );
     190    cmd( XPTR( local_cxy , this ) );
    161191
    162192    // return "error"
    163193    return this->nic_cmd.error;
    164 }
     194
     195}  // end dev_nic_set_run()
    165196
    166197//////////////////////////////////
     
    169200    thread_t * this = CURRENT_THREAD;
    170201
     202    // get cluster and local pointer fo the nic_tx[0] chdev
    171203    xptr_t    dev_xp  = chdev_dir.nic_tx[0];
    172204    chdev_t * dev_ptr = GET_PTR( dev_xp );
     205    cxy_t     dev_cxy = GET_CXY( dev_xp );
    173206   
    174     if( dev_xp == XPTR_NULL ) return -1;
     207    if( dev_xp == XPTR_NULL )
     208    {
     209
     210#if DEBUG_DEV_NIC_ERROR
     211printk("\n[ERROR] in %s : nic_tx[0] chdev undefined in chdev_dir of cluster %x\n",
     212__FUNCTION__, local_cxy );
     213#endif
     214        return -1;
     215    }
    175216   
    176217    // set command arguments in client thread descriptor
     
    178219    this->nic_cmd.type   = NIC_CMD_GET_INSTRU;
    179220
     221    // get cmd function pointer from nic_tx[0] chdev descriptor
     222    dev_cmd_t * cmd = hal_remote_lpt( XPTR( dev_cxy , &dev_ptr->cmd ));
     223   
    180224    // call driver
    181     dev_ptr->cmd( XPTR( local_cxy , this ) );
     225    cmd( XPTR( local_cxy , this ) );
    182226
    183227    // return "error"
    184228    return this->nic_cmd.error;
    185 }
     229
     230}  // end dev_nic_get_instru()
     231
    186232
    187233////////////////////////////////////
     
    190236    thread_t * this = CURRENT_THREAD;
    191237
     238    // get cluster and local pointer fo the nic_tx[0] chdev
    192239    xptr_t    dev_xp  = chdev_dir.nic_tx[0];
    193240    chdev_t * dev_ptr = GET_PTR( dev_xp );
     241    cxy_t     dev_cxy = GET_CXY( dev_xp );
    194242   
    195     if( dev_xp == XPTR_NULL ) return -1;
     243    if( dev_xp == XPTR_NULL )
     244    {
     245
     246#if DEBUG_DEV_NIC_ERROR
     247printk("\n[ERROR] in %s : nic_tx[0] chdev undefined in chdev_dir of cluster %x\n",
     248__FUNCTION__, local_cxy );
     249#endif
     250        return -1;
     251    }
    196252   
    197253    // set command arguments in client thread descriptor
     
    199255    this->nic_cmd.type   = NIC_CMD_GET_INSTRU;
    200256
     257    // get cmd function pointer from nic_tx[0] chdev descriptor
     258    dev_cmd_t * cmd = hal_remote_lpt( XPTR( dev_cxy , &dev_ptr->cmd ));
     259   
    201260    // call driver
    202     dev_ptr->cmd( XPTR( local_cxy , this ) );
     261    cmd( XPTR( local_cxy , this ) );
    203262
    204263    // return "error"
    205264    return this->nic_cmd.error;
    206 }
     265
     266}  // end dev_nic_clear_instru()
    207267
    208268
     
    261321
    262322////////////////////////////////////////////////////////////////////////////////////////
    263 // This static function computes the checksum for an UDP packet defined by
    264 // the <buffer> and <size> arguments.
     323// This static function computes the checksum for a TCP segment or an UDP packet,
     324// defined by the <buffer> and <length> arguments.
     325// It includes the "pseudo header "defined by the <src_ip_addr>, <dst_ip_addr>, and
     326// <tcp_length> arguments, and by the UDP/TCP protocol code.
    265327////////////////////////////////////////////////////////////////////////////////////////
    266 // @ buffer      : [in] pointer on UDP packet base.
    267 // @ size        : [in] number of bytes in this packet (including header).
     328// @ buffer      : [in] pointer on buffer containing the TCP segment or UDP packet.
     329// @ length      : [in] number of bytes in this packet/segment (including header).
     330// @ src_ip_addr : [in] source IP address (pseudo header).
     331// @ dst_ip_addr : [in] destination IP address (pseudo header).
     332// @ is_tcp      : [in] TCP if true / UDP if false (pseudo header).
    268333// @ return the checksum value on 16 bits
    269334////////////////////////////////////////////////////////////////////////////////////////
    270 static uint16_t dev_nic_udp_checksum( uint8_t  * buffer,
    271                                       uint32_t   size )
    272 {
    273     uint32_t   i;           
    274     uint32_t   carry;
    275     uint32_t   cs;      // 32 bits accumulator
    276     uint16_t * buf;     
    277     uint32_t   max;     // number of uint16_t in packet
    278    
    279     // compute max & buf
    280     buf = (uint16_t *)buffer;
    281     max = size >> 1;
    282 
    283     // extend buffer[] if required
    284     if( size & 1 )
    285     {
    286         max++;
    287         buffer[size] = 0;
    288     }
    289 
    290     // compute checksum for UDP packet
    291     for( i = 0 , cs = 0 ; i < size ; i++ )  cs += buf[i];
    292 
    293     // handle carry
    294     carry = (cs >> 16);
    295     if( carry )
    296     {
    297         cs += carry;
    298         carry = (cs >> 16);
    299         if( carry ) cs += carry;
    300     }
    301 
    302     // one's complement
    303     return ~cs;
    304 }
    305 
    306 ////////////////////////////////////////////////////////////////////////////////////////
    307 // This static function computes the checksum for a TCP segment defined by the <buffer>
    308 // and <size> arguments. It includes the pseudo header defined by the <src_ip_addr>,
    309 // <dst_ip_addr>, <size> arguments, and by the TCP_PROTOCOL code.
    310 ////////////////////////////////////////////////////////////////////////////////////////
    311 // @ buffer      : [in] pointer on TCP segment base.
    312 // @ tcp_length  : [in] number of bytes in this TCP segment (including header).
    313 // @ src_ip_addr : [in] source IP address (pseudo header)
    314 // @ dst_ip_addr : [in] destination IP address (pseudo header)
    315 // @ return the checksum value on 16 bits
    316 ////////////////////////////////////////////////////////////////////////////////////////
    317 static uint16_t dev_nic_tcp_checksum( uint8_t  * buffer,
    318                                       uint32_t   tcp_length,
    319                                       uint32_t   src_ip_addr,
    320                                       uint32_t   dst_ip_addr )
     335static uint16_t dev_nic_tcp_udp_checksum( uint8_t  * buffer,
     336                                          uint32_t   length,
     337                                          uint32_t   src_ip_addr,
     338                                          uint32_t   dst_ip_addr,
     339                                          bool_t     is_tcp )
    321340{
    322341    uint32_t   i;           
     
    324343    uint32_t   cs;      // 32 bits accumulator
    325344    uint16_t * buf;
    326     uint32_t   max;     // number of uint16_t in segment
     345    uint32_t   max;     // number of uint16_t in segment/paket
    327346
    328347    // compute max & buf
    329348    buf = (uint16_t *)buffer;
    330     max = tcp_length >> 1;
     349    max = length >> 1;
    331350
    332351    // extend buffer[] if required
    333     if( tcp_length & 1 )
     352    if( length & 1 )
    334353    {
    335354        max++;
    336         buffer[tcp_length] = 0;
     355        buffer[length] = 0;
    337356    }
    338357
    339358    // compute checksum for TCP segment
    340     for( i = 0 , cs = 0 ; i < tcp_length ; i++ )  cs += buf[i];
     359    for( i = 0 , cs = 0 ; i < max ; i++ )  cs += buf[i];
    341360
    342361    // complete checksum for pseudo-header
    343     cs += src_ip_addr;
    344     cs += dst_ip_addr;
    345     cs += PROTOCOL_TCP;
    346     cs += tcp_length;
     362    cs += (src_ip_addr & 0xFFFF);
     363    cs += (src_ip_addr >> 16 );
     364    cs += (dst_ip_addr & 0xFFFF);
     365    cs += (dst_ip_addr >> 16 );
     366    cs += length;
     367    cs += (is_tcp ? PROTOCOL_TCP : PROTOCOL_UDP);
    347368
    348369    // handle carry
     
    360381
    361382///////////////////////////////////////////////////////////////////////////////////////////
    362 // This static function is called by the NIC_TX or NIC_RX server threads to unblock
     383// This static function is called by the NIC_TX and NIC_RX server threads to unblock
    363384// the TX client thread after completion (success or error) of a TX command registered
    364 // in a socket identified by the <socket_xp> argument. The <status> argument defines
    365 // the command success/failure status: a null value signals a success, a non-null value
    366 // signals a failure. For all commands, it copies the status value in the tx_sts field,
    367 // and print an error message on TXT0 in case of failure.
     385// in a socket identified by the <socket_xp> argument.
     386// The <status> argument defines the command success/failure status.
     387// For all commands, it copies the status value in the tx_sts field, and print an error
     388// message on TXT0 in case of failure.
    368389///////////////////////////////////////////////////////////////////////////////////////////
    369390// @ socket_xp  : [in] extended pointer on socket
     
    377398    cxy_t      socket_cxy = GET_CXY( socket_xp );
    378399
    379     if( status != CMD_STS_SUCCESS )
     400    if( (status != CMD_STS_SUCCESS) && (status != CMD_STS_EOF) )
    380401    {
    381402        uint32_t sock_state = hal_remote_l32( XPTR( socket_cxy , &socket_ptr->state ));
     
    400421}  // end dev_nic_unblock_tx_client()
    401422
    402 ///////////////////////////////////////////////////////////////////////////////////////////
    403 // This static function is called by the NIC_TX or NIC_RX server threads to unblock
     423
     424///////////////////////////////////////////////////////////////////////////////////////////
     425//               Functions called by the NIC_RX server thread
     426///////////////////////////////////////////////////////////////////////////////////////////
     427
     428///////////////////////////////////////////////////////////////////////////////////////////
     429// This static function is called by the NIC_RX server threads to unblock
    404430// the RX client thread after completion (success or error) of an RX command registered
    405 // in a socket identified by the <socket_xp> argument. The <status> argument defines
    406 // the command success/failure status: a null value signals a success, a non-null value
    407 // signals a failure. For all commands, it copies the status value in the rx_sts field,
    408 // and print an error message on TXT0 in case of failure.
     431// in a socket identified by the <socket_xp> argument.
     432// The <status> argument defines the command success/failure status.
     433// For all commands, it copies the status value in the rx_sts field, and print an error
     434// message on TXT0 in case of failure.
    409435///////////////////////////////////////////////////////////////////////////////////////////
    410436// @ socket_xp  : [in] extended pointer on socket
     
    418444    cxy_t      socket_cxy = GET_CXY( socket_xp );
    419445
    420     if( status != CMD_STS_SUCCESS )
     446    if( (status != CMD_STS_SUCCESS) && (status != CMD_STS_EOF) )
    421447    {
    422448        uint32_t sock_state = hal_remote_l32( XPTR( socket_cxy , &socket_ptr->state ));
     
    440466
    441467}  // end dev_nic_unblock_rx_client()
    442 
    443 ///////////////////////////////////////////////////////////////////////////////////////////
    444 //               Functions called by the NIC_RX server thread
    445 ///////////////////////////////////////////////////////////////////////////////////////////
    446468
    447469///////////////////////////////////////////////////////////////////////////////////////////
     
    553575   
    554576    return 0;
    555 }
     577
     578}   // end dev_nic_rx_check_ip()
    556579
    557580///////////////////////////////////////////////////////////////////////////////////////////
     
    595618    xptr_t     socket_rbuf_xp;    // extended pointer on socket rx_buf
    596619    xptr_t     socket_lock_xp;    // extended pointer on socket lock
    597     xptr_t     socket_client_xp;  // extended pointer on socket rx_client field
    598     xptr_t     client_xp;         // extended pointer on client thread descriptor
     620    xptr_t     socket_rx_client;  // socket rx_client thread
     621    bool_t     socket_rx_valid;   // socket rx_command valid
     622    uint32_t   socket_rx_cmd;     // socket rx_command type
    599623    uint32_t   payload;           // number of bytes in payload
    600624    uint32_t   status;            // number of bytes in rx_buf
     
    602626    uint32_t   moved_bytes;       // number of bytes actually moved to rx_buf
    603627
     628#if DEBUG_DEV_NIC_RX || DEBUG_DEV_NIC_ERROR
     629thread_t * this  = CURRENT_THREAD;
     630uint32_t   cycle = (uint32_t)hal_get_cycles();
     631#endif
     632
     633#if DEBUG_DEV_NIC_RX
     634uint32_t   fdid;
     635uint32_t   pid;
     636if( DEBUG_DEV_NIC_RX < cycle )
     637printk("\n[%s] thread[%x,%x] enter / channel %d / plen %d / cycle %d\n",
     638__FUNCTION__, this->process->pid, this->trdid, chdev->channel, k_length, cycle );
     639if( (DEBUG_DEV_NIC_RX < cycle) && (DEBUG_DEV_NIC_RX & 1))
     640putb("64 first bytes in k_buf" , k_buf , 64 );
     641#endif
     642
    604643    // build extended pointers on list of sockets attached to NIC_RX chdev
    605644    root_xp = XPTR( local_cxy , &chdev->wait_root );
    606645    lock_xp = XPTR( local_cxy , &chdev->wait_lock );
    607646
    608     // compute UDP packet checksum
    609     checksum = dev_nic_udp_checksum( k_buf , k_length );
    610 
    611     // get checksum from received packet header
     647    // extract checksum from received UDP packet header
    612648    pkt_checksum = ((uint16_t)k_buf[6] << 8) | (uint16_t)k_buf[7];
    613649
     650    // reset checksum field
     651    k_buf[6] = 0;
     652    k_buf[7] = 0;
     653
     654    // compute checksum from received UDP packet
     655    checksum = dev_nic_tcp_udp_checksum( k_buf,
     656                                         k_length,
     657                                         pkt_src_addr,
     658                                         pkt_dst_addr,
     659                                         false );        // is_not_tcp
    614660    // discard corrupted packet 
    615     if( pkt_checksum != checksum ) return;
     661    if( pkt_checksum != checksum )
     662    {
     663
     664#if DEBUG_DEV_NIC_ERROR
     665printk("\n[WARNING] in %s : thread[%x,%x] discard corrupted packet on channel %d / cycle %d\n"
     666"   expected checksum %x / received checksum %x\n",
     667__FUNCTION__, this->process->pid, this->trdid, chdev->channel, cycle,
     668(uint32_t)checksum, (uint32_t)pkt_checksum );
     669#endif
     670        return;
     671    }
    616672   
    617673    // get src_port and dst_port from UDP header
     
    619675    uint32_t pkt_dst_port = ((uint32_t)k_buf[2] << 8) | (uint32_t)k_buf[3];
    620676
    621     // discard unexpected packet
    622     if( xlist_is_empty( root_xp ) ) return;
    623  
    624677    // take the lock protecting the sockets list
    625678    remote_busylock_acquire( lock_xp );
     
    658711        else                                  match_socket = local_match;
    659712
    660         // exit loop when socket found
    661         if( match_socket ) break;
     713        // exit loop if matching
     714        if( match_socket )
     715        {
     716
     717#if DEBUG_DEV_NIC_RX
     718fdid = hal_remote_l32( XPTR( socket_cxy , &socket_ptr->fdid ) );
     719pid  = hal_remote_l32( XPTR( socket_cxy , &socket_ptr->pid ) );
     720if( DEBUG_DEV_NIC_RX < cycle )
     721printk("\n[%s] thread[%x,%x] found matching UDP socket[%d,%d] / state %s\n",
     722__FUNCTION__, this->process->pid, this->trdid, pid, fdid, socket_state_str(socket_state) );
     723#endif
     724            break;
     725        }
    662726    }
    663727
     
    666730
    667731    // discard unexpected packet
    668     if( match_socket == false ) return;
    669    
    670     // build extended pointers on various socket fields
     732    if( match_socket == false )
     733    {
     734
     735#if DEBUG_DEV_NIC_ERROR
     736printk("\n[WARNING] in %s : thread[%x,%s] discard unexpected packet on channel %d / cycle %d\n",
     737__FUNCTION__, this->process->pid, this->trdid, chdev->channel, cycle );
     738#endif
     739        return;
     740    }
     741 
     742    // build extended pointers on socket.rx_buf and socket.lock
    671743    socket_rbuf_xp   = XPTR( socket_cxy , &socket_ptr->rx_buf );
    672744    socket_lock_xp   = XPTR( socket_cxy , &socket_ptr->lock );
    673     socket_client_xp = XPTR( socket_cxy , &socket_ptr->rx_client );
    674745
    675746    // take the lock protecting the socket
     
    678749    // get status & space from rx_buf
    679750    status = remote_buf_status( socket_rbuf_xp );
    680     space  = CONFIG_SOCK_RX_BUF_SIZE - status;
    681 
    682     // get client thread
    683     client_xp  = hal_remote_l64( socket_client_xp );
     751    space  = (1 << CONFIG_SOCK_RX_BUF_ORDER) - status;
     752
     753    // get socket rx_client, rx_valid and rx_cmd values
     754    socket_rx_client = hal_remote_l64( XPTR( socket_cxy , &socket_ptr->rx_client ) );
     755    socket_rx_valid  = hal_remote_l32( XPTR( socket_cxy , &socket_ptr->rx_valid ) );
     756    socket_rx_cmd    = hal_remote_l32( XPTR( socket_cxy , &socket_ptr->rx_cmd ) );
    684757
    685758    // get number of bytes in payload
     
    691764    // move payload from kernel buffer to socket rx_buf
    692765    remote_buf_put_from_kernel( socket_rbuf_xp,
    693                                  k_buf + UDP_HEAD_LEN,
    694                                  moved_bytes );
    695     // unblock client thread
    696     if( client_xp != XPTR_NULL )
    697     {
    698         thread_unblock( client_xp , THREAD_BLOCKED_IO );
     766                                k_buf + UDP_HEAD_LEN,
     767                                moved_bytes );
     768#if DEBUG_DEV_NIC_RX
     769if( DEBUG_DEV_NIC_RX < cycle )
     770printk("\n[%s] thread[%x,%x] for socket[%d,%d] move %d bytes to rx_buf / buf_sts %d\n",
     771__FUNCTION__, this->process->pid, this->trdid, pid, fdid,
     772moved_bytes, remote_buf_status(socket_rbuf_xp), moved_bytes );
     773#endif
     774
     775    // signal client thread if pending RECV command
     776    if( (socket_rx_valid == true) && (socket_rx_cmd == CMD_RX_RECV) )
     777    {
     778        // reset rx_valid
     779        hal_remote_s32( XPTR(socket_cxy , &socket_ptr->rx_valid), false );
     780
     781        // report success to RX client thread
     782        dev_nic_unblock_rx_client( socket_xp , CMD_STS_SUCCESS );
     783
     784#if DEBUG_DEV_NIC_RX
     785if( DEBUG_DEV_NIC_RX < cycle )
     786printk("\n[%s] thread[%x,%x] for UDP socket[%x,%d] / unblock client thread\n",
     787__FUNCTION__, this->process->pid, this->trdid, pid, fdid );
     788#endif
     789
     790    }
     791    else
     792    {
     793
     794#if DEBUG_DEV_NIC_RX
     795if( DEBUG_DEV_NIC_RX < cycle )
     796printk("\n[%s] thread[%x,%x] for socket[%x,%d] / no client thread\n"
     797"    rx_valid %d / rx_cmd %s\n",
     798__FUNCTION__, this->process->pid, this->trdid, pid, fdid,
     799socket_rx_valid , socket_cmd_type_str(socket_rx_cmd) );
     800#endif
     801
    699802    }
    700803
     
    707810// This static function is called by the dev_nic_rx_server() function to handle one RX
    708811// TCP segment contained in a kernel buffer defined by the <k_buf> & <k_length> arguments.
    709 // The <seg_remote_addr> and <seg_local_addr> arguments are obtained from the received
    710 // IP packet header. It the received segment doesn't match any connected socket attached
    711 // to the selected chdev[k], or any listening socket waiting connection, or if the segment
    712 // is corrupted, this segment is discarded.
    713 // If required by the TCP flags, it registers an R2T request in the socket R2T queue
    714 // to implement the TCP handcheck for close and connect.
     812// The <seg_remote_addr> and <seg_local_addr> arguments have been extracted from the IP
     813// IP header. The local and remote ports are obtained from the TCP header.
     814// It the received segment doesn't match any connected socket attached to the selected
     815// <chdev>, or any listening socket waiting connection, or if the segment is corrupted,
     816// the segment is discarded. This function implement the TCP error recovery protocol,
     817// as specified by the RFC. Depending on both the socket state, and the segment header:
     818//  - it register data in the RX buffer,
     819//  - it update the socket state and TCB,
     820//  - it register acknolegce requests in the R2T queue,
     821//  - it register connection requests in the CRQ queue,
    715822///////////////////////////////////////////////////////////////////////////////////////////
    716823// Implementation note:
     
    724831//    the SYN, FIN, ACK and RST flags. It updates the socket state when required, moves
    725832//    data to the rx_buf when possible, and return. It takes the lock protecting the socket,
    726 //    because an connected socket is accessed by both the NIC_TX and NIC_RX server threads.
     833//    because a connected socket is accessed by both the NIC_TX and NIC_RX server threads.
    727834// 4) If no matching connected socket has been found, it scans the list of listening
    728835//    sockets to find a matching listening socket.
     
    760867    bool_t     socket_tx_valid;    // TX command valid
    761868    uint32_t   socket_tx_cmd;      // TX command type
    762     uint32_t   socket_tx_todo;     // number of TX bytes not sent yet
    763869    uint32_t   socket_tx_nxt;      // next byte to send in TX stream
    764870    uint32_t   socket_tx_una;      // first unacknowledged byte in TX stream
     871    uint32_t   socket_tx_len;      // number of bytes in tx_buf
     872    uint32_t   socket_tx_ack;      // number of acknowledged bytes in tx_buf
    765873    bool_t     socket_rx_valid;    // RX command valid
    766874    uint32_t   socket_rx_cmd;      // TX command type
     
    804912    uint32_t seg_data_len = k_length - seg_hlen;  // number of bytes in payload
    805913
    806 #if DEBUG_DEV_NIC_RX
    807 thread_t * this = CURRENT_THREAD;
    808 uint32_t   cycle;
     914    uint32_t seg_data_dup;     // number of duplicated bytes in payload
     915    uint32_t seg_data_new;     // number of new bytes in payload
     916
     917#if DEBUG_DEV_NIC_RX || DEBUG_DEV_NIC_ERROR
    809918uint32_t   fdid;
    810919pid_t      pid;
    811 #endif
    812 
    813 #if DEBUG_DEV_NIC_RX
    814 cycle = (uint32_t)hal_get_cycles();
    815 if( cycle > DEBUG_DEV_NIC_RX )
     920thread_t * this  = CURRENT_THREAD;
     921uint32_t   cycle = (uint32_t)hal_get_cycles();
     922#endif
     923
     924#if DEBUG_DEV_NIC_RX
     925if( DEBUG_DEV_NIC_RX < cycle )
    816926printk("\n[%s] thread[%x,%x] enters / tcp_length %d / tcp_flags %x / cycle %d\n",
    817927__FUNCTION__, this->process->pid, this->trdid, k_length, seg_flags , cycle );
    818928#endif
    819929
    820     // compute and check TCP checksum
     930    // reset checksum field
    821931    k_buf[16] = 0;
    822932    k_buf[17] = 0;
    823     checksum = dev_nic_tcp_checksum( k_buf,
    824                                      k_length,
    825                                      seg_remote_addr,
    826                                      seg_local_addr );
    827 
     933
     934    // compute TCP checksum
     935    checksum = dev_nic_tcp_udp_checksum( k_buf,
     936                                         k_length,
     937                                         seg_remote_addr,
     938                                         seg_local_addr,
     939                                         true );            // is_tcp
    828940    // discard segment if corrupted
    829941    if( seg_checksum != checksum )
    830942    {
    831943
    832 #if DEBUG_DEV_NIC_RX
    833 if( cycle > DEBUG_DEV_NIC_RX )
    834 printk("\n[%s] thread[%x,%x] tcp checksum failure : received %x / computed %x\n",
    835 __FUNCTION__, this->process->pid, this->trdid, seg_checksum, checksum );
     944#if DEBUG_DEV_NIC_ERROR
     945printk("\n[WARNING] in %s : thread[%x,%x] / checksum failure on channel %d / cycle %d\n",
     946__FUNCTION__, this->process->pid, this->trdid, chdev->channel, cycle );
    836947#endif
    837948        return;
    838949    }
    839950   
    840     // scan list of attached sockets to find a matching TCP socket
    841     attached_match = false;
    842 
    843951    // build extended pointer on xlist of sockets attached to NIC_RX chdev
    844952    root_xp = XPTR( local_cxy , &chdev->wait_root );
    845953    lock_xp = XPTR( local_cxy , &chdev->wait_lock );
    846954
     955    attached_match = false;
     956
    847957    // take the lock protecting the list of attached sockets
    848958    remote_busylock_acquire( lock_xp );
    849959
     960    // scan list of attached sockets to find a matching TCP socket
    850961    XLIST_FOREACH( root_xp , iter_xp )
    851962    {
     
    878989        {
    879990
    880 #if DEBUG_DEV_NIC_RX
    881 fdid = hal_remote_l32( XPTR( socket_cxy , &socket_ptr->fdid ) );
    882 pid  = hal_remote_l32( XPTR( socket_cxy , &socket_ptr->pid ) );
    883 if( cycle > DEBUG_DEV_NIC_RX )
    884 printk("\n[%s] thread[%x,%x] matching attached socket[%d,%d] / state %s\n",
    885 __FUNCTION__, this->process->pid, this->trdid, pid, fdid, socket_state_str(socket_state) );
     991#if DEBUG_DEV_NIC_RX || DEBUG_DEV_NIC_ERROR
     992fdid  = hal_remote_l32( XPTR( socket_cxy , &socket_ptr->fdid ) );
     993pid   = hal_remote_l32( XPTR( socket_cxy , &socket_ptr->pid ) );
     994#endif
     995
     996#if DEBUG_DEV_NIC_RX
     997if( DEBUG_DEV_NIC_RX < cycle )
     998printk("\n[%s] matching attached TCP socket[%d,%d] / state %s\n",
     999__FUNCTION__, pid, fdid, socket_state_str(socket_state) );
    8861000#endif
    8871001            break;
     
    9121026        socket_tx_valid = hal_remote_l32(XPTR( socket_cxy , &socket_ptr->tx_valid ));
    9131027        socket_tx_cmd   = hal_remote_l32(XPTR( socket_cxy , &socket_ptr->tx_cmd ));
    914         socket_tx_todo  = hal_remote_l32(XPTR( socket_cxy , &socket_ptr->tx_todo ));
    9151028        socket_tx_nxt   = hal_remote_l32(XPTR( socket_cxy , &socket_ptr->tx_nxt ));
    9161029        socket_tx_una   = hal_remote_l32(XPTR( socket_cxy , &socket_ptr->tx_una ));
     1030        socket_tx_ack   = hal_remote_l32(XPTR( socket_cxy , &socket_ptr->tx_ack ));
     1031        socket_tx_len   = hal_remote_l32(XPTR( socket_cxy , &socket_ptr->tx_len ));
    9171032
    9181033        socket_rx_valid = hal_remote_l32(XPTR( socket_cxy , &socket_ptr->rx_valid ));
     
    9261041        {
    9271042            ////////////////////////
    928             case TCP_STATE_SYN_SENT:  // TCP client waiting for SYN-ACK in connect handshake
     1043            case TCP_STATE_SYN_SENT:  // TCP client waiting for SYN-ACK
    9291044            {
    930                 // [1] check ACK flag
     1045                // [1] & [2] check ACK and RST
    9311046                if( seg_ack_set )
    9321047                {
    933                     if( seg_ack_num != TCP_ISS_CLIENT + 1 )  // bad ACK => report error
     1048                    bool_t ack_ok = (seg_ack_num == (CONFIG_SOCK_ISS_CLIENT + 1) );
     1049
     1050                    if( seg_rst_set && ack_ok )
    9341051                    {
    9351052
    9361053#if DEBUG_DEV_NIC_RX
    937 printk("\n[%s] thread[%x,%x] socket[%x,%d] %s : expect ack_num %x / get %x\n",
    938 __FUNCTION__, this->process->pid, this->trdid, pid, fdid,
    939 socket_state_str(socket_state), TCP_ISS_CLIENT + 1, seg_ack_num );
    940 #endif
    941                         // make an RST request to R2T queue
     1054if( DEBUG_DEV_NIC_RX < cycle )
     1055printk("\n[%s]  socket[%x,%d] %s RST received from remote TCP => close\n",
     1056__FUNCTION__, pid, fdid, socket_state_str(socket_state) );
     1057#endif
     1058                        // report RST to local TCP client thread
     1059                        dev_nic_unblock_tx_client( socket_xp , CMD_STS_RST );
     1060
     1061                        // update socket state
     1062                        hal_remote_s32( XPTR( socket_cxy , &socket_ptr->state ),
     1063                                          TCP_STATE_BOUND );
     1064                        break;
     1065                    }
     1066
     1067                    if( seg_rst_set && (ack_ok == false) )
     1068                    {
     1069
     1070#if DEBUG_DEV_NIC_ERROR
     1071printk("\n[ERROR] in %s : socket[%x,%d] %s RST but expect ack_num %x != rcvd %x => discard\n",
     1072__FUNCTION__, pid, fdid, socket_state_str(socket_state),
     1073CONFIG_SOCK_ISS_CLIENT + 1, seg_ack_num );
     1074#endif
     1075                        break;
     1076                    }
     1077
     1078                    if( (seg_rst_set == false) && (ack_ok == false) )
     1079                    {
     1080
     1081#if DEBUG_DEV_NIC_ERROR
     1082printk("\n[ERROR] in %s : socket[%x,%d] %s expected ack_num %x != rcvd %x => send RST\n",
     1083__FUNCTION__, pid, fdid, socket_state_str(socket_state),
     1084CONFIG_SOCK_ISS_CLIENT + 1, seg_ack_num );
     1085#endif
     1086                        // send RST to remote TCP
    9421087                        socket_put_r2t_request( socket_r2tq_xp,
    9431088                                                TCP_FLAG_RST,
    9441089                                                chdev->channel );
    945 
    946                         // report error to local TX client thread
    947                         dev_nic_unblock_tx_client( socket_xp , CMD_STS_BADACK );
    948 
    9491090                        break;
    9501091                    }
    9511092                }
    9521093
    953                 // [2] check RST flag                       // receive RST => report error
    954                 if( seg_rst_set )
    955                 {
    956 
    957 #if DEBUG_DEV_NIC_RX
    958 printk("\n[%s] thread[%x,%x] socket[%x,%d] %s : received RST flag\n",
    959 __FUNCTION__, this->process->pid, this->trdid, pid, fdid, socket_state_str(socket_state) );
    960 #endif
    961                     // update socket state
    962                     hal_remote_s32( XPTR( socket_cxy , &socket_ptr->state ),
    963                                           TCP_STATE_BOUND );
    964 
    965                     // signal error to local TX client thread
    966                     dev_nic_unblock_tx_client( socket_xp , CMD_STS_RST );
    967 
    968                     break;
    969                 }
    970 
    9711094                // [3] handle security & precedence TODO ... someday
    9721095
     
    9761099
    9771100#if DEBUG_DEV_NIC_RX
    978 printk("\n[%s] thread[%x,%x] socket[%x,%d] %s : received expected SYN-ACK\n",
    979 __FUNCTION__, this->process->pid, this->trdid, pid, fdid , socket_state_str(socket_state) );
     1101if( DEBUG_DEV_NIC_RX < cycle )
     1102printk("\n[%s] socket[%x,%d] %s : received expected SYN-ACK\n",
     1103__FUNCTION__, pid, fdid , socket_state_str(socket_state) );
    9801104#endif
    9811105                    // set socket.tx_una 
     
    9991123                    dev_nic_unblock_tx_client( socket_xp , CMD_STS_SUCCESS );
    10001124                }
    1001                 else        // received SYN without ACK => client becomes server
     1125                else        // SYN without ACK => TCP client becomes a TCP server
    10021126                {
    10031127
    10041128#if DEBUG_DEV_NIC_RX
    1005 printk("\n[%s] thread[%x,%x] for socket[%x,%d] %s : received SYN-ACK => become server\n",
    1006 __FUNCTION__, this->process->pid, this->trdid, pid, fdid , socket_state_str(socket_state) );
     1129if( DEBUG_DEV_NIC_RX < cycle )
     1130printk("\n[%s] socket[%x,%d] %s : received SYN without ACK => send a SYN_ACK\n",
     1131__FUNCTION__, pid, fdid , socket_state_str(socket_state) );
    10071132#endif
    10081133                    // update socket.state
    1009                     hal_remote_s32( XPTR(socket_cxy,&socket_ptr->state), TCP_STATE_SYN_RCVD );
     1134                    hal_remote_s32( XPTR(socket_cxy,&socket_ptr->state),
     1135                                    TCP_STATE_SYN_RCVD );
    10101136
    10111137                    // set socket.tx_nxt
    1012                     hal_remote_s32( XPTR(socket_cxy , &socket_ptr->tx_nxt), TCP_ISS_SERVER );
     1138                    hal_remote_s32( XPTR(socket_cxy , &socket_ptr->tx_nxt),
     1139                                    CONFIG_SOCK_ISS_SERVER );
    10131140
    10141141                    // set socket.rx_nxt to seg_seq_num + 1
    10151142                    hal_remote_s32( XPTR(socket_cxy,&socket_ptr->rx_nxt), seg_seq_num + 1 );
    10161143
    1017                     // make a SYN.ACK request to R2T queue
     1144                    // send SYN.ACK to remote TCP
    10181145                    socket_put_r2t_request( socket_r2tq_xp,
    10191146                                            TCP_FLAG_SYN | TCP_FLAG_ACK,
     
    10211148                }
    10221149                break;
    1023             }
    1024             ////////////////////////
    1025             case TCP_STATE_SYN_RCVD:  // TCP server waiting last ACK in connect handshake
    1026             {
    1027                 // [1] check sequence number
    1028                 if( seg_seq_num != socket_rx_nxt )        // unexpected SEQ_NUM => discard
    1029                 {
    1030 
    1031 #if DEBUG_DEV_NIC_RX
    1032 printk("\n[%s] thread[%x,%x] socket[%x,%d] %s : expect seq_num %x / get %x\n",
    1033 __FUNCTION__, this->process->pid, this->trdid, pid, fdid,
    1034 socket_state_str(socket_state), socket_rx_nxt, seg_seq_num );
    1035 #endif
    1036                     // discard segment without reporting
    1037                     break;
    1038                 }
    1039 
    1040                 // [2] handle RST flag                    // received RST => report error
    1041                 if( seg_rst_set )
    1042                 {
    1043 
    1044 #if DEBUG_DEV_NIC_RX
    1045 printk("\n[%s] thread[%x,%x] socket[%x,%d] %s : received RST flag\n",
    1046 __FUNCTION__, this->process->pid, this->trdid, pid, fdid , socket_state_str(socket_state) );
    1047 #endif
    1048                     // update socket state
    1049                     hal_remote_s32( XPTR( socket_cxy , &socket_ptr->state ), TCP_STATE_BOUND );
    1050 
    1051                     // report error to local TX client thread
    1052                     dev_nic_unblock_tx_client( socket_xp , CMD_STS_RST );
    1053 
    1054                     break;
    1055                 }
    1056 
    1057                 // [3] handle security & precedence TODO ... someday
    1058 
    1059                 // [4] handle SYN flag
    1060                 if( seg_syn_set )                           // received SYN => discard
    1061                 {
    1062 
    1063 #if DEBUG_DEV_NIC_RX
    1064 printk("\n[%s] thread[%x,%x] socket[%x,%d] %s : received SYN flag\n",
    1065 __FUNCTION__, this->process->pid, this->trdid, pid, fdid , socket_state_str(socket_state) );
    1066 #endif
    1067                     // discard segment without reporting
    1068                     break;
    1069                 }
    1070 
    1071                 // [5] handle  ACK flag
    1072                 if( seg_ack_set == false )                      // missing ACK => discard
    1073                 {
    1074 
    1075 #if DEBUG_DEV_NIC_RX
    1076 printk("\n[%s] thread[%x,%x] socket[%x,%d] %s : no ACK in TCP segment\n",
    1077 __FUNCTION__, this->process->pid, this->trdid, pid, fdid , socket_state_str(socket_state) );
    1078 #endif
    1079                     // discard segment without reporting
    1080                     break;
    1081                 }
    1082                 else if( seg_ack_num != (TCP_ISS_SERVER + 1) )  // unacceptable ACK
    1083                 {
    1084 
    1085 #if DEBUG_DEV_NIC_RX
    1086 printk("\n[%s] thread[%x,%x] socket[%x,%d] %s : expect ack_num %x / get %x\n",
    1087 __FUNCTION__, this->process->pid, this->trdid, pid, fdid,
    1088 socket_state_str(socket_state), TCP_ISS_SERVER + 1, seg_ack_num );
    1089 #endif
    1090 
    1091                     // register an RST request to R2TQ for remote TCP client
    1092                     socket_put_r2t_request( socket_r2tq_xp,
    1093                                             TCP_FLAG_RST,
    1094                                             chdev->channel );
    1095 
    1096                     // report error to local TX client thread
    1097                     dev_nic_unblock_tx_client( socket_xp , CMD_STS_BADACK );
    1098                 }
    1099                 else                                           // acceptable ACK
    1100                 {
    1101 
    1102 #if DEBUG_DEV_NIC_RX
    1103 printk("\n[%s] thread[%x,%x] socket[%x,%d] %s : received expected ACK\n",
    1104 __FUNCTION__, this->process->pid, this->trdid, pid, fdid , socket_state_str(socket_state) );
    1105 #endif
    1106                     // set socket.tx_una 
    1107                     hal_remote_s32( XPTR(socket_cxy , &socket_ptr->tx_una), seg_ack_num );
    1108 
    1109                     // update socket.state
    1110                     hal_remote_s32( XPTR(socket_cxy , &socket_ptr->state),
    1111                                     TCP_STATE_ESTAB );
    1112 
    1113                     // report success to local TX client thread
    1114                     dev_nic_unblock_tx_client( socket_xp , CMD_STS_SUCCESS );
    1115                 }
    1116                 break;
    1117             }
    1118             /////////////////////
     1150            }  // end state SYN_SENT
     1151
     1152            ////////////////////////    all "connected" states
     1153            case TCP_STATE_SYN_RCVD:
    11191154            case TCP_STATE_ESTAB:
    11201155            case TCP_STATE_FIN_WAIT1:
     
    11251160            case TCP_STATE_TIME_WAIT:
    11261161            {
    1127                 // [1] check sequence number : out_of_order segments not accepted
    1128                 if( seg_seq_num != socket_rx_nxt )
     1162                // [1] check SEQ_NUM
     1163                // - we accept duplicate segments (i.e. seq_num < rx_next)
     1164                // - we don't accept out of order segment (i.e. seq_num_num > rx_next)
     1165                //   => seq_num must be in window [rx_nxt - rx_win , rx_nxt]
     1166
     1167                bool_t seq_ok =  is_in_window( seg_seq_num,
     1168                                               (socket_rx_nxt - socket_rx_wnd),
     1169                                               socket_rx_nxt );
     1170
     1171                if( seq_ok == false ) // SEQ_NUM not acceptable
    11291172                {
    1130 
    1131 #if DEBUG_DEV_NIC_RX
    1132 printk("\n[%s] thread[%x,%x] socket[%x,%d] %s : illegal SEQ_NUM %x / expected %x\n",
    1133 __FUNCTION__, this->process->pid, this->trdid, pid, fdid,
    1134 socket_state_str(socket_state), seg_seq_num, socket_rx_nxt );
    1135 #endif
    1136                     // discard segment
    1137                     break;
    1138                 }
    1139 
    1140                 // check all bytes in window when the payload exist
    1141                 // TODO : we could accept bytes that are in window,
    1142                 // but this implementation reject all bytes in segment
    1143                 if( seg_data_len > 0 )
    1144                 {
    1145                     // compute min & max acceptable sequence numbers
    1146                     uint32_t seq_min  = socket_rx_nxt;
    1147                     uint32_t seq_max  = socket_rx_nxt + socket_rx_wnd - 1;
    1148 
    1149                     // compute sequence number for last byte in segment
    1150                     uint32_t seg_seq_last = seg_seq_num + seg_data_len - 1;
    1151                      
    1152                     if( is_in_window( seg_seq_last, seq_min, seq_max ) == false )
     1173                    if( seg_rst_set )
    11531174                    {
    11541175
    1155 #if DEBUG_DEV_NIC_RX
    1156 printk("\n[%s] thread[%x,%x] socket[%x,%d] %s : last SEQ_NUM %x not in [%x,%x]\n",
    1157 __FUNCTION__, this->process->pid, this->trdid, pid, fdid,
    1158 socket_state_str(socket_state), seg_seq_last, seq_min, seq_max );
    1159 #endif
    1160                         // discard segment
     1176#if DEBUG_DEV_NIC_ERROR
     1177printk("\n[ERROR] in %s : socket[%x,%d] %s expect seq_num %x != rcvd %x and RST => discard\n",
     1178__FUNCTION__, pid, fdid, socket_state_str(socket_state),
     1179CONFIG_SOCK_ISS_CLIENT + 1, seg_seq_num );
     1180#endif
    11611181                        break;
    11621182                    }
    1163                 }
    1164 
    1165                 // [2] handle RST flag
    1166                 if( seg_rst_set )
     1183                    else  // no RST
     1184                    {
     1185                        // send ACK to remote TCP
     1186                        socket_put_r2t_request( socket_r2tq_xp,
     1187                                                TCP_FLAG_ACK,
     1188                                                chdev->channel );
     1189#if DEBUG_DEV_NIC_ERROR
     1190printk("\n[ERROR] in %s : socket[%x,%d] %s expect seq_num %x != rcvd %x => ACK and discard\n",
     1191__FUNCTION__, pid, fdid, socket_state_str(socket_state),
     1192CONFIG_SOCK_ISS_CLIENT + 1, seg_seq_num );
     1193#endif
     1194                        break;
     1195                    }
     1196                }
     1197                else                   // SEQ_NUM acceptable
    11671198                {
    1168 
    1169 #if DEBUG_DEV_NIC_RX
    1170 printk("\n[%s] thread[%x,%x] socket[%x,%d] %s : received RST flag\n",
    1171 __FUNCTION__, this->process->pid, this->trdid, pid, fdid, socket_state_str(socket_state) );
    1172 #endif
    1173                     if( (socket_state == TCP_STATE_ESTAB     ) ||
    1174                         (socket_state == TCP_STATE_FIN_WAIT1 ) ||
    1175                         (socket_state == TCP_STATE_FIN_WAIT2 ) ||
    1176                         (socket_state == TCP_STATE_CLOSE_WAIT) )
     1199                    // compute number of new bytes & number of duplicated bytes
     1200                    if( seg_seq_num != socket_rx_nxt )  // duplicate segment
    11771201                    {
    1178                         // TODO all pending send & received commands
    1179                         // must receive "reset" responses
    1180 
    1181                         // TODO destroy the socket
     1202                        seg_data_dup = socket_rx_nxt - seg_seq_num;
     1203                        seg_data_new = (seg_data_len > seg_data_dup) ?
     1204                                       (seg_data_len - seg_data_dup) : 0;
     1205                    }
     1206                    else                                // expected segment
     1207                    {
     1208                        seg_data_dup = 0;
     1209                        seg_data_new = seg_data_len;
     1210                    }
     1211                   
     1212#if DEBUG_DEV_NIC_RX
     1213if( DEBUG_DEV_NIC_RX < cycle )
     1214printk("\n[%s] socket[%x,%d] %s seq_num %x / rx_nxt %x / len %d / new %d / dup %d\n",
     1215__FUNCTION__, pid, fdid, socket_state_str(socket_state),
     1216seg_seq_num, socket_rx_nxt, seg_data_len, seg_data_new, seg_data_dup );
     1217#endif
     1218                }
     1219
     1220                // [2] handle RST flag (depending on socket state)
     1221                if( seg_rst_set  )
     1222                {
     1223                    if( socket_state == TCP_STATE_SYN_RCVD )
     1224                    {
     1225
     1226#if DEBUG_DEV_NIC_RX
     1227if( DEBUG_DEV_NIC_RX < cycle )
     1228printk("\n[%s] socket[%x,%d] %s RST received from remote TCP => report to user\n",
     1229__FUNCTION__, pid, fdid, socket_state_str(socket_state) );
     1230#endif
     1231                        // report RST to local TX client thread
     1232                        dev_nic_unblock_tx_client( socket_xp , CMD_STS_RST );
     1233
     1234                        // update socket state
     1235                        hal_remote_s32( XPTR(socket_cxy , &socket_ptr->state),
     1236                                        TCP_STATE_BOUND );
     1237                        break;
     1238                    }
     1239
     1240                    else if( (socket_state == TCP_STATE_ESTAB     ) ||
     1241                             (socket_state == TCP_STATE_FIN_WAIT1 ) ||
     1242                             (socket_state == TCP_STATE_FIN_WAIT2 ) ||
     1243                             (socket_state == TCP_STATE_CLOSE_WAIT) )
     1244                    {
     1245
     1246#if DEBUG_DEV_NIC_RX
     1247if( DEBUG_DEV_NIC_RX < cycle )
     1248printk("\n[%s] socket[%x,%d] %s / received RST flag\n",
     1249__FUNCTION__, pid, fdid, socket_state_str(socket_state) );
     1250#endif
     1251                        // report RST to local TX client thread
     1252                        if( socket_tx_valid ) dev_nic_unblock_tx_client( socket_xp,
     1253                                                                         CMD_STS_RST );
     1254                        // report RST to local RX client thread
     1255                        if( socket_rx_valid ) dev_nic_unblock_rx_client( socket_xp,
     1256                                                                         CMD_STS_RST );
     1257                        // update socket state
     1258                        hal_remote_s32( XPTR(socket_cxy , &socket_ptr->state),
     1259                                        TCP_STATE_BOUND );
     1260                        break;
    11821261                    }
    11831262                    else  // states CLOSING / LAST_ACK / TIME_WAIT
    11841263                    {
    1185                         // TODO         
     1264                        // update socket state
     1265                        hal_remote_s32( XPTR(socket_cxy , &socket_ptr->state),
     1266                                        TCP_STATE_BOUND );
     1267                        break;
    11861268                    }
     1269                }
     1270 
     1271                // [3] handle security & precedence TODO ... someday
     1272
     1273                // [4] check SYN 
     1274                if( seg_syn_set )           // received SYN => send RST to remote
     1275                {
     1276
     1277#if DEBUG_DEV_NIC_ERROR
     1278printk("\n[ERROR] in %s socket[%x,%d] %s : received SYN flag => send RST-ACK\n",
     1279__FUNCTION__, pid, fdid , socket_state_str(socket_state) );
     1280#endif
     1281                    // send RST & ACK to remote TCP
     1282                    socket_put_r2t_request( socket_r2tq_xp,
     1283                                            TCP_FLAG_RST | TCP_FLAG_ACK,
     1284                                            chdev->channel );
     1285
     1286                    // report RST to local TX client thread
     1287                    if( socket_tx_valid ) dev_nic_unblock_tx_client( socket_xp,
     1288                                                                     CMD_STS_RST );
     1289                    // report RST to local RX client thread
     1290                    if( socket_rx_valid ) dev_nic_unblock_rx_client( socket_xp,
     1291                                                                     CMD_STS_RST );
     1292                    // update socket state
     1293                    hal_remote_s32( XPTR(socket_cxy , &socket_ptr->state),
     1294                                    TCP_STATE_BOUND );
    11871295                    break;
    11881296                }
    11891297
    1190                 // [3] handle security & precedence TODO ... someday
    1191 
    1192                 // [4] check SYN flag
    1193                 if( seg_syn_set )                                // received SYN => ERROR
     1298                // [5] handle ACK (depending on socket state)
     1299                if( seg_ack_set == false )           // missing ACK => discard segment
    11941300                {
    11951301
    1196 #if DEBUG_DEV_NIC_RX
    1197 printk("\n[%s] thread[%x,%x] socket[%x,%d] %s : received unexpected SYN\n",
    1198 __FUNCTION__, this->process->pid, this->trdid, pid, fdid , socket_state_str(socket_state) );
    1199 #endif
    1200                     // TODO signal error to user
    1201 
    1202                     // make an RST request to R2T queue
    1203                     socket_put_r2t_request( socket_r2tq_xp,
    1204                                             TCP_FLAG_RST,
    1205                                             chdev->channel );
    1206 
    1207                     // update socket state
    1208                     hal_remote_s32( XPTR(socket_cxy , &socket_ptr->state), TCP_STATE_BOUND );
    1209 
     1302#if DEBUG_DEV_NIC_ERROR
     1303printk("\n[ERROR] in %s : socket[%x,%d] %s / no ACK in segment => discard\n",
     1304__FUNCTION__, pid, fdid, socket_state_str(socket_state) );
     1305#endif
    12101306                    break;
    12111307                }
    12121308
    1213                 // [5] check ACK 
    1214                 if( seg_ack_set == false )                           // missing ACK
     1309                // compute acceptable ACK
     1310                bool_t ack_ok = is_in_window( seg_ack_num,
     1311                                              socket_tx_una,
     1312                                              socket_tx_nxt );
     1313
     1314                if( socket_state == TCP_STATE_SYN_RCVD )
    12151315                {
    1216 
    1217 #if DEBUG_DEV_NIC_RX
    1218 printk("\n[%s] thread[%x,%x] socket[%x,%d] %s : no ACK flag\n",
    1219 __FUNCTION__, this->process->pid, this->trdid, pid, fdid, socket_state_str(socket_state) );
    1220 #endif
    1221                     // discard segment
    1222                     break;
    1223                 }
    1224                 else if( is_in_window( seg_ack_num,
    1225                                        socket_tx_una,
    1226                                        socket_tx_nxt ) == false )    // unacceptable ACK
    1227                 {
    1228 
    1229 #if DEBUG_DEV_NIC_RX
    1230 printk("\n[%s] thread[%x,%x] socket[%x,%d] %s : ACK_NUM %x not in [%x,%x]\n",
    1231 __FUNCTION__, this->process->pid, this->trdid, pid, fdid, socket_state_str(socket_state),
    1232 seg_ack_num, socket_tx_una, socket_tx_nxt );
    1233 #endif
    1234                     // discard segment
    1235                     break;
    1236                 }
    1237                 else                                                // acceptable ack
    1238                 {
    1239                     // update socket.tx_una
    1240                     hal_remote_s32( XPTR(socket_cxy , &socket_ptr->tx_una), seg_ack_num );
    1241 
    1242                     // update socket.tx_wnd 
    1243                     hal_remote_s32( XPTR(socket_cxy , &socket_ptr->tx_wnd), seg_window );
    1244 
    1245                     // check last data byte acknowledged for a SEND command
    1246                     if( (socket_tx_todo == 0) &&
    1247                         (seg_ack_num == socket_tx_nxt) &&
    1248                         (socket_tx_cmd == CMD_TX_SEND) )
     1316                    if( ack_ok )                      //  acceptable ACK
    12491317                    {
    1250                         // signal success to TX client thread
     1318
     1319#if DEBUG_DEV_NIC_RX
     1320if( DEBUG_DEV_NIC_RX < cycle )
     1321printk("\n[%s] socket[%x,%d] %s : received expected ACK => update socket\n",
     1322__FUNCTION__, pid, fdid , socket_state_str(socket_state) );
     1323#endif
     1324                        // set socket.tx_una 
     1325                        hal_remote_s32( XPTR(socket_cxy , &socket_ptr->tx_una), seg_ack_num );
     1326
     1327                        // update socket.state
     1328                        hal_remote_s32( XPTR(socket_cxy , &socket_ptr->state),
     1329                                        TCP_STATE_ESTAB );
     1330
     1331                        // report success to local TX client thread
    12511332                        dev_nic_unblock_tx_client( socket_xp , CMD_STS_SUCCESS );
    12521333                    }
     1334                    else                               // send RST to remote
     1335                    {
     1336
     1337#if DEBUG_DEV_NIC_ERROR
     1338printk("\n[ERROR] in %s : socket[%x,%d] %s / ACK %x not in [%x,%x] => discard\n",
     1339__FUNCTION__, pid, fdid, socket_state_str(socket_state),
     1340seg_ack_num, socket_tx_una, socket_tx_nxt );
     1341#endif
     1342                        // send RST & ACK to remote TCP
     1343                        socket_put_r2t_request( socket_r2tq_xp,
     1344                                                TCP_FLAG_RST | TCP_FLAG_ACK,
     1345                                                chdev->channel );
     1346                        break;
     1347                    }
    12531348                }
    1254                    
    1255                 // [7] handle URG flag  TODO ... someday
    1256 
    1257                 // [8] Move DATA to rx_buf / ACK request to R2T queue / unblock rx_client
    1258                 if( seg_data_len )
     1349
     1350                else if( (socket_state == TCP_STATE_ESTAB)      ||
     1351                         (socket_state == TCP_STATE_FIN_WAIT1)  ||
     1352                         (socket_state == TCP_STATE_FIN_WAIT2)  ||
     1353                         (socket_state == TCP_STATE_FIN_WAIT2)  ||
     1354                         (socket_state == TCP_STATE_CLOSE_WAIT) ||
     1355                         (socket_state == TCP_STATE_CLOSING)    )
    12591356                {
    1260                     if( (socket_state == TCP_STATE_ESTAB)     ||
    1261                         (socket_state == TCP_STATE_FIN_WAIT1) ||
    1262                         (socket_state == TCP_STATE_FIN_WAIT2) )
     1357                    if( ack_ok )                      // acceptable ack
     1358                    {
     1359                        // compute number of acknowledged bytes
     1360                        uint32_t ack_bytes =  seg_ack_num - socket_tx_una;
     1361
     1362                        if( ack_bytes )  // handle acknowledged bytes
     1363                        {
     1364#if DEBUG_DEV_NIC_RX
     1365if( DEBUG_DEV_NIC_RX < cycle )
     1366printk("\n[%s] socket[%x,%d] %d bytes acknowledged => update socket\n",
     1367__FUNCTION__, pid, fdid, ack_bytes );
     1368#endif
     1369                            // update socket.tx_una, socket.tx_ack, and socket.tx_wnd fields
     1370                            hal_remote_s32( XPTR(socket_cxy , &socket_ptr->tx_una),
     1371                                            seg_ack_num );
     1372                            hal_remote_s32( XPTR(socket_cxy , &socket_ptr->tx_ack),
     1373                                            socket_tx_ack + ack_bytes );
     1374                            hal_remote_s32( XPTR(socket_cxy , &socket_ptr->tx_wnd),
     1375                                            seg_window );
     1376
     1377                            //  unblock the TX client thread if last byte acknowledged
     1378                            if( (socket_tx_ack + ack_bytes) == socket_tx_len )
     1379                            {
     1380                                // report success to TX client thread
     1381                                dev_nic_unblock_tx_client( socket_xp , CMD_STS_SUCCESS );
     1382#if DEBUG_DEV_NIC_RX
     1383if( DEBUG_DEV_NIC_RX < cycle )
     1384printk("\n[%s] socket[%x,%d] %s : last ack => unblock TX client thread\n",
     1385__FUNCTION__, pid, fdid, socket_state_str(socket_state) );
     1386#endif
     1387                            }
     1388                        }
     1389
     1390                        if( socket_state == TCP_STATE_FIN_WAIT1 )
     1391                        {
     1392                            // update socket state
     1393                            hal_remote_s32( XPTR(socket_cxy , &socket_ptr->state),
     1394                                            TCP_STATE_FIN_WAIT2 );
     1395                        }
     1396                        if( socket_state == TCP_STATE_FIN_WAIT2 )
     1397                        {
     1398                            // TODO
     1399                        }
     1400                        else if( socket_state == TCP_STATE_CLOSING )
     1401                        {
     1402                            // update socket state
     1403                            hal_remote_s32( XPTR(socket_cxy , &socket_ptr->state),
     1404                                            TCP_STATE_TIME_WAIT );
     1405                        }
     1406                        else if( socket_state == TCP_STATE_CLOSING )
     1407                        {
     1408                            // TODO
     1409                        }
     1410                    }
     1411                    else                    // unacceptable ACK => discard segment
     1412                    {
     1413
     1414#if DEBUG_DEV_NIC_ERROR
     1415printk("\n[ERROR] in %s : socket[%x,%d] %s / ACK %x not in [%x,%x] => discard\n",
     1416__FUNCTION__, pid, fdid, socket_state_str(socket_state),
     1417seg_ack_num, socket_tx_una, socket_tx_nxt );
     1418#endif
     1419                        break;
     1420                    }
     1421                }
     1422   
     1423                else if( socket_state == TCP_STATE_LAST_ACK )
     1424                {
     1425                    // TODO
     1426                }
     1427
     1428                else if( socket_state == TCP_STATE_TIME_WAIT )
     1429                {
     1430                    // TODO
     1431                }
     1432
     1433                // [6] handle URG flag  TODO ... someday
     1434
     1435                // [7] handle received data : update socket state,
     1436                // move data to rx_buf, register ACK request to R2T queue,
     1437                // unblock the RX client thread in case of pending RX_RECV command
     1438                if((socket_state == TCP_STATE_ESTAB)     ||
     1439                   (socket_state == TCP_STATE_FIN_WAIT1) ||
     1440                   (socket_state == TCP_STATE_FIN_WAIT2) )
     1441                {
     1442                    // register new bytes if requested
     1443                    if( seg_data_new )
    12631444                    {
    12641445                        // get number of bytes already stored in rx_buf
    12651446                        uint32_t status = remote_buf_status( socket_rx_buf_xp );
    12661447
    1267                         // compute empty space in rx_buf
    1268                         uint32_t space = CONFIG_SOCK_RX_BUF_SIZE - status;
    1269 
    1270                         // compute number of bytes to move : min (space , seg_data_len)
    1271                         uint32_t nbytes = ( space < seg_data_len ) ? space : seg_data_len;
    1272 
    1273                         // move payload from k_buf to rx_buf
     1448                        // compute space in rx_buf and actual number of acceptable bytes
     1449                        // when (space < seg_data_new) the last new bytes are discarded
     1450                        uint32_t space = (1 << CONFIG_SOCK_RX_BUF_ORDER) - status;
     1451                        uint32_t rcv_bytes = (space < seg_data_new) ? space : seg_data_new;
     1452
     1453                        // move new bytes from k_buf to rx_buf
    12741454                        remote_buf_put_from_kernel( socket_rx_buf_xp,
    1275                                                     k_buf + seg_hlen,
    1276                                                     nbytes );
    1277 #if DEBUG_DEV_NIC_RX
    1278 printk("\n[%s] thread[%x,%x] socket[%x,%d] %s : move %d bytes to rx_buf\n",
    1279 __FUNCTION__, this->process->pid, this->trdid, pid, fdid,
    1280 socket_state_str(socket_state), nbytes );
    1281 #endif
    1282                         // update socket.rx_nxt
     1455                                                    k_buf + seg_hlen + seg_data_dup,
     1456                                                    rcv_bytes );
     1457#if DEBUG_DEV_NIC_RX
     1458if( DEBUG_DEV_NIC_RX < cycle )
     1459printk("\n[%s] socket[%x,%d] %s : move %d bytes to rx_buf\n",
     1460__FUNCTION__, pid, fdid, socket_state_str(socket_state), rcv_bytes );
     1461 #endif
     1462                        // update socket.rx_nxt and socket_rx_wnd fields
    12831463                        hal_remote_s32( XPTR( socket_cxy , &socket_ptr->rx_nxt ),
    1284                                               socket_rx_nxt + nbytes );
    1285 
    1286                         // update socket.rx_wnd
     1464                                        socket_rx_nxt + rcv_bytes );
    12871465                        hal_remote_s32( XPTR( socket_cxy , &socket_ptr->rx_wnd ),
    1288                                               socket_rx_wnd - nbytes );
    1289 
    1290                         // make an ACK request to R2T queue
     1466                                        socket_rx_wnd - rcv_bytes );
     1467
     1468                        // unblock RX client if required
     1469                        if( (socket_rx_valid == true) && (socket_rx_cmd == CMD_RX_RECV) )
     1470                        {
     1471                            // reset rx_valid
     1472                            hal_remote_s32( XPTR(socket_cxy,&socket_ptr->rx_valid), false );
     1473
     1474                            // report success to RX client thread
     1475                            dev_nic_unblock_rx_client( socket_xp , CMD_STS_SUCCESS );
     1476#if DEBUG_DEV_NIC_RX
     1477if( DEBUG_DEV_NIC_RX < cycle )
     1478printk("\n[%s] socket[%x,%d] %s : last data => unblock RX client thread\n",
     1479__FUNCTION__, pid, fdid, socket_state_str(socket_state) );
     1480#endif
     1481                        }
     1482                    }
     1483
     1484                    // make an ACK request to remote
     1485                    socket_put_r2t_request( socket_r2tq_xp,
     1486                                            TCP_FLAG_ACK,
     1487                                            chdev->channel );
     1488                }  // end payload handling
     1489
     1490                // [8] handle FIN flag depending on socket state
     1491                if( (socket_state == TCP_STATE_SYN_RCVD) ||
     1492                    (socket_state == TCP_STATE_ESTAB )   )
     1493                {
     1494                    if( seg_fin_set )     
     1495                    {
     1496
     1497#if DEBUG_DEV_NIC_RX
     1498if( DEBUG_DEV_NIC_RX < cycle )
     1499printk("\n[%s] socket[%x,%d] %s : FIN-ACK => goes CLOSE_WAIT\n",
     1500__FUNCTION__, pid, fdid, socket_state_str(socket_state) );
     1501#endif
     1502                        // update socket.rx_nxt when FIN received
     1503                        hal_remote_s32( XPTR( socket_cxy , &socket_ptr->rx_nxt ),
     1504                                        socket_rx_nxt + 1 );
     1505
     1506                        // update socket state
     1507                        hal_remote_s32( XPTR( socket_cxy , &socket_ptr->state ),
     1508                                        TCP_STATE_CLOSE_WAIT );
     1509
     1510                        // send ACK to remote TCP
    12911511                        socket_put_r2t_request( socket_r2tq_xp,
    12921512                                                TCP_FLAG_ACK,
     
    12941514
    12951515                        // check pending RX_RECV command
    1296                         if( (socket_rx_valid == true) &&
    1297                             (socket_rx_cmd == CMD_RX_RECV) )
     1516                        if( (socket_rx_valid == true) && (socket_rx_cmd == CMD_RX_RECV) )
    12981517                        {
    12991518                            // reset rx_valid
    13001519                            hal_remote_s32( XPTR(socket_cxy,&socket_ptr->rx_valid), false );
    13011520
    1302                             // report success to RX client thread
    1303                             dev_nic_unblock_rx_client( socket_xp , CMD_STS_SUCCESS );
    1304 #if DEBUG_DEV_NIC_RX
    1305 printk("\n[%s] thread[%x,%x] socket[%x,%d] %s : unblock waiting RX client thread\n",
    1306 __FUNCTION__, this->process->pid, this->trdid, pid, fdid,
    1307 socket_state_str(socket_state) );
    1308 #endif
    1309                         }
    1310                     }
    1311                 }
    1312 
    1313                 // [9] handle FIN flag
    1314                 if( socket_state == TCP_STATE_ESTAB )
    1315                 {
    1316                     if( seg_fin_set )  // received ACK & FIN   
    1317                     {
    1318 
    1319 #if DEBUG_DEV_NIC_RX
    1320 printk("\n[%s] thread[%x,%x] socket[%x,%d] %s : FIN-ACK => goes CLOSE_WAIT\n",
    1321 __FUNCTION__, this->process->pid, this->trdid, pid, fdid,
    1322 socket_state_str(socket_state) );
    1323 #endif
    1324                         // update socket.rx_nxt when FIN received
    1325                         hal_remote_s32( XPTR( socket_cxy , &socket_ptr->rx_nxt ),
    1326                                         socket_rx_nxt + 1 );
    1327 
    1328                         // update socket state
    1329                         hal_remote_s32( XPTR( socket_cxy , &socket_ptr->state ),
    1330                                         TCP_STATE_CLOSE_WAIT );
    1331 
    1332                         // make an ACK request to R2T queue
    1333                         socket_put_r2t_request( socket_r2tq_xp,
    1334                                                 TCP_FLAG_ACK,
    1335                                                 chdev->channel );
    1336 
    1337                         // check pending RX_RECV command
    1338                         if( (socket_rx_valid == true) &&
    1339                             (socket_rx_cmd == CMD_RX_RECV) )
    1340                         {
    1341                             // reset rx_valid
    1342                             hal_remote_s32( XPTR(socket_cxy,&socket_ptr->rx_valid), false );
    1343 
    1344                             // report error to RX client thread
     1521                            // report FIN to RX client thread
    13451522                            dev_nic_unblock_rx_client( socket_xp , CMD_STS_EOF );
    13461523#if DEBUG_DEV_NIC_RX
    1347 printk("\n[%s] thread[%x,%x] socket[%x,%d] %s : unblock RX client waiting on RECV\n",
    1348 __FUNCTION__, this->process->pid, this->trdid, pid, fdid,
    1349 socket_state_str(socket_state) );
     1524if( DEBUG_DEV_NIC_RX < cycle )
     1525printk("\n[%s] socket[%x,%d] %s : unblock RX client waiting on RECV\n",
     1526__FUNCTION__, pid, fdid, socket_state_str(socket_state) );
    13501527#endif
    13511528                        }
     
    13541531                else if( socket_state == TCP_STATE_FIN_WAIT1 )
    13551532                {
    1356                     if( seg_fin_set )  // received ACK & FIN
     1533                    if( seg_fin_set )
    13571534                    {
    13581535
    13591536#if DEBUG_DEV_NIC_RX
    1360 printk("\n[%s] thread[%x,%x] socket[%x,%d] %s : FIN-ACK => goes CLOSING\n",
    1361 __FUNCTION__, this->process->pid, this->trdid, pid, fdid,
    1362 socket_state_str(socket_state) );
    1363 #endif
    1364                         // update socket.rx_nxt when FIN received
     1537if( DEBUG_DEV_NIC_RX < cycle )
     1538printk("\n[%s] socket[%x,%d] %s : FIN-ACK => goes CLOSING\n",
     1539__FUNCTION__, pid, fdid, socket_state_str(socket_state) );
     1540#endif
     1541                        // update socket.rx_nxt
    13651542                        hal_remote_s32( XPTR( socket_cxy , &socket_ptr->rx_nxt ),
    13661543                                        socket_rx_nxt + 1 );
     
    13701547                                        TCP_STATE_CLOSING );
    13711548
    1372                         // make an ACK request to R2T queue
     1549                        // send ACK request to remote
    13731550                        socket_put_r2t_request( socket_r2tq_xp,
    13741551                                                TCP_FLAG_ACK,
     
    13791556
    13801557#if DEBUG_DEV_NIC_RX
    1381 printk("\n[%s] thread[%x,%x] socket[%x,%d] %s : only ACK => goes FIN_WAIT2\n",
    1382 __FUNCTION__, this->process->pid, this->trdid, pid, fdid,
    1383 socket_state_str(socket_state) );
     1558if( DEBUG_DEV_NIC_RX < cycle )
     1559printk("\n[%s] socket[%x,%d] %s : only ACK => goes FIN_WAIT2\n",
     1560__FUNCTION__, pid, fdid, socket_state_str(socket_state) );
    13841561#endif
    13851562                        // update socket state
     
    13941571
    13951572#if DEBUG_DEV_NIC_RX
    1396 printk("\n[%s] thread[%x,%x] socket[%x,%d] %s : FIN-ACK => goes CLOSED / unblock client\n",
    1397 __FUNCTION__, this->process->pid, this->trdid, pid, fdid,
    1398 socket_state_str(socket_state) );
     1573if( DEBUG_DEV_NIC_RX < cycle )
     1574printk("\n[%s] socket[%x,%d] %s : FIN-ACK => goes CLOSED / unblock client\n",
     1575__FUNCTION__, pid, fdid, socket_state_str(socket_state) );
    13991576#endif
    14001577                        // update socket.rx_nxt when FIN received
     
    14381615                    dev_nic_unblock_tx_client( socket_xp , CMD_STS_SUCCESS );
    14391616                }
    1440             }  // end case connecteded states
     1617            }  // end case connected states
    14411618        }  // end switch socket state
    14421619
     
    14911668        {
    14921669
    1493 #if DEBUG_DEV_NIC_RX
    1494 fdid = hal_remote_l32( XPTR( socket_cxy , &socket_ptr->fdid ) );
    1495 pid  = hal_remote_l32( XPTR( socket_cxy , &socket_ptr->pid ) );
    1496 if( cycle > DEBUG_DEV_NIC_RX )
    1497 printk("\n[%s] thread[%x,%x] matching listening socket[%d,%d] / state %s\n",
    1498 __FUNCTION__, this->process->pid, this->trdid, pid, fdid, socket_state_str(socket_state) );
     1670#if DEBUG_DEV_NIC_RX || DEBUG_DEV_NIC_ERROR
     1671fdid  = hal_remote_l32( XPTR( socket_cxy , &socket_ptr->fdid ) );
     1672pid   = hal_remote_l32( XPTR( socket_cxy , &socket_ptr->pid ) );
     1673#endif
     1674
     1675#if DEBUG_DEV_NIC_RX
     1676if( DEBUG_DEV_NIC_RX < cycle )
     1677printk("\n[%s] matching listening socket[%d,%d] / state %s\n",
     1678__FUNCTION__, pid, fdid, socket_state_str(socket_state) );
    14991679#endif
    15001680            break;
     
    15091689    {
    15101690        // The actions depend on the received segment flags
    1511         // - discard segment for RST or ACK
    1512         // - update socket state & remote IP address,
    1513         //   register connect request in socket CRQ queue,
    1514         //   and unblock client thread for SYN
     1691        // - discard segment for RST or ACK,
     1692        // - for SYN, register the connect request in listening socket CRQ queue,
     1693        //   and  unblock the client thread in case of pending RX_ACCEPT command.
    15151694 
    1516         // discard segment if RST flag
    1517         if( seg_rst_set )
     1695        // [1] check RST
     1696        if( seg_rst_set )       // discard segment
    15181697        {
    15191698
    1520 #if DEBUG_DEV_NIC_RX
    1521 if( cycle > DEBUG_DEV_NIC_RX )
    1522 printk("\n[%s] thread[%x,%x] for listening socket[%x,%d] : received RST\n",
    1523 __FUNCTION__, this->process->pid, this->trdid, pid, fdid );
     1699#if DEBUG_DEV_NIC_ERROR
     1700printk("\n[ERROR] in %s : socket[%x,%d] %s / received RST => discard segment\n",
     1701__FUNCTION__, pid, fdid, socket_state_str(socket_state) );
    15241702#endif
    15251703            return;
    15261704        }
    15271705
    1528         // discard segment if ACK flag
    1529         if( seg_ack_set )
     1706        // [2] check ACK
     1707        if( seg_ack_set )    // send RST to remote
    15301708        {
    15311709
    1532 #if DEBUG_DEV_NIC_RX
    1533 if( cycle > DEBUG_DEV_NIC_RX )
    1534 printk("\n[%s] thread[%x,%x] for listening socket[%x,%d] : received ACK\n",
    1535 __FUNCTION__, this->process->pid, this->trdid, pid, fdid );
    1536 #endif
     1710#if DEBUG_DEV_NIC_ERROR
     1711printk("\n[ERROR] in %s : socket[%x,%d] %s received ACK => send RST & discard \n",
     1712__FUNCTION__, pid, fdid, socket_state_str(socket_state) );
     1713#endif
     1714            // make an RST request to R2T queue
     1715            socket_put_r2t_request( socket_r2tq_xp,
     1716                                    TCP_FLAG_RST,
     1717                                    chdev->channel );
    15371718            return;
    15381719        }
    15391720
    1540         // SYN flag == CONNECT request / seq_num cannot be wrong
     1721        // [3] handle security & precedence TODO ... someday
     1722
     1723        // handle SYN == CONNECT request
    15411724        if( seg_syn_set )
    15421725        {
    1543             // build extended pointer on listening socket CRQ
     1726            // build extended pointers on various listening socket fields
     1727            socket_lock_xp = XPTR( socket_cxy , &socket_ptr->lock );
    15441728            socket_crqq_xp = XPTR( socket_cxy , &socket_ptr->crqq );
     1729            socket_r2tq_xp = XPTR( socket_cxy , &socket_ptr->r2tq );
     1730
     1731            // take the lock protecting the matching socket
     1732            remote_queuelock_acquire( socket_lock_xp );
    15451733
    15461734            // try to register request into CRQ queue
     
    15501738                                            seg_seq_num,
    15511739                                            seg_window );
    1552 
    15531740            if ( error )   // CRQ full
    15541741            {
    15551742
    1556 #if DEBUG_DEV_NIC_RX
    1557 if( cycle > DEBUG_DEV_NIC_RX )
    1558 printk("\n[%s] thread[%x,%x] listening socket[%x,%d] CRQ full => send RST\n",
    1559 __FUNCTION__, this->process->pid, this->trdid, pid, fdid );
     1743#if DEBUG_DEV_NIC_ERROR
     1744printk("\n[ERROR] in %s : listening socket[%x,%d] %s receive SYN but CRQ full => send RST\n",
     1745__FUNCTION__, pid, fdid );
    15601746#endif
    15611747                // make an RST request to R2T queue
     
    15641750                                        chdev->channel );
    15651751            }
    1566             else          // new connection request registered in CRQ
     1752            else          // register request in listening socket CRQ
    15671753            {
    15681754
    15691755#if DEBUG_DEV_NIC_RX
     1756if( DEBUG_DEV_NIC_RX < cycle )
    15701757if( cycle > DEBUG_DEV_NIC_RX )
    1571 printk("\n[%s] thread[%x,%x] for listening socket[%x,%d] : register request in CRQ\n",
    1572 __FUNCTION__, this->process->pid, this->trdid, pid, fdid );
    1573 #endif
    1574                 // check pending RX_ACCEPT command
    1575                 if( (hal_remote_l32(XPTR(socket_cxy,&socket_ptr->rx_valid)) == true) &&
    1576                     (hal_remote_l32(XPTR(socket_cxy,&socket_ptr->rx_cmd)) == CMD_RX_ACCEPT) )
     1758printk("\n[%s] listening socket[%x,%d] register request in CRQ\n",
     1759__FUNCTION__, pid, fdid );
     1760#endif
     1761                bool_t   rx_valid = hal_remote_l32( XPTR(socket_cxy , &socket_ptr->rx_valid));
     1762                uint32_t rx_cmd   = hal_remote_l32( XPTR(socket_cxy , &socket_ptr->rx_cmd));
     1763               
     1764                // check pending ACCEPT command
     1765                if( rx_valid && (rx_cmd == CMD_RX_ACCEPT) )
    15771766                {
    15781767                    // reset rx_valid
    15791768                    hal_remote_s32( XPTR( socket_cxy , &socket_ptr->rx_valid ), false );
    15801769                     
    1581                     // report success to RX client thread
     1770                    // report success to RX client thread, that will
     1771                    // create a new socket and request a SYN-ACK to TX server thread
    15821772                    dev_nic_unblock_rx_client( socket_xp , CMD_STS_SUCCESS );
    15831773
    15841774#if DEBUG_DEV_NIC_RX
     1775if( DEBUG_DEV_NIC_RX < cycle )
    15851776if( cycle > DEBUG_DEV_NIC_RX )
    1586 printk("\n[%s] thread[%x,%x] for listening socket[%x,%d] unblock RX client thread\n",
    1587 __FUNCTION__, this->process->pid, this->trdid, pid, fdid );
     1777printk("\n[%s] listening socket[%x,%d] unblock RX client thread\n",
     1778__FUNCTION__, fdid );
    15881779#endif
    15891780                }
    15901781            }   // end register request in CRQ
     1782
     1783            // release the lock protecting the matching socket
     1784            remote_queuelock_release( socket_lock_xp );
     1785
    15911786        }   // end if SYN
    1592        
     1787
    15931788        return;
    15941789
    15951790    }  // end if listening_match
    15961791
    1597     // 6. no socket found => discard segment
    1598 
    1599 #if DEBUG_DEV_NIC_RX
    1600 if( cycle > DEBUG_DEV_NIC_RX )
    1601 printk("\n[%s] thread[%x,%x] exit failure : no socket found => discard segment\n",
    1602 __FUNCTION__, this->process->pid, this->trdid );
     1792    // 6. no attached socket found and no listening socket found => discard segment
     1793
     1794#if DEBUG_DEV_NIC_ERROR
     1795printk("\n[ERROR] in %s : thread[%x,%d] / unexpected TCP segment => discard / cycle %d\n",
     1796__FUNCTION__, this->process->pid, this->trdid, chdev->channel, cycle );
    16031797#endif
    16041798
     
    16181812
    16191813    thread_t    * this = CURRENT_THREAD;
    1620 
     1814   
    16211815// check thread can yield
    16221816thread_assert_can_yield( this , __FUNCTION__ );
     
    16261820"illegal chdev type or direction" );
    16271821
    1628 #if DEBUG_DEV_NIC_RX
    1629 uint32_t   cycle = (uint32_t)hal_get_cycles();
     1822#if DEBUG_DEV_NIC_RX || DEBUG_DEV_NIC_ERROR
     1823uint32_t cycle = (uint32_t)hal_get_cycles();
     1824#endif
     1825
     1826#if DEBUG_DEV_NIC_RX
    16301827if( cycle > DEBUG_DEV_NIC_RX )
    16311828printk("\n[%s] thread[%x,%x] starts / cycle %d\n",
    16321829__FUNCTION__, this->process->pid, this->trdid, cycle );
    16331830#endif
     1831
     1832    // avoid warning
     1833    ip_length = 0;
     1834    error     = 0;
    16341835
    16351836    // get extended pointers on server tread and chdev
     
    16741875__FUNCTION__, this->process->pid, this->trdid, cycle );
    16751876#endif
    1676 
     1877            // check possible error reported by NIC ISR
     1878            if( this->nic_cmd.error ) 
     1879            {
     1880                printk("\n[PANIC] in %s : %s DMA engine cannot access RX_QUEUE / cycle %d\n",
     1881                __FUNCTION__, chdev->name , (uint32_t)hal_get_cycles() );
     1882            }
    16771883        }
    16781884        else                 // success => handle packet
     
    16821888cycle = (uint32_t)hal_get_cycles();
    16831889if( DEBUG_DEV_NIC_RX < cycle )
    1684 dev_nic_packet_display( false,               // is_tx
    1685                         this->process->pid,
    1686                         this->trdid,
    1687                         cycle,
    1688                         k_buf );
    16891890#endif
    16901891
     
    16971898            {
    16981899
    1699 #if DEBUG_DEV_NIC_RX
    1700 cycle = (uint32_t)hal_get_cycles();
    1701 if( DEBUG_DEV_NIC_RX < cycle )
    1702 printk("\n[%s] thread[%x,%x] discard ETH packet / cycle %d\n",
     1900#if DEBUG_DEV_NIC_ERROR
     1901printk("\n[WARNING] in %s : thread[%x,%x] discard ETH packet / cycle %d\n",
    17031902__FUNCTION__, this->process->pid, this->trdid, cycle );
    17041903#endif
     
    17231922            {
    17241923
    1725 #if DEBUG_DEV_NIC_RX
    1726 cycle = (uint32_t)hal_get_cycles();
    1727 if( DEBUG_DEV_NIC_RX < cycle )
    1728 printk("\n[%s] thread[%x,%x] discarded IP packet / cycle %d\n",
     1924#if DEBUG_DEV_NIC_ERROR
     1925printk("\n[WARNING] in %s : thread[%x,%x] discard IP packet / cycle %d\n",
    17291926__FUNCTION__, this->process->pid, this->trdid, cycle );
    17301927#endif
     
    17621959            {
    17631960 
    1764 #if DEBUG_DEV_NIC_RX
     1961#if DEBUG_DEV_NIC_ERROR
    17651962cycle = (uint32_t)hal_get_cycles();
    17661963if( DEBUG_DEV_NIC_RX < cycle )
    1767 printk("\n[%s] thread[%x,%x] discarded unsupported transport protocol %d\n",
     1964printk("\n[WARNING] in %s : thread[%x,%x] unsupported transport protocol %d / cycle %d\n",
    17681965__FUNCTION__, this->process->pid, this->trdid, trsp_protocol, cycle );
    17691966#endif
    17701967                continue;
    17711968            }
    1772         }
    1773     } // end of while loop
    1774 // end dev_nic_rx_server()
     1969        }   // end else success
     1970    }   // end of while loop
     1971 // end dev_nic_rx_server()
    17751972
    17761973
     
    17821979
    17831980///////////////////////////////////////////////////////////////////////////////////////////
    1784 // This static function is called by the dev_nic_tx_build_packet() function.
     1981// This static function is called by the dev_nic_tx_send_packet() function.
    17851982// It moves one ETH/IP/UDP packet from the kernel buffer identified by the <buffer> and
    17861983// <length> arguments to the NIC_TX_QUEUE identified the <chdev> argument.
     
    18162013    this->nic_cmd.buffer = k_buf;
    18172014    this->nic_cmd.length = length;
     2015    this->nic_cmd.error  = 0;
    18182016
    18192017    while( 1 )
     
    18682066// <socket_xp> argument. The <length> argument defines the number of bytes in payload.
    18692067// It set the "src_port", "dst_port", "total_length" and "checksum" fields in UDP header.
    1870 // The payload must be previouly loaded in the pernel buffer.
     2068// The payload must be previouly loaded in the kernel buffer.
    18712069///////////////////////////////////////////////////////////////////////////////////////////
    18722070// @ k_buf      : [in]  pointer on first byte of UDP header in kernel buffer.
     
    19042102    k_buf[3] = remote_port;
    19052103
     2104    // reset checksum
     2105    k_buf[6] = 0;
     2106    k_buf[7] = 0;
     2107
    19062108    // set packet length in header
    19072109    k_buf[4] = total_length >> 8;
     
    19092111   
    19102112    // compute UDP packet checksum
    1911     checksum = dev_nic_udp_checksum( k_buf , total_length );
    1912 
     2113    checksum = dev_nic_tcp_udp_checksum( k_buf,
     2114                                         total_length,
     2115                                         local_addr,
     2116                                         remote_addr,
     2117                                         false );       // is_not_tcp
    19132118    // set checksum
    19142119    k_buf[6] = checksum >> 8;
     
    19202125// This static function is called by the dev_nic_tx_server() function.
    19212126// It builds a TCP header in the kernel buffer defined by the <k_buf> argument.
    1922 // The payload must have been previouly registered in this buffer.
     2127// The payload must have been previouly registered in this buffer (for checksum).
    19232128// The "local_addr", "local_port", "remote_addr", "remote_port", seq_num", "ack_num",
    19242129// and "window" fields are obtained from the <socket_xp> argument.
     
    19992204 
    20002205    // compute TCP segment checksum
    2001     checksum = dev_nic_tcp_checksum( k_buf,
    2002                                      total_length,
    2003                                      src_addr,
    2004                                      dst_addr );
     2206    checksum = dev_nic_tcp_udp_checksum( k_buf,
     2207                                         total_length,
     2208                                         src_addr,
     2209                                         dst_addr,
     2210                                         true );       // is_tcp
    20052211    // set "checksum"
    20062212    k_buf[16] = checksum >> 8;
     
    21082314}  // end dev_nic_tx_build_eth_header()
    21092315
    2110 ///////////////////////////////////////////////////////////////////////////////////////////
    2111 // This static function is called by the dev_nic_tx_server() function to handle one TX
    2112 // command, or one R2T request, as defined by the <cmd_valid> and <r2t_valid> arguments,
    2113 // for the socket identified by the <socket_xp> argument. It builds an ETH/IP/UDP packet
    2114 // or ETH/IP/TCP segment, in the buffer defined by the <k_buf> argument, and registers
    2115 // it in the NIC_TX queue defined by the <chdev> argument.
    2116 // For a TCP header, the "seq_num", ack_num", and "window" fiels are defined by the
    2117 // "socket.tx_next", "socket.rx_next" and "socket.rx_wnd" fields respectively.
    2118 // It updates the "socket.state", "socket.tx_nxt", "socket.r2tq", and "socket.crqq"
    2119 // The supported TX command types are CONNECT / ACCEPT / SEND / CLOSE.
    2120 // fields as required by the command type.
    2121 // - For an UDP socket, it reset the "socket.tx_valid" field, and unblock the client
    2122 //   thread when the packet has been sent, or when an error must be reported.
    2123 // - For a TCP socket, it reset the "socket.tx_valid" field when the segment has been
    2124 //   sent, but does not unblocks the client thread, that will be unblocqued by the
    2125 //   NIC_RX thread when the TX command is fully completed.
     2316
     2317///////////////////////////////////////////////////////////////////////////////////////////
     2318// This static function implement the TCP protocol as specified by the RFC.
     2319// It is called by the dev_nic_tx_server() function to handle one TX command,
     2320// or one R2T request, for the socket identified by the <socket_xp> argument.
     2321// It builds an ETH/IP/UDP packet or ETH/IP/TCP segment, in the 2 Kbytes kernel buffer,
     2322// defined by the <k_buf> argument from informations found in socket descriptor.
     2323// It returns a command status code (defined in the ksocket.h file), and returns in the
     2324// <total_length> argument the actual packet length.
     2325// It updates the "socket.state", "socket.tx_nxt", "socket.r2tq", "socket.crqq",
     2326// "socket.todo" fields as required by the command type, but it does NOT reset
     2327// the "socket.tx_valid" field and does NOT unblock the client thread.
     2328// It does NOt take the socket lock, that is taken by the dev_nic_server().
    21262329///////////////////////////////////////////////////////////////////////////////////////////
    21272330// To build a packet, it makes the following actions:
    2128 // 1) it takes the lock protecting the socket state.
    2129 // 2) it get the command arguments from socket descriptor.
    2130 // 3) it build an UDP packet or a TCP segment, depending on command type and socket state.
    2131 // 4) it updates the socket state.
    2132 // 5) it releases the lock protecting the socket.
    2133 // 6) it build the IP header.
    2134 // 7) it build the ETH header.
    2135 // 8) it copies the packet in the NIC_TX queue.
    2136 ///////////////////////////////////////////////////////////////////////////////////////////
    2137 // @ cmd_state   : [in] TX command valid in socket descriptor.
    2138 // @ r2t_valid   : [in] R2T request valid in command descriptor.
    2139 // @ socket_xp   : [in] extended pointer on client socket. 
    2140 // @ k_buf       : [in] local pointer on kernel buffer (2 Kbytes).
    2141 // @ chdev       : [in] local pointer on NIC_RX chdev.
    2142 ///////////////////////////////////////////////////////////////////////////////////////////
    2143 static void dev_nic_tx_build_packet( bool_t    cmd_valid,
    2144                                      bool_t    r2t_valid,
    2145                                      xptr_t    socket_xp,
    2146                                      uint8_t * k_buf,
    2147                                      chdev_t * chdev )
     2331// 1) it get the command arguments from socket descriptor.
     2332// 2) it build an UDP packet or a TCP segment, and update socket state.
     2333// 3) it build the IP header.
     2334// 4) it build the ETH header.
     2335///////////////////////////////////////////////////////////////////////////////////////////
     2336// @ socket_xp    : [in]  extended pointer on client socket. 
     2337// @ k_buf        : [in]  local pointer on kernel buffer (2 Kbytes).
     2338// @ total_length : [out] total number of bytes written in k_buf.
     2339// @ return command status.
     2340///////////////////////////////////////////////////////////////////////////////////////////
     2341static socket_cmd_sts_t dev_nic_tx_build_packet( xptr_t     socket_xp,
     2342                                                 uint8_t  * k_buf,
     2343                                                 uint32_t * total_length )
    21482344{
    21492345    socket_t  * socket_ptr;
    21502346    cxy_t       socket_cxy;
    21512347    xptr_t      client_xp;       // extended pointer on client thread 
     2348    bool_t      cmd_valid;       // valid user command
     2349    bool_t      r2t_valid;       // valid R2T queue request
    21522350    uint32_t    cmd_type;        // NIC command type
    2153     uint8_t   * tx_buf;          // local pointer on kernel buffer for payload
     2351    uint8_t   * tx_buf;          // local pointer on socket buffer for payload
    21542352    uint32_t    len;             // tx_buf length (bytes)
    21552353    uint32_t    todo;            // number of bytes not yet sent
    21562354    uint32_t    socket_type;     // socket type (UDP/TCP)
    21572355    uint32_t    socket_state;    // socket state       
    2158     xptr_t      socket_lock_xp;  // extended pointer on socket lock
    21592356    xptr_t      socket_r2tq_xp;  // extended pointer on R2T queue
    21602357    uint32_t    src_ip_addr;     // source IP address
     
    21662363    uint8_t     trsp_protocol;   // transport protocol type (UDP/TCP)
    21672364    uint8_t     r2t_flags;       // flags defined by one R2T queue request
    2168     bool_t      do_send;         // build & send a packet when true
    2169  
     2365 
    21702366    // get socket cluster and local pointer
    21712367    socket_cxy = GET_CXY( socket_xp );
    21722368    socket_ptr = GET_PTR( socket_xp );
    21732369
     2370#if DEBUG_DEV_NIC_TX  || DEBUG_DEV_NIC_ERROR
     2371uint32_t   cycle       = (uint32_t)hal_get_cycles();
     2372uint32_t   socket_fdid = hal_remote_l32( XPTR( socket_cxy , &socket_ptr->fdid ));
     2373uint32_t   socket_pid  = hal_remote_l32( XPTR( socket_cxy , &socket_ptr->pid ));
     2374#endif
     2375
     2376    // build extended pointer on socket r2t queue
     2377    socket_r2tq_xp = XPTR( socket_cxy , &socket_ptr->r2tq );
     2378
     2379    // get cmd_valid & t2t_valid from socket descriptor
     2380    cmd_valid = (bool_t)hal_remote_l32( XPTR( socket_cxy , &socket_ptr->tx_valid ));
     2381    r2t_valid = (bool_t)remote_buf_status( XPTR( socket_cxy , &socket_ptr->r2tq ));
     2382
    21742383#if DEBUG_DEV_NIC_TX
    2175 thread_t * this = CURRENT_THREAD;;
    2176 uint32_t   cycle = (uint32_t)hal_get_cycles();
    2177 uint32_t   fdid  = hal_remote_l32( XPTR( socket_cxy , &socket_ptr->fdid ));
    2178 uint32_t   pid   = hal_remote_l32( XPTR( socket_cxy , &socket_ptr->pid ));
    21792384if( cycle > DEBUG_DEV_NIC_TX )
    2180 printk("\n[%s] thread[%x,%x] enter for socket[%x,%d] : cmd_valid %d / r2t_valid %d / cycle %d\n",
    2181 __FUNCTION__, this->process->pid, this->trdid, pid, fdid, cmd_valid, r2t_valid, cycle );
    2182 #endif
    2183 
    2184     // build extended pointers on socket lock and r2t queue
    2185     socket_lock_xp = XPTR( socket_cxy , &socket_ptr->lock );   
    2186     socket_r2tq_xp = XPTR( socket_cxy , &socket_ptr->r2tq );
    2187 
    2188     // 1. take lock protecting this socket
    2189     remote_queuelock_acquire( socket_lock_xp );
    2190 
    2191     // get relevant socket infos
     2385printk("\n[%s] enter for socket[%x,%d] : cmd_val %d / r2t_val %d / cycle %d\n",
     2386__FUNCTION__, socket_pid, socket_fdid, cmd_valid, r2t_valid, cycle );
     2387#endif
     2388
     2389    // 1. get relevant socket infos
    21922390    socket_type  = hal_remote_l32( XPTR( socket_cxy , &socket_ptr->type ));
    21932391    socket_state = hal_remote_l32( XPTR( socket_cxy , &socket_ptr->state ));
     
    21952393    dst_ip_addr  = hal_remote_l32( XPTR( socket_cxy , &socket_ptr->remote_addr ));
    21962394
    2197     // compute UDP/TCP packet base in kernel buffer
     2395    // compute UDP/TCP packet base in local kernel buffer
    21982396    k_trsp_base = k_buf + ETH_HEAD_LEN + IP_HEAD_LEN;
    21992397
    2200     // set default values
    2201     do_send     = false;
     2398    // default value
    22022399    trsp_length = 0;
    2203     nbytes      = 0;
    2204 
    2205     if( cmd_valid )  // handle TX command
    2206     {
    2207         // 2. get command arguments from socket
     2400
     2401    if( cmd_valid )  // handle TX command depending on type
     2402    {
     2403        // get command arguments from socket
    22082404        cmd_type  = hal_remote_l32( XPTR( socket_cxy , &socket_ptr->tx_cmd ));
    22092405        tx_buf    = hal_remote_lpt( XPTR( socket_cxy , &socket_ptr->tx_buf ));
     
    22132409       
    22142410#if DEBUG_DEV_NIC_TX
    2215 cycle = (uint32_t)hal_get_cycles();
    22162411if( cycle > DEBUG_DEV_NIC_TX )
    2217 printk("\n[%s] thread[%x,%x] cmd_valid for socket[%x,%d] : %s / %s / cycle %d\n",
    2218 __FUNCTION__, this->process->pid, this->trdid, pid, fdid,
    2219 socket_cmd_type_str(cmd_type), socket_state_str(socket_state), cycle );
     2412printk("\n[%s] socket[%x,%d] / %s / command %s \n",
     2413__FUNCTION__, socket_pid, socket_fdid,
     2414socket_cmd_type_str(cmd_type),socket_state_str(socket_state) );
    22202415#endif
    22212416
    22222417        //////////////////////////////////////////////////////////
    2223         // 3. UDP : build UDP packet and update UDP socket state
     2418        // 2. UDP : build UDP packet and update UDP socket state
    22242419        if( socket_type == SOCK_DGRAM )       
    22252420        {
     
    22282423            if( socket_state != UDP_STATE_ESTAB )
    22292424            {
    2230                 // reset tx_valid
    2231                 hal_remote_s32( XPTR( socket_cxy , &socket_ptr->tx_valid ) , false );
    2232 
    2233                 // unblock client thread / report error
    2234                 dev_nic_unblock_tx_client( socket_xp , CMD_STS_BADSTATE );
     2425                return  CMD_STS_BADSTATE;
    22352426            }
    2236             else
     2427            else if( cmd_type == CMD_TX_SEND )
    22372428            {
    2238                 if( cmd_type == CMD_TX_SEND )
    2239                 {
    2240                     // compute payload length
    2241                     nbytes = ( PAYLOAD_MAX_LEN < todo ) ? PAYLOAD_MAX_LEN : todo;
    2242 
    2243                     // move payload from tx_buf to 2 Kbytes kernel buffer
    2244                     memcpy( k_trsp_base + UDP_HEAD_LEN,
    2245                             tx_buf + (len - todo),
    2246                             nbytes );
    2247 
    2248                     // build UDP header
    2249                     dev_nic_tx_build_udp_header( k_trsp_base,
    2250                                                  socket_xp,
    2251                                                  nbytes );
    2252 
    2253                     // update "tx_todo" in socket descriptor
    2254                     hal_remote_s32( XPTR(socket_cxy , &socket_ptr->tx_todo), todo - nbytes );
    2255 
    2256                     // send UDP packet
    2257                     trsp_length = UDP_HEAD_LEN + nbytes;
    2258                     do_send     = true;
    2259 
    2260 #if( DEBUG_DEV_NIC_TX & 1)
    2261 cycle = (uint32_t)hal_get_cycles();
     2429                // compute payload length
     2430                nbytes = ( CONFIG_SOCK_PAYLOAD_MAX < todo ) ? CONFIG_SOCK_PAYLOAD_MAX : todo;
     2431
     2432                // move payload from remote socket tx_buf to local kernel buffer
     2433                hal_remote_memcpy( XPTR( local_cxy  , k_trsp_base + UDP_HEAD_LEN ),
     2434                                   XPTR( socket_cxy , tx_buf + (len - todo) ),
     2435                                   nbytes );
     2436
     2437                // build UDP header
     2438                dev_nic_tx_build_udp_header( k_trsp_base,
     2439                                             socket_xp,
     2440                                             nbytes );
     2441
     2442                // update "tx_todo" in socket descriptor
     2443                hal_remote_s32( XPTR(socket_cxy , &socket_ptr->tx_todo), todo - nbytes );
     2444
     2445                // set UDP packet length
     2446                trsp_length = UDP_HEAD_LEN + nbytes;
     2447
     2448#if DEBUG_DEV_NIC_TX
    22622449if( cycle > DEBUG_DEV_NIC_TX )
    2263 printk("\n[%s] thread[%x,%x] socket[%x,%d] UDP packet build / length %d / cycle %d\n",
    2264 __FUNCTION__, this->process->pid, this->trdid, trsp_length , cycle );
    2265 #endif
    2266                     if( nbytes == todo )    // last byte sent
    2267                     {
    2268                         // reset tx_valid
    2269                         hal_remote_s32( XPTR( socket_cxy , &socket_ptr->tx_valid ) , false );
    2270 
    2271                         // report success to TX client
    2272                         dev_nic_unblock_tx_client( socket_xp , CMD_STS_SUCCESS );
    2273                     }
    2274                 }
    2275                 else // CONNECT, ACCEPT, or CLOSE commands are illegal for UDP
    2276                 {
    2277                     // reset tx_valid
    2278                     hal_remote_s32( XPTR( socket_cxy , &socket_ptr->tx_valid ) , false );
    2279 
    2280                     // report error
    2281                     dev_nic_unblock_tx_client( socket_xp , CMD_STS_BADCMD );
    2282                 }
     2450printk("\n[%s] socket[%x,%d] UDP packet build / %d bytes\n",
     2451__FUNCTION__, socket_pid, socket_fdid, nbytes );
     2452#endif
     2453            }
     2454            else // CONNECT, ACCEPT, or CLOSE commands are illegal for UDP
     2455            {
     2456
     2457#if DEBUG_DEV_NIC_ERROR
     2458printk("\n[ERROR] in %s : bad state %s for socket[%x,%x] / cycle %d\n",
     2459__FUNCTION__, socket_state_str(socket_state), socket_pid, socket_fdid, cycle );
     2460#endif
     2461                return  CMD_STS_BADCMD;
    22832462            }
    22842463        }  // end UDP
    22852464
    22862465        ///////////////////////////////////////////////////////////
    2287         // 3. TCP : build TCP segment and update TCP socket state
     2466        // 2. TCP : build TCP segment and update TCP socket state
    22882467        else if( socket_type == SOCK_STREAM )
    22892468        {
     
    22962475                socket_r2tq_xp = XPTR( socket_cxy , &socket_ptr->r2tq );
    22972476       
    2298                 // get one request from R2T queue 
    2299                 remote_buf_get_to_kernel( socket_r2tq_xp , &r2t_flags , 1 );
     2477                // get one request from R2T queue, and update R2T queue
     2478                socket_get_r2t_request( socket_r2tq_xp , &r2t_flags );
    23002479            }
    23012480            else
     
    23112490                {
    23122491                    // initialises socket tx_nxt, and rx_wnd
    2313                     hal_remote_s32(XPTR(socket_cxy , &socket_ptr->tx_nxt), TCP_ISS_CLIENT );
    2314                     hal_remote_s32(XPTR(socket_cxy , &socket_ptr->rx_wnd), TCP_MAX_WINDOW );
     2492                    hal_remote_s32(XPTR(socket_cxy , &socket_ptr->tx_nxt),
     2493                                   CONFIG_SOCK_ISS_CLIENT );
     2494                    hal_remote_s32(XPTR(socket_cxy , &socket_ptr->rx_wnd),
     2495                                   CONFIG_SOCK_MAX_WINDOW );
    23152496
    23162497                    // build TCP SYN segment
     
    23192500                                                 0,        // length
    23202501                                                 TCP_FLAG_SYN );   
    2321                     // send segment
     2502                    // set TCP packet length
    23222503                    trsp_length = TCP_HEAD_LEN;
    2323                     do_send     = true;
    2324 
    2325 #if DEBUG_DEV_NIC_TX
    2326 cycle = (uint32_t)hal_get_cycles();
    2327 if( cycle > DEBUG_DEV_NIC_TX )
    2328 printk("\n[%s] thread[%x,%x] socket[%x,%d] %s / CONNECT / "
    2329 "TCP SYN build / cycle %d\n",
    2330 __FUNCTION__, this->process->pid, this->trdid, pid, fdid,
    2331 socket_state_str( socket_state ), cycle );
    2332 #endif
     2504
    23332505                    // update socket.state
    23342506                    hal_remote_s32( XPTR( socket_cxy , &socket_ptr->state ),
     
    23372509                    // update socket.tx_nxt
    23382510                    hal_remote_s32( XPTR( socket_cxy , &socket_ptr->tx_nxt ),
    2339                                           TCP_ISS_CLIENT + 1 );
    2340 
    2341                     // reset tx_valid but do not unblock client thread
    2342                     hal_remote_s32( XPTR( socket_cxy , &socket_ptr->tx_valid ), false );
     2511                                          CONFIG_SOCK_ISS_CLIENT + 1 );
     2512#if DEBUG_DEV_NIC_TX
     2513if( cycle > DEBUG_DEV_NIC_TX )
     2514printk("\n[%s] socket[%x,%d] %s / CONNECT / TCP SYN build\n",
     2515__FUNCTION__, socket_pid, socket_fdid, socket_state_str(socket_state) );
     2516#endif
    23432517                }
    23442518                else                      // report error for all other socket states
    23452519                {
    2346                     // reset tx_valid
    2347                     hal_remote_s32( XPTR( socket_cxy , &socket_ptr->tx_valid ) , false );
    2348                    
    2349                     // report error
    2350                     dev_nic_unblock_tx_client( socket_xp , CMD_STS_BADSTATE );
     2520
     2521#if DEBUG_DEV_NIC_ERROR
     2522printk("\n[ERROR] in %s : bad state %s socket[%x,%x] / cycle %d\n",
     2523__FUNCTION__, socket_state_str(socket_state), socket_pid, socket_fdid, cycle );
     2524#endif
     2525                    return CMD_STS_BADSTATE;
    23512526                }
    23522527            }
     
    23582533                {
    23592534                    // initialize socket tx_nxt, and rx_wnd
    2360                     hal_remote_s32(XPTR(socket_cxy , &socket_ptr->tx_nxt), TCP_ISS_SERVER );
    2361                     hal_remote_s32(XPTR(socket_cxy , &socket_ptr->rx_wnd), CONFIG_SOCK_RX_BUF_SIZE);
     2535                    hal_remote_s32(XPTR(socket_cxy , &socket_ptr->tx_nxt),
     2536                                        CONFIG_SOCK_ISS_SERVER );
     2537                    hal_remote_s32(XPTR(socket_cxy , &socket_ptr->rx_wnd),
     2538                                        (1 << CONFIG_SOCK_RX_BUF_ORDER) );
    23622539               
    23632540                    // build TCP ACK-SYN segment
     
    23662543                                                 0,         //  length
    23672544                                                 TCP_FLAG_SYN | TCP_FLAG_ACK );
    2368                     // send segment
     2545                    // set TCP packet length
    23692546                    trsp_length = TCP_HEAD_LEN;
    2370                     do_send     = true;
    2371 
    2372 #if DEBUG_DEV_NIC_TX
    2373 cycle = (uint32_t)hal_get_cycles();
    2374 if( cycle > DEBUG_DEV_NIC_TX )
    2375 printk("\n[%s] thread[%x,%x] socket[%x,%d] %s / ACCEPT / send SYN-ACK / cycle %d\n",
    2376 __FUNCTION__, this->process->pid, this->trdid, pid, fdid,
    2377 socket_state_str( socket_state ), cycle );
    2378 #endif
     2547
    23792548                    // update socket.state
    23802549                    hal_remote_s32( XPTR( socket_cxy , &socket_ptr->state ),
     
    23832552                    // update socket.tx_nxt
    23842553                    hal_remote_s32( XPTR( socket_cxy , &socket_ptr->tx_nxt ),
    2385                                           TCP_ISS_SERVER + 1 );
    2386 
    2387                     // reset tx_valid but do not unblock client thread
    2388                     hal_remote_s32( XPTR( socket_cxy , &socket_ptr->tx_valid ), false );
     2554                                          CONFIG_SOCK_ISS_SERVER + 1 );
     2555#if DEBUG_DEV_NIC_TX
     2556if( cycle > DEBUG_DEV_NIC_TX )
     2557printk("\n[%s] socket[%x,%d] %s / ACCEPT / SYN-ACK build\n",
     2558__FUNCTION__, socket_pid, socket_fdid, socket_state_str(socket_state) );
     2559#endif
    23892560                }
    23902561                else                     // report error in all other socket states
    23912562                {
    2392                     // reset tx_valid
    2393                     hal_remote_s32( XPTR( socket_cxy , &socket_ptr->tx_valid ), false );
    2394 
    2395                     // report error to TX client thread
    2396                     dev_nic_unblock_tx_client( socket_xp , CMD_STS_BADSTATE );
     2563
     2564#if DEBUG_DEV_NIC_ERROR
     2565printk("\n[ERROR] in %s : bad state %s for socket[%x,%x] / cycle %d\n",
     2566__FUNCTION__, socket_state_str(socket_state), socket_pid, socket_fdid, cycle );
     2567#endif
     2568                    return CMD_STS_BADSTATE;
    23972569                }
    23982570            }
     
    24232595                    hal_remote_s32( XPTR(socket_cxy , &socket_ptr->tx_nxt), tx_nxt + 1 );
    24242596
    2425                     // send segment
     2597                    // set TCP packet length
    24262598                    trsp_length = TCP_HEAD_LEN;
    2427                     do_send     = true;
    24282599
    24292600#if DEBUG_DEV_NIC_TX
    2430 cycle = (uint32_t)hal_get_cycles();
    24312601if( cycle > DEBUG_DEV_NIC_TX )
    2432 printk("\n[%s] thread[%x,%x] socket[%x,%d] %s / CLOSE / send FIN-ACK / cycle %d\n",
    2433 __FUNCTION__, this->process->pid, this->trdid, pid, fdid,
    2434 socket_state_str( socket_state ), cycle );
    2435 #endif
    2436                     // reset tx_valid but do not unblock client thread
    2437                     hal_remote_s32( XPTR( socket_cxy , &socket_ptr->tx_valid ), false );
     2602printk("\n[%s] socket[%x,%d] %s / CLOSE / FIN-ACK build\n",
     2603__FUNCTION__, socket_pid, socket_fdid, socket_state_str(socket_state) );
     2604#endif
    24382605                }
    24392606                else                                 // all other states => signal error
    24402607                {
    24412608
    2442 #if DEBUG_DEV_NIC_TX
    2443 cycle = (uint32_t)hal_get_cycles();
    2444 if( cycle > DEBUG_DEV_NIC_TX )
    2445 printk("\n[%s] thread[%x,%x] socket[%x,%d] %s / CLOSE / error BADSTATE / cycle %d\n",
    2446 __FUNCTION__, this->process->pid, this->trdid, pid, fdid,
    2447 socket_state_str( socket_state ), cycle );
    2448 #endif
    2449                     // reset tx_valid
    2450                     hal_remote_s32( XPTR( socket_cxy , &socket_ptr->tx_valid ), false );
    2451 
    2452                     // report error
    2453                     dev_nic_unblock_tx_client( socket_xp , CMD_STS_BADSTATE );
     2609#if DEBUG_DEV_NIC_ERROR
     2610printk("\n[ERROR] in %s : bad state %s for socket[%x,%x] / cycle %d\n",
     2611__FUNCTION__, socket_state_str(socket_state),  socket_pid, socket_fdid, cycle );
     2612#endif
     2613                    return CMD_STS_BADSTATE;
    24542614                }
    24552615            }
    2456             /////////////////////////////////////
     2616            //////////////////////////////////
    24572617            else if( cmd_type == CMD_TX_SEND )
    24582618            {
     
    24642624
    24652625                    // compute actual payload length
    2466                     nbytes = ( PAYLOAD_MAX_LEN < todo ) ? PAYLOAD_MAX_LEN : todo;
    2467 
    2468                     // compute TCP segment base in kernel buffer
    2469                     k_trsp_base = k_buf + ETH_HEAD_LEN + IP_HEAD_LEN;
    2470 
    2471                     // move payload to k_buf
    2472                     memcpy( k_trsp_base + TCP_HEAD_LEN,
    2473                             tx_buf + (len - todo),
    2474                             nbytes );
     2626                    nbytes = ( CONFIG_SOCK_PAYLOAD_MAX < todo ) ?
     2627                             CONFIG_SOCK_PAYLOAD_MAX : todo;
     2628
     2629                    // move payload from remote tx_buf to local kernel buffer
     2630                    hal_remote_memcpy( XPTR( local_cxy  , k_trsp_base + TCP_HEAD_LEN ),
     2631                                       XPTR( socket_cxy , tx_buf + (len - todo) ),
     2632                                       nbytes );
    24752633
    24762634                    // build TCP header
     
    24862644                    hal_remote_s32( XPTR(socket_cxy , &socket_ptr->tx_nxt), tx_nxt + nbytes );
    24872645
    2488                     // send TCP segment
     2646                    // set TCP packet length
    24892647                    trsp_length = TCP_HEAD_LEN + nbytes;
    2490                     do_send     = true;
    2491 
    2492                     if( todo == nbytes )   // last byte sent
    2493                     {
    2494                         // reset tx_valid when last byte has been sent
    2495                         hal_remote_s32( XPTR(socket_cxy , &socket_ptr->tx_valid), false );
    2496                     }
    24972648
    24982649#if DEBUG_DEV_NIC_TX
    2499 cycle = (uint32_t)hal_get_cycles();
    25002650if( cycle > DEBUG_DEV_NIC_TX )
    2501 printk("\n[%s] thread[%x,%x] socket[%x,%d] %s / SEND / "
    2502 "TCP DATA build / payload %d / cycle %d\n",
    2503 __FUNCTION__, this->process->pid, this->trdid, pid, fdid,
    2504 socket_state_str( socket_state ), nbytes, cycle );
     2651printk("\n[%s] socket[%x,%d] %s / SEND / %d bytes\n",
     2652__FUNCTION__, socket_pid, socket_fdid, socket_state_str(socket_state), nbytes );
    25052653#endif
    25062654                }
    25072655                else  // all other socket states
    25082656                {
    2509                     // reset tx_valid
    2510                     hal_remote_s32( XPTR( socket_cxy , &socket_ptr->tx_valid ), false );
    2511 
    2512                     // report error to TX client thread
    2513                     dev_nic_unblock_tx_client( socket_xp , CMD_STS_BADSTATE );
     2657
     2658#if DEBUG_DEV_NIC_ERROR
     2659printk("\n[ERROR] in %s : bad state %s for socket[%x,%x] / cycle %d\n",
     2660__FUNCTION__, socket_state_str(socket_state), socket_pid, socket_fdid, cycle );
     2661#endif
     2662                    return CMD_STS_BADSTATE;
    25142663                }
    25152664            }
     
    25172666            else  // undefined TX command type
    25182667            {
    2519                 // reset tx_valid
    2520                 hal_remote_s32( XPTR( socket_cxy , &socket_ptr->tx_valid ), false );
    2521 
    2522                 // report error to TX client thread
    2523                 dev_nic_unblock_tx_client( socket_xp , CMD_STS_BADCMD );
     2668
     2669#if DEBUG_DEV_NIC_ERROR
     2670printk("\n[ERROR] in %s : undefined command type for socket[%x,%x] %s / cycle %d\n",
     2671__FUNCTION__, socket_pid, socket_fdid, socket_state_str(socket_state), cycle );
     2672#endif
     2673                return CMD_STS_BADCMD;
    25242674            }
    25252675        }  // end TCP
     
    25272677    else         // no valid TX command => handle R2T request only
    25282678    {
     2679
     2680assert( __FUNCTION__ , (socket_type == SOCK_STREAM) , "don't use R2T queue for UDP" );
     2681 
    25292682        // get one request from R2T queue
    2530         remote_buf_get_to_kernel( socket_r2tq_xp , &r2t_flags , 1 );
     2683        socket_get_r2t_request( socket_r2tq_xp , &r2t_flags );
    25312684
    25322685#if DEBUG_DEV_NIC_TX
    25332686cycle = (uint32_t)hal_get_cycles();
    25342687if( cycle > DEBUG_DEV_NIC_TX )
    2535 printk("\n[%s] thread[%x,%x] only r2t_valid for socket[%x,%d] / flags %x / cycle %d\n",
    2536 __FUNCTION__, this->process->pid, this->trdid, pid, fdid, r2t_flags, cycle );
    2537 #endif
    2538 
     2688printk("\n[%s] socket[%x,%d] %s / send only flags %x / no data\n",
     2689__FUNCTION__, socket_pid, socket_fdid, socket_state_str(socket_state), r2t_flags );
     2690#endif
    25392691        // build TCP header
    25402692        dev_nic_tx_build_tcp_header( k_trsp_base,
    25412693                                     socket_xp,
    2542                                      0,             // payload length
     2694                                     0,             // no payload
    25432695                                     r2t_flags );   // flags
    2544         // send TCP segment
     2696        // set protocol
    25452697        trsp_protocol = PROTOCOL_TCP;
     2698
     2699        // set TCP packet length
    25462700        trsp_length   = TCP_HEAD_LEN;
    2547         do_send       = true;
    25482701    }
    25492702
    2550     // 4. release the lock protecting the socket
    2551     remote_queuelock_release( socket_lock_xp );
    2552 
    2553     // return if no packet to send
    2554     if( do_send == false ) return;
    2555 
    2556     // 5. build IP header
     2703    // 3. build IP header
    25572704    dev_nic_tx_build_ip_header( k_buf + ETH_HEAD_LEN,
    25582705                                src_ip_addr,
     
    25612708                                trsp_length );
    25622709
    2563 #if( DEBUG_DEV_NIC_TX & 1)
    2564 cycle = (uint32_t)hal_get_cycles();
    2565 if( cycle > DEBUG_DEV_NIC_TX )
    2566 printk("\n[%s] thread[%x,%x] IP header build / length %d / cycle %d\n",
    2567 __FUNCTION__, this->process->pid, this->trdid, IP_HEAD_LEN + trsp_length , cycle );
    2568 #endif
    2569 
    2570     // 6. build ETH header
     2710    // 4. build ETH header
    25712711    dev_nic_tx_build_eth_header( k_buf,
    25722712                                 (uint8_t)DST_MAC_5,
     
    25842724                                 IP_HEAD_LEN + trsp_length );
    25852725
    2586 #if( DEBUG_DEV_NIC_TX & 1)
    2587 cycle = (uint32_t)hal_get_cycles();
    2588 if( cycle > DEBUG_DEV_NIC_TX )
    2589 printk("\n[%s] thread[%x,%x] ETH header build / cycle %d\n",
    2590 __FUNCTION__, this->process->pid, this->trdid, cycle );
    2591 #endif
    2592 
    2593     // 7. move packet to NIC_TX queue (blocking function)
    2594     dev_nic_tx_move_packet( chdev,
    2595                             k_buf,
    2596                             ETH_HEAD_LEN + IP_HEAD_LEN + trsp_length );
    2597 
    25982726#if DEBUG_DEV_NIC_TX
    25992727cycle = (uint32_t)hal_get_cycles();
    26002728if( cycle > DEBUG_DEV_NIC_TX )
    2601 printk("\n[%s] thread[%x,%x] for socket[%x,%d] moved packet to NIC_TX / cycle %d\n",
    2602 __FUNCTION__, this->process->pid, this->trdid, pid, fdid, cycle );
    2603 #endif
     2729printk("\n[%s] exit for socket[%x,%d] / packet build / cycle %d\n",
     2730__FUNCTION__, socket_pid, socket_fdid, cycle );
     2731#endif
     2732
     2733    // return success and total packet length
     2734    *total_length = ETH_HEAD_LEN + IP_HEAD_LEN + trsp_length;
     2735    return CMD_STS_SUCCESS;
    26042736
    26052737}  // end dev_nic_tx_build_packet()
    2606 
    26072738
    26082739/////////////////////////////////////////
    26092740void dev_nic_tx_server( chdev_t * chdev )
    26102741{
    2611     uint8_t       k_buf[CONFIG_SOCK_PKT_BUF_SIZE];  // buffer for one packet
    2612 
    2613     xptr_t        queue_root_xp;       // extended pointer on sockets list root
    2614     xptr_t        queue_lock_xp;       // extended pointer on lock protecting this list
    2615     xptr_t        socket_xp;           // extended pointer on on registered socket
    2616     socket_t    * socket_ptr;
    2617     cxy_t         socket_cxy;
    2618     xptr_t        iter_xp;             // iterator for loop on registered sockets
    2619     xlist_entry_t temp_root;           // root of temporary list of sockets
    2620     xptr_t        temp_root_xp;        // extended pointer on temporary list of sockets
    2621     uint32_t      temp_nr;             // number of active registered sockets
    2622     bool_t        cmd_valid;           // TX command valid in socket descriptor
    2623     bool_t        r2t_valid;           // valid R2T request in socket descriptor
    2624 
     2742    uint8_t           k_buf[CONFIG_SOCK_PKT_BUF_SIZE];  // buffer for one packet
     2743
     2744    xptr_t            queue_lock_xp;       // extended pointer on lock for sockets list
     2745    xptr_t            root_xp;             // extended pointer on sockets list root
     2746    xptr_t            iter_xp;             // iterator for loop on sockets list
     2747    xptr_t            list_xp;             // extended pointer on socket tx_list field
     2748    xptr_t            socket_xp;           // extended pointer on found socket
     2749    socket_t        * socket_ptr;          // local pointer on found socket
     2750    cxy_t             socket_cxy;          // found socket cluster identifier
     2751    xptr_t            socket_lock_xp;      // extented pointer on found socket lock
     2752    bool_t            cmd_valid;           // TX command valid in socket descriptor
     2753    bool_t            r2t_valid;           // valid R2T request in socket descriptor
     2754    uint32_t          sock_type;           // socket type
     2755    socket_cmd_sts_t  cmd_sts;             // value returned by dev_nic_tx_build_packet()
     2756    socket_cmd_type_t tx_cmd;              // socket TX command type
     2757    uint32_t          tx_todo;             // socket number of bytes not sent yet
     2758    uint32_t          total_length;        // length of the ETH/IP/TCP packet (bytes)
     2759    bool_t            found;               // one active socket found
     2760   
    26252761    thread_t * this = CURRENT_THREAD;
    26262762
     
    26382774"illegal chdev type or direction" );
    26392775
    2640 // check thread can yield
    2641 thread_assert_can_yield( this , __FUNCTION__ );
    2642 
    2643     // build extended pointer on temporary list
    2644     temp_root_xp = XPTR( local_cxy , &temp_root );
    2645                                                          
    2646     // build extended pointer on client sockets queue (lock & root)
     2776    // build extended pointers on client sockets queue lock
    26472777    queue_lock_xp = XPTR( local_cxy , &chdev->wait_lock );
    2648     queue_root_xp = XPTR( local_cxy , &chdev->wait_root );
     2778
     2779    // build extended pointers on client sockets queue root and first item
     2780    root_xp  = XPTR( local_cxy , &chdev->wait_root );
    26492781
    26502782    while( 1 )  // TX server infinite loop
    26512783    {
    2652         // initialize temporary list of registered sockets as empty
    2653         xlist_root_init( temp_root_xp );
    2654         temp_nr = 0;
    2655 
    26562784        // take the lock protecting the client sockets queue
    26572785        remote_busylock_acquire( queue_lock_xp );
    26582786
    2659         // build temporary list of all registered sockets
    2660         if( xlist_is_empty( queue_root_xp ) == false ) 
     2787        found = false;
     2788
     2789        // scan registered sockets to find one active socket
     2790        // with a round robin priority between the registered sockets
     2791        if( xlist_is_empty( root_xp ) == false ) 
    26612792        {
    2662             XLIST_FOREACH( queue_root_xp , iter_xp )
     2793            XLIST_FOREACH( root_xp , iter_xp )
    26632794            {
    2664                 // get client socket cluster and local pointer
     2795                // get client socket cluster and pointers
    26652796                socket_xp  = XLIST_ELEMENT( iter_xp , socket_t , tx_list );
    26662797                socket_ptr = GET_PTR( socket_xp );
    26672798                socket_cxy = GET_CXY( socket_xp );
    26682799
    2669                 // register socket in temporary list
    2670                 xlist_add_last( temp_root_xp , XPTR( socket_cxy , &socket_ptr->tx_temp ));
    2671                 temp_nr++;
    2672             }
     2800                // build extended pointer on socket tx_list field
     2801                list_xp = XPTR( socket_cxy , &socket_ptr->tx_list );
     2802
     2803                // get cmd_valid & r2t_valid from socket descriptor
     2804                cmd_valid = (bool_t)hal_remote_l32( XPTR( socket_cxy , &socket_ptr->tx_valid ));
     2805
     2806                // get r2t_valid from socket descriptor
     2807                r2t_valid = (bool_t)remote_buf_status( XPTR( socket_cxy , &socket_ptr->r2tq ));
     2808
     2809                if( cmd_valid || r2t_valid )    // active => move socket, and exit loop
     2810                {
     2811                    // move selected socket to last position for round-robin
     2812                    xlist_unlink( list_xp );
     2813                    xlist_add_last( root_xp , list_xp );
     2814
     2815                    // exit loop
     2816                    found = true;
     2817                    break;
     2818                }
     2819            }   // end loop on sockets
    26732820        }
    2674 
     2821       
    26752822        // release the lock protecting the client sockets queue
    26762823        remote_busylock_release( queue_lock_xp );
    26772824
    2678         if( temp_nr > 0 )
    2679         {
    2680             // loop on temporary list
    2681             XLIST_FOREACH( temp_root_xp , iter_xp )
    2682             {
    2683                 // get client socket cluster and local pointer
    2684                 socket_xp  = XLIST_ELEMENT( iter_xp , socket_t , tx_temp );
    2685                 socket_ptr = GET_PTR( socket_xp );
    2686                 socket_cxy = GET_CXY( socket_xp );
    2687 
    2688                 // get cmd_valid & t2t_valid from socket descriptor
    2689                 cmd_valid = hal_remote_l32( XPTR( socket_cxy , &socket_ptr->tx_valid ));
    2690 
    2691                 // get r2t_valid from socket descriptor
    2692                 r2t_valid = (bool_t)remote_buf_status( XPTR( socket_cxy , &socket_ptr->r2tq ));
    2693 
    2694                 // test if socket is active
    2695                 if( cmd_valid || r2t_valid )  // active socket
    2696                 {
    2697 
    2698 #if DEBUG_DEV_NIC_TX
    2699 cycle = (uint32_t)hal_get_cycles();
    2700 pid  = hal_remote_l32( XPTR( socket_cxy , &socket_ptr->pid ));
    2701 fdid = hal_remote_l32( XPTR( socket_cxy , &socket_ptr->fdid ));
    2702 if( cycle > DEBUG_DEV_NIC_TX )
    2703 printk("\n[%s] thread[%x,%x] found socket[%x,%d] / cmd_valid %d / r2t_valid %d / cycle %d\n",
    2704 __FUNCTION__, this->process->pid, this->trdid, pid, fdid, cmd_valid, r2t_valid, cycle );
    2705 #endif
    2706                     // build and send one packet/segment for this socket
    2707                     dev_nic_tx_build_packet( cmd_valid,
    2708                                              r2t_valid,
    2709                                              socket_xp,
    2710                                              k_buf,
    2711                                              chdev );
    2712 #if DEBUG_DEV_NIC_TX
    2713 cycle = (uint32_t)hal_get_cycles();
    2714 if( cycle > DEBUG_DEV_NIC_TX )
    2715 dev_nic_packet_display( true,                // is_tx
    2716                         this->process->pid,
    2717                         this->trdid,
    2718                         cycle,
    2719                         k_buf );
    2720 #endif
    2721                 }
    2722                 else                          // inactive socket
    2723                 {
    2724                    temp_nr--;
    2725                 }
    2726             }  // end loop on temporary list
    2727         }
    2728 
    2729         // block & deschedule if no active socket found in current iteration
    2730         if( temp_nr == 0 )
     2825        if( found == false ) // block & deschedule if no active socket
    27312826        {
    27322827 
     
    27372832__FUNCTION__, this->process->pid, this->trdid, cycle );
    27382833#endif
    2739 
    27402834            // block and deschedule
    27412835            thread_block( XPTR( local_cxy , this ) , THREAD_BLOCKED_CLIENT );
     
    27492843#endif
    27502844        }
     2845        else              // handle active socket request
     2846        {
     2847            // avoid warning
     2848            total_length = 0;
     2849 
     2850            // build extended pointer on socket lock
     2851            socket_lock_xp = XPTR( socket_cxy , &socket_ptr->lock );
     2852
     2853            // take socket lock
     2854            remote_queuelock_acquire( socket_lock_xp );
     2855
     2856#if DEBUG_DEV_NIC_TX
     2857cycle = (uint32_t)hal_get_cycles();
     2858pid  = hal_remote_l32( XPTR( socket_cxy , &socket_ptr->pid ));
     2859fdid = hal_remote_l32( XPTR( socket_cxy , &socket_ptr->fdid ));
     2860#endif
     2861
     2862#if DEBUG_DEV_NIC_TX
     2863if( cycle > DEBUG_DEV_NIC_TX )
     2864printk("\n[%s] thread[%x,%x] select socket[%x,%d] / cmd_val %d / r2t_val %d / cycle %d\n",
     2865__FUNCTION__, this->process->pid, this->trdid, pid, fdid, cmd_valid, r2t_valid, cycle );
     2866#endif
     2867            // build one UDP packet / TCP segment
     2868            cmd_sts = dev_nic_tx_build_packet( socket_xp,
     2869                                               k_buf,
     2870                                               &total_length );
     2871#if DEBUG_DEV_NIC_TX
     2872cycle = (uint32_t)hal_get_cycles();
     2873if( cycle > DEBUG_DEV_NIC_TX )
     2874printk("\n[%s] thread[%x,%x] for socket[%x,%x] build packet / %d bytes / sts %d / cycle %d\n",
     2875__FUNCTION__, this->process->pid, this->trdid, pid, fdid, total_length, cmd_sts, cycle );
     2876#endif
     2877            // release socket lock
     2878            remote_queuelock_release( socket_lock_xp );
     2879
     2880            if( cmd_sts == CMD_STS_SUCCESS )    // move packet to TX queue
     2881            {
     2882                // move packet to NIC_TX queue
     2883                dev_nic_tx_move_packet( chdev,
     2884                                        k_buf,
     2885                                        total_length );
     2886#if DEBUG_DEV_NIC_TX
     2887cycle = (uint32_t)hal_get_cycles();
     2888if( cycle > DEBUG_DEV_NIC_TX )
     2889dev_nic_packet_display( pid, fdid, cycle, k_buf );
     2890#endif
     2891                // get socket.type, socket.tx_cmd and socket.tx_todo values
     2892                tx_cmd    = hal_remote_l32( XPTR( socket_cxy , &socket_ptr->tx_cmd ));
     2893                tx_todo   = hal_remote_l32( XPTR( socket_cxy , &socket_ptr->tx_todo ));
     2894                sock_type = hal_remote_l32( XPTR( socket_cxy , &socket_ptr->type ));
     2895
     2896                // client signaling depends on command type and socket type
     2897                if( (tx_cmd == CMD_TX_SEND) &&  (tx_todo == 0) )
     2898                {
     2899                    // reset tx_valid for both UDP and TCP
     2900                    hal_remote_s32( XPTR( socket_cxy , &socket_ptr->tx_valid), false );
     2901
     2902                    // unblock client thread for UDP only
     2903                    if(sock_type == SOCK_DGRAM)
     2904                    dev_nic_unblock_tx_client( socket_xp , CMD_STS_SUCCESS );
     2905                }
     2906                else  // type is CONNECT / ACCEPT / CLOSE
     2907                {
     2908                    // reset tx_valid
     2909                    hal_remote_s32( XPTR( socket_cxy , &socket_ptr->tx_valid), false );
     2910                }
     2911            }
     2912            else                          // signal error to client thread
     2913            {
     2914                // reset tx_valid
     2915                hal_remote_s32( XPTR( socket_cxy , &socket_ptr->tx_valid), false );
     2916
     2917                // unblock tx_client thread
     2918                dev_nic_unblock_tx_client( socket_xp , cmd_sts );
     2919            }
     2920        }   // end active socket handling
    27512921    }   // end infinite while loop
    27522922}  // end dev_nic_tx_server()
    27532923
    27542924
    2755 /////////////////////////////////////////////
    2756 void dev_nic_packet_display( bool_t    is_tx,
    2757                              pid_t     thread_pid,
    2758                              trdid_t   thread_trdid,
     2925
     2926
     2927
     2928//////////////////////////////////////////////////
     2929void dev_nic_packet_display( pid_t     socket_pid,
     2930                             uint32_t  socket_fdid,
    27592931                             uint32_t  cycle,
    27602932                             uint8_t * buf )
     
    28152987    remote_busylock_acquire( lock_xp );
    28162988
    2817     if( is_tx )
    2818     {
    2819         nolock_printk("\n*** NIC_TX server thread[%x,%x] send packet / cycle %d\n",
    2820         thread_pid, thread_trdid, cycle );
    2821     }
    2822     else
    2823     {
    2824         nolock_printk("\n*** NIC_RX server thread[%x,%x] get packet / cycle %d\n",
    2825         thread_pid, thread_trdid, cycle );
    2826     }
    2827 
    2828     nolock_printk("\n***** ETH header *****\n");
     2989    nolock_printk("\n***** packet sent by NIC_TX server for socket[%x,%d] / cycle %d\n",
     2990    socket_pid, socket_fdid, cycle );
     2991
     2992    nolock_printk(" ETH header\n");
    28292993    nolock_printk(" - dst_mac  [6] = %l\n" , eth_dst_mac );
    28302994    nolock_printk(" - src_mac  [6] = %l\n" , eth_src_mac );
    28312995    nolock_printk(" - length   [2] = %d\n" , (uint32_t)eth_length );
    2832     nolock_printk("***** IP  header *****\n");
     2996    nolock_printk(" IP  header\n");
    28332997    nolock_printk(" - version  [1] = %x\n" , (uint32_t)ip_version );
    28342998    nolock_printk(" - tos      [1] = %x\n" , (uint32_t)ip_tos );
     
    28503014                                ((uint16_t)buf[37]     ) ;
    28513015
    2852         nolock_printk("***** UDP header *****\n");
     3016        nolock_printk(" UDP header\n");
    28533017        nolock_printk(" - src_port [2] = %d\n" , (uint32_t)udp_src_port );
    28543018        nolock_printk(" - dst_port [2] = %d\n" , (uint32_t)udp_dst_port );
     
    28813045                                 ((uint16_t)buf[53]     ) ;
    28823046
    2883         nolock_printk("***** TCP header *****\n");
     3047        nolock_printk(" TCP header\n");
    28843048        nolock_printk(" - src_port [2] = %x\n" , (uint32_t)tcp_src_port );
    28853049        nolock_printk(" - dst_port [2] = %x\n" , (uint32_t)tcp_dst_port );
  • trunk/kernel/devices/dev_nic.h

    r674 r683  
    9999 *
    100100 * - GET_KEY      : get channel index from remote IP address and port
    101  * - SET_RUN      : activate/desactivate one channel
     101 * - SET_RUN      : activate/desactivate one channel (both directions)
    102102 * - GET_INSTRU   : get one instrumentation counter value
    103103 * - CLEAR_INSTRU : reset all instrumentation counters
     
    140140#define PROTOCOL_TCP           0x06
    141141
    142 #define TCP_ISS_CLIENT         0x10000      // initial sequence number for TCP client
    143 #define TCP_ISS_SERVER         0x20000      // initial sequence number for TCP server
    144 #define TCP_MAX_WINDOW         0xFFFFF      // initial TCP send window
    145 
    146 #define PAYLOAD_MAX_LEN        1500         // max length for an UDP packet / TCP segment
    147 
    148142#define TCP_FLAG_FIN           0x01
    149143#define TCP_FLAG_SYN           0x02
     
    152146#define TCP_FLAG_ACK           0x10
    153147#define TCP_FLAG_URG           0x20
    154 
    155 #define TCP_RETRANSMISSION_TIMEOUT  10000000
    156148
    157149/*****************************************************************************************
     
    192184 *   in the server thread descriptor, to access the NIC_RX & NIC_TX packet queues.
    193185 *   The buffer is always a 2K bytes kernel buffer, containing an Ethernet packet.
    194  * - The next 4 synchronous commands are used by the client th, and stored in the
     186 * - The next 4 synchronous commands are used by the client thread, and stored in the
    195187 *   client thread descriptor, to directly access the NIC registers.
    196188 ****************************************************************************************/
     
    212204    xptr_t      dev_xp;       /*! extended pointer on NIC chdev descriptor              */
    213205    nic_cmd_t   type;         /*! command type                                          */
    214     uint8_t   * buffer;       /*! local pointer on kernel buffer                        */ 
    215     uint32_t    length;       /*! number of bytes in buffer                             */
     206    uint8_t   * buffer;       /*! local pointer on kernel buffer (when READ / WRITE)    */ 
     207    uint32_t    length;       /*! number of bytes in buffer (when READ / WRITE )        */
    216208    uint32_t    status;       /*! return value (depends on command type)                */
    217209    uint32_t    error;        /*! return an error from the hardware (0 if no error)     */
     
    282274 * This TX server thread is created by the dev_nic_init() function.
    283275 * It build and send UDP packets or TCP segments for all clients threads registered in
    284  * the NIC_TX[channel] chdev. The command types are (CONNECT / SEND / CLOSE), and the
    285  * priority between clients is round-robin. It takes into account the request registered
    286  * by the RX server thread in the R2T queue associated to the involved socket.
    287  * When a command is completed, it unblocks the client thread. For a SEND command, the
    288  * last byte must have been sent for an UDP socket, and it must have been acknowledged
    289  * for a TCP socket.
    290  * When the TX client threads queue is empty, it blocks on THREAD_BLOCKED_CLIENT
    291  * condition and deschedules. It is re-activated by a client thread registering a command.
     276 * the NIC_TX[channel] chdev. The command types are (CONNECT / ACCEPT / CLOSE / SEND).
     277 * It takes into account the request registered by the RX server thread in the R2T queues.
     278 * The loop on registered sockets implements a round-robin priority between sockets.
     279 * When no registered socket is active, it blocks on the THREAD_BLOCKED_CLIENT condition
     280 * and deschedules. It is re-activated by a client thread registering a command.
    292281 * When the NIC_TX packet queue is full, it blocks on the THREAD_BLOCKED_ISR condition
    293282 * and deschedules. It is reactivated by the NIC_TX DMA engine.
    294283 ******************************************************************************************
    295284 * Implementation note:
    296  * It execute an infinite loop in which it takes the lock protecting the clients list
    297  * to build a "kleenex" list of currently registered clients.
    298  * For each client registered in this "kleenex" list, it takes the lock protecting the
    299  * socket state, build one packet/segment in a local 2K bytes kernel buffer, calls the
    300  * transport layer to add the UDP/TCP header, calls the IP layer to add the IP header,
     285 * At each iteration in the infinite loop, it takes the lock protecting the registered
     286 * client sockets queue to find one active socket (tx_valid or r2t_valid flags set).
     287 * For each registered socket, it takes the lock protecting the socket state, and
     288 * exit the scan when an active socket has been found, without releasing the socket state.
     289 * When the scan is completed, it release the lock protecting the queue, before handling
     290 * the found active socket. The socket lock is released only when the requested packet
     291 * has been build, and the active socket state has been updated.
     292 * To handle a socket request, it calls the transport layer to build the UDP packet or
     293 * TCP segment in a local 2K bytes kernel buffer, calls the IP layer to add the IP header,
    301294 * calls the ETH layer to add the ETH header, and moves the packet to the NIC_TX_QUEUE.
    302  * Finally, it updates the socket state, and release the socket lock.
    303295 ******************************************************************************************
    304296 * @ chdev    : [in] local pointer on one local NIC_TX[channel] chdev descriptor.
     
    331323
    332324/******************************************************************************************
    333  * This function displays all the fields of an ETH/IP/TCP segment or ETH/IP/UDP packet.
    334  ******************************************************************************************
    335  * @ is_tx   : [in] sent packet if true / received packet if false.
     325 * This debug function can be called by the dev_nic_tx_server() function to display
     326 * on TXT0 the header of a TX [ETH/IP/TCP] segment or [ETH/IP/UDP] packet.
     327 ******************************************************************************************
    336328 * @ pid     : [in] process identifier.
    337  * @ trdid   : [in] thread identifier.
     329 * @ fdid    : [in] socket identifier.
    338330 * @ cycle   : [in] date (number of cycles).
    339331 * @ buf     : [in] local pointer on kernel buffer containing the packet.
    340332 *****************************************************************************************/
    341 void dev_nic_packet_display( bool_t    is_tx,
    342                              pid_t     pid,
    343                              trdid_t   trdid,
     333void dev_nic_packet_display( pid_t     pid,
     334                             uint32_t  fdid,
    344335                             uint32_t  cycle,
    345336                             uint8_t * buf );
Note: See TracChangeset for help on using the changeset viewer.