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