├── .gitignore ├── .local.example ├── .readme └── AS209306.svg ├── README.md ├── bgp-internal ├── Fermata.conf ├── _backbone.conf ├── _global.conf ├── _mainland.conf ├── rr1-Symphony.conf ├── rr2-Piano.conf └── rr3-Bass.conf ├── bgp.conf ├── bgp └── _ibgp.conf ├── bird.conf ├── filter.conf ├── filter ├── 00_soha.conf ├── 10_bgp-cn-path.conf └── 10_bgp.conf ├── ospf.conf ├── ospf ├── .sohanet.0.interface.example └── sohanet.conf ├── scripts ├── cron-generate-ptp-cost.sh ├── generate-ptp-cost.sh ├── setup.sh └── update.sh ├── static.conf └── static ├── .announce.example ├── .interconnection.example ├── _catch_all.conf └── _ipv4_conditional.conf /.gitignore: -------------------------------------------------------------------------------- 1 | local.conf 2 | {bgp,ospf,static}/* 3 | !ospf/sohanet.conf 4 | !**/_* 5 | !**/.* 6 | -------------------------------------------------------------------------------- /.local.example: -------------------------------------------------------------------------------- 1 | router id 44.32.69.251; 2 | 3 | define LOCAL_AS = 209306; 4 | define LOCAL_ROUTER_NUM = 1; 5 | define LOCAL_CODE_AREA = 1; 6 | define LOCAL_CODE_COUNTRY = 156; 7 | 8 | define IBGP_SOURCE_ADDRESS = 2406:840:feed:1::1; 9 | -------------------------------------------------------------------------------- /.readme/AS209306.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 |
World Backbone
World Backbone
China Mainland
China Mainland
User Access
User Access
Core iBGP / OSPF
Core iBGP...
Edge iBGP
Edge iBGP
Pork
Shanghai, China
Pork...
Vegetable
Jinhua, China
Vegetable...
Internet
via AS4842
Internet...
eBGP Peering
eBGP Peeri...
Internet
via AS38008
Internet...
ZXIX Shanghai
ZXIX Shanghai
foobarIX
foobarIX
Internet
via AS4842
Internet...
ZXIX Hong Kong
ZXIX Hong Kong
GeekIX
GeekIX
Unnamed
Paris, France
Unnamed...
Internet
via AS20473
Internet...
eBGP Transit
eBGP Trans...
AS209306 Network (BGP)
AS209306 Network (BGP)
Internet
via AS59105
Internet...
PoemaIX
PoemaIX
Bass
Tokyo, Japan
Bass...
Piano
Hong Kong
Piano...
Symphony
Jinhua, China
Symphony...
Marcato
Melbourne, Australia
Marcato...
Fermata
Taoyuan, Taiwan Prov.
Fermata...
Choir
Shanghai, China
Choir...
Text is not SVG - cannot display
-------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SohaNET(AS209306) BIRD configuration 2 | 3 | It just works. 4 | 5 | ![AS209306](.readme/AS209306.svg) 6 | 7 | *Diagram represents the network structure in Jan. 2024, it may be outdated.* 8 | -------------------------------------------------------------------------------- /bgp-internal/Fermata.conf: -------------------------------------------------------------------------------- 1 | # for node Fermata 2 | 3 | template bgp tpl_ibgp_from_fermata from tpl_ibgp { 4 | ipv6 { 5 | export filter { 6 | if !bgp_export(LOCAL_AS, "core") then reject; 7 | bgp_next_hop = IBGP_SOURCE_ADDRESS; # KSKB-IX removes GUA from next hop 8 | accept; 9 | }; 10 | }; 11 | } 12 | 13 | protocol bgp ibgp_piano from tpl_ibgp_from_fermata { 14 | description "HK-TKO Piano"; 15 | neighbor 2406:840:feed:2::1 as LOCAL_AS; 16 | } 17 | 18 | protocol bgp ibgp_bass from tpl_ibgp_from_fermata { 19 | description "JP-ZAD Bass"; 20 | neighbor 2406:840:feed:3::1 as LOCAL_AS; 21 | } 22 | -------------------------------------------------------------------------------- /bgp-internal/_backbone.conf: -------------------------------------------------------------------------------- 1 | # World Backbone, full-meshed each other 2 | 3 | # RR1 Symfony @ Jinhua, CN 4 | protocol bgp ibgp_symphony from tpl_ibgp { 5 | description "CN-JHA Symphony"; 6 | neighbor 2406:840:feed:1::1 as LOCAL_AS; 7 | } 8 | 9 | # RR2 Piano @ Tseung Kwan O, HK 10 | protocol bgp ibgp_piano from tpl_ibgp { 11 | description "HK-TKO Piano"; 12 | neighbor 2406:840:feed:2::1 as LOCAL_AS; 13 | } 14 | 15 | # RR3 Bass @ Ōta-ku, JP 16 | protocol bgp ibgp_bass from tpl_ibgp { 17 | description "JP-ZAD Bass"; 18 | neighbor 2406:840:feed:3::1 as LOCAL_AS; 19 | } 20 | -------------------------------------------------------------------------------- /bgp-internal/_global.conf: -------------------------------------------------------------------------------- 1 | # for global nodes, belong to RR2, RR3 2 | 3 | protocol bgp ibgp_piano from tpl_ibgp { 4 | description "HK-TKO Piano"; 5 | neighbor 2406:840:feed:2::1 as LOCAL_AS; 6 | } 7 | 8 | protocol bgp ibgp_bass from tpl_ibgp { 9 | description "JP-ZAD Bass"; 10 | neighbor 2406:840:feed:3::1 as LOCAL_AS; 11 | } 12 | -------------------------------------------------------------------------------- /bgp-internal/_mainland.conf: -------------------------------------------------------------------------------- 1 | # for China mainland nodes, belong to RR1, RR2 2 | 3 | protocol bgp ibgp_symphony from tpl_ibgp { 4 | description "CN-JHA Symphony"; 5 | neighbor 2406:840:feed:1::1 as LOCAL_AS; 6 | } 7 | 8 | protocol bgp ibgp_piano from tpl_ibgp { 9 | description "HK-TKO Piano"; 10 | neighbor 2406:840:feed:2::1 as LOCAL_AS; 11 | } 12 | -------------------------------------------------------------------------------- /bgp-internal/rr1-Symphony.conf: -------------------------------------------------------------------------------- 1 | # for node Symphony 2 | include "../bgp-internal/_backbone.conf"; 3 | 4 | # RR1: Contains China mainland nodes 5 | template bgp tpl_ibgp_rr1 from tpl_ibgp { 6 | rr client; 7 | rr cluster id 44.32.69.251; 8 | } 9 | 10 | protocol bgp ibgp_choir from tpl_ibgp_rr1 { 11 | description "CN-SGH Choir"; 12 | neighbor 2406:840:feed:40::1 as LOCAL_AS; 13 | } 14 | -------------------------------------------------------------------------------- /bgp-internal/rr2-Piano.conf: -------------------------------------------------------------------------------- 1 | # for node Piano 2 | include "../bgp-internal/_backbone.conf"; 3 | 4 | # RR2: Contains Greater China nodes, global nodes 5 | template bgp tpl_ibgp_rr2 from tpl_ibgp { 6 | rr client; 7 | rr cluster id 44.32.69.252; 8 | } 9 | 10 | protocol bgp ibgp_choir from tpl_ibgp_rr2 { 11 | description "CN-SGH Choir"; 12 | neighbor 2406:840:feed:40::1 as LOCAL_AS; 13 | } 14 | 15 | protocol bgp ibgp_marcato from tpl_ibgp_rr2 { 16 | description "AU-MEL Marcato"; 17 | neighbor 2406:840:feed:51::1 as LOCAL_AS; 18 | } 19 | 20 | protocol bgp ibgp_fermata from tpl_ibgp_rr2 { 21 | description "TW-TYN Fermata"; 22 | neighbor 2406:840:feed:41::1 as LOCAL_AS; 23 | } 24 | -------------------------------------------------------------------------------- /bgp-internal/rr3-Bass.conf: -------------------------------------------------------------------------------- 1 | # for node Bass 2 | include "../bgp-internal/_backbone.conf"; 3 | 4 | # RR3: Contains Greater China (w/o mainland) nodes, global nodes 5 | template bgp tpl_ibgp_rr3 from tpl_ibgp { 6 | rr client; 7 | rr cluster id 44.32.69.253; 8 | } 9 | 10 | protocol bgp ibgp_marcato from tpl_ibgp_rr3 { 11 | description "AU-MEL Marcato"; 12 | neighbor 2406:840:feed:51::1 as LOCAL_AS; 13 | } 14 | 15 | protocol bgp ibgp_fermata from tpl_ibgp_rr3 { 16 | description "TW-TYN Fermata"; 17 | neighbor 2406:840:feed:41::1 as LOCAL_AS; 18 | } 19 | -------------------------------------------------------------------------------- /bgp.conf: -------------------------------------------------------------------------------- 1 | template bgp tpl_bgp { 2 | graceful restart; 3 | local as LOCAL_AS; 4 | } 5 | 6 | template bgp tpl_ibgp from tpl_bgp { 7 | source address IBGP_SOURCE_ADDRESS; 8 | multihop; 9 | ipv4 { 10 | next hop keep; 11 | import filter { 12 | if is_default() then { 13 | bgp_local_pref = 200; 14 | if bgp_is_crossing_mainland_border() then bgp_local_pref = 85; 15 | accept; 16 | } 17 | if bgp_import(LOCAL_AS, "core") then accept; 18 | reject; 19 | }; 20 | export where bgp_export(LOCAL_AS, "core"); 21 | }; 22 | ipv6 { 23 | next hop keep; 24 | import where bgp_import(LOCAL_AS, "core"); 25 | export where bgp_export(LOCAL_AS, "core"); 26 | }; 27 | } 28 | 29 | include "bgp/*.conf"; 30 | -------------------------------------------------------------------------------- /bgp/_ibgp.conf: -------------------------------------------------------------------------------- 1 | # Deprecated. Please create symbolic link to corresponding ../bgp-internal/*.conf 2 | -------------------------------------------------------------------------------- /bird.conf: -------------------------------------------------------------------------------- 1 | log syslog all; 2 | 3 | include "local.conf"; 4 | include "filter.conf"; 5 | 6 | protocol device {} 7 | 8 | filter kernel_export { 9 | if is_default() && proto ~ "static_default?" then reject; 10 | accept; 11 | } 12 | protocol kernel { ipv4 { import none; export filter kernel_export; }; } 13 | protocol kernel { ipv6 { import none; export filter kernel_export; }; } 14 | 15 | include "static.conf"; 16 | include "bgp.conf"; 17 | include "ospf.conf"; 18 | -------------------------------------------------------------------------------- /filter.conf: -------------------------------------------------------------------------------- 1 | function is_default() { 2 | return net.len = 0; 3 | } 4 | 5 | function net_len_too_long() { 6 | case net.type { 7 | NET_IP4: return net.len > 24; 8 | NET_IP6: return net.len > 48; 9 | else: print "net_len_too_long: unexpected net.type ", net.type, " ", net; return false; 10 | } 11 | } 12 | 13 | function is_bogon_prefix() { 14 | case net.type { 15 | ############## ipv4 ############## 16 | NET_IP4: return net ~ [ 17 | 0.0.0.0/8+, # RFC 1122 'this' network 18 | 10.0.0.0/8+, # RFC 1918 private space 19 | 100.64.0.0/10+, # RFC 6598 Carrier grade nat space 20 | 127.0.0.0/8+, # RFC 1122 localhost 21 | 169.254.0.0/16+, # RFC 3927 link local 22 | 172.16.0.0/12+, # RFC 1918 private space 23 | 192.0.2.0/24+, # RFC 5737 TEST-NET-1 24 | 192.88.99.0/24+, # RFC 7526 6to4 anycast relay 25 | 192.168.0.0/16+, # RFC 1918 private space 26 | 198.18.0.0/15+, # RFC 2544 benchmarking 27 | 198.51.100.0/24+, # RFC 5737 TEST-NET-2 28 | 203.0.113.0/24+, # RFC 5737 TEST-NET-3 29 | 224.0.0.0/4+, # multicast 30 | 240.0.0.0/4+ # reserved 31 | ]; 32 | ############## ipv6 ############## 33 | NET_IP6: return net ~ [ 34 | ::/8+, # RFC 4291 IPv4-compatible, loopback, et al 35 | 0100::/64+, # RFC 6666 Discard-Only 36 | 2001:2::/48+, # RFC 5180 BMWG 37 | 2001:10::/28+, # RFC 4843 ORCHID 38 | 2001:db8::/32+, # RFC 3849 documentation 39 | 2002::/16+, # RFC 7526 6to4 anycast relay 40 | 3ffe::/16+, # RFC 3701 old 6bone 41 | fc00::/7+, # RFC 4193 unique local unicast 42 | fe80::/10+, # RFC 4291 link local unicast 43 | fec0::/10+, # RFC 3879 old site local unicast 44 | ff00::/8+ # RFC 4291 multicast 45 | ]; 46 | else: return false; 47 | } 48 | } 49 | 50 | define BOGON_ASN = [ 51 | 0, 52 | 23456, 53 | 64496..64511, 54 | 64512..65534, 55 | 65535, 56 | 65536..65551, 57 | 65552..131071, 58 | 4200000000..4294967294, 59 | 4294967295 60 | ]; 61 | 62 | function is_bogon_asn() { 63 | return bgp_path ~ BOGON_ASN; 64 | } 65 | 66 | include "filter/*.conf"; 67 | -------------------------------------------------------------------------------- /filter/00_soha.conf: -------------------------------------------------------------------------------- 1 | function is_in_sohanet() { 2 | case net.type { 3 | NET_IP4: return net ~ [ 4 | 44.32.69.0/24+ 5 | ]; 6 | NET_IP6: return net ~ [ 7 | 2a13:1802:0000::/36+, 8 | 2a0e:aa06:0400::/44+, 9 | 2406:0840:fee0::/44+ 10 | ]; 11 | else: return false; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /filter/10_bgp-cn-path.conf: -------------------------------------------------------------------------------- 1 | function bgp_is_cn_path() { 2 | return bgp_path ~ [ 3 | 37963, # Alibaba 4 | 133865, # iQiyi 5 | 58593, # Azure CN 6 | 45090, # Tencent 7 | # 7497, # CSTNET 8 | # 4538, 23911, 38255 # CERNET 1/2/3 9 | 4837, # China Unicom 10 | 9808, # China Mobile 11 | 4134 # China Telecom 12 | ]; 13 | } 14 | 15 | function bgp_mark_cn_path(pair comm) { 16 | bgp_community.delete(comm); 17 | if bgp_is_cn_path() then { 18 | bgp_community.add(comm); 19 | return true; 20 | } 21 | return false; 22 | } 23 | -------------------------------------------------------------------------------- /filter/10_bgp.conf: -------------------------------------------------------------------------------- 1 | # BGP Large Community: (AA: u32, BB: u32, NN: u32) 2 | define BGPCOMM_AA = 209306; 3 | 4 | define BGPCOMM_BB_TYPE = 1; 5 | define BGPCOMM_BB_PEER = 2; 6 | define BGPCOMM_BB_ROUTER = 10; 7 | define BGPCOMM_BB_AREA = 11; 8 | define BGPCOMM_BB_COUNTRY = 12; 9 | define BGPCOMM_BB_EXPORT_POLICY = 209306; 10 | define BGPCOMM_BB_NO_EXPORT_POLICY = 0; 11 | 12 | define BGPCOMM_NN_TYPE_SOHANET = 1; 13 | define BGPCOMM_NN_TYPE_PEERING = 10; 14 | define BGPCOMM_NN_TYPE_TRANSIT = 11; 15 | define BGPCOMM_NN_EXPORT_POLICY_ANY = 209306; 16 | define BGPCOMM_NN_EXPORT_POLICY_ROUTER_PREFIX = 4210000000; 17 | define BGPCOMM_NN_EXPORT_POLICY_AREA_PREFIX = 4211000000; 18 | define BGPCOMM_NN_EXPORT_POLICY_COUNTRY_PREFIX = 4212000000; 19 | 20 | define BGPCOMM_FL_IS_SOHANET = (BGPCOMM_AA, BGPCOMM_BB_TYPE, BGPCOMM_NN_TYPE_SOHANET); 21 | define BGPCOMM_FL_EXPORT_ANY = (BGPCOMM_AA, BGPCOMM_BB_EXPORT_POLICY, BGPCOMM_NN_EXPORT_POLICY_ANY); 22 | 23 | # bgp_add_local_communities() 24 | # community to be added to imported routes on this router 25 | function bgp_add_local_communities() { 26 | bgp_large_community.add((BGPCOMM_AA, BGPCOMM_BB_AREA, LOCAL_CODE_AREA)); 27 | bgp_large_community.add((BGPCOMM_AA, BGPCOMM_BB_ROUTER, LOCAL_ROUTER_NUM)); 28 | bgp_large_community.add((BGPCOMM_AA, BGPCOMM_BB_COUNTRY, LOCAL_CODE_COUNTRY)); 29 | return true; 30 | } 31 | 32 | # bgp_transit_should_no_export() 33 | # Some peers have reverse path filter. 34 | # To make them happy and not impacting announcement, 35 | # mark NO_ADVERTISE and lengthen AS path. 36 | function bgp_transit_should_no_export() { 37 | bgp_community.add((65535, 65281)); 38 | bgp_community.add((65535, 65282)); 39 | bgp_path.prepend(LOCAL_AS); 40 | bgp_path.prepend(LOCAL_AS); 41 | bgp_path.prepend(LOCAL_AS); 42 | bgp_path.prepend(LOCAL_AS); 43 | bgp_path.prepend(LOCAL_AS); 44 | bgp_path.prepend(LOCAL_AS); 45 | bgp_path.prepend(LOCAL_AS); 46 | } 47 | 48 | function bgp_is_crossing_mainland_border() { 49 | return ((BGPCOMM_AA, BGPCOMM_BB_COUNTRY, 156) ~ bgp_large_community) && (LOCAL_CODE_COUNTRY != 156); 50 | } 51 | 52 | # bgp_import(peer_asn: int, import_type: string) 53 | # import filter for BGP protocol 54 | # Import types 55 | # - default: receive default route only 56 | # - transit: endpoint is transit 57 | # - peering: endpoint is peering 58 | # - core: iBGP session with core routers 59 | # - edge: iBGP session with edge routers who don't have OSPF and attribute allocated 60 | function bgp_import(int peer_asn; string import_type) { 61 | if !(import_type = "transit" || import_type = "peering" || import_type = "core" || import_type = "edge" || import_type = "default") then return false; 62 | 63 | if is_default() then { 64 | if import_type != "default" then return false; 65 | bgp_local_pref = 200; 66 | if bgp_is_crossing_mainland_border() then bgp_local_pref = 100; 67 | } 68 | 69 | # 保留地址, 长度大于 100 的 as path, 前缀长度不达标的就不要了 70 | if is_bogon_prefix() || (bgp_path.len > 100) || net_len_too_long() then return false; 71 | if import_type != "core" && import_type != "edge" then { 72 | if bgp_path.len = 0 then bgp_path.prepend(peer_asn); # no empty as path 73 | if is_in_sohanet() then return false; # 不从别人那里收本网前缀 74 | bgp_large_community.delete([(BGPCOMM_AA, *, *)]); 75 | bgp_large_community.add((BGPCOMM_AA, BGPCOMM_BB_PEER, peer_asn)); 76 | bgp_add_local_communities(); 77 | } 78 | 79 | if import_type = "transit" && bgp_path.last = peer_asn then { 80 | import_type = "peering"; 81 | } 82 | 83 | bgp_local_pref = 1; 84 | if import_type = "transit" then { 85 | bgp_local_pref = 1600; 86 | bgp_large_community.add((BGPCOMM_AA, BGPCOMM_BB_TYPE, BGPCOMM_NN_TYPE_TRANSIT)); 87 | } else if import_type = "peering" then { 88 | bgp_local_pref = 2600; 89 | bgp_large_community.add((BGPCOMM_AA, BGPCOMM_BB_TYPE, BGPCOMM_NN_TYPE_PEERING)); 90 | } else if import_type = "core" then { 91 | if (BGPCOMM_AA, BGPCOMM_BB_TYPE, BGPCOMM_NN_TYPE_PEERING) ~ bgp_large_community then { 92 | bgp_local_pref = 2500; # peering is always 2500 and uses IGP metric 93 | } else if(BGPCOMM_AA, BGPCOMM_BB_TYPE, BGPCOMM_NN_TYPE_TRANSIT) ~ bgp_large_community then { 94 | bgp_local_pref = 1500; # transit is always 1500 and uses IGP metric 95 | if bgp_is_crossing_mainland_border() then { # better not to cross the mainland border 96 | bgp_local_pref = 1020; 97 | } 98 | # also DON'T FORGET to specify `cost ;` in some expensive transits 99 | } 100 | } else if import_type = "edge" then { 101 | bgp_local_pref = 3999; 102 | bgp_add_local_communities(); 103 | } 104 | 105 | return true; 106 | } 107 | 108 | # bgp_export(peer_asn: int, export_type: string) 109 | # export filter for BGP protocol 110 | # Export types 111 | # - default: only default routes 112 | # - full: full table 113 | # - core: iBGP session with core routers 114 | # - transit: endpoint is transit 115 | # - peering: endpoint is peering 116 | function bgp_export(int peer_asn; string export_type) 117 | lclist specific_export_policies; 118 | { 119 | if !(export_type = "default" || export_type = "full" || export_type = "core" || export_type = "transit" || export_type = "peering") then return false; 120 | 121 | if is_bogon_prefix() || net_len_too_long() then return false; 122 | # 只有 default 模式才导出 default 123 | if is_default() then { 124 | if export_type = "default" then { 125 | bgp_add_local_communities(); 126 | return true; 127 | } 128 | return false; 129 | } else if export_type = "default" then return false; 130 | 131 | if filter(bgp_large_community, [(BGPCOMM_AA, *, *)]).len = 0 then return false; 132 | if export_type = "full" then { 133 | # seems nothing to do 134 | } else if export_type = "transit" then { 135 | if !is_in_sohanet() then return false; 136 | # transit 默认只导出当前路由进来的,或按照导出规则 137 | specific_export_policies = filter(bgp_large_community, [(BGPCOMM_AA, BGPCOMM_BB_EXPORT_POLICY, *)]); 138 | if specific_export_policies.len = 0 then { 139 | # 如果不是从当前路由导入的 140 | if (BGPCOMM_AA, BGPCOMM_BB_ROUTER, LOCAL_ROUTER_NUM) !~ bgp_large_community then bgp_transit_should_no_export(); 141 | } else { 142 | # 有宣告策略,但不符合要求 143 | if filter(specific_export_policies, [ 144 | (BGPCOMM_AA, BGPCOMM_BB_EXPORT_POLICY, BGPCOMM_NN_EXPORT_POLICY_ANY), 145 | (BGPCOMM_AA, BGPCOMM_BB_EXPORT_POLICY, BGPCOMM_NN_EXPORT_POLICY_ROUTER_PREFIX + LOCAL_ROUTER_NUM), 146 | (BGPCOMM_AA, BGPCOMM_BB_EXPORT_POLICY, BGPCOMM_NN_EXPORT_POLICY_AREA_PREFIX + LOCAL_CODE_AREA), 147 | (BGPCOMM_AA, BGPCOMM_BB_EXPORT_POLICY, BGPCOMM_NN_EXPORT_POLICY_COUNTRY_PREFIX + LOCAL_CODE_COUNTRY) 148 | ]).len = 0 then bgp_transit_should_no_export(); 149 | } 150 | } else if export_type = "peering" then { 151 | if !is_in_sohanet() then return false; 152 | } 153 | 154 | if export_type = "transit" || export_type = "peering" then { 155 | bgp_large_community.delete([(BGPCOMM_AA, *, *)]); 156 | } if export_type != "core" then { # 除了 core 的导出都扬掉导出策略 157 | bgp_large_community.delete([(BGPCOMM_AA, BGPCOMM_BB_EXPORT_POLICY, *)]); 158 | } 159 | 160 | return true; 161 | } 162 | -------------------------------------------------------------------------------- /ospf.conf: -------------------------------------------------------------------------------- 1 | filter ospf_import { 2 | # 公网可见路由降权,比 BGP 低,优先考虑 iBGP 的路由。这个只是为了不接入 BGP 的路由器使用 3 | if net.type = NET_IP6 && net.len <= 48 && net.len > 8 then { 4 | preference = 40; 5 | } 6 | if net.type = NET_IP4 && net.len <= 24 && net.len > 3 then { 7 | preference = 40; 8 | } 9 | accept; 10 | } 11 | filter ospf_export { 12 | if is_default() then { 13 | # propagate default routes if the default route is not the one defined in ./static.conf 14 | if proto ~ "static_default?" then reject; else accept; 15 | } 16 | if source !~ [RTS_STATIC, RTS_DEVICE] then reject; 17 | if source = RTS_STATIC then { 18 | # 允许 SohaNET 自己的前缀进入 OSPF 19 | if BGPCOMM_FL_IS_SOHANET ~ bgp_large_community then accept; 20 | # 打过 community 的 STATIC 走 iBGP,不走 OSPF 21 | if bgp_large_community.len > 0 then reject; 22 | } 23 | accept; 24 | } 25 | 26 | include "ospf/*.conf"; 27 | -------------------------------------------------------------------------------- /ospf/.sohanet.0.interface.example: -------------------------------------------------------------------------------- 1 | interface "snh-piano" { type pointopoint; cost PTP_IF_COST__SNH_PIANO; }; 2 | -------------------------------------------------------------------------------- /ospf/sohanet.conf: -------------------------------------------------------------------------------- 1 | # `?` in `include` clause is workaround for non-existence file, replace it by `.` on fs 2 | include "ptp?cost"; # generated by ../scripts/generate-ptp-cost.sh 3 | 4 | protocol ospf v3 ospf_net { 5 | area 0 { 6 | stubnet 2a13:1802:f:979::/64 { summary; hidden; }; # on-link /128 loopback for tracert, suppress propagation 7 | stubnet 2a0e:aa06:404:701::/64 { summary; hidden; }; # on-link /128 loopback for tracert, suppress propagation 8 | include "sohanet.inet6.0?area"; 9 | include "sohanet.0?interface"; 10 | }; 11 | include "sohanet?extra"; 12 | include "sohanet?extra.inet6"; 13 | 14 | ipv6 { 15 | import filter ospf_import; 16 | export filter ospf_export; 17 | }; 18 | } 19 | 20 | protocol ospf v3 ospf_net4 { 21 | area 0 { 22 | include "sohanet.inet4.0?area"; 23 | include "sohanet.0?interface"; 24 | }; 25 | include "sohanet?extra"; 26 | include "sohanet?extra.inet4"; 27 | 28 | ipv4 { 29 | import filter ospf_import; 30 | export filter ospf_export; 31 | }; 32 | } 33 | -------------------------------------------------------------------------------- /scripts/cron-generate-ptp-cost.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | cd "$(dirname "$0")"/../ 4 | ./scripts/generate-ptp-cost.sh > ./ospf/ptp.cost 5 | -------------------------------------------------------------------------------- /scripts/generate-ptp-cost.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | for with_ll in $(cat /proc/net/if_inet6 | grep "^fe80" | tr -s ' ' | cut -d ' ' -f 6); do 4 | if [ $(expr \( $(($(cat /sys/class/net/$with_ll/flags))) / 16 \) % 2) -ne 1 ]; then 5 | continue 6 | fi 7 | cost=65535 8 | ping_rtt=N/A 9 | ping_result=$(ping -q -L -n -i 1 -c 10 -W 10 ff02::1%$with_ll) 10 | ping_loss=$(echo "$ping_result" | grep -oP '\d+(?=% packet loss)') 11 | if [ $ping_loss -ne 100 ]; then 12 | ping_rtt=$(echo "$ping_result" | tail -1 | cut -d ' ' -f 4 | cut -d '/' -f 2) 13 | cost=$(echo | awk '{ printf "%0.0f\n", ('$ping_rtt' * 100 / (100 - '$ping_loss') * 10); }') 14 | fi 15 | echo 'define PTP_IF_COST__'$(printf $with_ll | tr -c [:alnum:] _ | tr [a-z] [A-Z])' = '$cost'; # loss '$ping_loss'%, rtt '$ping_rtt'ms' 16 | done 17 | -------------------------------------------------------------------------------- /scripts/setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | cd $(dirname "$0")/../ 4 | echo 'include "'$(basename $(pwd))'/bird.conf";' > ../bird.conf 5 | -------------------------------------------------------------------------------- /scripts/update.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | cd "$(dirname "$0")" 4 | git pull && birdc configure 5 | -------------------------------------------------------------------------------- /static.conf: -------------------------------------------------------------------------------- 1 | # It's only used by export which needs only the default route 2 | protocol static static_default4 { ipv4 { preference 1; }; route 0.0.0.0/0 reject; } 3 | protocol static static_default6 { ipv6 { preference 1; }; route ::/0 reject; } 4 | 5 | filter direct_ic_import { 6 | ospf_metric1 = 0; 7 | accept; 8 | } 9 | 10 | template direct tpl_direct_ic { 11 | ipv6 { import filter direct_ic_import; }; 12 | ipv4 { import filter direct_ic_import; }; 13 | } 14 | 15 | include "static/*.conf"; 16 | -------------------------------------------------------------------------------- /static/.announce.example: -------------------------------------------------------------------------------- 1 | protocol static { 2 | ipv6 { import filter { 3 | bgp_add_local_communities(); 4 | bgp_large_community.add(BGPCOMM_FL_IS_SOHANET); 5 | accept; 6 | }; }; 7 | route 2a0e:aa06:40e::/48 reject; 8 | } 9 | -------------------------------------------------------------------------------- /static/.interconnection.example: -------------------------------------------------------------------------------- 1 | protocol direct direct_ic from tpl_direct_ic { 2 | interface "ens18"; 3 | } 4 | -------------------------------------------------------------------------------- /static/_catch_all.conf: -------------------------------------------------------------------------------- 1 | protocol static static_catch_all { 2 | ipv6 { import filter { 3 | bgp_add_local_communities(); 4 | bgp_large_community.add(BGPCOMM_FL_IS_SOHANET); 5 | accept; 6 | }; }; 7 | route 2a0e:aa06:400::/44 reject; 8 | route 2406:840:feed::/48 reject { 9 | bgp_large_community.add(BGPCOMM_FL_EXPORT_ANY); 10 | bgp_community.add((4842, 19999)); 11 | }; 12 | route 2a13:1802::/44 reject { 13 | bgp_large_community.add(BGPCOMM_FL_EXPORT_ANY); 14 | bgp_community.add((4842, 19999)); 15 | }; 16 | } 17 | -------------------------------------------------------------------------------- /static/_ipv4_conditional.conf: -------------------------------------------------------------------------------- 1 | ipv4 table anycast4_condition; 2 | 3 | protocol pipe anycast4_condition_pipe { 4 | table anycast4_condition; 5 | peer table master4; 6 | import filter { 7 | if net ~ [44.32.69.0/24{25,32}] then { 8 | # OSPF inter area only, router id not within global area should be router local services 9 | if source = RTS_OSPF && ospf_router_id ~ [44.32.69.0..44.32.69.255] then { 10 | accept; 11 | } 12 | } 13 | reject; 14 | }; 15 | export filter { 16 | if net = 44.32.69.0/24 && dest != RTD_UNREACHABLE then { 17 | bgp_add_local_communities(); 18 | bgp_large_community.add(BGPCOMM_FL_IS_SOHANET); 19 | bgp_community.add((4842, 10001)); 20 | dest = RTD_UNREACHABLE; # revert to unreachable in master table 21 | accept; 22 | } 23 | reject; 24 | }; 25 | } 26 | 27 | protocol static anycast4_condition_decision { 28 | ipv4 { table anycast4_condition; }; 29 | route 44.32.69.0/24 recursive 44.32.69.0; 30 | route 44.32.69.0/24 recursive 44.32.69.1; 31 | route 44.32.69.0/24 recursive 44.32.69.2; 32 | route 44.32.69.0/24 recursive 44.32.69.3; 33 | route 44.32.69.0/24 recursive 44.32.69.4; 34 | route 44.32.69.0/24 recursive 44.32.69.5; 35 | route 44.32.69.0/24 recursive 44.32.69.6; 36 | route 44.32.69.0/24 recursive 44.32.69.7; 37 | route 44.32.69.0/24 recursive 44.32.69.8; 38 | route 44.32.69.0/24 recursive 44.32.69.9; 39 | route 44.32.69.0/24 recursive 44.32.69.10; 40 | route 44.32.69.0/24 recursive 44.32.69.11; 41 | route 44.32.69.0/24 recursive 44.32.69.12; 42 | route 44.32.69.0/24 recursive 44.32.69.13; 43 | route 44.32.69.0/24 recursive 44.32.69.14; 44 | route 44.32.69.0/24 recursive 44.32.69.15; 45 | route 44.32.69.0/24 recursive 44.32.69.16; 46 | route 44.32.69.0/24 recursive 44.32.69.17; 47 | route 44.32.69.0/24 recursive 44.32.69.18; 48 | route 44.32.69.0/24 recursive 44.32.69.19; 49 | route 44.32.69.0/24 recursive 44.32.69.20; 50 | route 44.32.69.0/24 recursive 44.32.69.21; 51 | route 44.32.69.0/24 recursive 44.32.69.22; 52 | route 44.32.69.0/24 recursive 44.32.69.23; 53 | route 44.32.69.0/24 recursive 44.32.69.24; 54 | route 44.32.69.0/24 recursive 44.32.69.25; 55 | route 44.32.69.0/24 recursive 44.32.69.26; 56 | route 44.32.69.0/24 recursive 44.32.69.27; 57 | route 44.32.69.0/24 recursive 44.32.69.28; 58 | route 44.32.69.0/24 recursive 44.32.69.29; 59 | route 44.32.69.0/24 recursive 44.32.69.30; 60 | route 44.32.69.0/24 recursive 44.32.69.31; 61 | route 44.32.69.0/24 recursive 44.32.69.32; 62 | route 44.32.69.0/24 recursive 44.32.69.33; 63 | route 44.32.69.0/24 recursive 44.32.69.34; 64 | route 44.32.69.0/24 recursive 44.32.69.35; 65 | route 44.32.69.0/24 recursive 44.32.69.36; 66 | route 44.32.69.0/24 recursive 44.32.69.37; 67 | route 44.32.69.0/24 recursive 44.32.69.38; 68 | route 44.32.69.0/24 recursive 44.32.69.39; 69 | route 44.32.69.0/24 recursive 44.32.69.40; 70 | route 44.32.69.0/24 recursive 44.32.69.41; 71 | route 44.32.69.0/24 recursive 44.32.69.42; 72 | route 44.32.69.0/24 recursive 44.32.69.43; 73 | route 44.32.69.0/24 recursive 44.32.69.44; 74 | route 44.32.69.0/24 recursive 44.32.69.45; 75 | route 44.32.69.0/24 recursive 44.32.69.46; 76 | route 44.32.69.0/24 recursive 44.32.69.47; 77 | route 44.32.69.0/24 recursive 44.32.69.48; 78 | route 44.32.69.0/24 recursive 44.32.69.49; 79 | route 44.32.69.0/24 recursive 44.32.69.50; 80 | route 44.32.69.0/24 recursive 44.32.69.51; 81 | route 44.32.69.0/24 recursive 44.32.69.52; 82 | route 44.32.69.0/24 recursive 44.32.69.53; 83 | route 44.32.69.0/24 recursive 44.32.69.54; 84 | route 44.32.69.0/24 recursive 44.32.69.55; 85 | route 44.32.69.0/24 recursive 44.32.69.56; 86 | route 44.32.69.0/24 recursive 44.32.69.57; 87 | route 44.32.69.0/24 recursive 44.32.69.58; 88 | route 44.32.69.0/24 recursive 44.32.69.59; 89 | route 44.32.69.0/24 recursive 44.32.69.60; 90 | route 44.32.69.0/24 recursive 44.32.69.61; 91 | route 44.32.69.0/24 recursive 44.32.69.62; 92 | route 44.32.69.0/24 recursive 44.32.69.63; 93 | route 44.32.69.0/24 recursive 44.32.69.64; 94 | route 44.32.69.0/24 recursive 44.32.69.65; 95 | route 44.32.69.0/24 recursive 44.32.69.66; 96 | route 44.32.69.0/24 recursive 44.32.69.67; 97 | route 44.32.69.0/24 recursive 44.32.69.68; 98 | route 44.32.69.0/24 recursive 44.32.69.69; 99 | route 44.32.69.0/24 recursive 44.32.69.70; 100 | route 44.32.69.0/24 recursive 44.32.69.71; 101 | route 44.32.69.0/24 recursive 44.32.69.72; 102 | route 44.32.69.0/24 recursive 44.32.69.73; 103 | route 44.32.69.0/24 recursive 44.32.69.74; 104 | route 44.32.69.0/24 recursive 44.32.69.75; 105 | route 44.32.69.0/24 recursive 44.32.69.76; 106 | route 44.32.69.0/24 recursive 44.32.69.77; 107 | route 44.32.69.0/24 recursive 44.32.69.78; 108 | route 44.32.69.0/24 recursive 44.32.69.79; 109 | route 44.32.69.0/24 recursive 44.32.69.80; 110 | route 44.32.69.0/24 recursive 44.32.69.81; 111 | route 44.32.69.0/24 recursive 44.32.69.82; 112 | route 44.32.69.0/24 recursive 44.32.69.83; 113 | route 44.32.69.0/24 recursive 44.32.69.84; 114 | route 44.32.69.0/24 recursive 44.32.69.85; 115 | route 44.32.69.0/24 recursive 44.32.69.86; 116 | route 44.32.69.0/24 recursive 44.32.69.87; 117 | route 44.32.69.0/24 recursive 44.32.69.88; 118 | route 44.32.69.0/24 recursive 44.32.69.89; 119 | route 44.32.69.0/24 recursive 44.32.69.90; 120 | route 44.32.69.0/24 recursive 44.32.69.91; 121 | route 44.32.69.0/24 recursive 44.32.69.92; 122 | route 44.32.69.0/24 recursive 44.32.69.93; 123 | route 44.32.69.0/24 recursive 44.32.69.94; 124 | route 44.32.69.0/24 recursive 44.32.69.95; 125 | route 44.32.69.0/24 recursive 44.32.69.96; 126 | route 44.32.69.0/24 recursive 44.32.69.97; 127 | route 44.32.69.0/24 recursive 44.32.69.98; 128 | route 44.32.69.0/24 recursive 44.32.69.99; 129 | route 44.32.69.0/24 recursive 44.32.69.100; 130 | route 44.32.69.0/24 recursive 44.32.69.101; 131 | route 44.32.69.0/24 recursive 44.32.69.102; 132 | route 44.32.69.0/24 recursive 44.32.69.103; 133 | route 44.32.69.0/24 recursive 44.32.69.104; 134 | route 44.32.69.0/24 recursive 44.32.69.105; 135 | route 44.32.69.0/24 recursive 44.32.69.106; 136 | route 44.32.69.0/24 recursive 44.32.69.107; 137 | route 44.32.69.0/24 recursive 44.32.69.108; 138 | route 44.32.69.0/24 recursive 44.32.69.109; 139 | route 44.32.69.0/24 recursive 44.32.69.110; 140 | route 44.32.69.0/24 recursive 44.32.69.111; 141 | route 44.32.69.0/24 recursive 44.32.69.112; 142 | route 44.32.69.0/24 recursive 44.32.69.113; 143 | route 44.32.69.0/24 recursive 44.32.69.114; 144 | route 44.32.69.0/24 recursive 44.32.69.115; 145 | route 44.32.69.0/24 recursive 44.32.69.116; 146 | route 44.32.69.0/24 recursive 44.32.69.117; 147 | route 44.32.69.0/24 recursive 44.32.69.118; 148 | route 44.32.69.0/24 recursive 44.32.69.119; 149 | route 44.32.69.0/24 recursive 44.32.69.120; 150 | route 44.32.69.0/24 recursive 44.32.69.121; 151 | route 44.32.69.0/24 recursive 44.32.69.122; 152 | route 44.32.69.0/24 recursive 44.32.69.123; 153 | route 44.32.69.0/24 recursive 44.32.69.124; 154 | route 44.32.69.0/24 recursive 44.32.69.125; 155 | route 44.32.69.0/24 recursive 44.32.69.126; 156 | route 44.32.69.0/24 recursive 44.32.69.127; 157 | route 44.32.69.0/24 recursive 44.32.69.128; 158 | route 44.32.69.0/24 recursive 44.32.69.129; 159 | route 44.32.69.0/24 recursive 44.32.69.130; 160 | route 44.32.69.0/24 recursive 44.32.69.131; 161 | route 44.32.69.0/24 recursive 44.32.69.132; 162 | route 44.32.69.0/24 recursive 44.32.69.133; 163 | route 44.32.69.0/24 recursive 44.32.69.134; 164 | route 44.32.69.0/24 recursive 44.32.69.135; 165 | route 44.32.69.0/24 recursive 44.32.69.136; 166 | route 44.32.69.0/24 recursive 44.32.69.137; 167 | route 44.32.69.0/24 recursive 44.32.69.138; 168 | route 44.32.69.0/24 recursive 44.32.69.139; 169 | route 44.32.69.0/24 recursive 44.32.69.140; 170 | route 44.32.69.0/24 recursive 44.32.69.141; 171 | route 44.32.69.0/24 recursive 44.32.69.142; 172 | route 44.32.69.0/24 recursive 44.32.69.143; 173 | route 44.32.69.0/24 recursive 44.32.69.144; 174 | route 44.32.69.0/24 recursive 44.32.69.145; 175 | route 44.32.69.0/24 recursive 44.32.69.146; 176 | route 44.32.69.0/24 recursive 44.32.69.147; 177 | route 44.32.69.0/24 recursive 44.32.69.148; 178 | route 44.32.69.0/24 recursive 44.32.69.149; 179 | route 44.32.69.0/24 recursive 44.32.69.150; 180 | route 44.32.69.0/24 recursive 44.32.69.151; 181 | route 44.32.69.0/24 recursive 44.32.69.152; 182 | route 44.32.69.0/24 recursive 44.32.69.153; 183 | route 44.32.69.0/24 recursive 44.32.69.154; 184 | route 44.32.69.0/24 recursive 44.32.69.155; 185 | route 44.32.69.0/24 recursive 44.32.69.156; 186 | route 44.32.69.0/24 recursive 44.32.69.157; 187 | route 44.32.69.0/24 recursive 44.32.69.158; 188 | route 44.32.69.0/24 recursive 44.32.69.159; 189 | route 44.32.69.0/24 recursive 44.32.69.160; 190 | route 44.32.69.0/24 recursive 44.32.69.161; 191 | route 44.32.69.0/24 recursive 44.32.69.162; 192 | route 44.32.69.0/24 recursive 44.32.69.163; 193 | route 44.32.69.0/24 recursive 44.32.69.164; 194 | route 44.32.69.0/24 recursive 44.32.69.165; 195 | route 44.32.69.0/24 recursive 44.32.69.166; 196 | route 44.32.69.0/24 recursive 44.32.69.167; 197 | route 44.32.69.0/24 recursive 44.32.69.168; 198 | route 44.32.69.0/24 recursive 44.32.69.169; 199 | route 44.32.69.0/24 recursive 44.32.69.170; 200 | route 44.32.69.0/24 recursive 44.32.69.171; 201 | route 44.32.69.0/24 recursive 44.32.69.172; 202 | route 44.32.69.0/24 recursive 44.32.69.173; 203 | route 44.32.69.0/24 recursive 44.32.69.174; 204 | route 44.32.69.0/24 recursive 44.32.69.175; 205 | route 44.32.69.0/24 recursive 44.32.69.176; 206 | route 44.32.69.0/24 recursive 44.32.69.177; 207 | route 44.32.69.0/24 recursive 44.32.69.178; 208 | route 44.32.69.0/24 recursive 44.32.69.179; 209 | route 44.32.69.0/24 recursive 44.32.69.180; 210 | route 44.32.69.0/24 recursive 44.32.69.181; 211 | route 44.32.69.0/24 recursive 44.32.69.182; 212 | route 44.32.69.0/24 recursive 44.32.69.183; 213 | route 44.32.69.0/24 recursive 44.32.69.184; 214 | route 44.32.69.0/24 recursive 44.32.69.185; 215 | route 44.32.69.0/24 recursive 44.32.69.186; 216 | route 44.32.69.0/24 recursive 44.32.69.187; 217 | route 44.32.69.0/24 recursive 44.32.69.188; 218 | route 44.32.69.0/24 recursive 44.32.69.189; 219 | route 44.32.69.0/24 recursive 44.32.69.190; 220 | route 44.32.69.0/24 recursive 44.32.69.191; 221 | route 44.32.69.0/24 recursive 44.32.69.192; 222 | route 44.32.69.0/24 recursive 44.32.69.193; 223 | route 44.32.69.0/24 recursive 44.32.69.194; 224 | route 44.32.69.0/24 recursive 44.32.69.195; 225 | route 44.32.69.0/24 recursive 44.32.69.196; 226 | route 44.32.69.0/24 recursive 44.32.69.197; 227 | route 44.32.69.0/24 recursive 44.32.69.198; 228 | route 44.32.69.0/24 recursive 44.32.69.199; 229 | route 44.32.69.0/24 recursive 44.32.69.200; 230 | route 44.32.69.0/24 recursive 44.32.69.201; 231 | route 44.32.69.0/24 recursive 44.32.69.202; 232 | route 44.32.69.0/24 recursive 44.32.69.203; 233 | route 44.32.69.0/24 recursive 44.32.69.204; 234 | route 44.32.69.0/24 recursive 44.32.69.205; 235 | route 44.32.69.0/24 recursive 44.32.69.206; 236 | route 44.32.69.0/24 recursive 44.32.69.207; 237 | route 44.32.69.0/24 recursive 44.32.69.208; 238 | route 44.32.69.0/24 recursive 44.32.69.209; 239 | route 44.32.69.0/24 recursive 44.32.69.210; 240 | route 44.32.69.0/24 recursive 44.32.69.211; 241 | route 44.32.69.0/24 recursive 44.32.69.212; 242 | route 44.32.69.0/24 recursive 44.32.69.213; 243 | route 44.32.69.0/24 recursive 44.32.69.214; 244 | route 44.32.69.0/24 recursive 44.32.69.215; 245 | route 44.32.69.0/24 recursive 44.32.69.216; 246 | route 44.32.69.0/24 recursive 44.32.69.217; 247 | route 44.32.69.0/24 recursive 44.32.69.218; 248 | route 44.32.69.0/24 recursive 44.32.69.219; 249 | route 44.32.69.0/24 recursive 44.32.69.220; 250 | route 44.32.69.0/24 recursive 44.32.69.221; 251 | route 44.32.69.0/24 recursive 44.32.69.222; 252 | route 44.32.69.0/24 recursive 44.32.69.223; 253 | route 44.32.69.0/24 recursive 44.32.69.224; 254 | route 44.32.69.0/24 recursive 44.32.69.225; 255 | route 44.32.69.0/24 recursive 44.32.69.226; 256 | route 44.32.69.0/24 recursive 44.32.69.227; 257 | route 44.32.69.0/24 recursive 44.32.69.228; 258 | route 44.32.69.0/24 recursive 44.32.69.229; 259 | route 44.32.69.0/24 recursive 44.32.69.230; 260 | route 44.32.69.0/24 recursive 44.32.69.231; 261 | route 44.32.69.0/24 recursive 44.32.69.232; 262 | route 44.32.69.0/24 recursive 44.32.69.233; 263 | route 44.32.69.0/24 recursive 44.32.69.234; 264 | route 44.32.69.0/24 recursive 44.32.69.235; 265 | route 44.32.69.0/24 recursive 44.32.69.236; 266 | route 44.32.69.0/24 recursive 44.32.69.237; 267 | route 44.32.69.0/24 recursive 44.32.69.238; 268 | route 44.32.69.0/24 recursive 44.32.69.239; 269 | route 44.32.69.0/24 recursive 44.32.69.240; 270 | route 44.32.69.0/24 recursive 44.32.69.241; 271 | route 44.32.69.0/24 recursive 44.32.69.242; 272 | route 44.32.69.0/24 recursive 44.32.69.243; 273 | route 44.32.69.0/24 recursive 44.32.69.244; 274 | route 44.32.69.0/24 recursive 44.32.69.245; 275 | route 44.32.69.0/24 recursive 44.32.69.246; 276 | route 44.32.69.0/24 recursive 44.32.69.247; 277 | route 44.32.69.0/24 recursive 44.32.69.248; 278 | route 44.32.69.0/24 recursive 44.32.69.249; 279 | route 44.32.69.0/24 recursive 44.32.69.250; 280 | route 44.32.69.0/24 recursive 44.32.69.251; 281 | route 44.32.69.0/24 recursive 44.32.69.252; 282 | route 44.32.69.0/24 recursive 44.32.69.253; 283 | route 44.32.69.0/24 recursive 44.32.69.254; 284 | route 44.32.69.0/24 recursive 44.32.69.255; 285 | } 286 | --------------------------------------------------------------------------------