Skip to content

Commit

Permalink
IP version specific local files
Browse files Browse the repository at this point in the history
  • Loading branch information
pierky committed Feb 20, 2017
1 parent 841611a commit ffc271b
Show file tree
Hide file tree
Showing 14 changed files with 129 additions and 12 deletions.
17 changes: 13 additions & 4 deletions docs/CONFIG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -136,17 +136,26 @@ For each community, values can be set for any of the three *formats*: standard (
Site-specific custom configuration files
****************************************

Local configuration files can be used to load static site-specific options into the BGP speaker, bypassing ARouteServer configuration building logic. These files can be used to configure, for example, neighborship with peers which are not route server members or that require custom settings.
Local configuration files can be used to load static site-specific options into the BGP speaker, bypassing the dynamic ARouteServer configuration building mechanisms. These files can be used to configure, for example, neighborship with peers which are not route server members or that require custom settings.

In BIRD, an *include* statement is used to add local files at the end of the main configuration file:
In BIRD, *include* statements are used to add local files at the end of the main configuration file.
Depending on the IP version that is in use to build the current configuration, an address family specific *include* statement is also added:

.. code::
# include statements for IPv4 configuration files
include "*.local";
include "*.local4";
Every file that is put into the same directory of the BIRD main configuration file and whose name matches the "\*.local" pattern is added to the end of the configuration. These files are not processed by ARouteServer but only by BIRD.
.. code::
# include statements for IPv6 configuration files
include "*.local";
include "*.local6";
Every file that is put into the same directory of the BIRD main configuration file and whose name matches the "\*.local" or "\*.local[4|6]" pattern is added to the end of the configuration. These files are not processed by ARouteServer but only by BIRD. Configuration options given in .local files must be IP version agnostic and must be supported by both the IPv4 and IPv6 processes; address family specific options must be set in .local4 or .local6 files.

Example: file name "01-route_collector.local" in "/etc/bird" directory:
Example: file name "01-route_collector.local4" in "/etc/bird" directory:

.. code::
Expand Down
3 changes: 2 additions & 1 deletion examples/default/bird4.conf
Original file line number Diff line number Diff line change
Expand Up @@ -429,4 +429,5 @@ protocol bgp AS10745_1 {



include "*.local";
include "*.local";
include "*.local4";
3 changes: 2 additions & 1 deletion examples/default/bird6.conf
Original file line number Diff line number Diff line change
Expand Up @@ -359,4 +359,5 @@ protocol bgp AS10745_2 {



include "*.local";
include "*.local";
include "*.local6";
3 changes: 2 additions & 1 deletion examples/rich/bird4.conf
Original file line number Diff line number Diff line change
Expand Up @@ -669,4 +669,5 @@ protocol bgp AS10745_1 {



include "*.local";
include "*.local";
include "*.local4";
3 changes: 2 additions & 1 deletion examples/rich/bird6.conf
Original file line number Diff line number Diff line change
Expand Up @@ -587,4 +587,5 @@ protocol bgp AS10745_2 {



include "*.local";
include "*.local";
include "*.local6";
47 changes: 47 additions & 0 deletions pierky/arouteserver/tests/live_tests/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,10 @@ class (the one where the ``DATA`` dictionary is set) must have
def _get_module_dir(cls):
return os.path.dirname(cls.MODULE_PATH)

@classmethod
def _get_local_file_path(cls, filename):
return os.path.join(cls._get_module_dir(), filename)

@classmethod
def _get_instance_by_name(cls, name):
for instance in cls.INSTANCES:
Expand Down Expand Up @@ -251,6 +255,26 @@ def build_rs_cfg(cls, tpl_dir_name, tpl_name, out_file_name,

return cfg_file_path

@classmethod
def use_static_file(cls, local_filename):
"""Prepare the local file in order to use it later.
Args:
filename (str): the name of the local file,
relative to the scenario directory.
Returns:
the path of the file to be used
"""

var_dir = cls._create_var_dir()
var_path = os.path.join(var_dir, local_filename)
local_path = os.path.join(cls._get_module_dir(), local_filename)
with open(local_path, "r") as src:
with open(var_path, "w") as dst:
dst.write(src.read())
return var_path

@classmethod
def mock_irrdb(cls):
def _mock_load_data_from_cache(*args, **kwargs):
Expand Down Expand Up @@ -574,6 +598,27 @@ def log_contains(self, inst, msg, instances={}):
if not inst.log_contains(expanded_msg):
self.fail("Expected message not found on {} logs:\n\t{}".format(inst.name, expanded_msg))

def session_exists(self, inst_a, inst_b_or_ip):
"""Test if a BGP session between the two instances exists.
Args:
inst_a: the :class:`BGPSpeakerInstance` instance where the
BGP session is looked for.
inst_b_or_ip: the :class:`BGPSpeakerInstance` instance or an
IP address that *inst_a* is expected to peer with.
"""

if inst_a.get_bgp_session(inst_b_or_ip) is None:
self.fail("A BGP session between '{}' ({}) and '{}' "
"does not exist.".format(
inst_a.name, inst_a.ip,
"{} ({})".format(
inst_b_or_ip.name, inst_b_or_ip.ip
) if isinstance(inst_b_or_ip, BGPSpeakerInstance)
else inst_b_or_ip
))

def session_is_up(self, inst_a, inst_b):
"""Test if a BGP session between the two instances is up.
Expand All @@ -588,6 +633,8 @@ def session_is_up(self, inst_a, inst_b):
expected to peer with.
"""

self.session_exists(inst_a, inst_b)

if inst_a.bgp_session_is_up(inst_b):
return
time.sleep(5)
Expand Down
18 changes: 14 additions & 4 deletions pierky/arouteserver/tests/live_tests/bird.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import re

from docker import DockerInstance
from instances import Route
from instances import Route, BGPSpeakerInstance


class BIRDInstance(DockerInstance):
Expand Down Expand Up @@ -106,11 +106,21 @@ def _get_protocols_status(self, force_update=False):
"{}: can't build protocols status map".format(self.name)
)

def bgp_session_is_up(self, other_inst, force_update=False):
def get_bgp_session(self, other_inst_or_ip, force_update=False):
if isinstance(other_inst_or_ip, BGPSpeakerInstance):
other_inst_ip = other_inst_or_ip.ip
else:
other_inst_ip = other_inst_or_ip
self._get_protocols_status(force_update=force_update)
for proto in self.protocols_status:
if self.protocols_status[proto]["ip"] == other_inst.ip:
return self.protocols_status[proto]["is_up"]
if self.protocols_status[proto]["ip"] == other_inst_ip:
return self.protocols_status[proto]
return None

def bgp_session_is_up(self, other_inst, force_update=False):
bgp_session_info = self.get_bgp_session(other_inst, force_update)
if bgp_session_info:
return bgp_session_info["is_up"]
raise Exception(
"Can't get BGP session status for {} on {} "
"(looking for {})".format(
Expand Down
18 changes: 18 additions & 0 deletions pierky/arouteserver/tests/live_tests/instances.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,24 @@ def reload_config(self):
def run_cmd(self, args):
raise NotImplementedError()

def get_bgp_session(self, other_inst, force_update=False):
"""Get information about the BGP session with ``other_inst``.
Args:
other_inst: the
:class:`BGPSpeakerInstance`
instance that the current instance is expected to have a
running BGP session with.
force_update (bool): if True, the instance must bypass
any caching mechanism used to keep the BGP sessions status.
Returns:
a dictionary containing information about the BGP session;
None if the BGP session is not found.
"""
raise NotImplementedError()

def bgp_session_is_up(self, other_inst, force_update=False):
"""Check if a BGP session with ``other_inst`` is up.
Expand Down
5 changes: 5 additions & 0 deletions templates/bird/main.j2
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,8 @@


include "*.local";
{% if ip_ver == 4 %}
include "*.local4";
{% else %}
include "*.local6";
{% endif %}
8 changes: 8 additions & 0 deletions tests/live_tests/scenarios/global/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ def _setup_instances(cls):
cls.build_rs_cfg("bird", "main.j2", "rs.conf",
cfg_roas="roas{}.yml".format(cls.IP_VER)),
"/etc/bird/bird.conf"
),
(
cls.use_static_file("local_file.local{}".format(cls.IP_VER)),
"/etc/bird/local_file.local{}".format(cls.IP_VER)
)
],
),
Expand Down Expand Up @@ -137,6 +141,10 @@ def test_020_sessions_up(self):
self.session_is_up(self.AS101, self.AS1_2)
self.session_is_up(self.AS101, self.AS2)

# A dummy session is configured using local include files.
# The following tests if those files are really included.
self.session_exists(self.rs, self.DATA["Dummy"])

def test_030_good_prefixes_received_by_rs(self):
"""{}: good prefixes received by rs"""
self.receive_route(self.rs, self.DATA["AS1_good1"], self.AS1_1)
Expand Down
7 changes: 7 additions & 0 deletions tests/live_tests/scenarios/global/local_file.local4
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# This is only used to verify that local files are included properly.
protocol bgp Dummy {
local as 999;
neighbor 192.0.2.99 as 65535;
import none;
export all;
}
7 changes: 7 additions & 0 deletions tests/live_tests/scenarios/global/local_file.local6
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# This is only used to verify that local files are included properly.
protocol bgp Dummy {
local as 999;
neighbor 2001:db8:1:1::999 as 65535;
import none;
export all;
}
1 change: 1 addition & 0 deletions tests/live_tests/scenarios/global/test_bird4.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class BasicScenario_BIRDIPv4(BasicScenario):
"AS1_2_IPAddress": "192.0.2.12",
"AS2_1_IPAddress": "192.0.2.21",
"AS101_IPAddress": "192.0.2.101",
"Dummy": "192.0.2.99",

"AS1_allowed_prefixes": "1.0.0.0/8",
"AS1_good1": "1.0.1.0/24",
Expand Down
1 change: 1 addition & 0 deletions tests/live_tests/scenarios/global/test_bird6.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class BasicScenario_BIRDIPv6(BasicScenario):
"AS1_2_IPAddress": "2001:db8:1:1::12",
"AS2_1_IPAddress": "2001:db8:1:1::21",
"AS101_IPAddress": "2001:db8:1:1::101",
"Dummy": "2001:db8:1:1::999",

"AS1_allowed_prefixes": "2a01:0::/32",
"AS1_good1": "2a01:0:1::/48",
Expand Down

0 comments on commit ffc271b

Please sign in to comment.