# ==== CONSTANTS ==== define OWNAS = ; # your autonomous system number # the first non-zero IPv4 you control. Since we're only using # IPv6. Use the first non-zero 32 bits you control. E.g., if # you control 255::/16, use 2.85.0.1 (255 is two hex bytes, # 0x02, and 0x55 which is 2.85 in a v4 addr). define OWNIP = ; # the router's actual IPv6 addr that it can be reached by. define OWNIPv6 = ; # the subnet you control define OWNNETv6 = ; # set of all addrs you control. define OWNNETSETv6 = [+]; # =================== router id OWNIP; # "everything" is a protocol in bird. The `device` protocol is not really # a protocol, it just instructs bird to ask the kernel for information # on devices (interfaces). protocol device { # scan devices every 10 seconds. scan time 10; } # ==== UTILITY FUNCTIONS ==== function is_self_net() { return net ~ OWNNETSETv6; } function is_valid_network() { return net ~ [ 0200::/7+ ]; } # Tell bird how to interact with the kernel (modify routes): # # Again, not really a protocol but ¯\_(ツ)_/¯ protocol kernel { # scan the routing table every 20 seconds (update bird state). scan time 20; # configure ipv6 ipv6 { # Don't import any routes from the kernel, let bird figure out # what routes to add or change. `none` is a "filter" that discards # routes that are given to it. The kernel gives bird routes and we # want bird to ignore them. kernel -> bird. import none; # We write an inline filter that describes what routes to give the # kernel from bird. bird -> kernel. export filter { # if the source of this route is static configuration, then we # don't want to give it to the kernel. (only want dynamic routes). # I don't know why this is important? Is that right? if source = RTS_STATIC then reject; # set the `krt_prefsrc` attribute for this route. # see comment above above the kernel block. krt_prefsrc = OWNIPv6; # accept this route (don't filter it out). accept; }; }; } # Static protocol lets you define static routes that do not change. protocol static { # reject any routes in our subnet (I think?) route OWNNETv6 reject; ipv6 { # tell bird about everything. static -> bird. import all; # bird can't configure static routes (default)?. # bird -> static. export none; }; } # Create a template for the `bgp` protocol. This is where the real # magic happens. We use a template since every peer will essentially # have the same BGP configuration. The template name is `alapeers`. # # Each peer gets its own template and file under `peers/*``. # # We're using BGP in "exterior" or `eBGP` mode. This means we're using # the protocol to define routes between Autonomous Systems, not really # between individual IP addrs. # # Each instance of the `bgp` protocol corresponds with one neighboring # router, or in our case, a peer. template bgp alapeers { # our `as` number is the OWNAS constant. This is defined in the local # defs file that comes later. local as OWNAS; # compare path lengths to determine which route is the best one. path metric 1; ipv6 { # only accept routes from peers that follow this inline filter. # bgp -> bird. import filter { # Accept the route if its a valid network and is not our # own network. (fns defined in local defs file). if is_valid_network() && !is_self_net() then { accept; } reject; }; # only send routes that follow this inline filter. # bird -> bgp (other peers). export filter { # Only send if it's a valid netowrk and the route comes from # static configuration or from BGP. if is_valid_network() && source ~ [RTS_STATIC, RTS_BGP] then { accept; } reject; }; # Only allow for 1000 total routes to be imported. Once we hit # 1000, block further routes. import limit 1000 action block; }; } # Include all of our peers! include "peers/*";