Skip to content

Commit 892469a

Browse files
Add uip_udp_packet_send2 function
This new function adds two major improvements over uip_udp_packet_send: - return an error code if the packet send fails before making it to the mac layer - add a mechanism by which applications can be notified when packet sending completes along with transmit status from the MAC layer.
1 parent b8aeef7 commit 892469a

File tree

11 files changed

+177
-34
lines changed

11 files changed

+177
-34
lines changed

core/net/ip/tcpip.c

+23-6
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ extern struct uip_fallback_interface UIP_FALLBACK_INTERFACE;
7777
#include "rpl/rpl.h"
7878
#endif
7979

80+
process_event_t tcpip_udp_sent_event;
8081
process_event_t tcpip_event;
8182
#if UIP_CONF_ICMP6
8283
process_event_t tcpip_icmp6_event;
@@ -126,22 +127,22 @@ setup_appstate(uip_tcp_appstate_t* as, void* state)
126127
/* Called on IP packet output. */
127128
#if NETSTACK_CONF_WITH_IPV6
128129

129-
static uint8_t (* outputfunc)(const uip_lladdr_t *a);
130+
static uint8_t (*outputfunc)(const uip_lladdr_t *a, struct tcpip_track *track);
130131

131132
uint8_t
132-
tcpip_output(const uip_lladdr_t *a)
133+
tcpip_output_sent(const uip_lladdr_t *a, struct tcpip_track *track)
133134
{
134135
int ret;
135136
if(outputfunc != NULL) {
136-
ret = outputfunc(a);
137+
ret = outputfunc(a, track);
137138
return ret;
138139
}
139140
UIP_LOG("tcpip_output: Use tcpip_set_outputfunc() to set an output function");
140141
return 0;
141142
}
142143

143144
void
144-
tcpip_set_outputfunc(uint8_t (*f)(const uip_lladdr_t *))
145+
tcpip_set_outputfunc(uint8_t (*f)(const uip_lladdr_t *, struct tcpip_track *))
145146
{
146147
outputfunc = f;
147148
}
@@ -164,7 +165,20 @@ tcpip_set_outputfunc(uint8_t (*f)(void))
164165
outputfunc = f;
165166
}
166167
#endif
168+
/*---------------------------------------------------------------------------*/
169+
void
170+
tcpip_udp_sent(struct tcpip_track *track, int status)
171+
{
172+
struct uip_udp_conn *conn = track->ptr;
173+
struct tcpip_udp_track_status data;
174+
175+
data.conn = conn;
176+
data.status = status;
177+
data.track = track;
167178

179+
process_post_synch(conn->appstate.p, tcpip_udp_sent_event, &data);
180+
}
181+
/*---------------------------------------------------------------------------*/
168182
#if UIP_CONF_IP_FORWARD
169183
unsigned char tcpip_is_forwarding; /* Forwarding right now? */
170184
#endif /* UIP_CONF_IP_FORWARD */
@@ -718,7 +732,7 @@ send_nd6_ns(uip_ipaddr_t *nexthop)
718732
}
719733
/*---------------------------------------------------------------------------*/
720734
int
721-
tcpip_ipv6_output(void)
735+
tcpip_ipv6_output_tracked(struct tcpip_track *track)
722736
{
723737
uip_ipaddr_t ipaddr;
724738
int err = TCPIP_SUCCESS;
@@ -795,7 +809,7 @@ tcpip_ipv6_output(void)
795809
linkaddr = NULL;
796810
}
797811

798-
if(tcpip_output(linkaddr)) {
812+
if(!tcpip_output_sent(linkaddr, track)) {
799813
err = TCPIP_ERR_NEXTLAYER;
800814
}
801815

@@ -880,6 +894,9 @@ PROCESS_THREAD(tcpip_process, ev, data)
880894
#endif
881895

882896
tcpip_event = process_alloc_event();
897+
898+
tcpip_udp_sent_event = process_alloc_event();
899+
883900
#if UIP_CONF_ICMP6
884901
tcpip_icmp6_event = process_alloc_event();
885902
#endif /* UIP_CONF_ICMP6 */

core/net/ip/tcpip.h

+40-3
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,25 @@
7070
#include "contiki.h"
7171

7272
struct uip_conn;
73+
struct tcpip_track {
74+
void (*callback)(struct tcpip_track *, int);
75+
void *ptr;
76+
77+
enum {
78+
FRAG_TRACK_NONE,
79+
FRAG_TRACK_UNQUEUED,
80+
FRAG_TRACK_ALL_QUEUED,
81+
FRAG_TRACK_ERROR
82+
} frag_track;
83+
int frag_count_queued;
84+
int first_fail_status;
85+
};
86+
87+
struct tcpip_udp_track_status {
88+
struct uip_udp_conn *conn;
89+
struct tcpip_track *track;
90+
int status;
91+
};
7392

7493
struct tcpip_uipstate {
7594
struct process *p;
@@ -327,6 +346,14 @@ void tcpip_icmp6_call(uint8_t type);
327346
* This event is posted to a process whenever a uIP event has occurred.
328347
*/
329348
CCIF extern process_event_t tcpip_event;
349+
/** @} */
350+
/**
351+
* The udp sent event
352+
*
353+
* This event is posted to a process whenever a udp packet has finished sending
354+
* (possibly as a result of error).
355+
*/
356+
CCIF extern process_event_t tcpip_udp_sent_event;
330357

331358
/**
332359
* \name TCP/IP packet processing
@@ -349,8 +376,12 @@ CCIF void tcpip_input(void);
349376
* The eventual parameter is the MAC address of the destination.
350377
*/
351378
#if NETSTACK_CONF_WITH_IPV6
352-
uint8_t tcpip_output(const uip_lladdr_t *);
353-
void tcpip_set_outputfunc(uint8_t (* f)(const uip_lladdr_t *));
379+
#define tcpip_output(addr) tcpip_output_sent(addr, NULL)
380+
381+
uint8_t tcpip_output_sent(const uip_lladdr_t *, struct tcpip_track *ptr);
382+
void tcpip_set_outputfunc(
383+
uint8_t (*f)(const uip_lladdr_t *, struct tcpip_track *)
384+
);
354385
#else
355386
uint8_t tcpip_output(void);
356387
void tcpip_set_outputfunc(uint8_t (* f)(void));
@@ -360,9 +391,15 @@ void tcpip_set_outputfunc(uint8_t (* f)(void));
360391
* \brief This function does address resolution and then calls tcpip_output
361392
*/
362393
#if NETSTACK_CONF_WITH_IPV6
363-
int tcpip_ipv6_output(void);
394+
#define tcpip_ipv6_output() tcpip_ipv6_output_tracked(NULL)
395+
int tcpip_ipv6_output_tracked(struct tcpip_track* track);
364396
#endif
365397

398+
/**
399+
* \brief call after sending a udp packet, informs the application
400+
*/
401+
void tcpip_udp_sent(struct tcpip_track *track, int status);
402+
366403
/**
367404
* \brief Is forwarding generally enabled?
368405
*/

core/net/ip/uip-udp-packet.c

+23-3
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,11 @@ extern uint16_t uip_slen;
4747
#include <string.h>
4848

4949
/*---------------------------------------------------------------------------*/
50-
void
51-
uip_udp_packet_send(struct uip_udp_conn *c, const void *data, int len)
50+
static int
51+
send(struct uip_udp_conn *c, const void *data, int len,
52+
struct tcpip_track* track)
5253
{
54+
int ret = 0;
5355
#if UIP_UDP
5456
if(data != NULL) {
5557
uip_udp_conn = c;
@@ -67,7 +69,7 @@ uip_udp_packet_send(struct uip_udp_conn *c, const void *data, int len)
6769
#endif /* UIP_IPV6_MULTICAST */
6870

6971
#if NETSTACK_CONF_WITH_IPV6
70-
tcpip_ipv6_output();
72+
ret = tcpip_ipv6_output_tracked(track);
7173
#else
7274
if(uip_len > 0) {
7375
tcpip_output();
@@ -76,6 +78,13 @@ uip_udp_packet_send(struct uip_udp_conn *c, const void *data, int len)
7678
}
7779
uip_slen = 0;
7880
#endif /* UIP_UDP */
81+
return ret;
82+
}
83+
/*---------------------------------------------------------------------------*/
84+
void
85+
uip_udp_packet_send(struct uip_udp_conn *c, const void *data, int len)
86+
{
87+
send(c, data, len, NULL);
7988
}
8089
/*---------------------------------------------------------------------------*/
8190
void
@@ -102,3 +111,14 @@ uip_udp_packet_sendto(struct uip_udp_conn *c, const void *data, int len,
102111
}
103112
}
104113
/*---------------------------------------------------------------------------*/
114+
int
115+
uip_udp_packet_send2(struct uip_udp_conn *c, const void *data, int len,
116+
struct tcpip_track* track)
117+
{
118+
track->ptr = c;
119+
track->callback = tcpip_udp_sent;
120+
track->frag_track = FRAG_TRACK_NONE;
121+
122+
return send(c, data, len, track);
123+
}
124+
/*---------------------------------------------------------------------------*/

core/net/ip/uip-udp-packet.h

+2
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@
4242

4343
#include "net/ip/uip.h"
4444

45+
int uip_udp_packet_send2(struct uip_udp_conn *c, const void *data, int len,
46+
struct tcpip_track* track);
4547
void uip_udp_packet_send(struct uip_udp_conn *c, const void *data, int len);
4648
void uip_udp_packet_sendto(struct uip_udp_conn *c, const void *data, int len,
4749
const uip_ipaddr_t *toaddr, uint16_t toport);

core/net/ipv6/sicslowpan.c

+69-7
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,28 @@ struct sicslowpan_frag_buf {
286286
};
287287

288288
static struct sicslowpan_frag_buf frag_buf[SICSLOWPAN_FRAGMENT_BUFFERS];
289-
289+
/*---------------------------------------------------------------------------*/
290+
static void track_frag_start(struct tcpip_track *track)
291+
{
292+
if(track) {
293+
track->frag_track = FRAG_TRACK_UNQUEUED;
294+
track->frag_count_queued = 0;
295+
}
296+
}
297+
/*---------------------------------------------------------------------------*/
298+
static void track_frag_queued(struct tcpip_track *track)
299+
{
300+
if(track) {
301+
track->frag_count_queued += 1;
302+
}
303+
}
304+
/*---------------------------------------------------------------------------*/
305+
static void track_frag_done(struct tcpip_track *track)
306+
{
307+
if(track && (track->frag_track != FRAG_TRACK_ERROR)) {
308+
track->frag_track = FRAG_TRACK_ALL_QUEUED;
309+
}
310+
}
290311
/*---------------------------------------------------------------------------*/
291312
static int
292313
clear_fragments(uint8_t frag_info_index)
@@ -1231,16 +1252,50 @@ packet_sent(void *ptr, int status, int transmissions)
12311252
if(callback != NULL) {
12321253
callback->output_callback(status);
12331254
}
1255+
1256+
if(ptr) {
1257+
struct tcpip_track *track = ptr;
1258+
1259+
switch(track->frag_track)
1260+
{
1261+
case FRAG_TRACK_NONE:
1262+
track->callback(track, status);
1263+
break;
1264+
case FRAG_TRACK_UNQUEUED:
1265+
track->frag_count_queued -= 1;
1266+
if(status != MAC_TX_OK) {
1267+
track->frag_track = FRAG_TRACK_ERROR;
1268+
}
1269+
break;
1270+
case FRAG_TRACK_ALL_QUEUED:
1271+
track->frag_count_queued -= 1;
1272+
if(status != MAC_TX_OK) {
1273+
track->frag_track = FRAG_TRACK_ERROR;
1274+
track->first_fail_status = status;
1275+
} else if(track->frag_count_queued == 0) {
1276+
track->callback(track, status);
1277+
}
1278+
break;
1279+
case FRAG_TRACK_ERROR:
1280+
track->frag_count_queued -= 1;
1281+
if(track->frag_count_queued == 0) {
1282+
track->callback(track, track->first_fail_status);
1283+
}
1284+
break;
1285+
}
1286+
}
1287+
12341288
last_tx_status = status;
12351289
}
12361290
/*--------------------------------------------------------------------*/
12371291
/**
12381292
* \brief This function is called by the 6lowpan code to send out a
12391293
* packet.
12401294
* \param dest the link layer destination address of the packet
1295+
* \param track data used for calling back into the application on tx done
12411296
*/
12421297
static void
1243-
send_packet(linkaddr_t *dest)
1298+
send_packet(linkaddr_t *dest,struct tcpip_track *track)
12441299
{
12451300
/* Set the link layer destination address for the packet as a
12461301
* packetbuf attribute. The MAC layer can access the destination
@@ -1255,7 +1310,7 @@ send_packet(linkaddr_t *dest)
12551310

12561311
/* Provide a callback function to receive the result of
12571312
a packet transmission. */
1258-
NETSTACK_LLSEC.send(&packet_sent, NULL);
1313+
NETSTACK_LLSEC.send(&packet_sent, track);
12591314

12601315
/* If we are sending multiple packets in a row, we need to let the
12611316
watchdog know that we are still alive. */
@@ -1265,14 +1320,15 @@ send_packet(linkaddr_t *dest)
12651320
/** \brief Take an IP packet and format it to be sent on an 802.15.4
12661321
* network using 6lowpan.
12671322
* \param localdest The MAC address of the destination
1323+
* \param track data used for calling back into the application on tx done
12681324
*
12691325
* The IP packet is initially in uip_buf. Its header is compressed
12701326
* and if necessary it is fragmented. The resulting
12711327
* packet/fragments are put in packetbuf and delivered to the 802.15.4
12721328
* MAC.
12731329
*/
12741330
static uint8_t
1275-
output(const uip_lladdr_t *localdest)
1331+
output(const uip_lladdr_t *localdest, struct tcpip_track *track)
12761332
{
12771333
int framer_hdrlen;
12781334
int max_payload;
@@ -1409,7 +1465,9 @@ output(const uip_lladdr_t *localdest)
14091465
PRINTFO("could not allocate queuebuf for first fragment, dropping packet\n");
14101466
return 0;
14111467
}
1412-
send_packet(&dest);
1468+
track_frag_start(track);
1469+
track_frag_queued(track);
1470+
send_packet(&dest, track);
14131471
queuebuf_to_packetbuf(q);
14141472
queuebuf_free(q);
14151473
q = NULL;
@@ -1455,7 +1513,11 @@ output(const uip_lladdr_t *localdest)
14551513
PRINTFO("could not allocate queuebuf, dropping fragment\n");
14561514
return 0;
14571515
}
1458-
send_packet(&dest);
1516+
track_frag_queued(track);
1517+
if((processed_ip_out_len + packetbuf_payload_len) >= uip_len) {
1518+
track_frag_done(track);
1519+
}
1520+
send_packet(&dest, track);
14591521
queuebuf_to_packetbuf(q);
14601522
queuebuf_free(q);
14611523
q = NULL;
@@ -1482,7 +1544,7 @@ output(const uip_lladdr_t *localdest)
14821544
memcpy(packetbuf_ptr + packetbuf_hdr_len, (uint8_t *)UIP_IP_BUF + uncomp_hdr_len,
14831545
uip_len - uncomp_hdr_len);
14841546
packetbuf_set_datalen(uip_len - uncomp_hdr_len + packetbuf_hdr_len);
1485-
send_packet(&dest);
1547+
send_packet(&dest, track);
14861548
}
14871549
return 1;
14881550
}

cpu/native/net/tapdev6.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ static unsigned long lasttime;
9898
#endif
9999

100100
static void do_send(void);
101-
uint8_t tapdev_send(const uip_lladdr_t *lladdr);
101+
uint8_t tapdev_send(const uip_lladdr_t *lladdr, struct tcpip_track *track);
102102

103103
/*---------------------------------------------------------------------------*/
104104
int
@@ -375,7 +375,7 @@ do_send(void)
375375
}
376376
/*---------------------------------------------------------------------------*/
377377
uint8_t
378-
tapdev_send(const uip_lladdr_t *lladdr)
378+
tapdev_send(const uip_lladdr_t *lladdr, struct tcpip_track *track)
379379
{
380380
/*
381381
* If L3 dest is multicast, build L2 multicast address

cpu/native/net/tapdev6.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
12
/*
23
* Copyright (c) 2003, Adam Dunkels.
34
* All rights reserved.
@@ -39,7 +40,7 @@
3940
#include "contiki-net.h"
4041

4142
void tapdev_init(void);
42-
uint8_t tapdev_send(const uip_lladdr_t *lladdr);
43+
uint8_t tapdev_send(const uip_lladdr_t *lladdr, struct tcpip_track *track);
4344
uint16_t tapdev_poll(void);
4445
void tapdev_do_send(void);
4546
void tapdev_exit(void); //math

cpu/native/net/wpcap.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -708,7 +708,7 @@ wfall_poll(void)
708708
/*---------------------------------------------------------------------------*/
709709
#if NETSTACK_CONF_WITH_IPV6
710710
uint8_t
711-
wpcap_send(const uip_lladdr_t *lladdr)
711+
wpcap_send(const uip_lladdr_t *lladdr, struct tcpip_track *track)
712712
{
713713
if(lladdr == NULL) {
714714
/* the dest must be multicast*/

0 commit comments

Comments
 (0)