mirror of
https://github.com/espressif/openthread.git
synced 2026-10-01 13:27:42 +00:00
[tcp] add support for otTcpForwardProgress callback (#7583)
This commit adds support for the remaining TCP callback, which was not yet supported. Originally, the unimplemented callback was otTcpSendReady, which would indicate to the application when new data added to the TCP send buffer would be sent out immediately. There was also discussion of adding an otTcpBytesAcked callback, which, together with the otTcpSendByExtension() call, would allow a circular buffer to be implemented efficiently on top of the otLinkedBuffer API. Ultimately, it seemed best to generalize the otTcpSendReady callback to include both cases where bytes are acked by the connection peer, and where the send buffer drains, allowing new data to be sent immediately. The reasoning behind this decision is that both the otTcpSendReady and otTcpBytesAcked callbacks are triggered by the same event --- an ACK received from the connection peer --- and that it may require the application to have to "coordinate state" across callbacks. Having a single callback function to indicate both conditions seemed like it could simplify applications significantly. The new, combined, callback is otTcpForwardProgress. This commit implements support and documentation for this callback function.
This commit is contained in:
Vendored
+7
-6
@@ -1186,6 +1186,7 @@ tcp_do_segment(struct ip6_hdr* ip6, struct tcphdr *th, otMessage* msg,
|
||||
{
|
||||
uint32_t poppedbytes = lbuf_pop(&tp->sendbuf, acked, &sig->links_popped);
|
||||
KASSERT(poppedbytes == acked, ("More bytes were acked than are in the send buffer"));
|
||||
sig->bytes_acked += poppedbytes;
|
||||
}
|
||||
if (SEQ_GT(tp->snd_una, tp->snd_recover) &&
|
||||
SEQ_LEQ(th->th_ack, tp->snd_recover))
|
||||
@@ -1329,10 +1330,9 @@ tcp_do_segment(struct ip6_hdr* ip6, struct tcphdr *th, otMessage* msg,
|
||||
*/
|
||||
|
||||
if (!tpiscantrcv(tp)) {
|
||||
size_t usedbefore = cbuf_used_space(&tp->recvbuf);
|
||||
cbuf_write(&tp->recvbuf, msg, otMessageGetOffset(msg) + drop_hdrlen, tlen, cbuf_copy_from_message);
|
||||
if (usedbefore == 0 && tlen > 0) {
|
||||
sig->recvbuf_notempty = true;
|
||||
if (tlen > 0) {
|
||||
sig->recvbuf_added = true;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
@@ -2213,10 +2213,12 @@ process_ACK:
|
||||
tp->snd_wnd -= usedspace;
|
||||
poppedbytes = lbuf_pop(&tp->sendbuf, usedspace, &sig->links_popped);
|
||||
KASSERT(poppedbytes == usedspace, ("Could not fully empty send buffer"));
|
||||
sig->bytes_acked += poppedbytes;
|
||||
ourfinisacked = 1;
|
||||
} else {
|
||||
uint32_t poppedbytes = lbuf_pop(&tp->sendbuf, acked, &sig->links_popped);
|
||||
KASSERT(poppedbytes == acked, ("Could not remove acked bytes from send buffer"));
|
||||
sig->bytes_acked += poppedbytes;
|
||||
tp->snd_wnd -= acked;
|
||||
ourfinisacked = 0;
|
||||
}
|
||||
@@ -2414,10 +2416,9 @@ step6:
|
||||
* sbappendstream_locked(&so->so_rcv, m, 0);).
|
||||
*/
|
||||
if (!tpiscantrcv(tp)) {
|
||||
size_t usedbefore = cbuf_used_space(&tp->recvbuf);
|
||||
cbuf_write(&tp->recvbuf, msg, otMessageGetOffset(msg) + drop_hdrlen, tlen, cbuf_copy_from_message);
|
||||
if (usedbefore == 0 && tlen > 0) {
|
||||
sig->recvbuf_notempty = true;
|
||||
if (tlen > 0) {
|
||||
sig->recvbuf_added = true;
|
||||
}
|
||||
} else if (tlen > 0) {
|
||||
/*
|
||||
|
||||
Vendored
+2
-2
@@ -103,8 +103,8 @@ present:
|
||||
KASSERT(merged == mergeable, ("Reassembly merge out of bounds: tried to merge %d, but merged %d", (int) mergeable, (int) merged));
|
||||
if (tpiscantrcv(tp)) {
|
||||
cbuf_pop(&tp->recvbuf, merged); // So no data really enters the buffer
|
||||
} else if (usedbefore == 0 && merged > 0) {
|
||||
sig->recvbuf_notempty = true;
|
||||
} else if (merged > 0) {
|
||||
sig->recvbuf_added = true;
|
||||
}
|
||||
} else {
|
||||
/* If there is data in the buffer AND we can't receive more, then that must be because we received a FIN,
|
||||
|
||||
Vendored
+2
-2
@@ -57,7 +57,7 @@ void lbuf_extend(struct lbufhead* buffer, size_t numbytes) {
|
||||
buffer->tail->mLength += numbytes;
|
||||
}
|
||||
|
||||
size_t lbuf_pop(struct lbufhead* buffer, size_t numbytes, int* ntraversed) {
|
||||
size_t lbuf_pop(struct lbufhead* buffer, size_t numbytes, uint32_t* ntraversed) {
|
||||
otLinkedBuffer* curr = buffer->head;
|
||||
size_t bytesleft = numbytes;
|
||||
size_t curroffset = buffer->offset;
|
||||
@@ -109,6 +109,6 @@ int lbuf_getrange(struct lbufhead* buffer, size_t offset, size_t numbytes,
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t lbuf_used_space(struct lbufhead* buffer) {
|
||||
size_t lbuf_used_space(const struct lbufhead* buffer) {
|
||||
return buffer->length;
|
||||
}
|
||||
|
||||
Vendored
+2
-2
@@ -65,7 +65,7 @@ void lbuf_extend(struct lbufhead* buffer, size_t numbytes);
|
||||
NUMBYTES bytes in the buffer to begin with). *NTRAVERSED is incremented once
|
||||
for each entry in the buffer that is no longer referenced and can be
|
||||
reclaimed. */
|
||||
size_t lbuf_pop(struct lbufhead* buffer, size_t numbytes, int* ntraversed);
|
||||
size_t lbuf_pop(struct lbufhead* buffer, size_t numbytes, uint32_t* ntraversed);
|
||||
|
||||
/* Given a range of indices, specified by an OFFSET from the start and a
|
||||
length NUMBYTES, this function locates the chain of linked buffer entries
|
||||
@@ -83,6 +83,6 @@ int lbuf_getrange(struct lbufhead* buffer, size_t offset, size_t numbytes,
|
||||
struct otLinkedBuffer** last, size_t* lastextra);
|
||||
|
||||
/* Returns the total number of bytes stored in the buffer. */
|
||||
size_t lbuf_used_space(struct lbufhead* buffer);
|
||||
size_t lbuf_used_space(const struct lbufhead* buffer);
|
||||
|
||||
#endif
|
||||
|
||||
Vendored
+31
-22
@@ -42,43 +42,52 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <openthread/ip6.h>
|
||||
#include <openthread/message.h>
|
||||
#include "bsdtcp/ip6.h"
|
||||
#include "bsdtcp/tcp.h"
|
||||
#include "bsdtcp/tcp_fsm.h"
|
||||
#include "bsdtcp/tcp_timer.h"
|
||||
#include "bsdtcp/tcp_var.h"
|
||||
#include <openthread/ip6.h>
|
||||
#include <openthread/message.h>
|
||||
|
||||
#define RELOOKUP_REQUIRED -1
|
||||
#define CONN_LOST_NORMAL 0
|
||||
|
||||
struct tcplp_signals {
|
||||
int links_popped;
|
||||
bool conn_established;
|
||||
bool recvbuf_notempty;
|
||||
bool rcvd_fin;
|
||||
struct tcplp_signals
|
||||
{
|
||||
uint32_t links_popped;
|
||||
uint32_t bytes_acked;
|
||||
bool conn_established;
|
||||
bool recvbuf_added;
|
||||
bool rcvd_fin;
|
||||
};
|
||||
|
||||
/*
|
||||
* Functions that the TCP protocol logic can call to interact with the rest of
|
||||
* the system.
|
||||
*/
|
||||
otMessage* tcplp_sys_new_message(otInstance* instance);
|
||||
void tcplp_sys_free_message(otInstance* instance, otMessage* pkt);
|
||||
void tcplp_sys_send_message(otInstance* instance, otMessage* pkt, otMessageInfo* info);
|
||||
uint32_t tcplp_sys_get_ticks();
|
||||
uint32_t tcplp_sys_get_millis();
|
||||
void tcplp_sys_set_timer(struct tcpcb* tcb, uint8_t timer_flag, uint32_t delay);
|
||||
void tcplp_sys_stop_timer(struct tcpcb* tcb, uint8_t timer_flag);
|
||||
struct tcpcb* tcplp_sys_accept_ready(struct tcpcb_listen* tpl, struct in6_addr* addr, uint16_t port);
|
||||
bool tcplp_sys_accepted_connection(struct tcpcb_listen* tpl, struct tcpcb* accepted, struct in6_addr* addr, uint16_t port);
|
||||
void tcplp_sys_connection_lost(struct tcpcb* tcb, uint8_t errnum);
|
||||
void tcplp_sys_on_state_change(struct tcpcb* tcb, int newstate);
|
||||
void tcplp_sys_log(const char* format, ...);
|
||||
void tcplp_sys_panic(const char* format, ...);
|
||||
bool tcplp_sys_autobind(otInstance *aInstance, const otSockAddr *aPeer, otSockAddr *aToBind, bool aBindAddress, bool aBindPort);
|
||||
uint32_t tcplp_sys_generate_isn();
|
||||
otMessage * tcplp_sys_new_message(otInstance *instance);
|
||||
void tcplp_sys_free_message(otInstance *instance, otMessage *pkt);
|
||||
void tcplp_sys_send_message(otInstance *instance, otMessage *pkt, otMessageInfo *info);
|
||||
uint32_t tcplp_sys_get_ticks();
|
||||
uint32_t tcplp_sys_get_millis();
|
||||
void tcplp_sys_set_timer(struct tcpcb *tcb, uint8_t timer_flag, uint32_t delay);
|
||||
void tcplp_sys_stop_timer(struct tcpcb *tcb, uint8_t timer_flag);
|
||||
struct tcpcb *tcplp_sys_accept_ready(struct tcpcb_listen *tpl, struct in6_addr *addr, uint16_t port);
|
||||
bool tcplp_sys_accepted_connection(struct tcpcb_listen *tpl,
|
||||
struct tcpcb * accepted,
|
||||
struct in6_addr * addr,
|
||||
uint16_t port);
|
||||
void tcplp_sys_connection_lost(struct tcpcb *tcb, uint8_t errnum);
|
||||
void tcplp_sys_on_state_change(struct tcpcb *tcb, int newstate);
|
||||
void tcplp_sys_log(const char *format, ...);
|
||||
void tcplp_sys_panic(const char *format, ...);
|
||||
bool tcplp_sys_autobind(otInstance * aInstance,
|
||||
const otSockAddr *aPeer,
|
||||
otSockAddr * aToBind,
|
||||
bool aBindAddress,
|
||||
bool aBindPort);
|
||||
uint32_t tcplp_sys_generate_isn();
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
|
||||
Reference in New Issue
Block a user