Message Filters¶
Filters let you select BGP messages based on type, prefixes, AS path, origin, MED, LOCAL_PREF, communities, tags, and more.
They are used by the grep and drop stages, and by the --if and --of options on any stage.
grep FILTER: keep only matching messagesdrop FILTER: remove matching messagesSTAGE --if FILTER: skip stage processing for non-matching messages (input filter)STAGE --of FILTER: drop non-matching stage output (output filter)
Quick Examples¶
# keep only IPv6 updates from AS65000
bgpipe -o read updates.mrt.gz -- grep 'ipv6 && as_origin == 65000'
# drop non-IPv6 updates where AS_PATH ends with ASN matching 204xxx
bgpipe -o read updates.mrt.gz -- drop '!ipv6 && aspath ~ ,204[0-9]+$'
# only for UPDATEs from AS15169, keep those with prefixes overlapping 8.0.0.0/8
bgpipe -o read updates.mrt.gz -- grep --if 'as_origin == 15169' 'prefix ~ 8.0.0.0/8'
# drop routes with long AS paths or incomplete origin
bgpipe -o read updates.mrt.gz -- drop 'aspath_len > 10 || origin == incomplete'
# keep only routes with local_pref above default
bgpipe -o read updates.mrt.gz -- grep 'local_pref > 100'
Syntax¶
A filter is one or more expressions chained with && (AND) and || (OR):
( ... )- group expressions!- negate an expressionattribute- what to test (e.g.,prefix,aspath,community)[index]- optional selector within the attributeoperator value- comparison; when omitted, tests for attribute existence
Operators¶
| Operator | Aliases | Meaning |
|---|---|---|
== |
= |
Equal |
!= |
=! |
Not equal |
< |
Less than (attribute-specific semantics) | |
<= |
Less than or equal | |
> |
Greater than (attribute-specific semantics) | |
>= |
Greater than or equal | |
~ |
Match (attribute-specific: overlap, regex, containment) | |
!~ |
~! |
Negative match |
Values¶
- Unquoted tokens:
65000,8.0.0.0/8,UPDATE - Quoted strings:
"65000:100"(supports\\escaping) - Numbers: integers, floats, hex (
0x...)
Important Notes¶
- Most attributes apply to UPDATE messages only. Non-UPDATE messages (OPEN, KEEPALIVE, etc.) evaluate to
falsefor UPDATE-only attributes. Usetypeconditions for non-UPDATE matching. - The
~operator uses Go regexp syntax (not shell globs) when matching strings. &&and||are evaluated left to right with short-circuit. Use parentheses for explicit grouping when mixing operators:(A && B) || Cinstead ofA && B || C.
Attributes¶
Message Type¶
| Attribute | Operators | Description |
|---|---|---|
type |
==, != |
Explicit type comparison: UPDATE, OPEN, KEEPALIVE, NOTIFY, REFRESH |
Shortcuts (no operator needed):
| Shortcut | Equivalent |
|---|---|
update |
type == UPDATE |
open |
type == OPEN |
keepalive |
type == KEEPALIVE |
Examples:
update # match UPDATE messages
open || keepalive # match session control messages
!update # match everything except UPDATEs
type == NOTIFY # match NOTIFICATION messages
Address Family¶
| Attribute | Operators | Description |
|---|---|---|
af |
==, != |
Address family (AFI/SAFI). |
Shortcuts:
| Shortcut | Equivalent |
|---|---|
ipv4 |
af == IPV4/UNICAST |
ipv6 |
af == IPV6/UNICAST |
The af value can match by full AFI/SAFI (e.g., IPV4/UNICAST), by AFI alone (e.g., IPV4), or by SAFI alone (e.g., UNICAST).
Examples:
ipv4 && update # IPv4 unicast updates
ipv6 # IPv6 unicast
af == IPV4/FLOWSPEC # IPv4 Flowspec
af == IPV6 # any IPv6 (unicast, multicast, etc.)
af != UNICAST # non-unicast SAFI (e.g., flowspec, multicast)
Prefixes (NLRI)¶
| Attribute | Operators | Description |
|---|---|---|
prefix |
==, ~, <, <=, >, >= |
Any prefix (reach or unreach) |
reach |
==, ~, <, <=, >, >= |
Announced prefixes only |
unreach |
==, ~, <, <=, >, >= |
Withdrawn prefixes only |
Prefixes include both classic IPv4 NLRI and MP-BGP (MP_REACH/MP_UNREACH) prefixes.
Operator semantics for prefixes:
| Operator | Meaning |
|---|---|
== |
Exact match: same address and prefix length |
~ |
Overlap: message prefix and reference prefix overlap in any way |
< |
Message prefix is more specific (longer) than reference, and overlaps |
<= |
Message prefix is more specific or equal, and overlaps |
> |
Message prefix is less specific (shorter) than reference, and overlaps |
>= |
Message prefix is less specific or equal, and overlaps |
By default, a match succeeds if any prefix in the message matches. Use prefix[*] to require all prefixes to match.
Examples:
prefix ~ 8.0.0.0/8 # any prefix overlapping 8.0.0.0/8
reach == 203.0.113.0/24 # exact announcement
unreach ~ 2001:db8::/32 # any IPv6 withdrawal overlapping 2001:db8::/32
prefix < 10.0.0.0/8 # more specific than /8 (e.g., 10.1.0.0/16)
prefix > 10.1.0.0/16 # less specific than /16 (e.g., 10.0.0.0/8)
prefix[*] ~ 8.0.0.0/8 # ALL prefixes in message overlap 8.0.0.0/8
Next-Hop¶
| Attribute | Operators | Description |
|---|---|---|
nexthop |
==, ~, <, <=, >, >= |
Next-hop IP address |
nh |
(alias for nexthop) |
Operator semantics for next-hop:
| Operator | Meaning |
|---|---|
== |
Exact IP address match |
~ |
Next-hop is contained in the given CIDR prefix |
<, <=, >, >= |
Numeric IP address comparison |
Examples:
nh == 192.0.2.1 # exact next-hop match
nexthop ~ 2001:db8::/64 # next-hop within this IPv6 prefix
nexthop ~ 0.0.0.0/0 # any next-hop (always matches)
AS Path¶
| Attribute | Operators | Description |
|---|---|---|
aspath |
==, ~, <, <=, >, >= |
Full AS_PATH |
aspath[N] |
==, <, <=, >, >= |
Specific hop by index |
aspath[*] |
==, <, <=, >, >= |
Any hop matches |
as_origin |
==, <, <=, >, >= |
Origin AS (last hop, index -1) |
as_upstream |
==, <, <=, >, >= |
Upstream of origin (index -2) |
as_peer |
==, <, <=, >, >= |
Peer AS (first hop, index 0) |
aspath_len |
==, <, <=, >, >= |
AS_PATH length (hop count) |
aspath_hops |
==, <, <=, >, >= |
Unique consecutive hops (ignores prepending) |
Index rules:
- Positive:
aspath[0]is the first (leftmost) AS,aspath[1]is second, etc. - Negative:
aspath[-1]is the last (origin) AS,aspath[-2]is the upstream, etc. - Wildcard:
aspath[*]matches if any hop satisfies the comparison.
Operator semantics:
| Operator | Without index | With index |
|---|---|---|
| (none) | AS_PATH exists and is non-empty | - |
== (int) |
Any hop equals the value | Specific hop equals the value |
== (string) |
Full path string matches exactly | - |
~ (regex) |
Regex match on JSON path text | - |
<, <=, >, >= |
Any hop ASN satisfies comparison | Specific hop ASN satisfies comparison |
The ~ regex matches against the JSON representation of the AS path (comma-separated ASNs without brackets).
Examples:
as_origin == 15169 # originated by AS15169
as_peer != 64512 # peer is not AS64512
aspath[1] == 3356 # second hop is AS3356
aspath[-2] == 3356 # upstream of origin is AS3356
aspath ~ ",15169," # AS15169 appears anywhere in the path
aspath ~ "^15169," # path starts with AS15169
aspath_len > 5 # reject long paths
aspath_len == 0 # no AS_PATH (direct peering or incomplete)
aspath_hops == 1 # single unique origin
aspath[*] > 64511 # any hop ASN > 64511
Origin¶
| Attribute | Operators | Description |
|---|---|---|
origin |
==, != |
BGP ORIGIN attribute |
Values: igp (or i, 0), egp (or e, 1), incomplete (or ?, 2).
Without an operator, tests for the attribute's existence.
Examples:
origin == igp # originated via IGP
origin != incomplete # not incomplete origin
origin # has ORIGIN attribute set
MED¶
| Attribute | Operators | Description |
|---|---|---|
med |
==, <, <=, >, >= |
Multi-Exit Discriminator |
metric |
(alias for med) |
Without an operator, tests for the attribute's existence.
Examples:
LOCAL_PREF¶
| Attribute | Operators | Description |
|---|---|---|
local_pref |
==, <, <=, >, >= |
LOCAL_PREF value |
localpref |
(alias for local_pref) |
Without an operator, tests for the attribute's existence.
Examples:
local_pref == 100 # default local preference
local_pref > 100 # preferred routes
localpref <= 50 # low-preference routes
OTC (Only To Customer)¶
| Attribute | Operators | Description |
|---|---|---|
otc |
==, <, <=, >, >= |
OTC attribute (RFC 9234) |
only_to_customer |
(alias for otc) |
Without an operator, tests for the attribute's existence.
Examples:
Communities¶
| Attribute | Operators | Description |
|---|---|---|
community, com |
==, ~ |
Standard communities |
ext_community, ext_com, com_ext |
==, ~ |
Extended communities |
large_community, large_com, com_large |
==, ~ |
Large communities |
Operator semantics:
| Operator | Meaning |
|---|---|
| (none) | Community attribute exists (has any value) |
== |
Message has an exact community value |
~ |
Regex match against JSON text of all communities |
The ~ regex matches against the JSON representation. For standard communities, this is "ASN:VALUE" strings. For extended communities, the JSON contains the full structure with type names like TARGET, IP4_TARGET, etc. (see JSON Format).
Examples:
community # has any standard community
community == "3356:100" # has exact community 3356:100
community ~ "3356:" # any community with ASN 3356
community !~ "3356:" # no standard community from ASN 3356
com_large ~ "1234:5678:9" # large community matching pattern
ext_community ~ "TARGET" # has any Route Target extended community
Tags¶
| Attribute | Operators | Description |
|---|---|---|
tag, tags |
==, ~ |
Pipeline metadata tags |
tag[KEY] |
==, ~ |
Specific tag by key name |
Tags are key-value pairs attached to messages by the tag stage and other stages (e.g., ris-live adds PEER_AS, PEER_IP; rpki adds rpki/status).
Tag filters work on all message types (not just UPDATEs).
| Operator | Without index | With [KEY] |
|---|---|---|
| (none) | Any tag has a non-empty value | Tag KEY has a non-empty value |
== |
Any tag value equals the string | Tag KEY equals the string |
~ |
Any tag value matches the regex | Tag KEY matches the regex |
Examples:
tag[rpki/status] == INVALID # RPKI validation failed
tag[PEER_AS] == "8218" # from RIS peer AS8218
tags[region] ~ "^eu-" # region tag starts with "eu-"
tag[rpki/status] != VALID # anything except VALID
Message Metadata¶
These attributes work on all message types (not just UPDATEs).
| Attribute | Operators | Description |
|---|---|---|
dir, direction |
==, != |
Message direction (L or R) |
seq, sequence |
==, <, <=, >, >= |
Message sequence number |
time, timestamp |
==, <, <=, >, >=, ~ |
Message timestamp |
The time attribute compares against timestamps. Values are parsed flexibly (e.g., "2023-03-01", "2023-03-01T12:30:45.000"). The ~ operator matches against the ISO 8601 string representation.
Without an operator, tests for a non-zero value.
Examples:
dir == L # messages from the left side
dir != R # not from the right side
seq > 100 # sequence number above 100
time > "2023-01-01" # after January 1, 2023
time ~ "^2023-03" # any time in March 2023
JSON Path Extraction¶
These attributes extract values from the message's JSON representation. The json attribute works on all message types, whereas the attr attribute works for UPDATEs only.
| Attribute | Operators | Description |
|---|---|---|
json[PATH] |
==, <, <=, >, >=, ~ |
Extract value at JSON path |
attr[ATTR.PATH] |
==, <, <=, >, >=, ~ |
Shortcut for attribute values |
The json attribute uses a dot-separated path to navigate the message data JSON (type-specific representation). The attr attribute is a convenience shortcut: attr[ORIGIN] is equivalent to json[attrs.ORIGIN.value], and attr[MP_REACH.af] is equivalent to json[attrs.MP_REACH.value.af].
Array indexing: Numeric path segments are treated as array indices. For example, json[reach.0] accesses the first element of the reach array, and attr[COMMUNITY.0] accesses the first community value.
Attribute names in attr[...] are case-insensitive and resolved against known BGP attribute codes (with or without ATTR_ prefix).
Without an operator, tests for the path's existence. Numeric comparisons (<, <=, >, >=) parse the extracted value as a number.
Examples:
json[attrs.ORIGIN.value] == IGP # ORIGIN is IGP
json[attrs.MED.value] > 100 # MED value above 100
json[reach.0] ~ "10\." # first announced prefix starts with 10.
attr[ORIGIN] == IGP # same as json[attrs.ORIGIN.value] == IGP
attr[MED] > 100 # same as json[attrs.MED.value] > 100
attr[COMMUNITY.0] ~ "^3356:" # first community is from AS3356
attr[MP_REACH.af] == "IPV4/FLOWSPEC" # MP_REACH address family
Operator Compatibility¶
Not all operators work with all attributes. This table summarizes:
!= and !~ are supported wherever == and ~ are supported (they are parsed as negated forms).
| Attribute | == |
< <= > >= |
~ !~ |
|---|---|---|---|
type |
yes | ||
af |
yes | ||
prefix |
yes | yes (specificity) | yes (overlap) |
nexthop |
yes | yes (numeric IP) | yes (containment) |
aspath |
yes | yes (ASN value) | yes (regex) |
aspath_len |
yes | yes (hop count) | |
aspath_hops |
yes | yes (hop count) | |
origin |
yes | ||
med |
yes | yes (uint32) | |
local_pref |
yes | yes (uint32) | |
otc |
yes | yes (uint32) | |
community |
yes | yes (regex) | |
ext_community |
yes | yes (regex) | |
large_community |
yes | yes (regex) | |
tag |
yes | yes (regex) | |
dir |
yes | ||
seq |
yes | yes (int64) | |
time |
yes | yes (timestamp) | yes (regex) |
json |
yes | yes (numeric) | yes (regex) |
attr |
yes | yes (numeric) | yes (regex) |
See Also¶
- grep / drop - Stages that use filters
- JSON Format - BGP message JSON structure (community
~matches against this) - Examples - Practical bgpipe pipelines