VyOSXXVIII · BGP Prefix FilteringPrefix filters
Prefix-list semantics — ordered, sequential, ge/le/exact-match, implicit deny
What you'll learn
- Explain the four operators on a prefix-list entry (exact, ge, le, ge+le)
- Walk the ordered sequential evaluation of a prefix-list
- Recognise the implicit deny at the end of every prefix-list
- Distinguish a prefix-list from an access-list
- Design a prefix-list that matches the expected set of prefixes
Prerequisites
Verified against VyOS 1.5.x LTS (circinus) · VyOS 1.4.x (sagitta) — legacy · FRRouting 10.x (VyOS 1.5) · Linux kernel 6.6 LTS (VyOS 1.5 base) · strongSwan 5.9.x (IPsec) · WireGuard 1.0.x (kernel module + userspace tooling) · 2026-08-15
A prefix-list is the BGP operator’s primary filter. It matches BGP routes by prefix and prefix-length, supports range operators (ge, le), and is evaluated in strict rule order. The implicit deny at the end of every prefix-list means a route that does not match any rule is rejected. The operator who designs a prefix-list must understand the evaluation order, the operator semantics, and the deny-by-default behaviour.
The prefix-list is the BGP filter of choice for two reasons. First, it is more efficient than an access-list — a prefix-list is compiled into a tree structure for fast matching. Second, the prefix and prefix-length are the right granularity for BGP routes — the operator wants to accept a route only if both the network and the subnet mask are in the expected range.
The four operators on a prefix-list entry
Each rule in a prefix-list has a prefix, a prefix-length, and an operator that constrains the prefix-length range:
| Operator | Match condition | Example |
|---|---|---|
| (no operator) | Prefix exactly, prefix-length exactly | 198.51.100.0/24 matches only 198.51.100.0/24 |
ge | Prefix exactly, prefix-length ≥ value | 198.51.100.0/24 ge 26 matches 198.51.100.0/26, 198.51.100.0/27, etc. |
le | Prefix exactly, prefix-length ≤ value | 198.51.100.0/24 le 26 matches 198.51.100.0/24, 198.51.100.0/25, 198.51.100.0/26 |
ge + le | Prefix exactly, prefix-length in range | 198.51.100.0/24 ge 26 le 28 matches 198.51.100.0/26, 198.51.100.0/27, 198.51.100.0/28 |
The operator constraint applies to the second part of the prefix (the prefix-length). The prefix itself is matched exactly — 198.51.100.0/24 ge 26 does not match 198.51.99.0/26. The rule is: the prefix must be exactly 198.51.100.0, and the prefix-length must be in the range.
The ge value must be greater than the prefix-length in the original entry. The le value must be greater than or equal to the ge value. The system rejects configurations that violate these constraints.
flowchart LR
subgraph "Rule: 198.51.100.0/24 ge 26"
P1["198.51.100.0/24<br/>prefix matches, length 24 < 26 — REJECT"]
P2["198.51.100.0/25<br/>prefix matches, length 25 < 26 — REJECT"]
P3["198.51.100.0/26<br/>prefix matches, length 26 ≥ 26 — ACCEPT"]
P4["198.51.100.64/26<br/>prefix matches, length 26 ≥ 26 — ACCEPT"]
P5["198.51.100.0/27<br/>prefix matches, length 27 ≥ 26 — ACCEPT"]
P6["198.51.101.0/24<br/>prefix does NOT match — REJECT<br/>(next rule is evaluated)"]
P7["198.51.100.0/23<br/>prefix matches, length 23 < 26 — REJECT"]
end
The diagram shows the matches and rejects for the rule 198.51.100.0/24 ge 26. The prefix must be exactly 198.51.100.0 (the network part of the rule). The prefix-length must be ≥ 26. The rule accepts /26, /27, /28, etc.; it rejects /24, /25, and any prefix that does not start with 198.51.100.0.
The ordered sequential evaluation
A prefix-list is a sequence of rules. The rules are evaluated in order, from the lowest rule number to the highest. The first rule that matches wins; the remaining rules are not evaluated.
vyos@vyos:~$ show configuration commands | grep prefix-list
set policy prefix-list MY-LIST rule 10 action 'permit'
set policy prefix-list MY-LIST rule 10 description 'exact match'
set policy prefix-list MY-LIST rule 10 prefix '198.51.100.0/24'
set policy prefix-list MY-LIST rule 20 action 'deny'
set policy prefix-list MY-LIST rule 20 description 'broader range'
set policy prefix-list MY-LIST rule 20 prefix '198.51.100.0/16'
set policy prefix-list MY-LIST rule 20 le '20'
set policy prefix-list MY-LIST rule 30 action 'permit'
set policy prefix-list MY-LIST rule 30 description 'catch-all'
set policy prefix-list MY-LIST rule 30 prefix '0.0.0.0/0'
set policy prefix-list MY-LIST rule 30 le '32'
The list has three rules:
- Rule 10: permit
198.51.100.0/24(exact match). - Rule 20: deny
198.51.100.0/16with prefix-length ≤ 20. - Rule 30: permit
0.0.0.0/0with prefix-length ≤ 32 (catch-all).
The walk for a route 198.51.100.0/24:
- Rule 10: prefix matches, length 24 matches. Permit. Stop.
The walk for a route 198.51.100.0/16:
- Rule 10: prefix matches, length 16 does not match (rule 10 wants exactly 24). No match.
- Rule 20: prefix matches, length 16 ≤ 20. Deny. Stop.
The walk for a route 203.0.113.0/24:
- Rule 10: prefix does not match. No match.
- Rule 20: prefix does not match. No match.
- Rule 30: prefix matches (0.0.0.0/0 matches any prefix), length 24 ≤ 32. Permit. Stop.
The walk for a route that does not match any rule:
- Rule 10: no match.
- Rule 20: no match.
- Rule 30: no match.
- Implicit deny. Reject.
The implicit deny is the rule that says “if no rule matches, reject”. The operator who does not add a catch-all permit rule sees every unmatched route rejected.
Difference between prefix-list and access-list
A prefix-list and an access-list both filter routes, but they operate on different primitives:
| Access-list | Prefix-list | |
|---|---|---|
| Match criterion | Source/destination IP, optionally with wildcard | Prefix and prefix-length |
| Granularity | Per-IP (single host) or per-network (with wildcard) | Per-prefix with length range |
| Performance | Linear scan (slower for large lists) | Tree structure (faster for large lists) |
| Use case | ACL filters, firewall rules, PBR | BGP route filters, prefix limits |
| Order | First match wins | First match wins |
| Implicit deny | Yes (at the end) | Yes (at the end) |
The access-list is the firewall and PBR tool. The prefix-list is the BGP route filter tool. The operator who uses an access-list for BGP filtering gets the wrong granularity (the access-list matches the prefix but not the prefix-length) and worse performance (the access-list is a linear scan).
The canonical migration path: an operator who has been using access-lists for BGP filtering should convert them to prefix-lists. The conversion is mechanical: an access-list entry permit ip 198.51.100.0 0.0.0.255 any becomes a prefix-list entry permit 198.51.100.0/24. The prefix-list is more efficient and more semantically precise.
The ge and le operator exercises
The operators are the source of subtle bugs. The four common cases:
Case 1: 198.51.100.0/24 (no operator). Matches exactly 198.51.100.0/24. Mismatches 198.51.100.0/25, 198.51.100.128/25, etc. The shortest form of the rule.
Case 2: 198.51.100.0/24 ge 26. Matches 198.51.100.0/26 to 198.51.100.0/32. Mismatches 198.51.100.0/24 and 198.51.100.0/25. The “more-specific” filter — the operator wants to accept subnets of the given prefix but not the prefix itself.
Case 3: 198.51.100.0/24 le 26. Matches 198.51.100.0/24 to 198.51.100.0/26. Mismatches 198.51.100.0/27 and more-specific. The “prefix and short subnets” filter — the operator wants to accept the prefix and subnets up to a certain length.
Case 4: 198.51.100.0/24 ge 26 le 28. Matches 198.51.100.0/26, 198.51.100.0/27, 198.51.100.0/28. Mismatches 198.51.100.0/24, 198.51.100.0/25, and /29 or more-specific. The “specific range” filter — the operator wants to accept subnets of a specific length range.
The operator who designs the prefix-list must choose the operator that matches the intended prefix-length range. The wrong operator (e.g., ge 25 instead of ge 26) is a common bug.
The wildcard semantics in ge and le
The ge and le values are inclusive bounds. ge 26 means “prefix-length ≥ 26”. le 28 means “prefix-length ≤ 28”. The range is closed on both ends.
The ge value must be strictly greater than the prefix-length in the original entry. 198.51.100.0/24 ge 24 is rejected — the ge value must be greater than the prefix-length. The system enforces this constraint.
The le value can be any value ≥ the prefix-length. 198.51.100.0/24 le 24 is permitted (and equivalent to no operator on the prefix-length part). 198.51.100.0/24 le 32 is permitted (matches all longer subnets).
The phrase-by-phrase walk
The operator who designs a prefix-list walks the rules in order and confirms the semantics:
set policy prefix-list MY-FILTER rule 10 action 'permit'
set policy prefix-list MY-FILTER rule 10 prefix '198.51.100.0/24'
The phrase-by-phrase walk:
set policy prefix-list MY-FILTER— the prefix-list name isMY-FILTER.rule 10— this is rule 10. The rules are evaluated in order.action 'permit'— the rule’s action is permit.prefix '198.51.100.0/24'— the rule matches the prefix exactly with no operator.
The rule accepts only 198.51.100.0/24. Every other route is rejected by the implicit deny.
set policy prefix-list MY-FILTER rule 20 action 'permit'
set policy prefix-list MY-FILTER rule 20 prefix '198.51.100.0/24'
set policy prefix-list MY-FILTER rule 20 ge '26'
The second rule:
prefix '198.51.100.0/24'— the prefix part is exactly198.51.100.0.ge '26'— the prefix-length must be ≥ 26.
The rule accepts 198.51.100.0/26, 198.51.100.0/27, 198.51.100.0/28, etc. It does not accept 198.51.100.0/24 or 198.51.100.0/25.
The two rules together accept 198.51.100.0/24 and any more-specific subnet of 198.51.100.0/24 with prefix-length ≥ 26. The intent is “accept the prefix and its subnets, but not subnets like /25”.
The “first match wins” rule
The first rule that matches the route wins. The subsequent rules are not evaluated. This is the canonical “first match wins” semantics, the same as firewall rules and route-maps.
The operator who designs a prefix-list with a permit 198.51.100.0/24 rule followed by a deny 198.51.100.0/16 le 20 rule sees the deny rule never fire for 198.51.100.0/24 — the permit rule matches first. The deny rule fires for other prefixes in 198.51.100.0/16 with prefix-length ≤ 20.
The operator who wants the deny rule to fire for 198.51.100.0/24 must put the deny rule first. The rule order is the operator’s lever.
The sequence number and the rule insertion
The rule number is also called the sequence number. The numbers are integers (typically 10, 20, 30, …) with gaps for future insertion. The operator who inserts a new rule between rules 10 and 20 uses rule 15:
set policy prefix-list MY-FILTER rule 15 action 'deny'
set policy prefix-list MY-FILTER rule 15 prefix '198.51.100.0/24'
set policy prefix-list MY-FILTER rule 15 ge '32'
The new rule is rule 15, evaluated between rule 10 and rule 20. The evaluation order is: 10, 15, 20, 30, …
The operator who uses sparse numbers (10, 20, 30) has room to insert new rules without renumbering. The operator who uses dense numbers (1, 2, 3) ends up renumbering every time a new rule is inserted.
The description field
Each rule has an optional description field. The description is included in the rendered FRR configuration as a comment:
set policy prefix-list MY-FILTER rule 10 description 'customer edged routes'
The rendered FRR configuration:
ip prefix-list MY-FILTER seq 10 permit 198.51.100.0/24
! customer edged routes
The description is a comment, not an active rule. The operator who documents the intent of each rule with a description makes the prefix-list self-documenting.
How the result is validated
show policy prefix-list
show ip bgp neighbors <ip> received-routes
show ip bgp neighbors <ip> routes
vtysh -c 'show ip prefix-list'
vtysh -c 'show ip prefix-list MY-FILTER'
The first command shows the prefix-list configuration. The second shows the routes the peer sent (before the filter). The third shows the routes that passed the filter. The fourth and fifth show the FRR-level prefix-list.
For deep debugging:
vtysh -c 'show ip prefix-list MY-FILTER 198.51.100.0/26'
The command shows which rule matched a specific prefix. The operator who is debugging a wrong permit/deny decision finds the matching rule in the output.
How it fails
The production failure modes the engineer must recognise:
- Implicit deny catching a route the operator expected to accept. The operator configures a permit rule but the implicit deny fires for a route they expected to be accepted. The fix is to add a catch-all permit rule.
- The wrong operator chosen. The operator uses
ge 26instead ofge 25, missing a subnet length. The fix is to correct the operator. - The wrong prefix-length range. The operator uses
le 26instead ofle 28, accepting fewer subnets than expected. The fix is to correct the range. - The rule order is wrong. The operator puts the deny rule before the permit rule. The deny rule fires first. The fix is to reorder the rules.
- The prefix-list is applied to the wrong direction. The operator applies the prefix-list inbound when the intent was outbound (or vice versa). The fix is to apply the prefix-list in the correct direction.
- The prefix-list is referenced by name but not defined. The operator references a prefix-list that does not exist. The commit fails at validator time. The fix is to define the prefix-list before referencing it.
Rollback
Prefix-list changes are configuration changes. The standard rollback path applies:
comparebeforecommitto see the prefix-list addition.commit-confirm <timeout>for any remote change.rollback N; commit; saveto revert to the previous configuration.load /config/archive/<known-good-file>; commit; saveto revert to a specific snapshot.
The operator who changes a prefix-list on a production router must also know how to roll back the change. The standard rollback is rollback 1; commit; save — the previous configuration had the old prefix-list, so the rollback restores it.
Production discipline
Cross-course references
The Linux course’s XIX-Linux-NetFoundations covers the kernel FIB. The OPNsense course’s XXX-OPNsense-DynamicRouting covers the same FRR prefix-list pattern on the firewall side. The BGP lessons vyos-xxvi-02-as-path (the AS_PATH attribute in detail) and vyos-xxviii-02-prefix-list-config (the configuration patterns) cover the broader context. The lesson vyos-xxviii-03-distribute-list covers the application of prefix-lists to BGP neighbours. The lesson vyos-xxviii-06-filter-troubleshoot walks the debugging of filter failures.
Quiz
Knowledge check · 4 questions
Q1. A prefix-list has the rule `permit 198.51.100.0/24 ge 26`. Which of the following routes does this rule match?
Q2. A prefix-list with a single `permit 198.51.100.0/24` rule accepts all routes except `198.51.100.0/24`.
Q3. An operator designs a prefix-list to accept `198.51.100.0/24` and any more-specific subnet with prefix-length ≥ 26. The operator adds rule 10 `permit 198.51.100.0/24 ge 26`. The operator expected the rule to accept the /24 and the more-specific subnets. The rule only accepts the more-specific subnets. Why?
The rule `198.51.100.0/24 ge 26` matches prefixes with prefix ≥ 26. The /24 has prefix-length 24, which is less than 26. The rule does not match the /24.
Q4. An operator has a prefix-list with rules 10, 20, 30. The operator wants to insert a new deny rule between rule 10 and rule 20. The operator uses rule 15. The commit fails with a validator error. What is the most likely cause?
The operator adds `set policy prefix-list MY-FILTER rule 15 action 'deny'` and the commit fails. The most likely cause is a missing prefix clause or operator constraint violation.
Passing score: 75%. Answers are checked in this browser.