Bird2 is a commonly used BGP daemon. This page provides configuration and help for using BGP communities with Bird2 for dn42.
Communities can be used to prioritize traffic based on different flags, in DN42 we are using communities to prioritize based on latency, bandwidth and encryption. Please note that everyone should be using community 64511.
The community is applied to the route when it is imported and exported, therefore you need to change your bird configuration in /etc/bird/peers/*
The filter helpers can be stored in a separate file, for example /etc/bird/community_filters.conf.
Below, you will see an example config for peers based on the original filter implementation by Jplitza. Additionally the below configuration applied BGP MED on exports using the communities as an example for what they can be used for. This is based on mk16's lab implemenation at https://mk16.de/blog/lab-en/
To properly assign the right community to your peer, please reference the table below. If you are running your own network and peering internally, please also apply the communities inside your network.
BGP community criteria
(64511, 1) :: latency \in (0, 2.7ms]
(64511, 2) :: latency \in (2.7ms, 7.3ms]
(64511, 3) :: latency \in (7.3ms, 20ms]
(64511, 4) :: latency \in (20ms, 55ms]
(64511, 5) :: latency \in (55ms, 148ms]
(64511, 6) :: latency \in (148ms, 403ms]
(64511, 7) :: latency \in (403ms, 1097ms]
(64511, 8) :: latency \in (1097ms, 2981ms]
(64511, 9) :: latency > 2981ms
(64511, x) :: latency \in [exp(x-1), exp(x)] ms (for x < 10)
(64511, 21) :: bw >= 0.1mbit
(64511, 22) :: bw >= 1mbit
(64511, 23) :: bw >= 10mbit
(64511, 24) :: bw >= 100mbit
(64511, 25) :: bw >= 1000mbit
(64511, 2x) :: bw >= 10^(x-2) mbit
bw = min(up,down) for asymmetric connections
(64511, 31) :: not encrypted
(64511, 32) :: encrypted with unsafe vpn solution
(64511, 33) :: encrypted with safe vpn solution (but no PFS - the usual OpenVPN p2p configuration falls in this category)
(64511, 34) :: encrypted with safe vpn solution with PFS (Perfect Forward Secrecy)
Propagation:
- - for latency pick max(received_route.latency, link_latency)
- - for encryption and bandwidth pick min between received BGP community and peer link
For example, if your peer is 12ms away and the link speed between you is 250Mbit/s and you are peering using OpenVPN P2P, then the community string would be (3, 24, 33).
Two utilities which measure round trip time and calculate community values automatically are provided, written in ruby and C.
Note: In general, the link latency metric only reflects the latency of the immediate link, and not the overall latency from following a path. A route may traverse multiple internal routers once it enters an AS, and because this is invisible to BGP, it's best to treat latency values as informational only and not use them to make routing decisions.
$ ruby bgp-community.rb --help
USAGE: bgp-community.rb host mbit_speed unencrypted|unsafe|encrypted|pfs
-6, --ipv6 Assume ipv6 for ping
$ ruby bgp-community.rb 212.129.13.123 300 encrypted
# 15 ms, 300 mbit/s, encrypted tunnel (updated: 2016-02-11)
import where dn42_import_filter(3,24,33);
export where dn42_export_filter(3,24,33);
$ ruby bgp-community.rb -6 dn42-2.higgsboson.tk 1000 pfs
# 11 ms, 1000 mbit/s, pfs tunnel (updated: 2016-02-11)
import where dn42_import_filter(3,25,34);
export where dn42_export_filter(3,25,34);
Route Origin
There are two type of route origin: region
and country
Region
The range 41-70
is assigned to the region property.
The communities for route origin region were first defined in December 2015 and further extended in May 2022:
(64511, 41) :: Europe
(64511, 42) :: North America-E
(64511, 43) :: North America-C
(64511, 44) :: North America-W
(64511, 45) :: Central America
(64511, 46) :: South America-E
(64511, 47) :: South America-W
(64511, 48) :: Africa-N (above Sahara)
(64511, 49) :: Africa-S (below Sahara)
(64511, 50) :: Asia-S (IN,PK,BD)
(64511, 51) :: Asia-SE (TH,SG,PH,ID,MY)
(64511, 52) :: Asia-E (JP,CN,KR,TW,HK)
(64511, 53) :: Pacific&Oceania (AU,NZ,FJ)
(64511, 54) :: Antarctica
(64511, 55) :: Asia-N (RU)
(64511, 56) :: Asia-W (IR,TR,UAE)
(64511, 57) :: Central Asia (AF,UZ,KZ)
Country
The range 1000-1999
is assigned to the country property. Here we use ISO-3166-1 numeric country codes, adding 1000
to each value to get the country origin community:
(64511, 1124) :: Canada
(64511, 1156) :: China
(64511, 1158) :: Taiwan
(64511, 1250) :: France
(64511, 1276) :: Germany
(64511, 1344) :: Hong Kong
(64511, 1392) :: Japan
(64511, 1528) :: Netherlands
(64511, 1578) :: Norway
(64511, 1643) :: Russian Federation
(64511, 1702) :: Singapore
(64511, 1756) :: Switzerland
(64511, 1826) :: United Kingdom
(64511, 1840) :: United States of America
etc. Please follow the ISO-3166-1 Numeric standard
https://github.com/lukes/ISO-3166-Countries-with-Regional-Codes/blob/master/all/all.csv.
You need to add following lines to your config(s):
-
define DN42_REGION = $VALUE_FROM_ABOVE
to your node's config (where OWNAS and OWNIP are set) -
if source = RTS_STATIC then bgp_community.add((64511, DN42_REGION));
just aboveupdate_flags
indn42_export_filter
function - Unlike the other community values, the DN42_REGION community should only be set on routes originating from your network! (This is what the
source = RTS_STATIC
check does).- Otherwise, if you export routes across multiple regions within your network, you may be sending incorrect origin information to other peers.
This is not applicable for the below example configurations
that have it included, since networks usually use the region to do
routing policies like cold_potato.
Example configuration for BIRD2
And in your /etc/bird/peers/example.conf peer where your parameters as as such 11 ms, 1000 mbit/s, pfs tunnel example with MP-BGP with ENHfunction update_latency(int link_latency) -> int { bgp_community.add((64511, link_latency)); if (64511, 9) ~ bgp_community then { bgp_community.delete([(64511, 1..8)]); return 9; } else if (64511, 8) ~ bgp_community then { bgp_community.delete([(64511, 1..7)]); return 8; } else if (64511, 7) ~ bgp_community then { bgp_community.delete([(64511, 1..6)]); return 7; } else if (64511, 6) ~ bgp_community then { bgp_community.delete([(64511, 1..5)]); return 6; } else if (64511, 5) ~ bgp_community then { bgp_community.delete([(64511, 1..4)]); return 5; } else if (64511, 4) ~ bgp_community then { bgp_community.delete([(64511, 1..3)]); return 4; } else if (64511, 3) ~ bgp_community then { bgp_community.delete([(64511, 1..2)]); return 3; } else if (64511, 2) ~ bgp_community then { bgp_community.delete([(64511, 1..1)]); return 2; } else return 1; } function update_bandwidth(int link_bandwidth) -> int { bgp_community.add((64511, link_bandwidth)); if (64511, 21) ~ bgp_community then { bgp_community.delete([(64511, 22..29)]); return 21; } else if (64511, 22) ~ bgp_community then { bgp_community.delete([(64511, 23..29)]); return 22; } else if (64511, 23) ~ bgp_community then { bgp_community.delete([(64511, 24..29)]); return 23; } else if (64511, 24) ~ bgp_community then { bgp_community.delete([(64511, 25..29)]); return 24; } else if (64511, 25) ~ bgp_community then { bgp_community.delete([(64511, 26..29)]); return 25; } else if (64511, 26) ~ bgp_community then { bgp_community.delete([(64511, 27..29)]); return 26; } else if (64511, 27) ~ bgp_community then { bgp_community.delete([(64511, 28..29)]); return 27; } else if (64511, 28) ~ bgp_community then { bgp_community.delete([(64511, 29..29)]); return 28; } else return 29; } function update_crypto(int link_crypto) -> int { bgp_community.add((64511, link_crypto)); if (64511, 31) ~ bgp_community then { bgp_community.delete([(64511, 32..34)]); return 31; } else if (64511, 32) ~ bgp_community then { bgp_community.delete([(64511, 33..34)]); return 32; } else if (64511, 33) ~ bgp_community then { bgp_community.delete([(64511, 34..34)]); return 33; } else return 34; } #Remove the following function if you do not want to advertize your region in the BGP community. function update_geo_flags() -> bool { if is_self_net() || is_self_net_v6() then { bgp_community.add((64511, DN_REGION_GEO)); bgp_community.add((64511, DN_REGION_COUNTRY)); } } function update_flags(int link_latency; int link_bandwidth; int link_crypto) -> bool int dn42_latency; int dn42_bandwidth; int dn42_crypto; { dn42_latency = update_latency(link_latency); dn42_bandwidth = update_bandwidth(link_bandwidth) - 20; dn42_crypto = update_crypto(link_crypto) - 30; # replace 4 with your calculated bandwidth value if dn42_bandwidth > 4 then dn42_bandwidth = 4; return true; } #Uses ROA, which means it should be imported before these functions function dn42_import_filter(int link_latency; int link_bandwidth; int link_crypto) { # IPv4 routes with ROA if is_valid_network() && !is_self_net() then { if (roa_check(dn42_roa, net, bgp_path.last) != ROA_VALID) then { # Reject when unknown or invalid according to ROA print "[dn42] IPv4 ROA check failed for ", net, " ASN ", bgp_path.last; reject; } update_flags(link_latency, link_bandwidth, link_crypto); if (bgp_path.len = 1) then bgp_local_pref = bgp_local_pref + 500; accept; } # IPv6 routes with ROA if is_valid_network_v6() && !is_self_net_v6() then { if (roa_check(dn42_roa_v6, net, bgp_path.last) != ROA_VALID) then { # Reject when unknown or invalid according to ROA print "[dn42] IPv6 ROA check failed for ", net, " ASN ", bgp_path.last; reject; } update_flags(link_latency, link_bandwidth, link_crypto); if (bgp_path.len = 1) then bgp_local_pref = bgp_local_pref + 500; accept; } # Re reject; } function dn42_export_filter(int link_latency; int link_bandwidth; int link_crypto) { if is_valid_network() || is_valid_network_v6() then { update_flags(link_latency, link_bandwidth, link_crypto); update_geo_flags(); bgp_med = 0; bgp_med = bgp_med + ( ( 4 - ( link_crypto - 30 ) ) * 600 ); bgp_med = bgp_med + ( ( 9 - ( link_bandwidth - 20 ) ) * 100); bgp_med = bgp_med + ( ( link_latency - 1) * 300); accept; } reject; }
Please remember to include /etc/bird/community_filters.conf and to define your GEO regions in your bird.confprotocol bgp example from dnpeers { neighbor neighbor <neighborip><%interface if Link Local is used> as <AUT_NUM>; ipv4 { extended next hop on; import where dn42_import_filter(3,25,34); export where dn42_export_filter(3,25,34); }; ipv6 { import where dn42_import_filter(3,25,34); export where dn42_export_filter(3,25,34); };
# local configuration ###################### # In the variable header or anywhere before the include for the community filters add define DN_REGION_GEO = xx; define DN_REGION_COUNTRY = xxxx; #If you wish to add the BGP Geographical Communities. #before you import your peers add the community filters eg #include "/etc/bird/community_filters.conf"; #include "/etc/bird/peers/*"; include "/etc/bird/community_filters.conf";
- Otherwise, if you export routes across multiple regions within your network, you may be sending incorrect origin information to other peers.
This is not applicable for the below example configurations
that have it included, since networks usually use the region to do
routing policies like cold_potato.