Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Next Hop-based routing with fallback to flooding #2856

Open
wants to merge 48 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
0d6729b
Initial version of NextHopRouter
GUVWAF Oct 2, 2023
3776064
Merge branch 'master' into NextHopRouter
thebentern Oct 3, 2023
44dc270
Set original hop limit in header flags
GUVWAF Oct 13, 2023
9b1dd75
Short-circuit to FloodingRouter for broadcasts
GUVWAF Oct 14, 2023
27a492a
If packet traveled 1 hop, set `relay_node` as `next_hop` for the orig…
GUVWAF Oct 14, 2023
c7293cf
Merge branch 'master' into NextHopRouter
caveman99 Oct 31, 2023
42757d8
Merge branch 'master' into NextHopRouter
caveman99 Nov 16, 2023
81f57b6
Merge branch 'master' into NextHopRouter
thebentern Nov 26, 2023
ef2c6ee
Set last byte to 0xFF if it ended at 0x00
GUVWAF Nov 27, 2023
3ba9ecb
Also update next-hop based on received DM for us
GUVWAF Nov 28, 2023
25ec051
Resolve conflicts (needs testing)
GUVWAF Apr 20, 2024
b456e34
Merge branch 'master' into NextHopRouter
caveman99 Apr 23, 2024
d4ef0cd
Merge branch 'master' into NextHopRouter
caveman99 May 3, 2024
b8e01b4
Merge branch 'master' into NextHopRouter
caveman99 Jun 19, 2024
e91dcb4
Merge branch 'master' into NextHopRouter
caveman99 Sep 4, 2024
913268b
temp
GUVWAF Aug 9, 2024
2e303a3
Add 1 retransmission for intermediate hops when using NextHopRouter
GUVWAF Aug 10, 2024
6fe42ed
Add next_hop and relayed_by in PacketHistory for setting next-hop and…
GUVWAF Nov 1, 2024
aae4443
Merge remote-tracking branch 'origin/master' into NextHopRouter
GUVWAF Nov 1, 2024
ba4220f
Update protos, store multiple relayers
GUVWAF Nov 1, 2024
9de8d5a
Remove next-hop update logic from NeighborInfoModule
GUVWAF Nov 1, 2024
0134483
Fix retransmissions
GUVWAF Nov 1, 2024
e4c9818
Improve ACKs for repeated packets and responses
GUVWAF Nov 2, 2024
aab973e
Stop retransmission even if there's not relay node
GUVWAF Nov 2, 2024
28944ad
Merge remote-tracking branch 'origin/master' into NextHopRouter
GUVWAF Nov 5, 2024
790801f
Revert perhapsRebroadcast()
GUVWAF Nov 5, 2024
bb64b14
Remove relayer if we cancel a transmission
GUVWAF Nov 5, 2024
24ff7c0
Better checking for fallback to flooding
GUVWAF Nov 5, 2024
69f88b9
Fix newlines in traceroute print logs
GUVWAF Nov 5, 2024
fbefce7
Merge remote-tracking branch 'origin/master' into NextHopRouter
GUVWAF Nov 8, 2024
70aa28c
Stop retransmission for original packet
GUVWAF Nov 8, 2024
78bf1e1
Use relayID
GUVWAF Nov 8, 2024
f37abe8
Also when want_ack is set, we should try to retransmit
GUVWAF Nov 8, 2024
be73b09
Fix cppcheck error
GUVWAF Nov 8, 2024
71a90b3
Fix 'router' not in scope error
GUVWAF Nov 8, 2024
93bcee3
Fix another cppcheck error
GUVWAF Nov 9, 2024
17495e7
Check for hop_limit and also update next hop when `hop_start == hop_l…
GUVWAF Nov 11, 2024
3725319
Merge remote-tracking branch 'origin/master' into NextHopRouter
GUVWAF Nov 11, 2024
42d17b3
Formatting and correct NUM_RETRANSMISSIONS
GUVWAF Nov 11, 2024
dbe520c
Merge remote-tracking branch 'origin/master' into NextHopRouter
GUVWAF Nov 14, 2024
b229abc
Update protos
GUVWAF Nov 16, 2024
3ea2918
Merge remote-tracking branch 'origin/master' into NextHopRouter
GUVWAF Nov 16, 2024
360637c
Start retransmissions in NextHopRouter if ReliableRouter didn't do it
GUVWAF Nov 16, 2024
bfc6a19
Handle repeated/fallback to flooding packets properly
GUVWAF Nov 16, 2024
98719e4
Merge branch 'master' into NextHopRouter
fifieldt Nov 17, 2024
47116f6
Guard against clients setting `next_hop`/`relay_node`
GUVWAF Nov 18, 2024
6a29793
Merge remote-tracking branch 'origin/master' into NextHopRouter
GUVWAF Nov 18, 2024
e593d54
Merge remote-tracking branch 'origin/master' into NextHopRouter
GUVWAF Nov 19, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -653,9 +653,9 @@ void setup()
// but we need to do this after main cpu init (esp32setup), because we need the random seed set
nodeDB = new NodeDB;

// If we're taking on the repeater role, use flood router and turn off 3V3_S rail because peripherals are not needed
// If we're taking on the repeater role, use NextHopRouter and turn off 3V3_S rail because peripherals are not needed
if (config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER) {
router = new FloodingRouter();
router = new NextHopRouter();
#ifdef PIN_3V3_EN
digitalWrite(PIN_3V3_EN, LOW);
#endif
Expand Down
40 changes: 21 additions & 19 deletions src/mesh/FloodingRouter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,31 +13,25 @@ FloodingRouter::FloodingRouter() {}
ErrorCode FloodingRouter::send(meshtastic_MeshPacket *p)
{
// Add any messages _we_ send to the seen message list (so we will ignore all retransmissions we see)
wasSeenRecently(p); // FIXME, move this to a sniffSent method
p->relay_node = nodeDB->getLastByteOfNodeNum(getNodeNum()); // First set the relayer to us
wasSeenRecently(p); // FIXME, move this to a sniffSent method

return Router::send(p);
}

bool FloodingRouter::shouldFilterReceived(const meshtastic_MeshPacket *p)
{
if (wasSeenRecently(p)) { // Note: this will also add a recent packet record
printPacket("Ignore dupe incoming msg", p);
rxDupe++;
if (config.device.role != meshtastic_Config_DeviceConfig_Role_ROUTER &&
config.device.role != meshtastic_Config_DeviceConfig_Role_REPEATER) {
// cancel rebroadcast of this message *if* there was already one, unless we're a router/repeater!
if (Router::cancelSending(p->from, p->id))
txRelayCanceled++;
}

/* If the original transmitter is doing retransmissions (hopStart equals hopLimit) for a reliable transmission, e.g., when
the ACK got lost, we will handle the packet again to make sure it gets an ACK to its packet. */
the ACK got lost, we will handle the packet again to make sure it gets an implicit ACK. */
bool isRepeated = p->hop_start > 0 && p->hop_start == p->hop_limit;
if (isRepeated) {
LOG_DEBUG("Repeated reliable tx");
if (!perhapsRebroadcast(p) && isToUs(p) && p->want_ack) {
sendAckNak(meshtastic_Routing_Error_NONE, getFrom(p), p->id, p->channel, 0);
}
// Check if it's still in the Tx queue, if not, we have to relay it again
if (!findInTxQueue(p->from, p->id))
perhapsRebroadcast(p);
} else {
perhapsCancelDupe(p);
}

return true;
Expand All @@ -46,13 +40,25 @@ bool FloodingRouter::shouldFilterReceived(const meshtastic_MeshPacket *p)
return Router::shouldFilterReceived(p);
}

void FloodingRouter::perhapsCancelDupe(const meshtastic_MeshPacket *p)
{
printPacket("Ignore dupe incoming msg", p);
rxDupe++;
if (config.device.role != meshtastic_Config_DeviceConfig_Role_ROUTER &&
config.device.role != meshtastic_Config_DeviceConfig_Role_REPEATER) {
// cancel rebroadcast of this message *if* there was already one, unless we're a router/repeater!
if (Router::cancelSending(p->from, p->id))
txRelayCanceled++;
}
}

bool FloodingRouter::isRebroadcaster()
{
return config.device.role != meshtastic_Config_DeviceConfig_Role_CLIENT_MUTE &&
config.device.rebroadcast_mode != meshtastic_Config_DeviceConfig_RebroadcastMode_NONE;
}

bool FloodingRouter::perhapsRebroadcast(const meshtastic_MeshPacket *p)
void FloodingRouter::perhapsRebroadcast(const meshtastic_MeshPacket *p)
{
if (!isToUs(p) && (p->hop_limit > 0) && !isFromUs(p)) {
if (p->id != 0) {
Expand All @@ -72,17 +78,13 @@ bool FloodingRouter::perhapsRebroadcast(const meshtastic_MeshPacket *p)
// Note: we are careful to resend using the original senders node id
// We are careful not to call our hooked version of send() - because we don't want to check this again
Router::send(tosend);

return true;
} else {
LOG_DEBUG("No rebroadcast: Role = CLIENT_MUTE or Rebroadcast Mode = NONE");
}
} else {
LOG_DEBUG("Ignore 0 id broadcast");
}
}

return false;
}

void FloodingRouter::sniffReceived(const meshtastic_MeshPacket *p, const meshtastic_Routing *c)
Expand Down
16 changes: 9 additions & 7 deletions src/mesh/FloodingRouter.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#pragma once

#include "PacketHistory.h"
#include "Router.h"

/**
Expand All @@ -26,14 +25,11 @@
Any entries in recentBroadcasts that are older than X seconds (longer than the
max time a flood can take) will be discarded.
*/
class FloodingRouter : public Router, protected PacketHistory
class FloodingRouter : public Router
{
private:
bool isRebroadcaster();

/** Check if we should rebroadcast this packet, and do so if needed
* @return true if rebroadcasted */
bool perhapsRebroadcast(const meshtastic_MeshPacket *p);
/* Check if we should rebroadcast this packet, and do so if needed */
void perhapsRebroadcast(const meshtastic_MeshPacket *p);

public:
/**
Expand Down Expand Up @@ -62,4 +58,10 @@ class FloodingRouter : public Router, protected PacketHistory
* Look for broadcasts we need to rebroadcast
*/
virtual void sniffReceived(const meshtastic_MeshPacket *p, const meshtastic_Routing *c) override;

/* Call when receiving a duplicate packet to check whether we should cancel a packet in the Tx queue */
void perhapsCancelDupe(const meshtastic_MeshPacket *p);

// Return true if we are a rebroadcaster
bool isRebroadcaster();
};
13 changes: 13 additions & 0 deletions src/mesh/MeshPacketQueue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,19 @@ meshtastic_MeshPacket *MeshPacketQueue::remove(NodeNum from, PacketId id)
return NULL;
}

/* Attempt to find a packet from this queue. Return true if it was found. */
bool MeshPacketQueue::find(NodeNum from, PacketId id)
{
for (auto it = queue.begin(); it != queue.end(); it++) {
auto p = (*it);
if (getFrom(p) == from && p->id == id) {
return true;
}
}

return false;
}

/** Attempt to find and remove a packet from this queue. Returns the packet which was removed from the queue */
bool MeshPacketQueue::replaceLowerPriorityPacket(meshtastic_MeshPacket *p)
{
Expand Down
5 changes: 4 additions & 1 deletion src/mesh/MeshPacketQueue.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,7 @@ class MeshPacketQueue

/** Attempt to find and remove a packet from this queue. Returns the packet which was removed from the queue */
meshtastic_MeshPacket *remove(NodeNum from, PacketId id);
};

/* Attempt to find a packet from this queue. Return true if it was found. */
bool find(NodeNum from, PacketId id);
};
4 changes: 3 additions & 1 deletion src/mesh/MeshService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,9 @@ void MeshService::handleToRadio(meshtastic_MeshPacket &p)
return;
}
#endif
p.from = 0; // We don't let phones assign nodenums to their sent messages
p.from = 0; // We don't let clients assign nodenums to their sent messages
p.next_hop = NO_NEXT_HOP_PREFERENCE; // We don't let clients assign next_hop to their sent messages
p.relay_node = NO_RELAY_NODE; // We don't let clients assign relay_node to their sent messages

if (p.id == 0)
p.id = generatePacketId(); // If the phone didn't supply one, then pick one
Expand Down
5 changes: 5 additions & 0 deletions src/mesh/MeshTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ enum RxSource {
/// We normally just use max 3 hops for sending reliable messages
#define HOP_RELIABLE 3

// For old firmware or when falling back to flooding, there is no next-hop preference
#define NO_NEXT_HOP_PREFERENCE 0
// For old firmware there is no relay node set
#define NO_RELAY_NODE 0

typedef int ErrorCode;

/// Alloc and free packets to our global, ISR safe pool
Expand Down
Loading