📄 ipdispatchp.nc
字号:
message_t *replacement = call FragPool.get();
send_entry_t *s_entry = call SendEntryPool.get();
uint16_t lowpan_size;
uint8_t lowpan_offset;
if (replacement == NULL || s_entry == NULL) {
// we have to drop the rest of the framents if we don't have
// a buffer...
if (replacement != NULL)
call FragPool.put(replacement);
if (s_entry != NULL)
call SendEntryPool.put(s_entry);
BLIP_STATS_INCR(stats.fw_drop);
fwd->timeout = T_FAILED1;
goto fail;
}
// keep a reference for ourself, and pass it off to the
// send_entry_t
SENDINFO_INCR(fwd->s_info);
getFragDgramOffset(&lowmsg, &lowpan_offset);
getFragDgramSize(&lowmsg, &lowpan_size);
if ((lowpan_offset * 8) + (lowmsg.len - (payload - lowmsg.data)) == lowpan_size) {
// this is the last fragment. since delivery is in-order,
// we want to free up that forwarding table entry.
// take back the reference the table had.
SENDINFO_DECR(fwd->s_info);
fwd->timeout = T_UNUSED;
}
setFragDgramTag(&lowmsg, fwd->new_tag);
s_entry->msg = msg;
s_entry->info = fwd->s_info;
dbg("IPDispatch", "forwarding: dest: 0x%x\n",
fwd->s_info->policy.dest[s_entry->info->policy.current]);
if (call SendQueue.enqueue(s_entry) != SUCCESS) {
BLIP_STATS_INCR(stats.encfail);
dbg("Drops", "drops: receive enqueue failed\n");
}
post sendTask();
return replacement;
} else goto fail;
goto done;
}
fail:
dbg("Drops", "drops: receive()\n");;
BLIP_STATS_INCR(stats.rx_drop);
done:
return msg;
}
/*
* Send-side functionality
*/
task void sendTask() {
send_entry_t *s_entry;
if (radioBusy || state != S_RUNNING) return;
if (call SendQueue.empty()) return;
// this does not dequeue
s_entry = call SendQueue.head();
call Ieee154Packet.setDestination(s_entry->msg,
s_entry->info->policy.dest[s_entry->info->policy.current]);
call PacketLink.setRetries(s_entry->msg, s_entry->info->policy.retries);
call PacketLink.setRetryDelay(s_entry->msg, s_entry->info->policy.delay);
#ifdef LPL_SLEEP_INTERVAL
call LowPowerListening.setRemoteWakeupInterval(s_entry->msg,
call LowPowerListening.getLocalWakeupInterval());
#endif
dbg("IPDispatch", "sendTask dest: 0x%x len: 0x%x \n",
call Ieee154Packet.destination(s_entry->msg),
call Packet.payloadLength(s_entry->msg));
if (s_entry->info->failed) {
dbg("Drops", "drops: sendTask: dropping failed fragment\n");
goto fail;
}
if ((call Ieee154Send.send(call Ieee154Packet.destination(s_entry->msg),
s_entry->msg,
call Packet.payloadLength(s_entry->msg))) != SUCCESS) {
dbg("Drops", "drops: sendTask: send failed\n");
goto fail;
}
radioBusy = TRUE;
if (call SendQueue.empty()) return;
// this does not dequeue
s_entry = call SendQueue.head();
return;
fail:
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();
}
/*
* this interface is only for grownups; it is also only called for
* local sends.
*
* 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 IP.send[uint8_t prot](struct split_ip_msg *msg) {
msg->hdr.nxt_hdr = prot;
return call IP.bareSend[prot](msg, NULL, 0);
}
command error_t IP.bareSend[uint8_t prot](struct split_ip_msg *msg,
struct ip6_route *route,
int flags) {
uint16_t payload_length;
if (state != S_RUNNING) {
return EOFF;
}
if (msg->hdr.hlim != 0xff)
msg->hdr.hlim = call IPRouting.getHopLimit();
printfUART("sending...\n");
ip_memclr(msg->hdr.vlfc, 4);
msg->hdr.vlfc[0] = IPV6_VERSION << 4;
current_local_label++;
if (!(flags & IP_NOHEADERS)) {
call InternalIPExtension.addHeaders(msg, prot, current_local_label);
if (route == NULL)
route = call IPRouting.insertRoutingHeader(msg);
}
payload_length = msg->data_len;
{
struct generic_header *cur = msg->headers;
while (cur != NULL) {
payload_length += cur->len;
cur = cur->next;
}
}
msg->hdr.plen = htons(payload_length);
printfUART("sending: total length is: %i\n", payload_length);
// okay, so we ought to have a fully setup chain of headers here,
// so we ought to be able to compress everything into fragments.
//
{
error_t rc = SUCCESS;
send_info_t *s_info;
send_entry_t *s_entry;
uint8_t frag_len = 1;
message_t *outgoing;
fragment_t progress;
struct source_header *sh;
progress.offset = 0;
s_info = getSendInfo();
if (s_info == NULL) {
rc = ERETRY;
goto cleanup_outer;
}
s_info->local_flow_label = current_local_label;
// fill in destination information on outgoing fragments.
sh = (msg->headers != NULL) ? (struct source_header *)msg->headers->hdr.ext : NULL;
if (call IPRouting.getNextHop(&msg->hdr, route, 0x0,
&s_info->policy) != SUCCESS) {
dbg("Drops", "drops: IP send: getNextHop failed\n");
goto done;
}
//goto done;
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;
dbg("Drops", "drops: IP send: no fragments\n");
goto done;
}
// printfUART("getting frag... ");
// ip_dump_msg(msg);
frag_len = getNextFrag(msg, &progress,
call Packet.getPayload(outgoing, call Packet.maxPayloadLength()),
call Packet.maxPayloadLength());
// printfUART("got frag: len: %i\n", frag_len);
if (frag_len == 0) {
call FragPool.put(outgoing);
call SendEntryPool.put(s_entry);
goto done;
}
call Packet.setPayloadLength(outgoing, frag_len);
s_entry->msg = outgoing;
s_entry->info = s_info;
if (call SendQueue.enqueue(s_entry) != SUCCESS) {
BLIP_STATS_INCR(stats.encfail);
dbg("Drops", "drops: IP send: enqueue failed\n");
goto done;
}
SENDINFO_INCR(s_info);
// printfUART("enqueue len 0x%x dest: 0x%x retries: 0x%x delay: 0x%x\n",frag_len,
// s_info->policy.dest, s_info->policy.retries, s_info->policy.delay);
}
done:
BLIP_STATS_INCR(stats.sent);
SENDINFO_DECR(s_info);
post sendTask();
cleanup_outer:
call InternalIPExtension.free();
return rc;
}
}
event void Ieee154Send.sendDone(message_t *msg, error_t error) {
send_entry_t *s_entry = call SendQueue.head();
radioBusy = FALSE;
if (state == S_STOPPING) {
call RadioControl.stop();
state = S_STOPPED;
goto fail;
}
if (!call PacketLink.wasDelivered(msg)) {
// if we haven't sent out any fragments yet, we can try rerouting
if (s_entry->info->frags_sent == 0) {
// SDH : TODO : if sending a fragment fails, abandon the rest of
// the fragments
s_entry->info->policy.current++;
if (s_entry->info->policy.current < s_entry->info->policy.nchoices) {
// this is the retry case; we don't need to change anything.
post sendTask();
return;
}
// no more next hops to try, so free the buffers and move on
}
// a fragment failed, and it wasn't the first. we drop all
// remaining fragments.
goto fail;
} else {
// the fragment was successfully sent.
s_entry->info->frags_sent++;
goto done;
}
goto done;
fail:
s_entry->info->failed = TRUE;
if (s_entry->info->policy.dest[0] != 0xffff)
dbg("Drops", "drops: sendDone: frag was not delivered\n");
BLIP_STATS_INCR(stats.tx_drop);
done:
s_entry->info->policy.actRetries = call PacketLink.getRetries(msg);
signal IPExtensions.reportTransmission(s_entry->info->local_flow_label, &s_entry->info->policy);
// 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();
}
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;
}
event void ICMP.solicitationDone() {
}
/*
* Statistics interface
*/
command void Statistics.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();
printfUART("frag: %i sendinfo: %i sendentry: %i sendqueue: %i heap: %i\n",
stats.fragpool,
stats.sendinfo,
stats.sendentry,
stats.sndqueue,
stats.heapfree);
#endif
ip_memcpy(statistics, &stats, sizeof(ip_statistics_t));
}
command void Statistics.clear() {
ip_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) {
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -