Răsfoiți Sursa

* CommonCLI: new "multi.acks" config setting

Scott Powell 1 an în urmă
părinte
comite
6bc8dd28d4

+ 3 - 0
examples/simple_repeater/main.cpp

@@ -339,6 +339,9 @@ protected:
   int getAGCResetInterval() const override {
     return ((int)_prefs.agc_reset_interval) * 4000;   // milliseconds
   }
+  uint8_t getExtraAckTransmitCount() const override {
+    return _prefs.multi_acks;
+  }
 
   void onAnonDataRecv(mesh::Packet* packet, const uint8_t* secret, const mesh::Identity& sender, uint8_t* data, size_t len) override {
     if (packet->getPayloadType() == PAYLOAD_TYPE_ANON_REQ) {  // received an initial request by a possible admin client (unknown at this stage)

+ 11 - 4
examples/simple_room_server/main.cpp

@@ -424,6 +424,9 @@ protected:
   int getAGCResetInterval() const override {
     return ((int)_prefs.agc_reset_interval) * 4000;   // milliseconds
   }
+  uint8_t getExtraAckTransmitCount() const override {
+    return _prefs.multi_acks;
+  }
 
   bool allowPacketForward(const mesh::Packet* packet) override {
     if (_prefs.disable_fwd) return false;
@@ -583,12 +586,16 @@ protected:
             if (ack) sendFlood(ack, TXT_ACK_DELAY);
             delay_millis = TXT_ACK_DELAY + REPLY_DELAY_MILLIS;
           } else {
-            mesh::Packet* a1 = createMultiAck(ack_hash, 1);
-            if (a1) sendDirect(a1, client->out_path, client->out_path_len, TXT_ACK_DELAY);
+            uint32_t d = TXT_ACK_DELAY;
+            if (getExtraAckTransmitCount() > 0) {
+              mesh::Packet* a1 = createMultiAck(ack_hash, 1);
+              if (a1) sendDirect(a1, client->out_path, client->out_path_len, d);
+              d += 300;
+            }
 
             mesh::Packet* a2 = createAck(ack_hash);
-            if (a2) sendDirect(a2, client->out_path, client->out_path_len, TXT_ACK_DELAY + 300);
-            delay_millis = TXT_ACK_DELAY + REPLY_DELAY_MILLIS + 300;
+            if (a2) sendDirect(a2, client->out_path, client->out_path_len, d);
+            delay_millis = d + REPLY_DELAY_MILLIS;
           }
         } else {
           delay_millis = 0;

+ 15 - 42
src/Mesh.cpp

@@ -22,6 +22,9 @@ uint32_t Mesh::getRetransmitDelay(const mesh::Packet* packet) {
 uint32_t Mesh::getDirectRetransmitDelay(const Packet* packet) {
   return 0;  // by default, no delay
 }
+uint8_t Mesh::getExtraAckTransmitCount() const {
+  return 0;
+}
 
 uint32_t Mesh::getCADFailRetryDelay() const {
   return _rng->nextInt(1, 4)*120;
@@ -99,7 +102,6 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) {
       } else if (!_tables->hasSeen(pkt)) {
         onAckRecv(pkt, ack_crc);
         action = routeRecvPacket(pkt);
-        // routeRecvAcks(pkt, 0);  // experimental, double Acks in flood mode(?)
       }
       break;
     }
@@ -280,7 +282,6 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) {
             memcpy(&ack_crc, tmp.payload, 4);
 
             onAckRecv(&tmp, ack_crc);
-            // routeRecvAcks(&tmp, ((uint32_t)remaining) * 600);  // expect multipart ACK 300ms apart (x2)
             //action = routeRecvPacket(&tmp);  // NOTE: currently not needed, as multipart ACKs not sent Flood
           }
         } else {
@@ -324,37 +325,6 @@ DispatcherAction Mesh::routeRecvPacket(Packet* packet) {
   return ACTION_RELEASE;
 }
 
-#if 0
-void Mesh::routeRecvAcks(Packet* packet, uint32_t delay_millis) {
-  if (packet->isRouteFlood() && !packet->isMarkedDoNotRetransmit()
-    && packet->path_len + PATH_HASH_SIZE <= MAX_PATH_SIZE && allowPacketForward(packet)) {
-    // append this node's hash to 'path'
-    packet->path_len += self_id.copyHashTo(&packet->path[packet->path_len]);
-
-    uint32_t crc;
-    memcpy(&crc, packet->payload, 4);
-
-    delay_millis += getRetransmitDelay(packet);
-    auto a1 = createMultiAck(crc, 1);
-    if (a1) {
-      memcpy(a1->path, packet->path, a1->path_len = packet->path_len);
-      a1->header &= ~PH_ROUTE_MASK;
-      a1->header |= ROUTE_TYPE_FLOOD;
-      sendPacket(a1, 1, delay_millis);
-    }
-
-    delay_millis += 300;
-    auto a2 = createAck(crc);
-    if (a2) {
-      memcpy(a2->path, packet->path, a2->path_len = packet->path_len);
-      a2->header &= ~PH_ROUTE_MASK;
-      a2->header |= ROUTE_TYPE_FLOOD;
-      sendPacket(a2, 1, delay_millis);
-    }
-  }
-}
-#endif
-
 DispatcherAction Mesh::forwardMultipartDirect(Packet* pkt) {
   uint8_t remaining = pkt->payload[0] >> 4;  // num of packets in this multipart sequence still to be sent
   uint8_t type = pkt->payload[0] & 0x0F;
@@ -369,7 +339,7 @@ DispatcherAction Mesh::forwardMultipartDirect(Packet* pkt) {
 
     if (!_tables->hasSeen(&tmp)) {   // don't retransmit!
       removeSelfFromPath(&tmp);
-      routeDirectRecvAcks(&tmp, ((uint32_t)remaining) * 600);  // expect multipart ACKs 300ms apart (x2)
+      routeDirectRecvAcks(&tmp, ((uint32_t)remaining + 1) * 300);  // expect multipart ACKs 300ms apart (x2)
     }
   }
   return ACTION_RELEASE;
@@ -380,16 +350,19 @@ void Mesh::routeDirectRecvAcks(Packet* packet, uint32_t delay_millis) {
     uint32_t crc;
     memcpy(&crc, packet->payload, 4);
 
-    delay_millis += getDirectRetransmitDelay(packet);
-    auto a1 = createMultiAck(crc, 1);
-    if (a1) {
-      memcpy(a1->path, packet->path, a1->path_len = packet->path_len);
-      a1->header &= ~PH_ROUTE_MASK;
-      a1->header |= ROUTE_TYPE_DIRECT;
-      sendPacket(a1, 0, delay_millis);
+    uint8_t extra = getExtraAckTransmitCount();
+    while (extra > 0) {
+      delay_millis += getDirectRetransmitDelay(packet) + 300;
+      auto a1 = createMultiAck(crc, extra);
+      if (a1) {
+        memcpy(a1->path, packet->path, a1->path_len = packet->path_len);
+        a1->header &= ~PH_ROUTE_MASK;
+        a1->header |= ROUTE_TYPE_DIRECT;
+        sendPacket(a1, 0, delay_millis);
+      }
+      extra--;
     }
 
-    delay_millis += 300;
     auto a2 = createAck(crc);
     if (a2) {
       memcpy(a2->path, packet->path, a2->path_len = packet->path_len);

+ 5 - 0
src/Mesh.h

@@ -59,6 +59,11 @@ protected:
    */
   virtual uint32_t getDirectRetransmitDelay(const Packet* packet);
 
+  /**
+   * \returns  number of extra (Direct) ACK transmissions wanted.
+   */
+  virtual uint8_t getExtraAckTransmitCount() const;
+
   /**
    * \brief  Perform search of local DB of peers/contacts.
    * \returns  Number of peers with matching hash

+ 9 - 2
src/helpers/CommonCLI.cpp

@@ -51,7 +51,7 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) {
     file.read((uint8_t *) &_prefs->sf, sizeof(_prefs->sf));  // 112
     file.read((uint8_t *) &_prefs->cr, sizeof(_prefs->cr));  // 113
     file.read((uint8_t *) &_prefs->allow_read_only, sizeof(_prefs->allow_read_only));  // 114
-    file.read((uint8_t *) &_prefs->reserved2, sizeof(_prefs->reserved2));  // 115
+    file.read((uint8_t *) &_prefs->multi_acks, sizeof(_prefs->multi_acks));  // 115
     file.read((uint8_t *) &_prefs->bw, sizeof(_prefs->bw));  // 116
     file.read((uint8_t *) &_prefs->agc_reset_interval, sizeof(_prefs->agc_reset_interval));  // 120
     file.read(pad, 3);   // 121
@@ -69,6 +69,7 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) {
     _prefs->sf = constrain(_prefs->sf, 7, 12);
     _prefs->cr = constrain(_prefs->cr, 5, 8);
     _prefs->tx_power_dbm = constrain(_prefs->tx_power_dbm, 1, 30);
+    _prefs->multi_acks = constrain(_prefs->multi_acks, 0, 1);
 
     file.close();
   }
@@ -106,7 +107,7 @@ void CommonCLI::savePrefs(FILESYSTEM* fs) {
     file.write((uint8_t *) &_prefs->sf, sizeof(_prefs->sf));  // 112
     file.write((uint8_t *) &_prefs->cr, sizeof(_prefs->cr));  // 113
     file.write((uint8_t *) &_prefs->allow_read_only, sizeof(_prefs->allow_read_only));  // 114
-    file.write((uint8_t *) &_prefs->reserved2, sizeof(_prefs->reserved2));  // 115
+    file.write((uint8_t *) &_prefs->multi_acks, sizeof(_prefs->multi_acks));  // 115
     file.write((uint8_t *) &_prefs->bw, sizeof(_prefs->bw));  // 116
     file.write((uint8_t *) &_prefs->agc_reset_interval, sizeof(_prefs->agc_reset_interval));  // 120
     file.write(pad, 3);   // 121
@@ -180,6 +181,8 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
         sprintf(reply, "> %d", (uint32_t) _prefs->interference_threshold);
       } else if (memcmp(config, "agc.reset.interval", 18) == 0) {
         sprintf(reply, "> %d", ((uint32_t) _prefs->agc_reset_interval) * 4);
+      } else if (memcmp(config, "multi.acks", 10) == 0) {
+        sprintf(reply, "> %d", (uint32_t) _prefs->multi_acks);
       } else if (memcmp(config, "allow.read.only", 15) == 0) {
         sprintf(reply, "> %s", _prefs->allow_read_only ? "on" : "off");
       } else if (memcmp(config, "flood.advert.interval", 21) == 0) {
@@ -235,6 +238,10 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
         _prefs->agc_reset_interval = atoi(&config[19]) / 4;
         savePrefs();
         strcpy(reply, "OK");
+      } else if (memcmp(config, "multi.acks ", 11) == 0) {
+        _prefs->multi_acks = atoi(&config[11]);
+        savePrefs();
+        strcpy(reply, "OK");
       } else if (memcmp(config, "allow.read.only ", 16) == 0) {
         _prefs->allow_read_only = memcmp(&config[16], "on", 2) == 0;
         savePrefs();

+ 1 - 1
src/helpers/CommonCLI.h

@@ -21,7 +21,7 @@ struct NodePrefs {  // persisted to file
     uint8_t sf;
     uint8_t cr;
     uint8_t allow_read_only;
-    uint8_t reserved2;
+    uint8_t multi_acks;
     float bw;
     uint8_t flood_max;
     uint8_t interference_threshold;