diff --git a/examples/simple_repeater/main.cpp b/examples/simple_repeater/main.cpp index ae1beae4..4e0e060a 100644 --- a/examples/simple_repeater/main.cpp +++ b/examples/simple_repeater/main.cpp @@ -246,36 +246,36 @@ protected: return !_prefs.disable_fwd; } - void logRx(mesh::Packet* pkt, float score) override { + void logRx(mesh::Packet* pkt, int len, float score) override { if (_logging) { File f = openAppend(PACKET_LOG_FILE); if (f) { f.print(get_curr_time_str()); f.printf(": RX, len=%d (type=%d, route=%s, payload_len=%d) SNR=%d RSSI=%d score=%d\n", - 2 + pkt->path_len + pkt->payload_len, pkt->getPayloadType(), pkt->isRouteDirect() ? "D" : "F", pkt->payload_len, + len, pkt->getPayloadType(), pkt->isRouteDirect() ? "D" : "F", pkt->payload_len, (int)_radio->getLastSNR(), (int)_radio->getLastRSSI(), (int)(score*1000)); f.close(); } } } - void logTx(mesh::Packet* pkt) override { + void logTx(mesh::Packet* pkt, int len) override { if (_logging) { File f = openAppend(PACKET_LOG_FILE); if (f) { f.print(get_curr_time_str()); f.printf(": TX, len=%d (type=%d, route=%s, payload_len=%d)\n", - 2 + pkt->path_len + pkt->payload_len, pkt->getPayloadType(), pkt->isRouteDirect() ? "D" : "F", pkt->payload_len); + len, pkt->getPayloadType(), pkt->isRouteDirect() ? "D" : "F", pkt->payload_len); f.close(); } } } - void logTxFail(mesh::Packet* pkt) override { + void logTxFail(mesh::Packet* pkt, int len) override { if (_logging) { File f = openAppend(PACKET_LOG_FILE); if (f) { f.print(get_curr_time_str()); f.printf(": TX FAIL!, len=%d (type=%d, route=%s, payload_len=%d)\n", - 2 + pkt->path_len + pkt->payload_len, pkt->getPayloadType(), pkt->isRouteDirect() ? "D" : "F", pkt->payload_len); + len, pkt->getPayloadType(), pkt->isRouteDirect() ? "D" : "F", pkt->payload_len); f.close(); } } diff --git a/src/Dispatcher.cpp b/src/Dispatcher.cpp index 24b6b391..cda3c444 100644 --- a/src/Dispatcher.cpp +++ b/src/Dispatcher.cpp @@ -37,7 +37,7 @@ void Dispatcher::loop() { next_tx_time = futureMillis(t * getAirtimeBudgetFactor()); _radio->onSendFinished(); - logTx(outbound); + logTx(outbound, 2 + outbound->path_len + outbound->payload_len); if (outbound->isRouteFlood()) { n_sent_flood++; } else { @@ -49,7 +49,7 @@ void Dispatcher::loop() { MESH_DEBUG_PRINTLN("Dispatcher::loop(): WARNING: outbound packed send timed out!"); _radio->onSendFinished(); - logTxFail(outbound); + logTxFail(outbound, 2 + outbound->path_len + outbound->payload_len); releasePacket(outbound); // return to pool outbound = NULL; @@ -118,7 +118,7 @@ void Dispatcher::checkRecv() { 2 + pkt->path_len + pkt->payload_len, pkt->getPayloadType(), pkt->isRouteDirect() ? "D" : "F", pkt->payload_len, (int)_radio->getLastSNR(), (int)_radio->getLastRSSI(), (int)(score*1000)); #endif - logRx(pkt, score); // hook for custom logging + logRx(pkt, 2 + pkt->path_len + pkt->payload_len, score); // hook for custom logging if (pkt->isRouteFlood()) { n_recv_flood++; diff --git a/src/Dispatcher.h b/src/Dispatcher.h index de42430b..d77e1f18 100644 --- a/src/Dispatcher.h +++ b/src/Dispatcher.h @@ -117,9 +117,9 @@ protected: virtual DispatcherAction onRecvPacket(Packet* pkt) = 0; - virtual void logRx(Packet* packet, float score) { } // hooks for custom logging - virtual void logTx(Packet* packet) { } - virtual void logTxFail(Packet* packet) { } + virtual void logRx(Packet* packet, int len, float score) { } // hooks for custom logging + virtual void logTx(Packet* packet, int len) { } + virtual void logTxFail(Packet* packet, int len) { } virtual float getAirtimeBudgetFactor() const; virtual int calcRxDelay(float score, uint32_t air_time) const; diff --git a/src/helpers/SimpleMeshTables.h b/src/helpers/SimpleMeshTables.h index 87fd65b8..0dd6032a 100644 --- a/src/helpers/SimpleMeshTables.h +++ b/src/helpers/SimpleMeshTables.h @@ -7,16 +7,21 @@ #endif #define MAX_PACKET_HASHES 128 +#define MAX_PACKET_ACKS 64 class SimpleMeshTables : public mesh::MeshTables { uint8_t _hashes[MAX_PACKET_HASHES*MAX_HASH_SIZE]; int _next_idx; + uint32_t _acks[MAX_PACKET_ACKS]; + int _next_ack_idx; uint32_t _direct_dups, _flood_dups; public: SimpleMeshTables() { memset(_hashes, 0, sizeof(_hashes)); _next_idx = 0; + memset(_acks, 0, sizeof(_acks)); + _next_ack_idx = 0; _direct_dups = _flood_dups = 0; } @@ -24,14 +29,37 @@ public: void restoreFrom(File f) { f.read(_hashes, sizeof(_hashes)); f.read((uint8_t *) &_next_idx, sizeof(_next_idx)); + f.read((uint8_t *) &_acks[0], sizeof(_acks)); + f.read((uint8_t *) &_next_ack_idx, sizeof(_next_ack_idx)); } void saveTo(File f) { f.write(_hashes, sizeof(_hashes)); f.write((const uint8_t *) &_next_idx, sizeof(_next_idx)); + f.write((const uint8_t *) &_acks[0], sizeof(_acks)); + f.write((const uint8_t *) &_next_ack_idx, sizeof(_next_ack_idx)); } #endif bool hasSeen(const mesh::Packet* packet) override { + if (packet->getPayloadType() == PAYLOAD_TYPE_ACK) { + uint32_t ack; + memcpy(&ack, packet->payload, 4); + for (int i = 0; i < MAX_PACKET_ACKS; i++) { + if (ack == _acks[i]) { + if (packet->isRouteDirect()) { + _direct_dups++; // keep some stats + } else { + _flood_dups++; + } + return true; + } + } + + _acks[_next_ack_idx] = ack; + _next_ack_idx = (_next_ack_idx + 1) % MAX_PACKET_ACKS; // cyclic table + return false; + } + uint8_t hash[MAX_HASH_SIZE]; packet->calculatePacketHash(hash); @@ -49,7 +77,6 @@ public: memcpy(&_hashes[_next_idx*MAX_HASH_SIZE], hash, MAX_HASH_SIZE); _next_idx = (_next_idx + 1) % MAX_PACKET_HASHES; // cyclic table - return false; }