This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

LWIP Segmentation Problem

Hi All,

New to LWIP and I am at lost as to what caused the data segmentation problem I am experiencing. I am running TI's Demo LWIP in TMDXRM48HDK with FREERTOS. Basically the problem is, I am sending an 11 byte MODBUS/TCP Reply ADU to a remote client but during transmission for an unknown reason the 11 byte data is being segmented. Please see below the Wireshark trace:

Transmission Control Protocol, Src Port: asa-appl-proto (502), Dst Port: 51719 (51719), Seq: 45, Ack: 61, Len: 11

  Source port: asa-appl-proto (502)

  Destination port: 51719 (51719)

  [Stream index: 0]

  Sequence number: 45 (relative sequence number)

  [Next sequence number: 56 (relative sequence number)]

  Acknowledgment number: 61 (relative ack number)

  Header length: 20 bytes

  Flags: 0x018 (PSH, ACK)

  Window size value: 4036

  [Calculated window size: 4036]

  [Window size scaling factor: -1 (unknown)]

  Checksum: 0xa6a3 [validation disabled]

  [Good Checksum: False]

  [Bad Checksum: False]

  [SEQ/ACK analysis]

    [This is an ACK to the segment in frame: 76]

    [The RTT to ACK the segment was: 0.024228000 seconds]    

    [Bytes in flight: 11]

  [PDU Size: 10] (Why 10?)

  TCP segment data (1 byte)  (<--Problem: Segment data)

Modbus/TCP

  Transaction Identifier: 5

  Protocol Identifier: 0

  Length: 4

  Unit Identifier: 1

Modbus

   Function Code: Read Holding Registers (3)

   Byte Count: 2

   Data: 00

Please see below our code:

void vTask1(void *pvParameters)
{
    err_t err;

    EMAC_LwIP_Main (emacAddress);

    modbus_socket  = tcp_new();

    err = tcp_bind(modbus_socket, IP_ADDR_ANY, 502);
    if (err != ERR_OK)
    {
        return;
    }

    modbus_socket = tcp_listen(modbus_socket);
    tcp_accept(modbus_socket, socket_accept);
    while(1)
    {
        vTaskDelay(100);
    }
}
err_t socket_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
{
    tcp_recv(newpcb, socket_receive);
    tcp_sent(newpcb, socket_sent);
    return ERR_OK;
}
err_t socket_receive(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
{
    uint16 quantity;
    ReadHoldingRegs_st *readHoldingRegs;
    ModbusTCP_st *modbusTcp;

    if (p != NULL)
    {
        tcp_recved(tpcb, p->tot_len);
    }
    if(err != ERR_OK || p == NULL)
    {
        tcp_close(tpcb);
        if(p != NULL)
        {
            pbuf_free(p);
        }
        return ERR_OK;
    }
    modbusTcp = p->payload;

    if(modbusTcp->data[0] == 0x03) //READ HOLDING REGISTERS
    {
        readHoldingRegs = (ReadHoldingRegs_st *)modbusTcp->data;
        quantity = readHoldingRegs->quantity[0] << 8;
        quantity |= readHoldingRegs->quantity[1];

        //check for quantity
        if(quantity < 1 || quantity > 0x7DU)
        {
            //invalid quantity
            ReplyError(tpcb, modbusTcp, 0x03);
        }
        //create fake register content
        ReplyFakeData(tpcb, modbusTcp, quantity);
        //echo
        //tcp_write(tpcb, p->payload, p->len, TCP_WRITE_FLAG_COPY);

    }
    else
    {
        //unsupported function
        ReplyError(tpcb, modbusTcp, 0x01);
    }
    //process data
    pbuf_free(p);

    return ERR_OK;
}
void ReplyFakeData(struct tcp_pcb *tpcb, ModbusTCP_st *originalRqst, uint16 count)
{
    uint32 index = 0;

    ModbusTCP_st *replyModbusTcp;
    uint32 pduSize = 7 + 2 + (count * 2); //MODBUS/TCP ADU + MODBUS PDU + REGISTERS VALUE

    replyModbusTcp = pvPortMalloc(pduSize);

    //adu modbus
    replyModbusTcp->uintId        = originalRqst->uintId;
    replyModbusTcp->transactionId = originalRqst->transactionId;
    replyModbusTcp->protocolId    = originalRqst->protocolId;
    replyModbusTcp->length = swap16(2 +  (count * 2));
    //pdu modbus
    replyModbusTcp->data[0] = 0x03;
    replyModbusTcp->data[1] = count * 2;

    for(index=0; index < (count*2); index++)
    {
        replyModbusTcp->data[2+index] = index;
    }
    //check current send buffer if enough
    if(tcp_sndbuf(tpcb) >= pduSize)
    {
        tcp_write(tpcb, replyModbusTcp, pduSize, TCP_WRITE_FLAG_COPY);
    }

    vPortFree(replyModbusTcp);
}


Thanks in advance for the suport.


Regards,

Chris