SONiC
Module 3 · ASICs, Switching Pipelines, SAI & Forwarding

Route Object Correlation

60 minLabCorrelationVirtualOpen-source

Take a single installed route and trace it through the SAI object graph — route entry → next hop (or next-hop group) → router interface → neighbor → port — building a relationship graph that shows exactly what must exist for the route to forward.

Safety: Safe

Non-disruptive. Safe to run in the virtual lab.

Use SCAN with targeted MATCH patterns, never KEYS * on a busy system.

This lab is read-only; do not set/del any ASIC_DB keys — writing there does not 'fix' hardware and can desynchronize state.

Single node with one upstream route

  SONiC-VS
    ├─ Ethernet0  ── (routed) ── next-hop 10.0.0.2  (neighbor MAC learned)
    └─ route 10.20.0.0/24 ─→ next-hop ─→ RIF(Ethernet0) ─→ neighbor ─→ port

Objective

  • Correlate one route across all the SAI-facing objects it depends on.
  • Distinguish human-readable application state (APPL_DB) from implementation-oriented objects (ASIC_DB).
  • Produce a relationship graph you can reuse as a routed-forwarding checklist.

Starting state

  • SONiC-VS up; one routed interface with a resolved neighbor.
  • At least one non-connected route (e.g., 10.20.0.0/24) installed and forwarding.

Prerequisites: Lessons 3.3, 3.4, and 3.5 complete. · A SONiC-VS instance with at least one routed interface and an installed route with a resolved next hop (reuse Module 2's adjacency, or add a static route with a reachable next hop). · A 'baseline' snapshot to revert to.

Tasks

  1. 1

    Confirm the route in software (intent/applied)

    Establish the human-readable view first: the route in FRR and in APPL_DB.

    SONiC CLI
    show ip route 10.20.0.0/24
    SONiC DBAPPL_DB is DB 0; SCAN, not KEYS *
    redis-cli -n 0 SCAN 0 MATCH 'ROUTE_TABLE:10.20.0.0/24' COUNT 100
    SONiC DB
    redis-cli -n 0 HGETALL 'ROUTE_TABLE:10.20.0.0/24'
    Expected:
    • FRR shows the route with a next-hop IP and egress interface.
    • APPL_DB ROUTE_TABLE entry lists the nexthop and ifname in human-readable form.

    What happened internally: APPL_DB holds application/desired state produced from FRR (via fpmsyncd) and managers. It is human-readable and references interfaces/IPs by name — the top of the correlation chain.

  2. 2

    Find the route object in ASIC_DB and its next-hop reference

    SONiC DBASIC_DB is DB 1
    redis-cli -n 1 SCAN 0 MATCH 'ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY*10.20.0.0/24*' COUNT 500
    SONiC DBread SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID
    redis-cli -n 1 HGETALL 'ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY:{...10.20.0.0/24...}'
    Expected:
    • A ROUTE_ENTRY object whose SAI_ROUTE_ENTRY_ATTR_PACKET_ACTION is FORWARD and whose SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID is an oid: value (a VID).

    What happened internally: This is the sync-path representation of the route. The next-hop attribute is an opaque VID — the first edge in the object graph. (This is a database record of the SAI request, not the silicon.)

  3. 3

    Follow next hop → router interface → neighbor

    SONiC DBreveals RIF oid + next-hop IP
    redis-cli -n 1 HGETALL 'ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP:oid:0x...'
    SONiC DBRIF → port + src MAC + VRF
    redis-cli -n 1 HGETALL 'ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE:oid:0x...'
    SONiC DBneighbor keyed by (RIF, IP) → dst MAC
    redis-cli -n 1 SCAN 0 MATCH 'ASIC_STATE:SAI_OBJECT_TYPE_NEIGHBOR_ENTRY*' COUNT 500
    Expected:
    • The next hop references a router interface OID and a next-hop IP.
    • The router interface references a port OID (and holds the source MAC / VRF).
    • A neighbor entry for (that RIF, the next-hop IP) holds the destination MAC.

    What happened internally: You are walking the reference graph: NEXT_HOP → ROUTER_INTERFACE → PORT, plus NEIGHBOR_ENTRY supplying the dst MAC. If the neighbor is missing, the route is 'inert' (Lesson 3.5).

  4. 4

    Resolve the port OID to a front-panel port and translate a VID→RID

    SONiC DBmap port name ↔ oid (COUNTERS_DB also maps these)
    redis-cli -n 1 HGET COUNTERS_PORT_NAME_MAP Ethernet0
    SONiC DBvirtual OID → real (vendor) OID
    redis-cli -n 1 HGET VIDTORID oid:0x...
    Expected:
    • The port OID corresponds to a named front-panel port (e.g., Ethernet0).
    • VIDTORID returns the implementation's real OID for a given virtual OID.

    What happened internally: VIDTORID/RIDTOVID are maintained by syncd. This step shows that ASIC_DB uses virtual IDs that map to the vendor SAI's real handles — the abstraction boundary in action.

  5. 5

    Draw the relationship graph

    On paper or in a note, draw: route → next hop → RIF → (port) and RIF+IP → neighbor → dst MAC.

    Mark which nodes came from human-readable APPL_DB and which from implementation-oriented ASIC_DB.

    Expected:
    • A single-page graph you can reuse as a routed-forwarding checklist.

    What happened internally: The graph is the mental model for Lesson 3.5's troubleshooting order: break any node and predict the failure signature.

Troubleshooting branches

If: No ROUTE_ENTRY in ASIC_DB though FRR shows the route

Then: Suspect a stall in the swss→syncd path or resource exhaustion; check orchagent/syncd logs and CRM (Lessons 3.4/3.8).

If: Route + next hop present but no matching neighbor entry

Then: Adjacency unresolved — the 'inert route' pattern. Verify ARP/ND for the next-hop IP.

If: SCAN returns nothing for your key pattern

Then: Key formats vary by version; widen the MATCH pattern, and confirm you're in the right DB (-n 0 APPL_DB, -n 1 ASIC_DB).

Cleanup / rollback
  • None — read-only correlation. Revert to 'baseline' only if you added a temporary static route.

Lab evidence checklist

  • APPL_DB ROUTE_TABLE entry captured (human-readable).
  • ASIC_DB ROUTE_ENTRY with its NEXT_HOP_ID captured.
  • Next hop → RIF → port chain captured.
  • Neighbor entry (RIF, IP → MAC) captured.
  • One VID→RID translation captured.
  • Relationship graph drawn, nodes labeled by source DB.

Reflection

  • Which objects were human-readable and which were implementation-oriented opaque OIDs — and why is that split useful?
  • If the neighbor entry were missing, which of your captured objects would still be present, and would the route forward?
  • Why is ASIC_DB the right place to confirm the request reached SAI, but still not proof the packet forwards?
Lab notes & observations