@@ -461,6 +461,27 @@ void SignalRoutingModule::logNetworkTopology()
461461{
462462 if (!routingGraph) return ;
463463
464+ #ifdef SIGNAL_ROUTING_LITE_MODE
465+ auto appendGatewayDownstreams = [&](NodeNum gateway, std::vector<NodeNum> &out) {
466+ uint32_t now = getTime ();
467+ for (uint8_t i = 0 ; i < gatewayDownstreamCount; i++) {
468+ const GatewayDownstreamSet &set = gatewayDownstream[i];
469+ if (set.gateway != gateway) continue ;
470+ if ((now - set.lastSeen ) > CAPABILITY_TTL_SECS) return ;
471+ for (uint8_t j = 0 ; j < set.count ; j++) {
472+ out.push_back (set.downstream [j]);
473+ }
474+ return ;
475+ }
476+ };
477+ #else
478+ auto appendGatewayDownstreams = [&](NodeNum gateway, std::vector<NodeNum> &out) {
479+ auto it = gatewayDownstream.find (gateway);
480+ if (it == gatewayDownstream.end ()) return ;
481+ out.insert (out.end (), it->second .begin (), it->second .end ());
482+ };
483+ #endif
484+
464485#ifdef SIGNAL_ROUTING_LITE_MODE
465486 NodeNum nodeBuf[GRAPH_LITE_MAX_NODES];
466487 size_t nodeCount = routingGraph->getAllNodeIds (nodeBuf, GRAPH_LITE_MAX_NODES);
@@ -497,7 +518,32 @@ void SignalRoutingModule::logNetworkTopology()
497518 continue ;
498519 }
499520
500- LOG_INFO (" [SR] +- %s: connected to %d nodes" , nodeName, edges->edgeCount );
521+ std::vector<NodeNum> downstreams;
522+ appendGatewayDownstreams (nodeId, downstreams);
523+
524+ if (downstreams.empty ()) {
525+ LOG_INFO (" [SR] +- %s: connected to %d nodes" , nodeName, edges->edgeCount );
526+ } else {
527+ std::sort (downstreams.begin (), downstreams.end ());
528+ downstreams.erase (std::unique (downstreams.begin (), downstreams.end ()), downstreams.end ());
529+ char buf[128 ];
530+ size_t pos = 0 ;
531+ size_t maxList = std::min<size_t >(downstreams.size (), 4 );
532+ for (size_t i = 0 ; i < maxList; i++) {
533+ char dn[32 ];
534+ getNodeDisplayName (downstreams[i], dn, sizeof (dn));
535+ int written = snprintf (buf + pos, sizeof (buf) - pos, (i == 0 ) ? " %s" : " , %s" , dn);
536+ if (written < 0 || (size_t )written >= (sizeof (buf) - pos)) {
537+ buf[sizeof (buf) - 1 ] = ' \0 ' ;
538+ break ;
539+ }
540+ pos += static_cast <size_t >(written);
541+ }
542+ if (downstreams.size () > maxList && pos < sizeof (buf) - 6 ) {
543+ snprintf (buf + pos, sizeof (buf) - pos, " , +%zu" , downstreams.size () - maxList);
544+ }
545+ LOG_INFO (" [SR] +- %s: connected to %d nodes (gateway for: %s)" , nodeName, edges->edgeCount , buf);
546+ }
501547
502548 for (uint8_t i = 0 ; i < edges->edgeCount ; i++) {
503549 const EdgeLite& edge = edges->edges [i];
@@ -532,7 +578,32 @@ void SignalRoutingModule::logNetworkTopology()
532578 continue ;
533579 }
534580
535- LOG_INFO (" [SR] +- %s: connected to %d nodes" , nodeName, edges->size ());
581+ std::vector<NodeNum> downstreams;
582+ appendGatewayDownstreams (nodeId, downstreams);
583+
584+ if (downstreams.empty ()) {
585+ LOG_INFO (" [SR] +- %s: connected to %d nodes" , nodeName, edges->size ());
586+ } else {
587+ std::sort (downstreams.begin (), downstreams.end ());
588+ downstreams.erase (std::unique (downstreams.begin (), downstreams.end ()), downstreams.end ());
589+ char buf[128 ];
590+ size_t pos = 0 ;
591+ size_t maxList = std::min<size_t >(downstreams.size (), 4 );
592+ for (size_t i = 0 ; i < maxList; i++) {
593+ char dn[32 ];
594+ getNodeDisplayName (downstreams[i], dn, sizeof (dn));
595+ int written = snprintf (buf + pos, sizeof (buf) - pos, (i == 0 ) ? " %s" : " , %s" , dn);
596+ if (written < 0 || (size_t )written >= (sizeof (buf) - pos)) {
597+ buf[sizeof (buf) - 1 ] = ' \0 ' ;
598+ break ;
599+ }
600+ pos += static_cast <size_t >(written);
601+ }
602+ if (downstreams.size () > maxList && pos < sizeof (buf) - 6 ) {
603+ snprintf (buf + pos, sizeof (buf) - pos, " , +%zu" , downstreams.size () - maxList);
604+ }
605+ LOG_INFO (" [SR] +- %s: connected to %d nodes (gateway for: %s)" , nodeName, edges->size (), buf);
606+ }
536607
537608 // Sort edges by ETX for consistent output
538609 std::vector<Edge> sortedEdges = *edges;
@@ -764,14 +835,9 @@ bool SignalRoutingModule::shouldUseSignalBasedRouting(const meshtastic_MeshPacke
764835 LOG_DEBUG (" [SR] Destination %s (SR-capable=%d, legacy-router=%d)" ,
765836 destName, destCapable, destLegacy);
766837
767- if (!destCapable && !destLegacy) {
768- LOG_DEBUG (" [SR] Destination not SR-capable and not legacy router - fallback to flood" );
769- return false ;
770- }
771-
772838 NodeNum nextHop = getNextHop (p->to );
773839 if (nextHop == 0 ) {
774- LOG_DEBUG (" [SR] No route found to destination" );
840+ LOG_DEBUG (" [SR] No route found to destination (including gateway/fallback search) " );
775841 return false ;
776842 }
777843
@@ -915,7 +981,6 @@ NodeNum SignalRoutingModule::getNextHop(NodeNum destination)
915981 LOG_DEBUG (" [SR] Route to %s via %s (cost: %.2f)" ,
916982 destName, nextHopName, routeCost);
917983
918- // Log route quality indicators
919984 if (routeCost > 10 .0f ) {
920985 LOG_WARN (" [SR] High-cost route to %s (%.2f) - poor link quality expected" ,
921986 destName, routeCost);
@@ -924,8 +989,71 @@ NodeNum SignalRoutingModule::getNextHop(NodeNum destination)
924989 return route.nextHop ;
925990 }
926991
992+ // Fallback 1: if we know a gateway for this destination, and we have a direct link to it, forward there
993+ NodeNum gatewayForDest = getGatewayFor (destination);
994+ if (gatewayForDest != 0 && nodeDB) {
995+ #ifdef SIGNAL_ROUTING_LITE_MODE
996+ const NodeEdgesLite* myEdges = routingGraph->getEdgesFrom (nodeDB->getNodeNum ());
997+ if (myEdges) {
998+ for (uint8_t i = 0 ; i < myEdges->edgeCount ; i++) {
999+ if (myEdges->edges [i].to == gatewayForDest) {
1000+ char gwName[64 ];
1001+ getNodeDisplayName (gatewayForDest, gwName, sizeof (gwName));
1002+ LOG_DEBUG (" [SR] No direct route to %s, but forwarding to gateway %s" , destName, gwName);
1003+ return gatewayForDest;
1004+ }
1005+ }
1006+ }
1007+ #else
1008+ auto edges = routingGraph->getEdgesFrom (nodeDB->getNodeNum ());
1009+ if (edges) {
1010+ for (const Edge& e : *edges) {
1011+ if (e.to == gatewayForDest) {
1012+ char gwName[64 ];
1013+ getNodeDisplayName (gatewayForDest, gwName, sizeof (gwName));
1014+ LOG_DEBUG (" [SR] No direct route to %s, but forwarding to gateway %s" , destName, gwName);
1015+ return gatewayForDest;
1016+ }
1017+ }
1018+ }
1019+ #endif
1020+ }
1021+
1022+ // Fallback 2: opportunistic forward like broadcast — pick best direct neighbor (lowest ETX) to move the packet
1023+ NodeNum bestNeighbor = 0 ;
1024+ float bestEtx = 1e9f;
1025+ #ifdef SIGNAL_ROUTING_LITE_MODE
1026+ const NodeEdgesLite* myEdges = routingGraph->getEdgesFrom (nodeDB->getNodeNum ());
1027+ if (myEdges) {
1028+ for (uint8_t i = 0 ; i < myEdges->edgeCount ; i++) {
1029+ float etx = myEdges->edges [i].getEtx ();
1030+ if (etx < bestEtx) {
1031+ bestEtx = etx;
1032+ bestNeighbor = myEdges->edges [i].to ;
1033+ }
1034+ }
1035+ }
1036+ #else
1037+ auto edges = routingGraph->getEdgesFrom (nodeDB->getNodeNum ());
1038+ if (edges) {
1039+ for (const Edge& e : *edges) {
1040+ if (e.etx < bestEtx) {
1041+ bestEtx = e.etx ;
1042+ bestNeighbor = e.to ;
1043+ }
1044+ }
1045+ }
1046+ #endif
1047+
1048+ if (bestNeighbor != 0 ) {
1049+ char nhName[64 ];
1050+ getNodeDisplayName (bestNeighbor, nhName, sizeof (nhName));
1051+ LOG_DEBUG (" [SR] No route to %s; forwarding opportunistically via %s (ETX=%.2f)" , destName, nhName, bestEtx);
1052+ return bestNeighbor;
1053+ }
1054+
9271055 LOG_DEBUG (" [SR] No route found to %s" , destName);
928- return 0 ; // No route found
1056+ return 0 ;
9291057}
9301058
9311059void SignalRoutingModule::updateNeighborInfo (NodeNum nodeId, int32_t rssi, float snr, uint32_t lastRxTime, uint32_t variance)
0 commit comments