Skip to content

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 messages
  • drop FILTER: remove matching messages
  • STAGE --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):

[!] attribute[index] [operator value] [&& | ||] ...
  • ( ... ) - group expressions
  • ! - negate an expression
  • attribute - what to test (e.g., prefix, aspath, community)
  • [index] - optional selector within the attribute
  • operator 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 false for UPDATE-only attributes. Use type conditions 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) || C instead of A && 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:

med == 0                       # MED is zero
med > 100                      # MED above 100
med                            # has MED attribute

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:

otc                            # has OTC attribute
otc == 65001                   # OTC value is 65001

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