netom-cli

netom-cli inspects a running netom daemon with router-style commands over its HTTP API. It is read-only: every command is a GET, and nothing it can do changes the daemon’s state or configuration.

$ netom-cli show ip bgp summary

Neighbor        V     AS Src  UpdRcvd NotifRcvd   Up/Down State/PfxRcd
10.1.0.1        4  65001 bgp    13980         1  02:14:33       84,211
10.1.0.3        4  65003 bgp        0         0     never       Active
192.0.2.7       4  65100 bmp        -         -  01:02:11            -

Total neighbors 3 (bgp 2, bmp 1)

Running it

Three ways, plus a prompt:

netom-cli show ip bgp summary          # one-shot
netom-cli -e 'show version' -e 'show status'   # repeatable
printf 'show version\nshow status\n' | netom-cli   # batch
netom-cli                              # interactive: netom> prompt

Keywords abbreviate to any unambiguous prefix, so sh ip b sum is show ip bgp summary. A trailing ? lists what may follow — always as a list, even when only one keyword matches — and ends with <cr> when the line is already a command you can run. In interactive mode TAB completes instead, and ? works at any point in the line without disturbing it.

netom> show ip bgp ?
  summary      Summary of BGP neighbor status
  neighbors    Detailed neighbor information
  flowspec     FlowSpec rules
  <A.B.C.D/M>  Network in the BGP routing table
  source       Only routes learned over one kind of ingress
  ingress      Only routes stored under one ingress id
  origin-as    Only routes originated by one AS
  community    Only routes carrying one community
  <cr>

help prints the whole command tree at once, which is the place to start if you do not yet know what to press ? after:

netom> help
Commands:

  show ip bgp                               BGP information
  show ip bgp summary                       Summary of BGP neighbor status
  ...
  show running-config                       Current operating configuration
  show filters                              Roto filter script and entrypoints
  help                                      List every command
  exit                                      Exit the CLI

Finding the daemon

In order: --url, $NETOM_URL, -c <config>, ./netom.conf, /etc/netom/netom.conf, then http://127.0.0.1:8080.

netom ships http_listen = ["[::]:8080"], which is a wildcard and not something you can connect to. netom-cli rewrites wildcards to loopback (:: → ::1 then 127.0.0.1; 0.0.0.0 → 127.0.0.1), so discovery never sends a query off-box on its own initiative. When a connection fails it says which addresses it tried and where they came from:

% Unable to connect to netom at [::1]:8080, 127.0.0.1:8080: Connection refused
%   (from /etc/netom/netom.conf: http_listen)

Scripting

--json emits the daemon’s response bytes unchanged, so scripts see the API contract rather than a rendering of it:

netom-cli --json show ip bgp summary | jq '.data[] | select(.state != "Established")'

Whole-table route dumps are newline-delimited JSON — one object per line, not a JSON array — which is what the API emits and what jq -c and wc -l want:

netom-cli --json show ip bgp | wc -l

Exit codes: 0 success, 1 the command did not parse, 2 the daemon was unreachable or the response was truncated, 3 the daemon returned an error.

Output filters take Cisco’s form and match case-insensitive substrings (not regular expressions):

netom-cli show ip bgp summary '| exclude Established'
netom-cli show ingresses '| count'

What the numbers mean

netom is a collector, not a router, so some familiar columns cannot honestly be filled in. Rather than print plausible zeros, netom-cli names the counters for what they are and leaves the rest blank.

UpdRcvd / NotifRcvd, not MsgRcvd / MsgSent. netom counts the UPDATE and NOTIFICATION messages it receives. It never originates UPDATEs, and KEEPALIVEs are handled inside the BGP state machine without ever surfacing, so a total-message counter would be a guess and a sent-message counter would always read zero.

State/PfxRcd shows - for BMP-observed peers. For a session netom terminates itself the prefix count is maintained as routes enter and leave the RIB. For a session observed through a BMP feed, getting the same number would mean scanning the whole RIB once per peer — far too expensive for a command people run repeatedly. A dash means “not counted”, not “zero”.

PfxRcd is the current table size, not a running total. It counts the prefixes the peer currently has in the RIB, so re-advertisements do not inflate it: a peer that keeps re-announcing the same prefix with a new AS path is performing BGP’s implicit withdraw, and the count stays put. If you want the churn instead, it is the dupPrefixAdvertisements counter on /bgp/neighbors and in the peer’s BMP Statistics Report.

The hold time is the configured one. show ip bgp neighbors reports the hold time netom was configured with. The negotiated value — min(peer's, ours) — is computed inside the BGP library and kept private.

Src distinguishes the two kinds of peer. bgp is a session this netom terminates; bmp is one it observes through a monitored router. Narrow to one with show ip bgp summary bgp or ... bmp.

Narrowing a route query

show ip bgp dumps the whole table. Each of these narrows it, and works the same under show ipv6 bgp:

netom> show ip bgp source bmp                 routes learned through BMP
netom> show ip bgp source bgp                 sessions netom terminates itself
netom> show ip bgp source mrt                 peers replayed from MRT files
netom> show ip bgp neighbors 10.1.0.1 routes  what one neighbor sent
netom> show ip bgp ingress 5                  one exact ingress id
netom> show ip bgp origin-as 65001            originated by one AS
netom> show ip bgp community 65000:100        carrying one community

Two of these need a word about ADD-PATH, where each (peer, path_id) gets its own ingress id. ingress 5 is one exact id, so for such a peer it is one path, not the peer — while source and neighbors … routes resolve those children back to their session, and so return every path the peer sent. The ids come from show ingresses.

source bmp covers every peer under a monitored router, not the router’s own ingress, which holds no routes of its own.

Only one filter applies per command — the grammar is a path, not a set of flags — so stack | include on top when you need a second condition:

netom-cli show ip bgp source bmp '| include 10.0.'

FlowSpec takes source and ingress (show ip bgp flowspec source bmp) but not the others; the API implements only those two for FlowSpec, so the rest are not typeable there rather than failing at the daemon.

A filter narrows the output, not the work: the daemon still walks the whole table to answer, so a narrowed dump is no faster than a full one.

Best path

Which of the routes for a prefix wins the RFC 4271 decision process, and why the others lost:

netom> show ip bgp 10.0.0.0/24 best     the decision for one prefix
netom> show ip bgp best 10.0.0.7        the route that would forward an address

The second is a longest-prefix match, so the prefix in the answer is normally not the address that was typed — the header says which one answered:

netom> show ip bgp best 10.0.1.7
BGP routing table entry for 10.0.1.0/24 (best path for 10.0.1.7)
    Network              Next Hop             Path        Peer   Decided by
>   10.0.1.0/24          192.0.2.9            65001       3      asPathLength
    10.0.1.0/24          192.0.2.1            65001 65002 2      asPathLength

> marks the winner, as it does on a router. Decided by is the step of the decision process that put each row where it is: on the winner, the step that separated it from the runner-up; on the others, the step at which they lost to the winner. Peer is the owning session, so an ADD-PATH peer’s paths are attributed to the peer rather than to the internal path-child id.

= marks a path tied with the winner through step e — equally good on every criterion the RFC treats as a preference, and separated only by the BGP Identifier or the peer address. Those are tie-breakers, not preferences, so a line below the table says when the winner was picked by one rather than earned it:

netom> show ip bgp 10.0.0.0/24 best
BGP routing table entry for 10.0.0.0/24
    Network              Next Hop             Path    Peer   Decided by
>   10.0.0.0/24          192.0.2.2            65001   2      bgpIdentifier
=   10.0.0.0/24          192.0.2.1            65001   1      bgpIdentifier
  2 paths are equal-cost (=); the winner was picked by bgpIdentifier, not
  preferred over them

Routes that could not be weighed at all are listed separately with the reason, rather than silently omitted:

  excluded from the decision process:
    peer 9 - missingAsPath

A note: line appears when a tiebreaker had to be assumed — an MRT-replayed peer has neither a local ASN nor a BGP Identifier, so step d and step f fall back. docs/rib-query-api.md lists every step, reason and assumption.

source, ingress, origin-as and community work here too, narrowing the candidates: show ip bgp 10.0.0.0/24 best source bgp asks what the best path would be if only BGP-learned routes existed. neighbors <ip> routes is not among them — narrowing to a single peer leaves nothing to decide.

Peers that are down

A peer that has never established has no session and no routes, so before this existed it appeared nowhere at all — the one case where you most want a row. Configured peers are now always listed, with the RFC 4271 state saying why:

netom> show ip bgp summary
Neighbor        V     AS Src  UpdRcvd NotifRcvd   Up/Down State/PfxRcd
10.1.0.3        4  65003 bgp        0         0     never       Active

netom> show ip bgp neighbors 10.1.0.3
BGP neighbor is 10.1.0.3, remote AS 65003
  Description: PeerC
  BGP state = Active
  Learned via: direct BGP session
  Configured: yes (active mode; we initiate the connection)
  Last error: Connection refused (os error 111)

Active means netom is retrying the transport connection; Idle means it is waiting for a peer that has not connected. Only exactly-configured peers can be listed this way — a peer matched by a prefix has no single address to show until it connects.

Paging

There is no built-in pager, and piping a whole-table dump into one is a bad idea: the daemon aborts a dump whose reader stops draining, so a pager sitting on the first screen will truncate it. When that happens netom-cli says so and exits non-zero rather than presenting a partial table as a whole one:

% Output truncated: the daemon closed the connection before the dump was
  complete. It aborts dumps whose reader stalls, so avoid paging this
  command.

| include and friends are streamed line by line and are safe on any size of output.

Security

netom’s HTTP API is unauthenticated and unencrypted. Pointing --url at a non-loopback host sends queries, and receives configuration and routing data, in the clear.

show running-config redacts secrets — BGP TCP-MD5 keys and MQTT passwords — but still exposes topology: peer addresses, ASNs and listen ports. Treat access to the API port as equivalent to read access to the config.

See also

  • netom-cli(1) for the full option and command reference.

  • The RIB query API for the HTTP endpoints, filters and JSON shapes behind these commands.

  • ADD-PATH and FlowSpec for what these add on top.