Skip to content

Route Selection and Filters

Routing filters and route selection rules provide powerful mechanisms for controlling how routes are imported, exported, and selected in RouterOS. Routing filters use a script-like syntax that enables complex matching conditions and actions on route attributes, allowing network administrators to implement sophisticated routing policies. Route selection rules complement filters by providing additional control over how the router chooses between multiple candidate routes for output.

Understanding routing filters is essential for networks that require fine-grained control over route propagation, whether for security policy enforcement, traffic engineering, BGP community management, or compliance with upstream provider requirements. RouterOS v7 introduced a significantly updated filter syntax that differs from RouterOS v6, requiring administrators to adapt their existing filter configurations.

This documentation covers filter syntax and structure, readable and writeable route properties, available operators and commands, BGP community management, AS-PATH regular expression matching, community lists, route selection rules, and the routing filter wizard introduced in RouterOS v7.20.

Routing filters in RouterOS implement a script-like syntax that enables flexible route manipulation. A filter rule consists of matchers that evaluate route properties and actions that specify what to do with matching routes. The basic structure follows an if-then-else pattern where matchers are evaluated and corresponding actions are executed.

/routing filter rule add \
chain=myChain \
rule="if (dst in 192.168.1.0/24 && dst-len > 24) {set distance +1; accept} else {set distance -1; accept}"

The filter rule structure supports multiple matchers combined with logical operators and multiple actions within each branch. Matchers evaluate route properties against specified values or other properties, while actions modify route attributes or accept/reject the route. The syntax distinguishes between readable properties that can only be used in matchers and writeable properties that can be modified by actions.

Filter rules are organized into chains, which allow for modular filter design and reuse. A chain is a named sequence of filter rules that are evaluated in order. When a route matches a rule in a chain, the specified action is executed. If no explicit accept or reject action is taken, the default action depends on the chain configuration.

# Example: Simple filter that accepts connected routes and rejects everything else
/routing filter rule add chain=connected-filter rule="if (protocol == connected) {accept}"

Understanding the default behavior is critical: the default action of a routing filter chain is “reject.” Routes that reach the end of a chain without matching any rule that explicitly accepts them will be rejected. This default rejection behavior ensures that filters provide an explicit allowlist rather than an implicit deny.

Readable properties are route attributes that can be evaluated in filter matchers but cannot be directly modified by filter actions. These properties provide information about the route’s origin, path, protocol, and various protocol-specific attributes. Understanding which properties are available for matching is essential for creating effective filters.

Numeric Properties:

The numeric readable properties include destination prefix length (dst-len), BGP AS-PATH length (bgp-path-len), and various protocol-specific metrics. The dst-len property represents the prefix length in bits, allowing filters to match routes based on their specificity. BGP-related numeric properties include the input and output local and remote AS numbers, which are useful for identifying the peer relationships through which a route was learned or will be advertised.

OSPF and RIP protocols contribute their own metric and tag properties. The ospf-metric and rip-metric properties represent the respective protocol’s cost or hop count, while ospf-tag and rip-tag provide arbitrary tagging values that can be used for route classification or policy enforcement.

# Example: Match routes with prefix length between 16 and 24
/routing filter rule add chain=myChain rule="if (dst-len >= 16 && dst-len <= 24) {accept}"

Flag Properties:

Flag properties indicate boolean states about a route and are used without comparison operators in matchers. The active flag indicates whether a route is currently installed in the routing table as the best path. The bgp-communities-empty, bgp-ext-communities-empty, and bgp-large-communities-empty flags indicate whether respective BGP community attributes are present on the route.

The ospf-dn flag specifically indicates whether an OSPF route has the DN bit set, which is relevant in OSPFv2 VPN environments where the DN bit prevents route loops. The bgp-atomic-aggregate flag indicates that the route is an atomic aggregate, meaning information has been lost through route aggregation.

# Example: Reject routes that do not have BGP communities
/routing filter rule add chain=myChain rule="if (!bgp-communities-empty) {accept}"

Prefix Properties:

Prefix properties hold IP address values and are matched using prefix-specific operators. The dst property represents the destination prefix itself, while various bgp-input-remote-addr, bgp-output-local-addr, and similar properties hold the IP addresses of BGP peers involved in the route’s propagation. The ospf-fwd property holds the OSPF forwarding address for external routes.

# Example: Match routes from a specific BGP peer
/routing filter rule add chain=myChain rule="if (bgp-input-remote-addr == 203.0.113.1) {accept}"

Other Readable Properties:

The afi property indicates the address family of the route, with values including ipv4, ipv6, l2vpn, l2vpn-cisco, vpnv4, and vpnv6. The protocol property identifies the routing protocol from which the route was learned, with values including bgp, connected, dhcp, ospf, rip, static, and others.

The bgp-as-path property enables AS-PATH matching using regular expressions, which is covered in detail in the AS-PATH Regexp Matching section. The origin property matches the route’s origin instance, useful when filtering routes imported from specific OSPF instances. The ospf-type property matches the OSPF route type: ext1, ext2, inter, intra, nssa1, or nssa2.

The rtab property specifies the routing table name from which the route was imported, while the vrf property specifies the VRF name. The rpki property indicates the RPKI validation status: valid, invalid, unknown, or unverified.

Writeable properties can be modified by filter actions to change route attributes. These properties control how routes are selected, prioritized, and propagated. Modifying writeable properties is the primary mechanism for implementing traffic engineering and policy-based routing.

Numeric Writeable Properties:

The distance property sets the administrative distance for a route, affecting how RouterOS prioritizes routes from different sources. Lower distance values take precedence, so a static route (default distance 1) will be preferred over an OSPF route (default distance 110). Setting distance in filters allows for implementing backup paths or preferring certain routes based on policy.

# Example: Increase distance for routes learned from a specific peer to use as backup
/routing filter rule add chain=backup-filter \
rule="if (bgp-input-remote-as == 64500) {set distance +10; accept}"

The scope and scope-target properties control route visibility and selection scope within RouterOS. The bgp-weight property sets the BGP weight attribute, which is a Cisco-defined attribute used for local route selection within the local AS. The bgp-local-pref property sets the BGP LOCAL_PREF attribute, which is critical for traffic engineering within an AS.

The bgp-med and bgp-out-med properties control the BGP MULTI_EXIT_DISC attribute. The bgp-med is the received MED value, while bgp-out-med is the MED to send to peers. The bgp-igp-metric property sets the IGP metric that BGP uses when comparing routes from different next hops.

The bgp-path-peer-prepend and bgp-path-prepend properties prepend AS numbers to the AS-PATH. The bgp-path-peer-prepend prepends the remote peer’s ASN when receiving routes, while bgp-path-prepend prepends the local ASN when advertising routes. These are commonly used for traffic engineering to influence inbound traffic flows.

# Example: Prepend local AS twice to influence inbound traffic
/routing filter rule add chain=bgp-out \
rule="if (protocol == bgp) {set bgp-path-prepend 2; accept}"

Gateway Properties:

The gw property sets the next-hop gateway for a route, accepting either an IP address or an interface name. The gw-ll property specifically sets the IPv6 link-local next-hop. The gw-interface property attaches a specific interface to the next-hop, useful when dealing with routing table lookups that require interface context.

The gw-check property controls how the router validates the next-hop reachability, with options including none, arp, icmp, and bfd. This is particularly important for BGP sessions where next-hop reachability must be verified before accepting routes.

# Example: Set specific next-hop and interface
/routing filter rule add chain=myChain \
rule="if (dst in 10.0.0.0/8) {set gw 192.168.1.1; set gw-interface ether1; accept}"

BGP Community Properties:

The bgp-communities, bgp-ext-communities, and bgp-large-communities properties control BGP community attributes. Communities are 32-bit values (standard), 64-bit values (extended), or 12-byte values (large) that carry policy information. These are fundamental to implementing complex BGP policies with upstream providers.

# Example: Add community to routes before advertising
/routing filter rule add chain=bgp-out \
rule="if (protocol == bgp) {set bgp-communities 64500:100; accept}"

Flag Writeable Properties:

The blackhole property creates a blackhole route that discards matching traffic. The suppress-hw-offload property prevents hardware offloading for the route, useful when troubleshooting routing issues or when software processing is required. The use-te-nexhop property relates to traffic engineering next-hops in MPLS environments.

Filter commands define the actions taken when a route matches the specified conditions. Understanding the available commands and their effects is essential for creating correct filter policies.

Accept and Reject:

The accept command accepts the route, allowing it to continue through the routing process. The reject command rejects the route, storing it as “filtered” so it does not become a candidate for best-path selection. Both commands terminate rule processing for the matching route.

# Example: Accept routes from a trusted peer, reject others
/routing filter rule add chain=trusted-peer \
rule="if (bgp-input-remote-as == 64500) {accept}"
/routing filter rule add chain=trusted-peer \
rule="if (protocol == bgp) {reject}"

Chain Control Commands:

The return command returns to the parent chain, allowing processing to continue with subsequent rules in the calling chain. The jump command jumps to a specified chain, enabling modular filter design. Chains can call other chains, creating reusable filter modules.

# Example: Jump to a common filter chain for standard processing
/routing filter rule add chain=bgp-in \
rule="if (protocol == bgp) {jump standard-bgp-filter}"

Property Manipulation Commands:

The set command assigns a value to a writeable property. For numeric properties, values can be prefixed with + or - to increment or decrement the current value. Values can also be copied from other readable properties of compatible types.

# Example: Set distance based on OSPF metric
/routing filter rule add chain=myChain \
rule="if (protocol == ospf) {set distance +ospf-metric; accept}"

The unset command clears the value of specific properties, including pref-src, bgp-med, bgp-out-med, and bgp-local-pref. The append command adds values to the end of list or string properties. The filter command acts as an inverse delete, keeping only specified values. The delete command removes specific values from community properties.

# Example: Remove specific BGP communities
/routing filter rule add chain=clean-communities \
rule="if (protocol == bgp) {delete bgp-communities 64500:999; accept}"

The rpki-verify command enables RPKI validation in the current chain using a specified RPKI group.

Operators define how property values are compared and combined in matchers. RouterOS supports different operator types for different property categories.

Matcher Logical Operators:

The && operator performs logical AND, requiring all specified conditions to be true. The || operator performs logical OR, requiring at least one condition to be true. The not operator negates a condition.

# Example: Match routes from a specific subnet with specific prefix length
/routing filter rule add chain=myChain \
rule="if (dst in 192.168.0.0/16 && dst-len in 24-32) {accept}"

Numeric Property Operators:

Numeric properties support comparison operators including == (equal), != (not equal), > (greater than), < (less than), >= (greater than or equal), and <= (less than or equal). The in operator matches values within a specified numeric range.

# Example: Match routes with BGP MED less than 100
/routing filter rule add chain=bgp-filter \
rule="if (bgp-med < 100) {accept}"

Prefix Property Operators:

Prefix properties use the in operator to match prefixes within a network. When matching against address lists, only exact prefix matches are performed. The == and != operators perform exact prefix equality comparisons.

# Example: Match prefixes from an address list
/routing filter rule add chain=myChain \
rule="if (dst in my-address-list) {accept}"

BGP Community Operators:

Community operators provide sophisticated matching capabilities for BGP communities. The equal operator matches routes with exactly the specified communities. The any operator matches routes containing at least one of the specified communities. The includes operator matches routes containing all specified communities. The subset operator matches routes where the communities are a subset of the specified list.

# Example: Match routes with specific communities
/routing filter rule add chain=bgp-filter \
rule="if (bgp-communities any 64500:100,64500:200) {accept}"

String Operators:

String properties support the find operator to check for substring presence and the regexp operator for regular expression matching. These are useful for matching BGP AS-PATH strings or other text-based properties.

BGP communities are optional transitive attributes that carry policy information between BGP speakers. Communities allow network operators to tag routes with identifying information that other routers can use to apply consistent policies. Standard communities are 32-bit values typically written as AS-number:community-value. Extended communities are 64-bit values supporting additional types like route-target and site-of-origin. Large communities are 12-byte values supporting 32-bit AS numbers.

RouterOS provides comprehensive support for managing BGP communities through routing filters. Communities can be matched, added, modified, or removed as routes pass through filters. This capability is essential for implementing provider policies, traffic engineering, and complex routing architectures.

The delete command removes specific communities from routes. Different syntax applies depending on the community type being manipulated.

Standard Communities:

For standard BGP communities, the delete command accepts “wk” to remove well-known communities (such as NO_EXPORT or NO_ADVERTISE), “other” to remove non-well-known communities, a regular expression pattern, or a community-list name.

# Example: Remove all well-known communities from routes
/routing filter rule add chain=clean-communities \
rule="if (protocol == bgp) {delete bgp-communities wk; accept}"
# Example: Remove communities matching a regular expression
/routing filter rule add chain=clean-communities \
rule="if (protocol == bgp) {delete bgp-communities regexp \"64500:.*\"; accept}"

Extended Communities:

Extended community deletion supports “rt” for route-target communities, “soo” for site-of-origin communities, “other” for other extended communities, a regular expression, or an extended community list name.

# Example: Remove route-target extended communities
/routing filter rule add chain=vpn-filter \
rule="if (protocol == bgp) {delete bgp-ext-communities rt; accept}"

Large Communities:

Large community deletion supports “all” to remove everything, a regular expression, or a large community list name.

Community lists provide a named collection of communities that can be referenced in filters. Lists simplify filter management by centralizing community definitions and enabling reuse across multiple filter rules.

# Create a community list
/routing/filter/community-list add communities=64500:100,64500:200 list=my-communities
# Use the community list in a filter
/routing filter rule add chain=bgp-filter \
rule="if (bgp-communities any-list my-communities) {accept}"

The set command replaces communities, while the append command adds communities to existing values. This allows for implementing policies that tag routes with additional community information.

# Example: Append a community to routes from a specific peer
/routing filter rule add chain=bgp-in \
rule="if (bgp-input-remote-as == 64500) {append bgp-communities 64500:300; accept}"

The AS-PATH attribute is a sequence of autonomous system numbers that a route has traversed. When a route is originated by an AS, the AS-PATH contains only that AS number. As the route is advertised to neighboring ASes, each AS prepends its AS number to the beginning of the AS-PATH. The AS-PATH thus records the sequence of autonomous systems that a route has passed through, in reverse order of propagation.

AS-PATH matching is fundamental to BGP policy implementation. Common use cases include filtering routes from specific ASes, preventing route loops, implementing inbound traffic engineering by accepting or rejecting routes based on AS-PATH contents, and validating route origin.

RouterOS v7 implements AS-PATH matching at the ASN level rather than the character level, which differs significantly from RouterOS v6 and Cisco implementations. This means regular expressions operate on whole AS numbers rather than individual characters in the AS-PATH string.

In RouterOS v7, a regular expression like “.1234.” matches ASN 1234 appearing anywhere in the AS-PATH, treating “1234” as a complete AS number. In RouterOS v6, the same pattern would match any string containing “1234” as a substring within the AS-PATH string, which could match unintended AS numbers.

# RouterOS v7: Match routes that passed through ASN 1234
/routing filter rule add chain=myChain \
rule="if (bgp-as-path .1234.) {accept}"

This difference has significant implications for administrators migrating configurations from RouterOS v6 or other platforms. A pattern that worked correctly in v6 may produce unexpected results in v7, and vice versa.

RouterOS v7 AS-PATH regular expressions support the following operators:

The ^ operator matches the beginning of the AS-PATH, ensuring the specified ASN or pattern is at the start. The $ operator matches the end of the AS-PATH, ensuring the specified ASN or pattern is at the origin.

# Match routes originated by ASN 1234
/routing filter rule add chain=myChain \
rule="if (bgp-as-path ^1234\$) {accept}"
# Match routes that have passed through ASN 1234
/routing filter rule add chain=myChain \
rule="if (bgp-as-path .1234.) {accept}"

The * operator matches zero or more occurrences of the specified ASN. The + operator matches one or more occurrences. The ? operator matches zero or one occurrence.

# Match routes from ASN 1234 that may or may not appear (including null AS-PATH)
/routing filter rule add chain=myChain \
rule="if (bgp-as-path ^1234*\$) {accept}"
# Match routes that must have originated from ASN 1234
/routing filter rule add chain=myChain \
rule="if (bgp-as-path ^1234+\$) {accept}"

The . operator matches exactly one occurrence of any ASN. The | operator matches either of two ASNs or patterns. Parentheses group expressions for precedence.

# Match routes originated by either ASN 1234 or 5678
/routing filter rule add chain=myChain \
rule="if (bgp-as-path ^(1234|5678)\$) {accept}"
# Match routes with any single ASN in the AS-PATH
/routing filter rule add chain=myChain \
rule="if (bgp-as-path ^.\$) {accept}"

Square brackets define sets or ranges of ASNs. The [^] form negates the set. Num-lists can be referenced using [[:name:]] syntax.

# Match routes from ASNs in the range 1-100
/routing filter rule add chain=myChain \
rule="if (bgp-as-path ^[1-100] {accept}"

RouterOS provides a built-in tool for testing AS-PATH regular expressions before applying them to production filters. This tool helps prevent configuration errors by validating patterns against sample AS-PATH values.

# Create a num-list for testing
/routing/filter/num-list add list=test range=100-1500
# Test a regular expression
/routing/filter/test-as-path-regexp regexp=".*1234\$" as-path="64500,1234"

AS-PATH matching requires that an AS-PATH attribute exists. Routes without an AS-PATH (such as directly connected routes) cannot be matched using regular expressions. The bgp-path-len property should be used to match routes based on AS-PATH length when working with routes that may have empty AS-PATHs.

Repetition ranges using {} are not supported in RouterOS v7 AS-PATH regular expressions.

Num-lists provide named collections of numeric values that can be referenced in filter rules. They simplify filter management by centralizing common value definitions and enabling reuse across multiple rules.

# Create a num-list for BGP AS_PATH matching
/routing/filter/num-list add list=my-asns range=64500-64599
# Use the num-list in a filter
/routing filter rule add chain=myChain \
rule="if (bgp-as-path [[:my-asns:]]) {accept}"

Community lists define named collections of BGP communities for matching, appending, or setting. Extended community lists support route-target and site-of-origin communities. Large community lists support 12-byte large communities.

# Create standard community lists
/routing/filter/community-list add communities=64500:100,64500:200 list=my-communities
# Create extended community list
/routing/filter/community-ext-list add communities="rt:64500:1" list=my-rt
# Create large community list
/routing/filter/community-large-list add communities="64500:100:1" list=my-large

Route selection rules control how RouterOS chooses between multiple candidate routes when advertising routes to peers. By default, RouterOS selects the best route based on BGP path selection criteria. However, there are scenarios where administrators need custom selection logic, such as preferring routes based on local policy rather than standard BGP attributes.

Route selection rules are configured in the /routing/filter/select-rule menu. Select rules can be chained together and can optionally invoke routing filters to make selection decisions based on complex criteria.

# View routes in the routing table
/routing route print where dst-address=10.0.0.0/24

The routing table shows all candidate routes with their flags. The A flag indicates active routes (best path), while b and y flags indicate copies of the active route.

Select rules are organized into chains similar to filter chains. A select chain contains rules that are evaluated to determine which routes should be selected for output.

# Create a filter that selects active routes
/routing filter rule add chain=get_active rule="if (active) {accept}"
# Create a select rule chain that uses the filter
/routing filter select-rule add chain=my_select_chain do-where=get_active

This configuration demonstrates a basic selection rule that mimics default behavior by selecting only active routes. More complex selections can be implemented by modifying the filter criteria.

RouterOS v7.20 introduced the routing filter wizard to simplify filter creation. The wizard generates filter rules using a RouterOS v6-like syntax, making it easier for administrators familiar with older RouterOS versions to create filters without learning the new script-like syntax.

The wizard is accessed via /routing/filter/filter-wizard and provides tab-completion for available parameters.

[admin@router] /routing/filter> filter-wizard <tab>
action dst ospf-type scope-target set-gw-check
afi dst-len protocol set-bgp-ext-communities set-scope
bgp-as-path gateway routing-table set-blackhole set-scope-target
blackhole jump-target-chain rpki set-comment set-suppress-hw-offload
chain match-chain rpki-verify set-distance set-use-te-nexthop
distance ospf-metric scope set-gateway suppress-hw-offload

The wizard accepts parameters that specify matching criteria and actions. It generates the corresponding filter rule and adds it to the specified chain.

# Example: Accept VPNv4 routes and set extended community
/routing/filter/filter-wizard action=accept chain=vpn-in afi=vpnv4 \
set-bgp-ext-communities=rt:2:2

The wizard adds rules at the end of the specified chain and includes a comment indicating the rule was added by the wizard.

# View the generated rule
/routing/filter/rule/print
0 ;;; added by filter-wizard
chain=vpn-in rule="if (afi vpnv4) { set bgp-ext-communities rt:2:2; accept; }"

The wizard validates parameters and generates errors for invalid configurations. Error messages are printed to the CLI and logged to the system log with the “route,error” topic.

# Example error: creating a chain loop
/routing/filter/filter-wizard action=accept chain=vpn-in afi=vpnv4 match-chain=vpn-in
result: Error adding 'if (chain vpn-in && afi vpnv4) { accept; }'match with 'vpn-in' creates chain loop (6)

This filter accepts routes from a specific peer while rejecting all other BGP routes:

# Create the BGP input filter chain
/routing filter rule add chain=bgp-in
# Accept routes from a specific AS
/routing filter rule add chain=bgp-in \
rule="if (bgp-input-remote-as == 64500) {accept}"
# Reject all other BGP routes (default is reject, but explicit for clarity)
/routing filter rule add chain=bgp-in \
rule="if (protocol == bgp) {reject}"

This filter accepts only prefixes with lengths between /8 and /24:

# Accept prefixes with length 8 to 24
/routing filter rule add chain=prefix-filter \
rule="if (dst-len >= 8 && dst-len <= 24) {accept}"
# Reject everything else
/routing filter rule add chain=prefix-filter \
rule="if (protocol == bgp) {reject}"

This filter adds a community to routes from a specific peer and removes another community:

# Add community to routes from peer AS 64500
/routing filter rule add chain=community-filter \
rule="if (bgp-input-remote-as == 64500) {append bgp-communities 64500:100; accept}"
# Remove well-known communities
/routing filter rule add chain=community-filter \
rule="if (bgp-communities includes 64500:100) {delete bgp-communities wk; accept}"

This filter accepts routes originated by or passing through a specific AS:

# Accept routes from ASN 64500
/routing filter rule add chain=aspath-filter \
rule="if (bgp-as-path ^64500\$) {accept}"
# Accept routes that passed through ASN 64500
/routing filter rule add chain=aspath-filter \
rule="if (bgp-as-path .64500.) {accept}"
# Reject routes with long AS-PATHs (more than 4 AS hops)
/routing filter rule add chain=aspath-filter \
rule="if (bgp-path-len > 4) {reject}"

Example 5: Route Selection Based on Local Preference

Section titled “Example 5: Route Selection Based on Local Preference”

This filter sets local preference based on peer:

# Set higher local preference for routes from preferred peer
/routing filter rule add chain=lp-filter \
rule="if (bgp-input-remote-as == 64500) {set bgp-local-pref 200; accept}"
# Set lower local preference for backup peer
/routing filter rule add chain=lp-filter \
rule="if (bgp-input-remote-as == 64501) {set bgp-local-pref 100; accept}"

Routes not appearing after filter configuration often result from syntax errors in filter rules or rules not being applied to the correct chain. Always verify filter syntax with /routing/filter/rule print and ensure filters are attached to the correct BGP instance or peer.

Routes being rejected unexpectedly typically indicate that the default reject action is taking effect. Ensure explicit accept rules cover all intended routes and that rule order is correct.

BGP sessions not establishing may result from filters that reject all routes, including the BGP itself. Always ensure that BGP keepalive messages and the BGP session itself are not filtered.

Community modifications not taking effect may result from using the wrong community type (standard vs. extended vs. large) or syntax errors in community values.

# View filter rules
/routing/filter/rule print
# View filter chains
/routing/filter/chain print
# View BGP routes with filters applied
/routing/bgp/rib print
# View routes in the routing table
/routing route print
# Test AS-PATH regexp
/routing/filter/test-as-path-regexp
  • BGP - BGP routing protocol configuration
  • OSPF - OSPF routing protocol configuration
  • Route Management - Route management and manipulation
  • MPLS - MPLS configuration including label switching