-
- // Loop-detection functionality:
- if (call CtpInfo.getEtx(&gradient) != SUCCESS) {
- // If we have no metric, set our gradient conservatively so
- // that other nodes don't automatically drop our packets.
- gradient = 0;
- }
- call CtpPacket.setEtx(qe->msg, gradient);
-
- ackPending = (call PacketAcknowledgements.requestAck(qe->msg) == SUCCESS);
-
- // Set or clear the congestion bit on *outgoing* packets.
- if (call CtpCongestion.isCongested())
- call CtpPacket.setOption(qe->msg, CTP_OPT_ECN);
- else
- call CtpPacket.clearOption(qe->msg, CTP_OPT_ECN);
-
- subsendResult = call SubSend.send(dest, qe->msg, payloadLen);
- if (subsendResult == SUCCESS) {
- // Successfully submitted to the data-link layer.
- sending = TRUE;
- dbg("Forwarder", "%s: subsend succeeded with %p.\n", __FUNCTION__, qe->msg);
- if (qe->client < CLIENT_COUNT) {
- dbg("Forwarder", "%s: client packet.\n", __FUNCTION__);
- }
- else {
- dbg("Forwarder", "%s: forwarded packet.\n", __FUNCTION__);
- }
- return;
- }
- else if (subsendResult == EOFF) {
- // The radio has been turned off underneath us. Assume that
- // this is for the best. When the radio is turned back on, we'll
- // handle a startDone event and resume sending.
- radioOn = FALSE;
- dbg("Forwarder", "%s: subsend failed from EOFF.\n", __FUNCTION__);
- // send a debug message to the uart
- call CollectionDebug.logEvent(NET_C_FE_SUBSEND_OFF);
- }
- else if (subsendResult == EBUSY) {
- // This shouldn't happen, as we sit on top of a client and
- // control our own output; it means we're trying to
- // double-send (bug). This means we expect a sendDone, so just
- // wait for that: when the sendDone comes in, // we'll try
- // sending this packet again.
- dbg("Forwarder", "%s: subsend failed from EBUSY.\n", __FUNCTION__);
- // send a debug message to the uart
- call CollectionDebug.logEvent(NET_C_FE_SUBSEND_BUSY);
- }
- else if (subsendResult == ESIZE) {
- dbg("Forwarder", "%s: subsend failed from ESIZE: truncate packet.\n", __FUNCTION__);
- call Packet.setPayloadLength(qe->msg, call Packet.maxPayloadLength());
- post sendTask();
- call CollectionDebug.logEvent(NET_C_FE_SUBSEND_SIZE);
+ else {
+ /* The basic forwarding/sending case. */
+ call CtpPacket.setEtx(qe->msg, gradient);
+ call CtpPacket.clearOption(qe->msg, CTP_OPT_ECN | CTP_OPT_PULL);
+ if (call PacketAcknowledgements.requestAck(qe->msg) == SUCCESS) {
+ setState(ACK_PENDING);
+ }
+ if (hasState(QUEUE_CONGESTED)) {
+ call CtpPacket.setOption(qe->msg, CTP_OPT_ECN);
+ clearState(QUEUE_CONGESTED);
+ }
+
+ subsendResult = call SubSend.send(dest, qe->msg, payloadLen);
+ if (subsendResult == SUCCESS) {
+ // Successfully submitted to the data-link layer.
+ setState(SENDING);
+ dbg("Forwarder", "%s: subsend succeeded with %p.\n", __FUNCTION__, qe->msg);
+ return;
+ }
+ // The packet is too big: truncate it and retry.
+ else if (subsendResult == ESIZE) {
+ dbg("Forwarder", "%s: subsend failed from ESIZE: truncate packet.\n", __FUNCTION__);
+ call Packet.setPayloadLength(qe->msg, call Packet.maxPayloadLength());
+ post sendTask();
+ call CollectionDebug.logEvent(NET_C_FE_SUBSEND_SIZE);
+ }
+ else {
+ dbg("Forwarder", "%s: subsend failed from %i\n", __FUNCTION__, (int)subsendResult);
+ }