Rewrote LPP so that it uses 802.15.4 headers. A number of bugfixes with respect to alignment. Avoid turning off the radio in the middle of packet reception.

This commit is contained in:
adamdunkels 2010-04-30 07:31:44 +00:00
parent 55b6129bd2
commit e606c674c2

View file

@ -28,7 +28,7 @@
* *
* This file is part of the Contiki operating system. * This file is part of the Contiki operating system.
* *
* $Id: lpp.c,v 1.32 2010/02/23 20:09:11 nifi Exp $ * $Id: lpp.c,v 1.33 2010/04/30 07:31:44 adamdunkels Exp $
*/ */
/** /**
@ -74,7 +74,7 @@
#define PRINTF(...) #define PRINTF(...)
#endif #endif
#define WITH_ACK_OPTIMIZATION 1 #define WITH_ACK_OPTIMIZATION 0
#define WITH_PROBE_AFTER_RECEPTION 0 #define WITH_PROBE_AFTER_RECEPTION 0
#define WITH_PROBE_AFTER_TRANSMISSION 0 #define WITH_PROBE_AFTER_TRANSMISSION 0
#define WITH_ENCOUNTER_OPTIMIZATION 1 #define WITH_ENCOUNTER_OPTIMIZATION 1
@ -82,20 +82,11 @@
#define WITH_PENDING_BROADCAST 1 #define WITH_PENDING_BROADCAST 1
#define WITH_STREAMING 1 #define WITH_STREAMING 1
#ifdef LPP_CONF_LISTEN_TIME
#define LISTEN_TIME LPP_CONF_LISTEN_TIME
#else
#define LISTEN_TIME (CLOCK_SECOND / 128) #define LISTEN_TIME (CLOCK_SECOND / 128)
#endif /** LP_CONF_LISTEN_TIME */
#ifdef LPP_CONF_OFF_TIME
#define OFF_TIME LPP_CONF_OFF_TIME
#else
#define OFF_TIME (CLOCK_SECOND / MAC_CHANNEL_CHECK_RATE - LISTEN_TIME) #define OFF_TIME (CLOCK_SECOND / MAC_CHANNEL_CHECK_RATE - LISTEN_TIME)
#endif /* LPP_CONF_OFF_TIME */
#define PACKET_LIFETIME (LISTEN_TIME + OFF_TIME) #define PACKET_LIFETIME (LISTEN_TIME + OFF_TIME)
#define UNICAST_TIMEOUT (4 * PACKET_LIFETIME) #define UNICAST_TIMEOUT (1 * PACKET_LIFETIME)
#define PROBE_AFTER_TRANSMISSION_TIME (LISTEN_TIME * 2) #define PROBE_AFTER_TRANSMISSION_TIME (LISTEN_TIME * 2)
#define LOWEST_OFF_TIME (CLOCK_SECOND / 8) #define LOWEST_OFF_TIME (CLOCK_SECOND / 8)
@ -190,6 +181,11 @@ static struct ctimer stream_probe_timer, stream_off_timer;
#define STREAM_PROBE_TIME CLOCK_SECOND / 128 #define STREAM_PROBE_TIME CLOCK_SECOND / 128
#define STREAM_OFF_TIME CLOCK_SECOND / 2 #define STREAM_OFF_TIME CLOCK_SECOND / 2
#endif /* WITH_STREAMING */ #endif /* WITH_STREAMING */
#ifndef MIN
#define MIN(a, b) ((a) < (b)? (a) : (b))
#endif /* MIN */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static void static void
turn_radio_on(void) turn_radio_on(void)
@ -316,7 +312,8 @@ turn_radio_on_for_neighbor(rimeaddr_t *neighbor, struct queue_list_item *i)
time with modulo OFF_TIME. */ time with modulo OFF_TIME. */
now = clock_time(); now = clock_time();
wait = ((clock_time_t)(e->time - now)) % (OFF_TIME + LISTEN_TIME) - LISTEN_TIME; wait = (((clock_time_t)(e->time - now)) % (OFF_TIME + LISTEN_TIME)) -
2 * LISTEN_TIME;
/* printf("now %d e %d e-n %d w %d %d\n", now, e->time, e->time - now, (e->time - now) % (OFF_TIME), wait); /* printf("now %d e %d e-n %d w %d %d\n", now, e->time, e->time - now, (e->time - now) % (OFF_TIME), wait);
@ -359,6 +356,8 @@ remove_queued_packet(void *item)
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1]); rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1]);
queuebuf_to_packetbuf(i->packet);
ctimer_stop(&i->removal_timer); ctimer_stop(&i->removal_timer);
queuebuf_free(i->packet); queuebuf_free(i->packet);
list_remove(pending_packets_list, i); list_remove(pending_packets_list, i);
@ -414,8 +413,18 @@ send_probe(void)
hdr = packetbuf_dataptr(); hdr = packetbuf_dataptr();
hdr->type = TYPE_PROBE; hdr->type = TYPE_PROBE;
rimeaddr_copy(&hdr->sender, &rimeaddr_node_addr); rimeaddr_copy(&hdr->sender, &rimeaddr_node_addr);
rimeaddr_copy(&hdr->receiver, packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); /* rimeaddr_copy(&hdr->receiver, packetbuf_addr(PACKETBUF_ADDR_RECEIVER));*/
rimeaddr_copy(&hdr->receiver, &rimeaddr_null);
packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &rimeaddr_null);
{
int hdrlen = NETSTACK_FRAMER.create();
if(hdrlen == 0) {
/* Failed to send */
PRINTF("contikimac: send failed, too large header\n");
return MAC_TX_ERR_FATAL;
}
}
/* Construct the announcements */ /* Construct the announcements */
adata = (struct announcement_msg *)((char *)hdr + sizeof(struct lpp_hdr)); adata = (struct announcement_msg *)((char *)hdr + sizeof(struct lpp_hdr));
@ -542,8 +551,10 @@ dutycycle(void *ptr)
/* If we are not listening for announcements, we turn the radio /* If we are not listening for announcements, we turn the radio
off and wait until we send the next probe. */ off and wait until we send the next probe. */
if(is_listening == 0) { if(is_listening == 0) {
if(!NETSTACK_RADIO.receiving_packet()) {
turn_radio_off(); turn_radio_off();
compower_accumulate(&compower_idle_activity); compower_accumulate(&compower_idle_activity);
}
ctimer_set(t, off_time + off_time_adjustment, (void (*)(void *))dutycycle, t); ctimer_set(t, off_time + off_time_adjustment, (void (*)(void *))dutycycle, t);
off_time_adjustment = 0; off_time_adjustment = 0;
PT_YIELD(&dutycycle_pt); PT_YIELD(&dutycycle_pt);
@ -610,8 +621,17 @@ send_packet(mac_callback_t sent, void *ptr)
packetbuf_hdralloc(sizeof(struct lpp_hdr)); packetbuf_hdralloc(sizeof(struct lpp_hdr));
memcpy(packetbuf_hdrptr(), &hdr, sizeof(struct lpp_hdr)); memcpy(packetbuf_hdrptr(), &hdr, sizeof(struct lpp_hdr));
packetbuf_compact(); packetbuf_compact();
{
int hdrlen = NETSTACK_FRAMER.create();
if(hdrlen == 0) {
/* Failed to send */
PRINTF("contikimac: send failed, too large header\n");
return MAC_TX_ERR_FATAL;
}
}
PRINTF("%d.%d: queueing packet to %d.%d, channel %d\n", PRINTF("%d.%d: queueing packet to %d.%d, channel %d\n",
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
hdr.receiver.u8[0], hdr.receiver.u8[1], hdr.receiver.u8[0], hdr.receiver.u8[1],
@ -688,38 +708,52 @@ send_packet(mac_callback_t sent, void *ptr)
static void static void
input_packet(void) input_packet(void)
{ {
struct lpp_hdr *hdr; struct lpp_hdr hdr;
clock_time_t reception_time; clock_time_t reception_time;
reception_time = clock_time(); reception_time = clock_time();
hdr = packetbuf_dataptr(); if(!NETSTACK_FRAMER.parse()) {
printf("lpp input_packet framer error\n");
}
memcpy(&hdr, packetbuf_dataptr(), sizeof(struct lpp_hdr));;
packetbuf_hdrreduce(sizeof(struct lpp_hdr)); packetbuf_hdrreduce(sizeof(struct lpp_hdr));
/* PRINTF("got packet type %d\n", hdr->type);*/ /* PRINTF("got packet type %d\n", hdr->type);*/
if(hdr->type == TYPE_PROBE) { if(hdr.type == TYPE_PROBE) {
/* Parse incoming announcements */ struct announcement_msg adata;
struct announcement_msg *adata = packetbuf_dataptr();
int i; int i;
/* PRINTF("%d.%d: probe from %d.%d with %d announcements\n", /* Register the encounter with the sending node. We now know the
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], neighbor's phase. */
hdr->sender.u8[0], hdr->sender.u8[1], adata->num);*/ register_encounter(&hdr.sender, reception_time);
for(i = 0; i < adata->num; ++i) { /* Parse incoming announcements */
memcpy(&adata, packetbuf_dataptr(),
MIN(packetbuf_datalen(), sizeof(adata)));
#if 0
PRINTF("%d.%d: probe from %d.%d with %d announcements\n",
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
hdr.sender.u8[0], hdr.sender.u8[1], adata->num);
if(adata.num / sizeof(struct announcement_data) > sizeof(struct announcement_msg)) {
/* Sanity check. The number of announcements is too large -
corrupt packet has been received. */
return 0;
}
for(i = 0; i < adata.num; ++i) {
/* PRINTF("%d.%d: announcement %d: %d\n", /* PRINTF("%d.%d: announcement %d: %d\n",
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
adata->data[i].id, adata->data[i].id,
adata->data[i].value);*/ adata->data[i].value);*/
announcement_heard(&hdr->sender, announcement_heard(&hdr.sender,
adata->data[i].id, adata.data[i].id,
adata->data[i].value); adata.data[i].value);
} }
#endif /* 0 */
/* Register the encounter with the sending node. We now know the
neighbor's phase. */
register_encounter(&hdr->sender, reception_time);
/* Go through the list of packets to be sent to see if any of /* Go through the list of packets to be sent to see if any of
them match the sender of the probe, or if they are a them match the sender of the probe, or if they are a
@ -727,11 +761,11 @@ input_packet(void)
if(list_length(queued_packets_list) > 0) { if(list_length(queued_packets_list) > 0) {
struct queue_list_item *i; struct queue_list_item *i;
for(i = list_head(queued_packets_list); i != NULL; i = i->next) { for(i = list_head(queued_packets_list); i != NULL; i = i->next) {
struct lpp_hdr *qhdr; const rimeaddr_t *receiver;
qhdr = queuebuf_dataptr(i->packet); receiver = queuebuf_addr(i->packet, PACKETBUF_ADDR_RECEIVER);
if(rimeaddr_cmp(&qhdr->receiver, &hdr->sender) || if(rimeaddr_cmp(receiver, &hdr.sender) ||
rimeaddr_cmp(&qhdr->receiver, &rimeaddr_null)) { rimeaddr_cmp(receiver, &rimeaddr_null)) {
queuebuf_to_packetbuf(i->packet); queuebuf_to_packetbuf(i->packet);
#if WITH_PENDING_BROADCAST #if WITH_PENDING_BROADCAST
@ -740,15 +774,16 @@ input_packet(void)
i->num_transmissions = 1; i->num_transmissions = 1;
NETSTACK_RADIO.send(queuebuf_dataptr(i->packet), NETSTACK_RADIO.send(queuebuf_dataptr(i->packet),
queuebuf_datalen(i->packet)); queuebuf_datalen(i->packet));
turn_radio_off();
PRINTF("%d.%d: got a probe from %d.%d, sent packet to %d.%d\n", PRINTF("%d.%d: got a probe from %d.%d, sent packet to %d.%d\n",
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
hdr->sender.u8[0], hdr->sender.u8[1], hdr.sender.u8[0], hdr.sender.u8[1],
qhdr->receiver.u8[0], qhdr->receiver.u8[1]); receiver->u8[0], receiver->u8[1]);
} else { } else {
PRINTF("%d.%d: got a probe from %d.%d, did not send packet\n", PRINTF("%d.%d: got a probe from %d.%d, did not send packet\n",
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
hdr->sender.u8[0], hdr->sender.u8[1]); hdr.sender.u8[0], hdr.sender.u8[1]);
} }
#else /* WITH_PENDING_BROADCAST */ #else /* WITH_PENDING_BROADCAST */
i->num_transmissions = 1; i->num_transmissions = 1;
@ -756,11 +791,11 @@ input_packet(void)
queuebuf_datalen(i->packet)); queuebuf_datalen(i->packet));
PRINTF("%d.%d: got a probe from %d.%d, sent packet to %d.%d\n", PRINTF("%d.%d: got a probe from %d.%d, sent packet to %d.%d\n",
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
hdr->sender.u8[0], hdr->sender.u8[1], hdr.sender.u8[0], hdr.sender.u8[1],
qhdr->receiver.u8[0], qhdr->receiver.u8[1]); receiver->u8[0], receiver->u8[1]);
#endif /* WITH_PENDING_BROADCAST */ #endif /* WITH_PENDING_BROADCAST */
/* off();*/
/* Attribute the energy spent on listening for the probe /* Attribute the energy spent on listening for the probe
to this packet transmission. */ to this packet transmission. */
@ -770,7 +805,7 @@ input_packet(void)
now. Broadcast packets should be transmitted to all now. Broadcast packets should be transmitted to all
neighbors, and are dequeued by the dutycycling function neighbors, and are dequeued by the dutycycling function
instead, after the appropriate time. */ instead, after the appropriate time. */
if(!rimeaddr_cmp(&qhdr->receiver, &rimeaddr_null)) { if(!rimeaddr_cmp(receiver, &rimeaddr_null)) {
remove_queued_packet(i); remove_queued_packet(i);
#if WITH_PROBE_AFTER_TRANSMISSION #if WITH_PROBE_AFTER_TRANSMISSION
@ -799,22 +834,23 @@ input_packet(void)
} }
} }
} else if(hdr->type == TYPE_DATA) { } else if(hdr.type == TYPE_DATA) {
if(!rimeaddr_cmp(&hdr->receiver, &rimeaddr_null)) { turn_radio_off();
if(!rimeaddr_cmp(&hdr->receiver, &rimeaddr_node_addr)) { if(!rimeaddr_cmp(&hdr.receiver, &rimeaddr_null)) {
if(!rimeaddr_cmp(&hdr.receiver, &rimeaddr_node_addr)) {
/* Not broadcast or for us */ /* Not broadcast or for us */
PRINTF("%d.%d: data not for us from %d.%d\n", PRINTF("%d.%d: data not for us from %d.%d\n",
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
hdr->sender.u8[0], hdr->sender.u8[1]); hdr.sender.u8[0], hdr.sender.u8[1]);
return; return;
} }
packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &hdr->receiver); packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &hdr.receiver);
} }
packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &hdr->sender); packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &hdr.sender);
PRINTF("%d.%d: got data from %d.%d\n", PRINTF("%d.%d: got data from %d.%d\n",
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
hdr->sender.u8[0], hdr->sender.u8[1]); hdr.sender.u8[0], hdr.sender.u8[1]);
/* Accumulate the power consumption for the packet reception. */ /* Accumulate the power consumption for the packet reception. */
compower_accumulate(&current_packet); compower_accumulate(&current_packet);
@ -829,7 +865,7 @@ input_packet(void)
compower_clear(&current_packet); compower_clear(&current_packet);
#if WITH_PENDING_BROADCAST #if WITH_PENDING_BROADCAST
if(rimeaddr_cmp(&hdr->receiver, &rimeaddr_null)) { if(rimeaddr_cmp(&hdr.receiver, &rimeaddr_null)) {
/* This is a broadcast packet. Check the list of pending /* This is a broadcast packet. Check the list of pending
packets to see if we are currently sending a broadcast. If packets to see if we are currently sending a broadcast. If
so, we refrain from sending our broadcast until one sleep so, we refrain from sending our broadcast until one sleep
@ -853,7 +889,7 @@ input_packet(void)
/* XXX send probe after receiving a packet to facilitate data /* XXX send probe after receiving a packet to facilitate data
streaming. We must first copy the contents of the packetbuf into streaming. We must first copy the contents of the packetbuf into
a queuebuf to avoid overwriting the data with the probe packet. */ a queuebuf to avoid overwriting the data with the probe packet. */
if(rimeaddr_cmp(&hdr->receiver, &rimeaddr_node_addr)) { if(rimeaddr_cmp(&hdr.receiver, &rimeaddr_node_addr)) {
struct queuebuf *q; struct queuebuf *q;
q = queuebuf_new_from_packetbuf(); q = queuebuf_new_from_packetbuf();
if(q != NULL) { if(q != NULL) {