summaryrefslogtreecommitdiff
path: root/tests/examplefiles
diff options
context:
space:
mode:
authorPat Pannuto <pat.pannuto@gmail.com>2013-02-14 23:37:56 -0500
committerPat Pannuto <pat.pannuto@gmail.com>2013-02-14 23:37:56 -0500
commit9d6f717722f88ce4a57acd7c705802eb034b8d13 (patch)
treea64394e567d1be87b777800fd47a20159663db8c /tests/examplefiles
parentf504018244f7975b960f8db9eddade22fbea4411 (diff)
downloadpygments-9d6f717722f88ce4a57acd7c705802eb034b8d13.tar.gz
Add sample files for nesC
Adds a nesC module and configuration file for testing. IPDispatch should cover a good percentage of the nesC specific keywords.
Diffstat (limited to 'tests/examplefiles')
-rw-r--r--tests/examplefiles/IPDispatchC.nc104
-rw-r--r--tests/examplefiles/IPDispatchP.nc671
2 files changed, 775 insertions, 0 deletions
diff --git a/tests/examplefiles/IPDispatchC.nc b/tests/examplefiles/IPDispatchC.nc
new file mode 100644
index 00000000..95a61a2c
--- /dev/null
+++ b/tests/examplefiles/IPDispatchC.nc
@@ -0,0 +1,104 @@
+/*
+ * "Copyright (c) 2008-2011 The Regents of the University of California.
+ * All rights reserved."
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+ * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
+ *
+ */
+
+/**
+ *
+ *
+ */
+#include "IPDispatch.h"
+#include "BlipStatistics.h"
+
+configuration IPDispatchC {
+ provides {
+ interface SplitControl;
+ interface IPLower;
+ interface BlipStatistics<ip_statistics_t>;
+ }
+} implementation {
+
+ components MainC;
+ components NoLedsC as LedsC;
+
+ /* IPDispatchP wiring -- fragment rassembly and lib6lowpan bindings */
+ components IPDispatchP;
+ components CC2420RadioC as MessageC;
+ components ReadLqiC;
+ components new TimerMilliC();
+
+ SplitControl = IPDispatchP.SplitControl;
+ IPLower = IPDispatchP;
+ BlipStatistics = IPDispatchP;
+
+ IPDispatchP.Boot -> MainC;
+/* #else */
+/* components ResourceSendP; */
+/* ResourceSendP.SubSend -> MessageC; */
+/* ResourceSendP.Resource -> MessageC.SendResource[unique("RADIO_SEND_RESOURCE")]; */
+/* IPDispatchP.Ieee154Send -> ResourceSendP.Ieee154Send; */
+/* #endif */
+ IPDispatchP.RadioControl -> MessageC;
+
+ IPDispatchP.BarePacket -> MessageC.BarePacket;
+ IPDispatchP.Ieee154Send -> MessageC.BareSend;
+ IPDispatchP.Ieee154Receive -> MessageC.BareReceive;
+
+#ifdef LOW_POWER_LISTENING
+ IPDispatchP.LowPowerListening -> MessageC;
+#endif
+ MainC.SoftwareInit -> IPDispatchP.Init;
+
+ IPDispatchP.PacketLink -> MessageC;
+ IPDispatchP.ReadLqi -> ReadLqiC;
+ IPDispatchP.Leds -> LedsC;
+ IPDispatchP.ExpireTimer -> TimerMilliC;
+
+ components new PoolC(message_t, N_FRAGMENTS) as FragPool;
+ components new PoolC(struct send_entry, N_FRAGMENTS) as SendEntryPool;
+ components new QueueC(struct send_entry *, N_FRAGMENTS);
+ components new PoolC(struct send_info, N_CONCURRENT_SENDS) as SendInfoPool;
+
+ IPDispatchP.FragPool -> FragPool;
+ IPDispatchP.SendEntryPool -> SendEntryPool;
+ IPDispatchP.SendInfoPool -> SendInfoPool;
+ IPDispatchP.SendQueue -> QueueC;
+
+ components IPNeighborDiscoveryP;
+ IPDispatchP.NeighborDiscovery -> IPNeighborDiscoveryP;
+
+/* components ICMPResponderC; */
+/* #ifdef BLIP_MULTICAST */
+/* components MulticastP; */
+/* components new TrickleTimerMilliC(2, 30, 2, 1); */
+/* IP = MulticastP.IP; */
+
+/* MainC.SoftwareInit -> MulticastP.Init; */
+/* MulticastP.MulticastRx -> IPDispatchP.Multicast; */
+/* MulticastP.HopHeader -> IPExtensionP.HopByHopExt[0]; */
+/* MulticastP.TrickleTimer -> TrickleTimerMilliC.TrickleTimer[0]; */
+/* MulticastP.IPExtensions -> IPDispatchP; */
+/* #endif */
+
+#ifdef DELUGE
+ components NWProgC;
+#endif
+
+}
diff --git a/tests/examplefiles/IPDispatchP.nc b/tests/examplefiles/IPDispatchP.nc
new file mode 100644
index 00000000..628f39a0
--- /dev/null
+++ b/tests/examplefiles/IPDispatchP.nc
@@ -0,0 +1,671 @@
+/*
+ * "Copyright (c) 2008 The Regents of the University of California.
+ * All rights reserved."
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+ * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
+ *
+ */
+
+#include <lib6lowpan/blip-tinyos-includes.h>
+#include <lib6lowpan/6lowpan.h>
+#include <lib6lowpan/lib6lowpan.h>
+#include <lib6lowpan/ip.h>
+#include <lib6lowpan/in_cksum.h>
+#include <lib6lowpan/ip_malloc.h>
+
+#include "blip_printf.h"
+#include "IPDispatch.h"
+#include "BlipStatistics.h"
+#include "table.h"
+
+/*
+ * Provides IP layer reception to applications on motes.
+ *
+ * @author Stephen Dawson-Haggerty <stevedh@cs.berkeley.edu>
+ */
+
+module IPDispatchP {
+ provides {
+ interface SplitControl;
+ // interface for protocols not requiring special hand-holding
+ interface IPLower;
+
+ interface BlipStatistics<ip_statistics_t>;
+
+ }
+ uses {
+ interface Boot;
+
+
+ /* link-layer wiring */
+ interface SplitControl as RadioControl;
+
+ interface Packet as BarePacket;
+ interface Send as Ieee154Send;
+ interface Receive as Ieee154Receive;
+
+ /* context lookup */
+ interface NeighborDiscovery;
+
+ interface ReadLqi;
+ interface PacketLink;
+ interface LowPowerListening;
+
+ /* buffers for outgoing fragments */
+ interface Pool<message_t> as FragPool;
+ interface Pool<struct send_info> as SendInfoPool;
+ interface Pool<struct send_entry> as SendEntryPool;
+ interface Queue<struct send_entry *> as SendQueue;
+
+ /* expire reconstruction */
+ interface Timer<TMilli> as ExpireTimer;
+
+ interface Leds;
+
+ }
+ provides interface Init;
+} implementation {
+
+#define HAVE_LOWPAN_EXTERN_MATCH_CONTEXT
+int lowpan_extern_read_context(struct in6_addr *addr, int context) {
+ return call NeighborDiscovery.getContext(context, addr);
+}
+
+int lowpan_extern_match_context(struct in6_addr *addr, uint8_t *ctx_id) {
+ return call NeighborDiscovery.matchContext(addr, ctx_id);
+}
+
+ // generally including source files like this is a no-no. I'm doing
+ // this in the hope that the optimizer will do a better job when
+ // they're part of a component.
+#include <lib6lowpan/ieee154_header.c>
+#include <lib6lowpan/lib6lowpan.c>
+#include <lib6lowpan/lib6lowpan_4944.c>
+#include <lib6lowpan/lib6lowpan_frag.c>
+
+ enum {
+ S_RUNNING,
+ S_STOPPED,
+ S_STOPPING,
+ };
+ uint8_t state = S_STOPPED;
+ bool radioBusy;
+ uint8_t current_local_label = 0;
+ ip_statistics_t stats;
+
+ // this in theory could be arbitrarily large; however, it needs to
+ // be large enough to hold all active reconstructions, and any tags
+ // which we are dropping. It's important to keep dropped tags
+ // around for a while, or else there are pathological situations
+ // where you continually allocate buffers for packets which will
+ // never complete.
+
+ ////////////////////////////////////////
+ //
+ //
+
+ table_t recon_cache;
+
+ // table of packets we are currently receiving fragments from, that
+ // are destined to us
+ struct lowpan_reconstruct recon_data[N_RECONSTRUCTIONS];
+
+ //
+ //
+ ////////////////////////////////////////
+
+ // task void sendTask();
+
+ void reconstruct_clear(void *ent) {
+ struct lowpan_reconstruct *recon = (struct lowpan_reconstruct *)ent;
+ memclr((uint8_t *)&recon->r_meta, sizeof(struct ip6_metadata));
+ recon->r_timeout = T_UNUSED;
+ recon->r_buf = NULL;
+ }
+
+ struct send_info *getSendInfo() {
+ struct send_info *ret = call SendInfoPool.get();
+ if (ret == NULL) return ret;
+ ret->_refcount = 1;
+ ret->upper_data = NULL;
+ ret->failed = FALSE;
+ ret->link_transmissions = 0;
+ ret->link_fragments = 0;
+ ret->link_fragment_attempts = 0;
+ return ret;
+ }
+#define SENDINFO_INCR(X) ((X)->_refcount)++
+void SENDINFO_DECR(struct send_info *si) {
+ if (--(si->_refcount) == 0) {
+ call SendInfoPool.put(si);
+ }
+}
+
+ command error_t SplitControl.start() {
+ return call RadioControl.start();
+ }
+
+ command error_t SplitControl.stop() {
+ if (!radioBusy) {
+ state = S_STOPPED;
+ return call RadioControl.stop();
+ } else {
+ // if there's a packet in the radio, wait for it to exit before
+ // stopping
+ state = S_STOPPING;
+ return SUCCESS;
+ }
+ }
+
+ event void RadioControl.startDone(error_t error) {
+#ifdef LPL_SLEEP_INTERVAL
+ call LowPowerListening.setLocalWakeupInterval(LPL_SLEEP_INTERVAL);
+#endif
+
+ if (error == SUCCESS) {
+ call Leds.led2Toggle();
+ call ExpireTimer.startPeriodic(FRAG_EXPIRE_TIME);
+ state = S_RUNNING;
+ radioBusy = FALSE;
+ }
+
+ signal SplitControl.startDone(error);
+ }
+
+ event void RadioControl.stopDone(error_t error) {
+ signal SplitControl.stopDone(error);
+ }
+
+ command error_t Init.init() {
+ // ip_malloc_init needs to be in init, not booted, because
+ // context for coap is initialised in init
+ ip_malloc_init();
+ return SUCCESS;
+ }
+
+ event void Boot.booted() {
+ call BlipStatistics.clear();
+
+ /* set up our reconstruction cache */
+ table_init(&recon_cache, recon_data, sizeof(struct lowpan_reconstruct), N_RECONSTRUCTIONS);
+ table_map(&recon_cache, reconstruct_clear);
+
+ call SplitControl.start();
+ }
+
+ /*
+ * Receive-side code.
+ */
+ void deliver(struct lowpan_reconstruct *recon) {
+ struct ip6_hdr *iph = (struct ip6_hdr *)recon->r_buf;
+
+ // printf("deliver [%i]: ", recon->r_bytes_rcvd);
+ // printf_buf(recon->r_buf, recon->r_bytes_rcvd);
+
+ /* the payload length field is always compressed, have to put it back here */
+ iph->ip6_plen = htons(recon->r_bytes_rcvd - sizeof(struct ip6_hdr));
+ signal IPLower.recv(iph, (void *)(iph + 1), &recon->r_meta);
+
+ // printf("ip_free(%p)\n", recon->r_buf);
+ ip_free(recon->r_buf);
+ recon->r_timeout = T_UNUSED;
+ recon->r_buf = NULL;
+ }
+
+ /*
+ * Bulletproof recovery logic is very important to make sure we
+ * don't get wedged with no free buffers.
+ *
+ * The table is managed as follows:
+ * - unused entries are marked T_UNUSED
+ * - entries which
+ * o have a buffer allocated
+ * o have had a fragment reception before we fired
+ * are marked T_ACTIVE
+ * - entries which have not had a fragment reception during the last timer period
+ * and were active are marked T_ZOMBIE
+ * - zombie receptions are deleted: their buffer is freed and table entry marked unused.
+ * - when a fragment is dropped, it is entered into the table as T_FAILED1.
+ * no buffer is allocated
+ * - when the timer fires, T_FAILED1 entries are aged to T_FAILED2.
+ * - T_FAILED2 entries are deleted. Incomming fragments with tags
+ * that are marked either FAILED1 or FAILED2 are dropped; this
+ * prevents us from allocating a buffer for a packet which we
+ * have already dropped fragments from.
+ *
+ */
+ void reconstruct_age(void *elt) {
+ struct lowpan_reconstruct *recon = (struct lowpan_reconstruct *)elt;
+ if (recon->r_timeout != T_UNUSED)
+ printf("recon src: 0x%x tag: 0x%x buf: %p recvd: %i/%i\n",
+ recon->r_source_key, recon->r_tag, recon->r_buf,
+ recon->r_bytes_rcvd, recon->r_size);
+ switch (recon->r_timeout) {
+ case T_ACTIVE:
+ recon->r_timeout = T_ZOMBIE; break; // age existing receptions
+ case T_FAILED1:
+ recon->r_timeout = T_FAILED2; break; // age existing receptions
+ case T_ZOMBIE:
+ case T_FAILED2:
+ // deallocate the space for reconstruction
+ printf("timing out buffer: src: %i tag: %i\n", recon->r_source_key, recon->r_tag);
+ if (recon->r_buf != NULL) {
+ printf("ip_free(%p)\n", recon->r_buf);
+ ip_free(recon->r_buf);
+ }
+ recon->r_timeout = T_UNUSED;
+ recon->r_buf = NULL;
+ break;
+ }
+ }
+
+ void ip_print_heap() {
+#ifdef PRINTFUART_ENABLED
+ bndrt_t *cur = (bndrt_t *)heap;
+ while (((uint8_t *)cur) - heap < IP_MALLOC_HEAP_SIZE) {
+ printf ("heap region start: %p length: %u used: %u\n",
+ cur, (*cur & IP_MALLOC_LEN), (*cur & IP_MALLOC_INUSE) >> 15);
+ cur = (bndrt_t *)(((uint8_t *)cur) + ((*cur) & IP_MALLOC_LEN));
+ }
+#endif
+ }
+
+ event void ExpireTimer.fired() {
+ table_map(&recon_cache, reconstruct_age);
+
+
+ printf("Frag pool size: %i\n", call FragPool.size());
+ printf("SendInfo pool size: %i\n", call SendInfoPool.size());
+ printf("SendEntry pool size: %i\n", call SendEntryPool.size());
+ printf("Forward queue length: %i\n", call SendQueue.size());
+ ip_print_heap();
+ printfflush();
+ }
+
+ /*
+ * allocate a structure for recording information about incomming fragments.
+ */
+
+ struct lowpan_reconstruct *get_reconstruct(uint16_t key, uint16_t tag) {
+ struct lowpan_reconstruct *ret = NULL;
+ int i;
+
+ // printf("get_reconstruct: %x %i\n", key, tag);
+
+ for (i = 0; i < N_RECONSTRUCTIONS; i++) {
+ struct lowpan_reconstruct *recon = (struct lowpan_reconstruct *)&recon_data[i];
+
+ if (recon->r_tag == tag &&
+ recon->r_source_key == key) {
+
+ if (recon->r_timeout > T_UNUSED) {
+ recon->r_timeout = T_ACTIVE;
+ ret = recon;
+ goto done;
+
+ } else if (recon->r_timeout < T_UNUSED) {
+ // if we have already tried and failed to get a buffer, we
+ // need to drop remaining fragments.
+ ret = NULL;
+ goto done;
+ }
+ }
+ if (recon->r_timeout == T_UNUSED)
+ ret = recon;
+ }
+ done:
+ // printf("got%p\n", ret);
+ return ret;
+ }
+
+ event message_t *Ieee154Receive.receive(message_t *msg, void *msg_payload, uint8_t len) {
+ struct packed_lowmsg lowmsg;
+ struct ieee154_frame_addr frame_address;
+ uint8_t *buf = msg_payload;
+
+ // printf(" -- RECEIVE -- len : %i\n", len);
+
+ BLIP_STATS_INCR(stats.rx_total);
+
+ /* unpack the 802.15.4 address fields */
+ buf = unpack_ieee154_hdr(msg_payload, &frame_address);
+ len -= buf - (uint8_t *)msg_payload;
+
+ /* unpack and 6lowpan headers */
+ lowmsg.data = buf;
+ lowmsg.len = len;
+ lowmsg.headers = getHeaderBitmap(&lowmsg);
+ if (lowmsg.headers == LOWMSG_NALP) {
+ goto fail;
+ }
+
+ if (hasFrag1Header(&lowmsg) || hasFragNHeader(&lowmsg)) {
+ // start reassembly
+ int rv;
+ struct lowpan_reconstruct *recon;
+ uint16_t tag, source_key;
+
+ source_key = ieee154_hashaddr(&frame_address.ieee_src);
+ getFragDgramTag(&lowmsg, &tag);
+ recon = get_reconstruct(source_key, tag);
+ if (!recon) {
+ goto fail;
+ }
+
+ /* fill in metadata: on fragmented packets, it applies to the
+ first fragment only */
+ memcpy(&recon->r_meta.sender, &frame_address.ieee_src,
+ sizeof(ieee154_addr_t));
+ recon->r_meta.lqi = call ReadLqi.readLqi(msg);
+ recon->r_meta.rssi = call ReadLqi.readRssi(msg);
+
+ if (hasFrag1Header(&lowmsg)) {
+ if (recon->r_buf != NULL) goto fail;
+ rv = lowpan_recon_start(&frame_address, recon, buf, len);
+ } else {
+ rv = lowpan_recon_add(recon, buf, len);
+ }
+
+ if (rv < 0) {
+ recon->r_timeout = T_FAILED1;
+ goto fail;
+ } else {
+ // printf("start recon buf: %p\n", recon->r_buf);
+ recon->r_timeout = T_ACTIVE;
+ recon->r_source_key = source_key;
+ recon->r_tag = tag;
+ }
+
+ if (recon->r_size == recon->r_bytes_rcvd) {
+ deliver(recon);
+ }
+
+ } else {
+ /* no fragmentation, just deliver it */
+ int rv;
+ struct lowpan_reconstruct recon;
+
+ /* fill in metadata */
+ memcpy(&recon.r_meta.sender, &frame_address.ieee_src,
+ sizeof(ieee154_addr_t));
+ recon.r_meta.lqi = call ReadLqi.readLqi(msg);
+ recon.r_meta.rssi = call ReadLqi.readRssi(msg);
+
+ buf = getLowpanPayload(&lowmsg);
+ if ((rv = lowpan_recon_start(&frame_address, &recon, buf, len)) < 0) {
+ goto fail;
+ }
+
+ if (recon.r_size == recon.r_bytes_rcvd) {
+ deliver(&recon);
+ } else {
+ // printf("ip_free(%p)\n", recon.r_buf);
+ ip_free(recon.r_buf);
+ }
+ }
+ goto done;
+ fail:
+ BLIP_STATS_INCR(stats.rx_drop);
+ done:
+ return msg;
+ }
+
+
+ /*
+ * Send-side functionality
+ */
+ task void sendTask() {
+ struct send_entry *s_entry;
+
+ // printf("sendTask() - sending\n");
+
+ if (radioBusy || state != S_RUNNING) return;
+ if (call SendQueue.empty()) return;
+ // this does not dequeue
+ s_entry = call SendQueue.head();
+
+#ifdef LPL_SLEEP_INTERVAL
+ call LowPowerListening.setRemoteWakeupInterval(s_entry->msg,
+ call LowPowerListening.getLocalWakeupInterval());
+#endif
+
+ if (s_entry->info->failed) {
+ dbg("Drops", "drops: sendTask: dropping failed fragment\n");
+ goto fail;
+ }
+
+ if ((call Ieee154Send.send(s_entry->msg,
+ call BarePacket.payloadLength(s_entry->msg))) != SUCCESS) {
+ dbg("Drops", "drops: sendTask: send failed\n");
+ goto fail;
+ } else {
+ radioBusy = TRUE;
+ }
+
+ return;
+ fail:
+ printf("SEND FAIL\n");
+ post sendTask();
+ BLIP_STATS_INCR(stats.tx_drop);
+
+ // deallocate the memory associated with this request.
+ // other fragments associated with this packet will get dropped.
+ s_entry->info->failed = TRUE;
+ SENDINFO_DECR(s_entry->info);
+ call FragPool.put(s_entry->msg);
+ call SendEntryPool.put(s_entry);
+ call SendQueue.dequeue();
+ }
+
+
+ /*
+ * it will pack the message into the fragment pool and enqueue
+ * those fragments for sending
+ *
+ * it will set
+ * - payload length
+ * - version, traffic class and flow label
+ *
+ * the source and destination IP addresses must be set by higher
+ * layers.
+ */
+ command error_t IPLower.send(struct ieee154_frame_addr *frame_addr,
+ struct ip6_packet *msg,
+ void *data) {
+ struct lowpan_ctx ctx;
+ struct send_info *s_info;
+ struct send_entry *s_entry;
+ message_t *outgoing;
+
+ int frag_len = 1;
+ error_t rc = SUCCESS;
+
+ if (state != S_RUNNING) {
+ return EOFF;
+ }
+
+ /* set version to 6 in case upper layers forgot */
+ msg->ip6_hdr.ip6_vfc &= ~IPV6_VERSION_MASK;
+ msg->ip6_hdr.ip6_vfc |= IPV6_VERSION;
+
+ ctx.tag = current_local_label++;
+ ctx.offset = 0;
+
+ s_info = getSendInfo();
+ if (s_info == NULL) {
+ rc = ERETRY;
+ goto cleanup_outer;
+ }
+ s_info->upper_data = data;
+
+ while (frag_len > 0) {
+ s_entry = call SendEntryPool.get();
+ outgoing = call FragPool.get();
+
+ if (s_entry == NULL || outgoing == NULL) {
+ if (s_entry != NULL)
+ call SendEntryPool.put(s_entry);
+ if (outgoing != NULL)
+ call FragPool.put(outgoing);
+ // this will cause any fragments we have already enqueued to
+ // be dropped by the send task.
+ s_info->failed = TRUE;
+ printf("drops: IP send: no fragments\n");
+ rc = ERETRY;
+ goto done;
+ }
+
+ call BarePacket.clear(outgoing);
+ frag_len = lowpan_frag_get(call Ieee154Send.getPayload(outgoing, 0),
+ call BarePacket.maxPayloadLength(),
+ msg,
+ frame_addr,
+ &ctx);
+ if (frag_len < 0) {
+ printf(" get frag error: %i\n", frag_len);
+ }
+
+ printf("fragment length: %i offset: %i\n", frag_len, ctx.offset);
+ call BarePacket.setPayloadLength(outgoing, frag_len);
+
+ if (frag_len <= 0) {
+ call FragPool.put(outgoing);
+ call SendEntryPool.put(s_entry);
+ goto done;
+ }
+
+ if (call SendQueue.enqueue(s_entry) != SUCCESS) {
+ BLIP_STATS_INCR(stats.encfail);
+ s_info->failed = TRUE;
+ printf("drops: IP send: enqueue failed\n");
+ goto done;
+ }
+
+ s_info->link_fragments++;
+ s_entry->msg = outgoing;
+ s_entry->info = s_info;
+
+ /* configure the L2 */
+ if (frame_addr->ieee_dst.ieee_mode == IEEE154_ADDR_SHORT &&
+ frame_addr->ieee_dst.i_saddr == IEEE154_BROADCAST_ADDR) {
+ call PacketLink.setRetries(s_entry->msg, 0);
+ } else {
+ call PacketLink.setRetries(s_entry->msg, BLIP_L2_RETRIES);
+ }
+ call PacketLink.setRetryDelay(s_entry->msg, BLIP_L2_DELAY);
+
+ SENDINFO_INCR(s_info);}
+
+ // printf("got %i frags\n", s_info->link_fragments);
+ done:
+ BLIP_STATS_INCR(stats.sent);
+ SENDINFO_DECR(s_info);
+ post sendTask();
+ cleanup_outer:
+ return rc;
+ }
+
+ event void Ieee154Send.sendDone(message_t *msg, error_t error) {
+ struct send_entry *s_entry = call SendQueue.head();
+
+ radioBusy = FALSE;
+
+ // printf("sendDone: %p %i\n", msg, error);
+
+ if (state == S_STOPPING) {
+ call RadioControl.stop();
+ state = S_STOPPED;
+ goto done;
+ }
+
+ s_entry->info->link_transmissions += (call PacketLink.getRetries(msg));
+ s_entry->info->link_fragment_attempts++;
+
+ if (!call PacketLink.wasDelivered(msg)) {
+ printf("sendDone: was not delivered! (%i tries)\n",
+ call PacketLink.getRetries(msg));
+ s_entry->info->failed = TRUE;
+ signal IPLower.sendDone(s_entry->info);
+/* if (s_entry->info->policy.dest[0] != 0xffff) */
+/* dbg("Drops", "drops: sendDone: frag was not delivered\n"); */
+ // need to check for broadcast frames
+ // BLIP_STATS_INCR(stats.tx_drop);
+ } else if (s_entry->info->link_fragment_attempts ==
+ s_entry->info->link_fragments) {
+ signal IPLower.sendDone(s_entry->info);
+ }
+
+ done:
+ // kill off any pending fragments
+ SENDINFO_DECR(s_entry->info);
+ call FragPool.put(s_entry->msg);
+ call SendEntryPool.put(s_entry);
+ call SendQueue.dequeue();
+
+ post sendTask();
+ }
+
+#if 0
+ command struct tlv_hdr *IPExtensions.findTlv(struct ip6_ext *ext, uint8_t tlv_val) {
+ int len = ext->len - sizeof(struct ip6_ext);
+ struct tlv_hdr *tlv = (struct tlv_hdr *)(ext + 1);
+ while (len > 0) {
+ if (tlv->type == tlv_val) return tlv;
+ if (tlv->len == 0) return NULL;
+ tlv = (struct tlv_hdr *)(((uint8_t *)tlv) + tlv->len);
+ len -= tlv->len;
+ }
+ return NULL;
+ }
+#endif
+
+
+ /*
+ * BlipStatistics interface
+ */
+ command void BlipStatistics.get(ip_statistics_t *statistics) {
+#ifdef BLIP_STATS_IP_MEM
+ stats.fragpool = call FragPool.size();
+ stats.sendinfo = call SendInfoPool.size();
+ stats.sendentry= call SendEntryPool.size();
+ stats.sndqueue = call SendQueue.size();
+ stats.heapfree = ip_malloc_freespace();
+ printf("frag: %i sendinfo: %i sendentry: %i sendqueue: %i heap: %i\n",
+ stats.fragpool,
+ stats.sendinfo,
+ stats.sendentry,
+ stats.sndqueue,
+ stats.heapfree);
+#endif
+ memcpy(statistics, &stats, sizeof(ip_statistics_t));
+
+ }
+
+ command void BlipStatistics.clear() {
+ memclr((uint8_t *)&stats, sizeof(ip_statistics_t));
+ }
+
+/* default event void IP.recv[uint8_t nxt_hdr](struct ip6_hdr *iph, */
+/* void *payload, */
+/* struct ip_metadata *meta) { */
+/* } */
+
+/* default event void Multicast.recv[uint8_t scope](struct ip6_hdr *iph, */
+/* void *payload, */
+/* struct ip_metadata *meta) { */
+/* } */
+}