BGP

BGP Outbound Route Filtering (ORF): Pushing Your Filters to the Neighbor

BGP ORF - show ip bgp neighbors received prefix-filter output on Cisco IOS XE
In: BGP, Labs, CCIE

Inbound prefix filtering is normal hygiene: you accept the routes you want and drop the rest. But think about what actually happens on the wire. Your neighbour sends you a full table, your router receives every prefix, parses every attribute, runs every one against your prefix-list, and throws most of them away. You paid the CPU and the memory to discard routes you never wanted.

Outbound Route Filtering (ORF) fixes that by pushing your inbound filter to the neighbour. They apply it on egress. The routes never leave their router. This article shows ORF working on Cisco IOS XE with real output from a CML lab, including the exact commands the receiving router uses to see the filter you sent it. For the wider context, see the complete BGP guide.

What ORF actually is

ORF is a BGP capability, negotiated at session establishment, defined in RFC 5291 with the prefix-list ORF type in RFC 5292. The idea is simple: one router advertises a filter, the other router installs it as an outbound policy for that session.

Two modes are negotiated independently, and both sides have to agree:

send
"I will send you my inbound prefix-list." Configure this on the router that has the filter and wants the peer to enforce it.
receive
"I will accept a prefix-list from you and apply it outbound." Configure this on the router that will do the filtering work.
both
Send and receive on the same session. Common between peers who trust each other symmetrically.

The pairing has to be complementary. If R1 says send, R3 must say receive (or both). Two routers that both say send negotiate nothing useful.

Who actually uses this

ORF is most valuable in exactly one relationship: a customer taking a partial table from a provider. The customer knows which prefixes they care about. The provider has hundreds of thousands they could send. Without ORF, the provider sends the lot and the customer's CE drops 95% of it. With ORF, the customer's filter runs on the PE and only the wanted routes cross the link.

It also shows up between route reflectors and clients in very large iBGP meshes, where a client only needs a slice of the table.

Where it does not show up: between peers of equal standing on an internet exchange. Nobody wants a stranger installing filters on their router, and the trust model does not fit.

The lab

AS 65001 (R1) is dual-attached to ISP-A (AS 100, R3) over two parallel links. Both links carry an independent eBGP session. That makes for a clean experiment: enable ORF on one session only, and the other session stays as an in-place control group.

Before ORF, both sessions deliver three prefixes each:

R1#show ip bgp summary
Neighbor        V           AS MsgRcvd MsgSent   TblVer  InQ OutQ Up/Down  State/PfxRcd
2.2.2.2         4        65001       8      10       16    0    0 00:02:51        3
10.0.13.2       4          100       9      11       16    0    0 00:03:27        3
10.0.113.2      4          100       9      11       16    0    0 00:03:20        3

Configuration

R1 (the filter owner) wants only 6.6.60.0/24 from ISP-A. It builds a normal inbound prefix-list, applies it inbound as usual, and additionally offers to send it:

ip prefix-list ORF-IN seq 5 permit 6.6.60.0/24
ip prefix-list ORF-IN seq 10 deny 0.0.0.0/0 le 32

router bgp 65001
 address-family ipv4
  neighbor 10.0.13.2 capability orf prefix-list send
  neighbor 10.0.13.2 prefix-list ORF-IN in

R3 (the provider) agrees to receive and enforce it:

router bgp 100
 address-family ipv4
  neighbor 10.0.13.1 capability orf prefix-list receive

Two things matter in that config and both trip people up:

  • You still apply the prefix-list inbound. The prefix-list ORF-IN in line is not optional. ORF sends whatever prefix-list is applied inbound to that neighbour. No inbound prefix-list, nothing to send.
  • The explicit deny is deliberate. A prefix-list has an implicit deny anyway, but ORF encodes the list you wrote. Being explicit removes ambiguity about what the neighbour is being asked to enforce.

Capability changes require a session reset

ORF is a capability, and capabilities are negotiated in the OPEN message. Adding capability orf to an established session does nothing until the session restarts. In the lab, the session bounced on its own the moment the capability was added. In production, plan for that: clear ip bgp <neighbor> is a hard reset and it will drop traffic.

Once the capability is up, subsequent filter changes do not need a hard reset. You refresh the filter with:

R1#clear ip bgp 10.0.13.2 soft in prefix-filter

That pushes the current prefix-list across without tearing down the session. This is the operational payoff: change your filter, push it, and the neighbour immediately stops sending you the routes you no longer want.

Verification

The single most satisfying command in all of ORF, run on the receiving router, shows you exactly what filter the neighbour handed over:

R3#show ip bgp neighbors 10.0.13.1 received prefix-filter
Address family: IPv4 Unicast
ip prefix-list 10.0.13.1: 2 entries
   seq 5 permit 6.6.60.0/24
   seq 10 deny 0.0.0.0/0 le 32

That is R1's prefix-list, verbatim, living inside R3. R3 names it after the neighbour that sent it.

The capability negotiation itself is visible on both ends. On R3, which is doing the filtering:

R3#show ip bgp neighbors 10.0.13.1 | section Outbound
    Outbound Route Filter (ORF) type (128) Prefix-list:
      Capability code received: IETF standard and pre-standard
      Send-mode: received
      Receive-mode: advertised
  Outbound Route Filter (ORF): received (2 entries)

And on R1, which owns the filter:

R1#show ip bgp neighbors 10.0.13.2 | section Outbound
    Outbound Route Filter (ORF) type (128) Prefix-list:
      Capability code received: IETF standard and pre-standard
      Send-mode: advertised
      Receive-mode: received
  Outbound Route Filter (ORF): sent;

Read those carefully. Send-mode: advertised on R1 means "I told you I would send"; Send-mode: received on R3 means "you told me you would send". The mirror pairing is the sign of a healthy negotiation. If one side shows nothing, the capability did not negotiate and you are silently running without ORF.

Note the "IETF standard and pre-standard" line. Cisco implemented ORF before the RFC was finalised, so IOS advertises both the pre-standard capability code (128) and the standard one. This is why ORF between Cisco and a non-Cisco peer sometimes needs a nudge, and why you should always verify the capability rather than assuming.

The result

The ORF-enabled session now carries one prefix. The parallel session to the same router, without ORF, still carries three:

R1#show ip bgp summary
Neighbor        V           AS MsgRcvd MsgSent   TblVer  InQ OutQ Up/Down  State/PfxRcd
2.2.2.2         4        65001      10      18       26    0    0 00:04:37        3
10.0.13.2       4          100       6      13       26    0    0 00:01:22        1
10.0.113.2      4          100      14      17       26    0    0 00:05:07        3

That is the whole point in one screen. Same neighbour, same routes available, two sessions, and the ORF one only ever transmitted the prefix R1 asked for.

ORF vs soft reconfiguration vs route refresh

These three get conflated constantly. They solve different problems.

soft-reconfiguration inbound
Where the cost lands: your router
What it does: stores every received route pre-policy so you can re-apply a changed inbound filter without a reset
Cost: memory, and it grows with the table size
Route refresh (RFC 2918)
Where the cost lands: the link and the neighbour
What it does: asks the neighbour to re-send everything so you can re-apply policy
Cost: a full re-transmission of the table
ORF
Where the cost lands: the neighbour, once
What it does: the unwanted routes are never sent in the first place
Cost: negligible - and you save link, CPU, and memory

Route refresh is negotiated by default on modern IOS and you almost never need soft-reconfiguration inbound anymore, except when you specifically want to see what a neighbour sent you before your policy chewed it (which is a superb troubleshooting trick - see the expert BGP troubleshooting article). ORF is the only one of the three that reduces the traffic on the wire.

Limitations worth knowing

  • Prefix-list ORF only. The RFC allows other ORF types (community, AS-path, extended community) but Cisco IOS implements the prefix-list type. You cannot push "only send me routes tagged 65001:100" via ORF.
  • It is a per-address-family thing. Configure it under each AF you want it on. An IPv4 ORF does nothing for your IPv6 session.
  • Trust required. The receiving router is executing a policy it did not write. Providers who support ORF do so for customers, under a contract. Do not expect a random peer to enable receive for you.
  • Not a security control. ORF reduces what you are sent. It does not stop a malicious neighbour from sending you whatever they like. Keep your inbound prefix-list applied regardless - and it must stay applied anyway, because that is the list ORF sends.

Key takeaways

  • ORF moves your inbound filter onto your neighbour's outbound policy, so unwanted routes are never transmitted.
  • capability orf prefix-list send on the filter owner, receive on the router doing the work. The modes must be complementary.
  • The inbound prefix-list must still be applied to the neighbour - that is the list ORF transmits.
  • Enabling the capability resets the session. Changing the filter afterwards does not: use clear ip bgp <neighbor> soft in prefix-filter.
  • show ip bgp neighbors x.x.x.x received prefix-filter on the receiving router proves the filter arrived. It is the first command to run when ORF "is not working".
  • The real use case is customer-to-provider partial tables. It is a cost and scale tool, not a security tool.

Next: BGP route dampening and why a feature designed to protect the internet ended up doing more harm than good. The full cluster index lives on the BGP pillar guide.

Written by
More from Ping Labz
Great! You’ve successfully signed up.
Welcome back! You've successfully signed in.
You've successfully subscribed to Ping Labz.
Your link has expired.
Success! Check your email for magic link to sign-in.
Success! Your billing info has been updated.
Your billing was not updated.