forwardingenginep.nc
来自「tinyos-2.0源代码!转载而已!要的尽管拿!」· NC 代码 · 共 861 行 · 第 1/3 页
NC
861 行
fe_queue_entry_t *qe; dbg("Forwarder", "%s: sending packet from client %hhu: %x, len %hhu\n", __FUNCTION__, client, msg, len); if (!running) {return EOFF;} if (len > call Send.maxPayloadLength[client]()) {return ESIZE;} call Packet.setPayloadLength(msg, len); hdr = getHeader(msg); hdr->origin = TOS_NODE_ID; hdr->seqno = seqno++; hdr->collectid = call CollectionId.fetch[client](); if (clientPtrs[client] == NULL) { dbg("Forwarder", "%s: send failed as client is busy.\n", __FUNCTION__); return EBUSY; } qe = clientPtrs[client]; qe->msg = msg; qe->client = client; qe->retries = MAX_RETRIES; dbg("Forwarder", "%s: queue entry for %hhu is %hhu deep\n", __FUNCTION__, client, call SendQueue.size()); if (call SendQueue.enqueue(qe) == SUCCESS) { if (radioOn && !call RetxmitTimer.isRunning()) { post sendTask(); } clientPtrs[client] = NULL; return SUCCESS; } else { dbg("Forwarder", "%s: send failed as packet could not be enqueued.\n", __FUNCTION__); // send a debug message to the uart call CollectionDebug.logEvent(NET_C_FE_SEND_QUEUE_FULL); // Return the pool entry, as it's not for me... return FAIL; } } command error_t Send.cancel[uint8_t client](message_t* msg) { // cancel not implemented. will require being able // to pull entries out of the queue. return FAIL; } command uint8_t Send.maxPayloadLength[uint8_t client]() { return call Packet.maxPayloadLength(); } command void* Send.getPayload[uint8_t client](message_t* msg) { return call Packet.getPayload(msg, NULL); } /* * These is where all of the send logic is. When the ForwardingEngine * wants to send a packet, it posts this task. The send logic is * independent of whether it is a forwarded packet or a packet from * a send client. * * The task first checks that there is a packet to send and that * there is a valid route. It then marshals the relevant arguments * and prepares the packet for sending. If the node is a collection * root, it signals Receive with the loopback message. Otherwise, * it sets the packet to be acknowledged and sends it. It does not * remove the packet from the send queue: while sending, the * packet being sent is at the head of the queue; a packet is dequeued * in the sendDone handler, either due to retransmission failure * or to a successful send. */ task void sendTask() { dbg("Forwarder", "%s: Trying to send a packet. Queue size is %hhu.\n", __FUNCTION__, call SendQueue.size()); if (sending) { dbg("Forwarder", "%s: busy, don't send\n", __FUNCTION__); call CollectionDebug.logEvent(NET_C_FE_SEND_BUSY); return; } else if (call SendQueue.empty()) { dbg("Forwarder", "%s: queue empty, don't send\n", __FUNCTION__); call CollectionDebug.logEvent(NET_C_FE_SENDQUEUE_EMPTY); return; } else if (!call RootControl.isRoot() && !call UnicastNameFreeRouting.hasRoute()) { dbg("Forwarder", "%s: no route, don't send, start retry timer\n", __FUNCTION__); call RetxmitTimer.startOneShot(10000); // send a debug message to the uart call CollectionDebug.logEvent(NET_C_FE_NO_ROUTE); return; } else { error_t subsendResult; fe_queue_entry_t* qe = call SendQueue.head(); uint8_t payloadLen = call SubPacket.payloadLength(qe->msg); am_addr_t dest = call UnicastNameFreeRouting.nextHop(); uint32_t msg_uid = call CollectionPacket.getPacketID(qe->msg); uint16_t gradient; if (call SentCache.lookup(msg_uid)) { call CollectionDebug.logEvent(NET_C_FE_DUPLICATE_CACHE_AT_SEND); call SendQueue.dequeue(); post sendTask(); return; } /* If our current parent is not the same as the last parent we sent do, then reset the count of unacked packets: don't penalize a new parent for the failures of a prior one.*/ if (dest != lastParent) { qe->retries = MAX_RETRIES; lastParent = dest; } dbg("Forwarder", "Sending queue entry %p\n", qe); if (call RootControl.isRoot()) { collection_id_t collectid = getHeader(qe->msg)->collectid; memcpy(loopbackMsgPtr, qe->msg, sizeof(message_t)); ackPending = FALSE; dbg("Forwarder", "%s: I'm a root, so loopback and signal receive.\n", __FUNCTION__); loopbackMsgPtr = signal Receive.receive[collectid](loopbackMsgPtr, call Packet.getPayload(loopbackMsgPtr, NULL), call Packet.payloadLength(loopbackMsgPtr)); signal SubSend.sendDone(qe->msg, SUCCESS); return; } // Loop-detection functionality: if (call TreeRoutingInspect.getMetric(&gradient) != SUCCESS) { // If we have no metric, set our gradient conservatively so // that other nodes don't automatically drop our packets. gradient = 0; } call CollectionPacket.setGradient(qe->msg, gradient); ackPending = (call PacketAcknowledgements.requestAck(qe->msg) == SUCCESS); 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); } } } void sendDoneBug() { // send a debug message to the uart call CollectionDebug.logEvent(NET_C_FE_BAD_SENDDONE); } /* * The second phase of a send operation; based on whether the transmission was * successful, the ForwardingEngine either stops sending or starts the * RetxmitTimer with an interval based on what has occured. If the send was * successful or the maximum number of retransmissions has been reached, then * the ForwardingEngine dequeues the current packet. If the packet is from a * client it signals Send.sendDone(); if it is a forwarded packet it returns * the packet and queue entry to their respective pools. * */ event void SubSend.sendDone(message_t* msg, error_t error) { fe_queue_entry_t *qe = call SendQueue.head(); dbg("Forwarder", "%s to %hu and %hhu\n", __FUNCTION__, call AMPacket.destination(msg), error); if (qe == NULL || qe->msg != msg) { dbg("Forwarder", "%s: BUG: not our packet (%p != %p)!\n", __FUNCTION__, msg, qe->msg); sendDoneBug(); // Not our packet, something is very wrong... return; } else if (error != SUCCESS) { // Immediate retransmission is the worst thing to do. dbg("Forwarder", "%s: send failed\n", __FUNCTION__); call CollectionDebug.logEventRoute(NET_C_FE_SENDDONE_FAIL, call CollectionPacket.getSequenceNumber(msg), call CollectionPacket.getOrigin(msg), call AMPacket.destination(msg)); startRetxmitTimer(SENDDONE_FAIL_WINDOW, SENDDONE_FAIL_OFFSET); } else if (ackPending && !call PacketAcknowledgements.wasAcked(msg)) { // AckPending is for case when DL cannot support acks. if (--qe->retries) { dbg("Forwarder", "%s: not acked\n", __FUNCTION__); call CollectionDebug.logEventRoute(NET_C_FE_SENDDONE_WAITACK, call CollectionPacket.getSequenceNumber(msg), call CollectionPacket.getOrigin(msg), call AMPacket.destination(msg)); startRetxmitTimer(SENDDONE_NOACK_WINDOW, SENDDONE_NOACK_OFFSET); } else { //max retries, dropping packet if (qe->client < CLIENT_COUNT) { clientPtrs[qe->client] = qe; signal Send.sendDone[qe->client](msg, FAIL); call CollectionDebug.logEventRoute(NET_C_FE_SENDDONE_FAIL_ACK_SEND, call CollectionPacket.getSequenceNumber(msg), call CollectionPacket.getOrigin(msg), call AMPacket.destination(msg)); } else { if (call MessagePool.put(qe->msg) != SUCCESS) call CollectionDebug.logEvent(NET_C_FE_PUT_MSGPOOL_ERR); if (call QEntryPool.put(qe) != SUCCESS) call CollectionDebug.logEvent(NET_C_FE_PUT_QEPOOL_ERR); call CollectionDebug.logEventRoute(NET_C_FE_SENDDONE_FAIL_ACK_FWD, call CollectionPacket.getSequenceNumber(msg), call CollectionPacket.getOrigin(msg), call AMPacket.destination(msg)); } call SendQueue.dequeue(); sending = FALSE; startRetxmitTimer(SENDDONE_OK_WINDOW, SENDDONE_OK_OFFSET); } } else if (qe->client < CLIENT_COUNT) { network_header_t* hdr; uint8_t client = qe->client; dbg("Forwarder", "%s: our packet for client %hhu, remove %p from queue\n", __FUNCTION__, client, qe); call CollectionDebug.logEventRoute(NET_C_FE_SENT_MSG, call CollectionPacket.getSequenceNumber(msg), call CollectionPacket.getOrigin(msg), call AMPacket.destination(msg)); clientPtrs[client] = qe; hdr = getHeader(qe->msg); call SendQueue.dequeue(); signal Send.sendDone[client](msg, SUCCESS); sending = FALSE; startRetxmitTimer(SENDDONE_OK_WINDOW, SENDDONE_OK_OFFSET); } else if (call MessagePool.size() < call MessagePool.maxSize()) { // A successfully forwarded packet. dbg("Forwarder,Route", "%s: successfully forwarded packet (client: %hhu), message pool is %hhu/%hhu.\n", __FUNCTION__, qe->client, call MessagePool.size(), call MessagePool.maxSize()); call CollectionDebug.logEventRoute(NET_C_FE_FWD_MSG, call CollectionPacket.getSequenceNumber(msg), call CollectionPacket.getOrigin(msg), call AMPacket.destination(msg)); call SentCache.insert(call CollectionPacket.getPacketID(qe->msg)); call SendQueue.dequeue(); if (call MessagePool.put(qe->msg) != SUCCESS) call CollectionDebug.logEvent(NET_C_FE_PUT_MSGPOOL_ERR); if (call QEntryPool.put(qe) != SUCCESS) call CollectionDebug.logEvent(NET_C_FE_PUT_QEPOOL_ERR); sending = FALSE; startRetxmitTimer(SENDDONE_OK_WINDOW, SENDDONE_OK_OFFSET); } else { dbg("Forwarder", "%s: BUG: we have a pool entry, but the pool is full, client is %hhu.\n", __FUNCTION__, qe->client); sendDoneBug(); // It's a forwarded packet, but there's no room the pool; // someone has double-stored a pointer somewhere and we have nowhere // to put this, so we have to leak it... } }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?