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