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 + -
显示快捷键?