mirror of
https://github.com/meshtastic/firmware.git
synced 2025-04-24 01:16:55 +00:00
Use the hop_limit field of MeshPacket to limit max delivery depth in
the mesh.
This commit is contained in:
parent
53c3d9baa2
commit
26d3ef529e
@ -1,12 +1,10 @@
|
||||
# Mesh broadcast algorithm
|
||||
|
||||
FIXME - instead look for standard solutions. this approach seems really suboptimal, because too many nodes will try to rebroast. If
|
||||
all else fails could always use the stock Radiohead solution - though super inefficient.
|
||||
|
||||
great source of papers and class notes: http://www.cs.jhu.edu/~cs647/
|
||||
|
||||
reliable messaging tasks (stage one for DSR):
|
||||
|
||||
- fix FIXME - should snoop packet not sent to us
|
||||
- add a 'messagePeek' hook for all messages that pass through our node.
|
||||
- DONE use the same 'recentmessages' array used for broadcast msgs to detect duplicate retransmitted messages.
|
||||
- keep possible retries in the list with to be rebroadcast messages?
|
||||
@ -14,7 +12,6 @@ reliable messaging tasks (stage one for DSR):
|
||||
- delay some random time for each retry (large enough to allow for acks to come in)
|
||||
- once an ack comes in, remove the packet from the retry list and deliver the ack to the original sender
|
||||
- after three retries, deliver a no-ack packet to the original sender (i.e. the phone app or mesh router service)
|
||||
- add a max hops parameter, use it for broadcast as well (0 means adjacent only, 1 is one forward etc...). Store as three bits in the header.
|
||||
|
||||
dsr tasks
|
||||
|
||||
@ -55,6 +52,8 @@ when we receive a routeError packet
|
||||
|
||||
TODO:
|
||||
|
||||
- optimize our generalized flooding with heuristics, possibly have particular nodes self mark as 'router' nodes.
|
||||
|
||||
- DONE reread the radiohead mesh implementation - hop to hop acknowledgement seems VERY expensive but otherwise it seems like DSR
|
||||
- DONE read about mesh routing solutions (DSR and AODV)
|
||||
- DONE read about general mesh flooding solutions (naive, MPR, geo assisted)
|
||||
@ -62,6 +61,7 @@ TODO:
|
||||
- REJECTED - seems dying - possibly dash7? https://www.slideshare.net/MaartenWeyn1/dash7-alliance-protocol-technical-presentation https://github.com/MOSAIC-LoPoW/dash7-ap-open-source-stack - does the opensource stack implement multihop routing? flooding? their discussion mailing list looks dead-dead
|
||||
- update duty cycle spreadsheet for our typical usecase
|
||||
- DONE generalize naive flooding
|
||||
- DONE add a max hops parameter, use it for broadcast as well (0 means adjacent only, 1 is one forward etc...). Store as three bits in the header.
|
||||
|
||||
a description of DSR: https://tools.ietf.org/html/rfc4728 good slides here: https://www.slideshare.net/ashrafmath/dynamic-source-routing
|
||||
good description of batman protocol: https://www.open-mesh.org/projects/open-mesh/wiki/BATMANConcept
|
||||
|
2
proto
2
proto
@ -1 +1 @@
|
||||
Subproject commit bc3ecd97e381b724c1a28acce0d12c688de73ba3
|
||||
Subproject commit 5799cb10b8f3cf353e7791d0609002cc93d9d13d
|
@ -2,8 +2,6 @@
|
||||
#include "configuration.h"
|
||||
#include "mesh-pb-constants.h"
|
||||
|
||||
static bool supportFlooding = true; // Sometimes to simplify debugging we want jusT simple broadcast only
|
||||
|
||||
FloodingRouter::FloodingRouter() : toResend(MAX_NUM_NODES) {}
|
||||
|
||||
/**
|
||||
@ -13,9 +11,7 @@ FloodingRouter::FloodingRouter() : toResend(MAX_NUM_NODES) {}
|
||||
*/
|
||||
ErrorCode FloodingRouter::send(MeshPacket *p)
|
||||
{
|
||||
// We update our table of recent broadcasts, even for messages we send
|
||||
if (supportFlooding)
|
||||
wasSeenRecently(p);
|
||||
wasSeenRecently(p);
|
||||
|
||||
return Router::send(p);
|
||||
}
|
||||
@ -29,28 +25,28 @@ ErrorCode FloodingRouter::send(MeshPacket *p)
|
||||
*/
|
||||
void FloodingRouter::handleReceived(MeshPacket *p)
|
||||
{
|
||||
if (supportFlooding) {
|
||||
if (wasSeenRecently(p)) {
|
||||
DEBUG_MSG("Ignoring incoming floodmsg, because we've already seen it\n");
|
||||
packetPool.release(p);
|
||||
} else {
|
||||
if (p->to == NODENUM_BROADCAST) {
|
||||
if (p->id != 0) {
|
||||
MeshPacket *tosend = packetPool.allocCopy(*p); // keep a copy because we will be sending it
|
||||
if (wasSeenRecently(p)) {
|
||||
DEBUG_MSG("Ignoring incoming msg, because we've already seen it\n");
|
||||
packetPool.release(p);
|
||||
} else {
|
||||
if (p->to == NODENUM_BROADCAST && p->hop_limit > 0) {
|
||||
if (p->id != 0) {
|
||||
MeshPacket *tosend = packetPool.allocCopy(*p); // keep a copy because we will be sending it
|
||||
|
||||
DEBUG_MSG("Rebroadcasting received floodmsg to neighbors, fr=0x%x,to=0x%x,id=%d\n", p->from, p->to, p->id);
|
||||
// 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);
|
||||
tosend->hop_limit--; // bump down the hop count
|
||||
|
||||
} else {
|
||||
DEBUG_MSG("Ignoring a simple (0 hop) broadcast\n");
|
||||
}
|
||||
DEBUG_MSG("Rebroadcasting received floodmsg to neighbors, fr=0x%x,to=0x%x,id=%d,hop_limit=%d\n", p->from, p->to,
|
||||
p->id, tosend->hop_limit);
|
||||
// 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);
|
||||
|
||||
} else {
|
||||
DEBUG_MSG("Ignoring a simple (0 id) broadcast\n");
|
||||
}
|
||||
|
||||
// handle the packet as normal
|
||||
Router::handleReceived(p);
|
||||
}
|
||||
} else
|
||||
|
||||
// handle the packet as normal
|
||||
Router::handleReceived(p);
|
||||
}
|
||||
}
|
||||
|
@ -285,6 +285,7 @@ MeshPacket *MeshService::allocForSending()
|
||||
p->which_payload = MeshPacket_decoded_tag; // Assume payload is decoded at start.
|
||||
p->from = nodeDB.getNodeNum();
|
||||
p->to = NODENUM_BROADCAST;
|
||||
p->hop_limit = HOP_MAX;
|
||||
p->id = generatePacketId();
|
||||
p->rx_time = getValidTime(); // Just in case we process the packet locally - make sure it has a valid timestamp
|
||||
|
||||
|
@ -14,6 +14,15 @@ typedef uint8_t PacketId; // A packet sequence number
|
||||
#define ERRNO_NO_INTERFACES 33
|
||||
#define ERRNO_UNKNOWN 32 // pick something that doesn't conflict with RH_ROUTER_ERROR_UNABLE_TO_DELIVER
|
||||
|
||||
/**
|
||||
* the max number of hops a message can pass through, used as the default max for hop_limit in MeshPacket.
|
||||
*
|
||||
* We reserve 3 bits in the header so this could be up to 7, but given the high range of lora and typical usecases, keeping
|
||||
* maxhops to 3 should be fine for a while. This also serves to prevent routing/flooding attempts to be attempted for
|
||||
* too long.
|
||||
**/
|
||||
#define HOP_MAX 3
|
||||
|
||||
typedef int ErrorCode;
|
||||
|
||||
/// Alloc and free packets to our global, ISR safe pool
|
||||
|
@ -115,8 +115,9 @@ size_t RadioInterface::beginSending(MeshPacket *p)
|
||||
|
||||
h->from = p->from;
|
||||
h->to = p->to;
|
||||
h->flags = 0;
|
||||
h->id = p->id;
|
||||
assert(p->hop_limit <= HOP_MAX);
|
||||
h->flags = p->hop_limit;
|
||||
|
||||
// if the sender nodenum is zero, that means uninitialized
|
||||
assert(h->from);
|
||||
|
@ -16,7 +16,14 @@
|
||||
* wtih the old radiohead implementation.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t to, from, id, flags;
|
||||
uint8_t to, from, id;
|
||||
|
||||
/**
|
||||
* Usage of flags:
|
||||
*
|
||||
* The bottom three bits of flags are use to store hop_limit when sent over the wire.
|
||||
**/
|
||||
uint8_t flags;
|
||||
} PacketHeader;
|
||||
|
||||
typedef enum {
|
||||
|
@ -288,13 +288,16 @@ void RadioLibInterface::handleReceiveInterrupt()
|
||||
|
||||
rxGood++;
|
||||
if (h->to != 255 && h->to != ourAddr) {
|
||||
DEBUG_MSG("ignoring packet not sent to us\n");
|
||||
DEBUG_MSG("FIXME - should snoop packet not sent to us\n");
|
||||
} else {
|
||||
MeshPacket *mp = packetPool.allocZeroed();
|
||||
|
||||
mp->from = h->from;
|
||||
mp->to = h->to;
|
||||
mp->id = h->id;
|
||||
assert(HOP_MAX <= 0x07); // If hopmax changes, carefully check this code
|
||||
mp->hop_limit = h->flags & 0x07;
|
||||
|
||||
addReceiveMetadata(mp);
|
||||
|
||||
mp->which_payload = MeshPacket_encrypted_tag; // Mark that the payload is still encrypted at this point
|
||||
|
@ -59,7 +59,8 @@ class Router
|
||||
* Handle any packet that is received by an interface on this node.
|
||||
* Note: some packets may merely being passed through this node and will be forwarded elsewhere.
|
||||
*
|
||||
* Note: this method will free the provided packet
|
||||
* Note: this packet will never be called for messages sent/generated by this node.
|
||||
* Note: this method will free the provided packet.
|
||||
*/
|
||||
virtual void handleReceived(MeshPacket *p);
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user