21  Routing

org.arl.unet.Services.ROUTING

21.1 Overview

In many Unets, not every node can communicate directly with every other node — the network is not fully connected. The ROUTING service delivers datagrams to such distant nodes by forwarding them through intermediate nodes, hop by hop, until they reach their destination.

A routing agent maintains a routing table: a set of entries that map a destination node to the next-hop neighbor (and the link) that should be used to reach it. When a datagram is sent to the routing agent (as a DatagramReq, since the agent provides the DATAGRAM service, Chapter 16), the agent looks up the destination in its table and forwards the datagram to the appropriate next hop. Each entry also carries a metric, which is used to choose between alternative routes to the same destination; the route with the best metric is preferred.

Routes can be managed in three ways:

  • Statically, by adding entries manually with an EditRouteReq (or the addroute command) — useful when the topology is known and fixed.
  • Dynamically, by letting the ROUTE_MAINTENANCE service (Chapter 22) discover routes automatically.
  • Reactively, by editing or disabling entries at runtime, for example to prefer a newly available link.

Routing in larger networks, including static routes, route metrics and multilink routing, is covered with worked examples in Chapter 6 and Section 7.1. The default router is accessed as router.

21.2 Messages

Agents providing this service honor the following requests:

  • GetRouteReq – query routing table entries

    Field Type Default Remarks
    all boolean false true to get all matching routes (including disabled ones) instead of only the best route
    to int -1 destination node address
    uuid string route ID
  • EditRouteReq – add, edit or delete a route

    Field Type Default Remarks
    MTU int
    RTU int
    auto boolean
    dataRate float
    enabled boolean
    hops int
    link string
    metric float
    nextHop int next-hop neighbor address
    op RouteInfo.Operation
    poll float
    reliability boolean
    to int destination node address
    uuid string route ID (for edit/delete)

A GetRouteReq for the best route to a destination is answered with a single RouteRsp (or a REFUSE if no matching route exists). With all set, it is answered with a series of RouteRsp messages — one per matching route — terminated by an AGREE response that marks the end of the list (or a REFUSE if there are none). An EditRouteReq is answered with an AGREE once the change is made:

  • RouteRsp – routing table entry (response to GetRouteReq)

    Field Type Default Remarks
    MTU int
    RTU int
    auto boolean
    dataRate float
    enabled boolean
    hops int
    link string
    metric float
    nextHop int
    op enum
    poll float
    reliability boolean
    to int
    uuid string

Changes to the routing table — whether made by request or by route discovery — are announced by publishing the following notification on the agent’s topic, so that interested agents can track the topology as it evolves:

  • RouteChangeNtf – routing table change notification

    Field Type Default Remarks
    MTU int
    RTU int
    auto boolean
    dataRate float
    enabled boolean
    hops int
    link string
    metric float
    nextHop int
    op enum
    poll float
    reliability boolean
    to int
    uuid string

Every routing provider must also honor a DatagramTraceReq — a special DatagramReq used to trace the path taken to a destination. Because its behaviour is bound up with how the router forwards datagrams, it is documented separately under Section 21.7.

If a request is invalid, a REFUSE response may be generated. If the request fails, a FAILURE response may be generated.

21.3 Anatomy of a route

Each entry in the routing table — what you see in the routes listing, set with addroute/EditRouteReq, and returned in a RouteRsp — is a RouteInfo record. Its fields fall into three groups.

Where the route goes:

  • to — the destination node address the route is for. The special destination * (RouteInfo.DEFAULT_ROUTE) is a default route, used for any destination that has no more specific entry.
  • nextHop — the neighbour to forward to in order to reach to.
  • link — the link agent (a LINK/DATAGRAM provider, Chapter 18) over which the next hop is reached. On a gateway node with several links, this selects which one carries the traffic.
  • uuid — a unique identifier assigned to the entry when it is created. Use it to edit, delete or query one specific route (an EditRouteReq/GetRouteReq carrying the uuid, or the delroute command).

How good the route is — used to choose between alternative routes to the same destination:

  • metric — the overall quality of the route; higher is better. When several enabled routes reach the same destination, the router forwards over the one with the highest metric. By default this rewards higher data rates and penalizes each extra hop (see How it works below); a custom metric closure can replace the policy.
  • hops — the number of hops to the destination, if known (null/unknown otherwise); recorded as 0 when unspecified.
  • dataRate — the link’s data rate in bits per second, if known.
  • reliability — whether the link delivers reliably (acknowledged).
  • MTU / RTU — the maximum and recommended transmission units of the link (bytes), which tell higher layers how large a datagram the route can carry, and carry efficiently.

How the route behaves over time:

  • enabled — whether the route is currently in use. A disabled route stays in the table but is skipped during forwarding — for example after its link is reported down — until it is re-enabled.
  • auto — when true, the router enables or disables the route automatically in response to LinkStatusNtf messages (Chapter 18) from the link, so the table follows link up/down events without manual intervention.
  • poll — how often, in seconds, the router re-checks a disabled route to see whether its link has recovered; 0 turns polling off.
  • op — carried only on an EditRouteReq, naming the change to make: CREATE a new route, CHANGE an existing one (identified by uuid), or DELETE it.

Putting it together: when a datagram needs forwarding, the router matches its destination against the to of each enabled route (falling back to the default route), picks the best metric among the matches, and sends the datagram to that route’s nextHop over its link. The uuid lets you address a single entry when editing the table, while enabled, auto and poll govern how routes respond to links coming and going.

Tip

If a route’s link supports reliable delivery, set the route’s reliability flag so each hop is acknowledged and retransmitted at the link level. Per-hop reliability is far cheaper than end-to-end recovery: a lost fragment is retransmitted across one hop rather than the whole path, so the transport layer (Chapter 23) rarely needs to step in.

21.4 Parameters

  • MTU – maximum data transfer size
  • RTU – recommended data transfer size
  • auto1hop – automatically assume single hop routes
  • defaultLink – default link to use

21.5 Commands

  • routes – print routing table

    Examples:

    routes              // display routing table
    routes 2            // display routes to node 2
    
  • addroute – add a route to the routing table

    Example:

    addroute 27, 29                // add a route to node 27 via node 29
    addroute 27, 29, link2, false  // add route on link2 with no reliability
    addroute to: 27, metric: 3.2   // add route to 27 with metric 3.2
    
  • editroute – edit a route in the routing table

    The route UUID can be obtained by displaying the routing table using the ‘routes’ command.

    Example:

    editroute 'as731', metric: 2.1 // edit route to change metric
    editroute 'as731', nextHop: 21 // edit route to change next hop
    
  • delroute – delete a route from the routing table

    The route UUID can be obtained by displaying the routing table using the ‘routes’ command.

    Example:

    delroute 'as7623'   // delete route with UUID as7623
    
  • delroutesto – delete all routes to specified node from the routing table

    Example:

    delroutesto 27      // delete all routes to node 27
    
  • delroutes – delete all routes from the routing table

    Example:

    delroutes           // delete all routes

21.6 Examples

Add a static route to a distant node and inspect the routing table. Here node 27 is reachable in two hops via next-hop neighbor 31, so we say so when adding the route (when the hop count is not given, it is recorded as 0, meaning unknown):

> addroute to: 27, nextHop: 31, hops: 2
OK
> routes
    uuid      to nextHop         link reliability hops dataRate metric enabled  auto  poll
------------------------------------------------------------------------------------------
  7nyi32      27      31       uwlink        true    2      965   -7.0    true  true   0.0

See Chapter 6 for full examples, including multi-hop and multilink routing.

21.7 Route tracing

Beyond ordinary datagrams, the router honors a special request — a DatagramTraceReq:

  • DatagramTraceReq – trace the route taken to a node

    Field Type Default Remarks
    data byte[]
    from int 0
    priority enum NORMAL
    progress boolean false
    protocol int 0
    reliability boolean
    robustness enum NORMAL
    route string
    shortcircuit boolean true
    to int 0 destination node address to trace to
    ttl float NaN

It is a DatagramReq subclass that adds no fields of its own — setting its to (the destination) is enough. It acts as a marker that switches the router into a trace-forwarding mode, and is the mechanism behind the user-facing trace command (Section 22.6); you do not normally construct one yourself.

A trace probe is forwarded towards its destination like any other datagram, but with two differences that let it record the path it takes:

  1. Each node appends its own address to the datagram before forwarding it, so the probe accumulates the sequence of nodes it has passed through.
  2. It is never short-circuited, even on a one-hop route — the router always adds its routing header rather than taking the header-less fast path — so every node on the path, endpoints included, is recorded.

The route-maintenance agent (Chapter 22) is a client of this mechanism: to trace a route, it sends a DatagramTraceReq from the source to the destination and back, then reports the collected hop sequence. See Section 22.6 for the full trace facility.

21.8 Implementation

21.8.1 Router (router)

Class Services Capabilities Availability
Router ROUTING, DATAGRAM CANCELLATION default stack

The default implementation is the router agent, loaded as part of the default stack (Chapter 13). Datagrams sent to it are forwarded towards their destination using the routing table.

21.8.1.1 How it works

The router keeps a table of routes, each naming a destination, the next-hop neighbor, the link agent to reach that neighbor, and metrics such as the hop count, the link data rate and whether the link is reliable. When a datagram arrives, the router looks up its destination: if it is this node, the datagram is delivered locally; otherwise it is forwarded to the chosen next hop over the assigned link. When several routes to a destination exist, the router picks one using a metric that, by default, penalizes each additional hop and rewards higher link data rates, so short, fast paths are preferred (a custom metric closure can replace this policy). Two parameters change the table’s behavior in bulk: with auto1hop enabled, the router assumes any address is directly reachable in a single hop over defaultLink (useful in fully connected networks where explicit routes are unnecessary), and with relay enabled, the router forwards traffic on behalf of other nodes rather than only sourcing and sinking its own. Routes are normally populated automatically by the route discovery agent (Chapter 22).

21.8.1.2 Automatic failover

Three distinct mechanisms let the routing table follow links as they come and go, without manual intervention:

  • Link status tracking — when a link publishes a LinkStatusNtf (Chapter 18) reporting that connectivity to a neighbor is lost or restored, the router disables or re-enables every route marked auto that uses that link and next hop. Disabled routes stay in the table but are skipped during forwarding, so traffic immediately shifts to the next best enabled route.
  • Failure-triggered retry — if a link reports a DatagramFailureNtf for a forwarded datagram, the router selects the best alternative route to the destination excluding the failed link, and silently retransmits the datagram over it. Retries continue for up to retryTimeout seconds (default 30) after the original request, so a transient link failure costs latency rather than a lost datagram. Since end-to-end reliability is only supported on single-hop routes, this retry switches between single-hop alternatives for reliable datagrams.
  • Poll-based recovery — a disabled route with a non-zero poll is re-checked every poll seconds: the router probes the next hop with a small reliable datagram over the route’s link. A successful probe causes the link to report itself up again, re-enabling the route. Links that detect recovery on their own (e.g. through peer advertisements) do not need polling.

A worked example showing all three mechanisms in action — traffic failing over from a UDP link to an acoustic link and back — is given in Section 7.4.

21.8.1.3 Usage notes

  • For small fixed networks, set up routes by hand (addroute) or enable auto1hop; for larger or changing networks, let rdp discover them (Chapter 22).
  • Disable relay on leaf nodes that should never forward other nodes’ traffic.