Skip to content

Commit

Permalink
Configurable default BGP address families (implements #366)
Browse files Browse the repository at this point in the history
  • Loading branch information
ipspace committed Sep 8, 2022
1 parent 328edbb commit 97890e2
Show file tree
Hide file tree
Showing 22 changed files with 480 additions and 143 deletions.
22 changes: 13 additions & 9 deletions docs/module/bgp.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ More interesting BGP topologies can be created with [custom plugins](../plugins.
* Next-hop-self control on IBGP sessions
* BGP community propagation
* IPv4 and IPv6 address families
* Configurable activation of default address families
* Configurable link prefix advertisement
* Additional (dummy) prefix advertisement
* Changing local autonomous system for individual BGP sessions (*local-as*)
Expand All @@ -35,14 +36,14 @@ More interesting BGP topologies can be created with [custom plugins](../plugins.

[Platforms supporting BGP configuration module](platform-routing-support) support most of the functionality mentioned above. The following features are only supported on a subset of platforms:

| Operating system | Unnumbered<br />interfaces | local AS |
| --------------------- | :-: | :-: |
| Arista EOS |||
| Cisco IOS/IOS XE |||
| Cumulus Linux |||
| Dell OS10 |||
| FRR 7.5.0 |||
| Nokia SR Linux |||
| Operating system | Unnumbered<br />interfaces | local AS | IBGP<br>local AS | Configurable<br>default AF |
| --------------------- | :-: | :-: | :-: | :-: |
| Arista EOS |||||
| Cisco IOS/IOS XE |||||
| Cumulus Linux |||||
| Dell OS10 |||||
| FRR 7.5.0 |||||
| Nokia SR Linux |||||

## Global BGP Configuration Parameters

Expand Down Expand Up @@ -113,10 +114,13 @@ Finally, BGP configuration module supports these advanced node parameters that y

* **bgp.rr_cluster_id** -- set static route reflector cluster ID. The default value is the lowest router ID of all route reflectors within the autonomous system.
* **bgp.replace_global_as** (default: True) -- the default implementation of **neighbor local-as** command replaces the real autonomous system (**bgp.as**) with the *local* autonomous system. Set this parameter to *false* to disable that functionality and include both autonomous systems in the AS path[^RAS_P].
* **bgp.sessions** -- specifies which transport sessions (IPv4 and/or IPv6) should be created for each BGP session type (IBGP, EBGP, or IBGP created through *local-as*)[^SESS_DM]. See *[bgp-sessions](https://github.com/ipspace/netlab/blob/dev/tests/topology/input/bgp-sessions.yml)* test case for an example.
* **bgp.sessions** (node or global parameter) -- specifies which transport sessions (IPv4 and/or IPv6) should be created for each BGP session type (IBGP, EBGP, or IBGP created through *local-as*)[^SESS_DM]. See *[bgp-sessions](https://github.com/ipspace/netlab/blob/dev/tests/topology/input/bgp-sessions.yml)* test case for an example.
* **bgp.activate** (node or global parameter) -- specifies which default address families (IPv4 AF on IPv4 session, IPv6 on IPv6 session) should be created for each BGP session type (IBGP, EBGP, or IBGP created through *local-as*)[^ACT_CFG]. See *[leaf-spine](https://github.com/ipspace/netlab/blob/dev/tests/integration/bgp/local-as/leaf-spine.yml)* local AS test case for an example.

[^SESS_DM]: This parameter influences the data structures built during the data transformation phase and is thus available on all platforms supporting BGP configuration module.

[^ACT_CFG]: This parameter has to be supported by the device configuration templates and is thus not available on all platforms.

[^RAS_P]: This functionality might not be configurable on all platforms. For example, Arista EOS supports only the **neighbor local-as no-prepend replace-as** command.

## Link-Level Parameters
Expand Down
4 changes: 3 additions & 1 deletion netsim/ansible/templates/bgp/eos.j2
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
router bgp {{ bgp.as }}
bgp advertise-inactive
bgp log-neighbor-changes
no bgp default ipv4-unicast
no bgp default ipv6-unicast
{% if bgp.router_id|ipv4 %}
router-id {{ bgp.router_id }}
{% endif %}
Expand Down Expand Up @@ -36,7 +38,7 @@ router bgp {{ bgp.as }}
network {{ pfx|ipaddr('0') }}
{% endfor %}
!
{% for n in bgp.neighbors if n[af] is defined %}
{% for n in bgp.neighbors if n[af] is defined and n.activate[af] is defined and n.activate[af] %}
neighbor {{ n[af] }} activate
{% endfor %}
{% endif %}
Expand Down
2 changes: 1 addition & 1 deletion netsim/ansible/templates/bgp/ios.j2
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ router bgp {{ bgp.as }}
{{ bgpcfg.bgp_network(af,pfx) }}
{% endfor %}
!
{% for n in bgp.neighbors if n[af] is defined %}
{% for n in bgp.neighbors if n[af] is defined and n.activate[af] is defined and n.activate[af] %}
{{ bgpcfg.neighbor_af(n,n[af],bgp) }}
{% endfor %}
{% endfor %}
Expand Down
37 changes: 33 additions & 4 deletions netsim/modules/bgp.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,20 +48,20 @@ def check_bgp_parameters(node: Box) -> None:
BGP_VALID_AF: typing.Final[list] = ['ipv4','ipv6']
BGP_VALID_SESSION_TYPE: typing.Final[list] = ['ibgp','ebgp','localas_ibgp']

def validate_bgp_sessions(node: Box, sessions: Box) -> bool:
def validate_bgp_sessions(node: Box, sessions: Box, attribute: str) -> bool:
OK = True
for k in list(sessions.keys()):
if not k in BGP_VALID_AF:
common.error(
f'Invalid address family in bgp.sessions in node {node.name}',
f'Invalid address family in bgp.{attribute} in node {node.name}',
common.IncorrectValue,
'bgp')
OK = False
else:
if data.must_be_list(
parent=sessions,
key=k,
path=f'nodes.{node.name}.bgp.sessions',
path=f'nodes.{node.name}.bgp.{attribute}',
true_value=BGP_VALID_SESSION_TYPE,
valid_values=BGP_VALID_SESSION_TYPE,
module='bgp') is None:
Expand Down Expand Up @@ -229,6 +229,19 @@ def build_ebgp_sessions(node: Box, sessions: Box, topology: Box) -> None:
else: # Global neighbor
node.bgp.neighbors.append(ebgp_data)

"""
activate_bgp_default_af -- activate default AF on IPv4 and/or IPv6 transport sessions
Based on transport session(s) with a BGP neighbor, local BGP AF, and BGP AF configuration
parameters, set neighbor.activate.AF flags
"""

def activate_bgp_default_af(node: Box, activate: Box, topology: Box) -> None:
for ngb in node.bgp.neighbors:
for af in ('ipv4','ipv6'):
if af in ngb:
ngb.activate[af] = node.bgp.get(af) and af in activate and ngb.type in activate[af]

"""
build_bgp_sessions: create BGP session data structure
Expand All @@ -250,7 +263,7 @@ def build_bgp_sessions(node: Box, topology: Box) -> None:

node.bgp.neighbors = []
bgp_sessions = node.bgp.get('sessions') or Box(BGP_DEFAULT_SESSIONS)
if not validate_bgp_sessions(node,bgp_sessions):
if not validate_bgp_sessions(node,bgp_sessions,'sessions'):
return

build_ibgp_sessions(node,bgp_sessions,topology)
Expand All @@ -264,6 +277,22 @@ def build_bgp_sessions(node: Box, topology: Box) -> None:
node.bgp[af] = True
break

# Activate default BGP address families
features = devices.get_device_features(node,topology.defaults)
if 'activate' in node.bgp:
if not features.bgp.activate_af:
common.error(
f'node {node.name} (device {node.device}) does not support configurable activation of default BGP address families',
common.IncorrectValue,
'bgp')
return

activate = node.bgp.get('activate') or Box(BGP_DEFAULT_SESSIONS)
if not validate_bgp_sessions(node,activate,'activate'):
return

activate_bgp_default_af(node,activate,topology)

"""
bgp_set_advertise: set bgp.advertise flag on stub links
"""
Expand Down
7 changes: 5 additions & 2 deletions netsim/topology-defaults.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@ bgp:
next_hop_self: true
attributes:
global: [
af, as, next_hop_self, rr_cluster_id, rr_list, ebgp_role, as_list, sessions,
af, as, next_hop_self, rr_cluster_id, rr_list, ebgp_role, as_list, sessions, activate,
advertise_loopback, advertise_roles, community, address_families, replace_global_as ]
node: [
af, as, next_hop_self, rr, rr_cluster_id, originate, advertise_loopback, sessions,
af, as, next_hop_self, rr, rr_cluster_id, originate, advertise_loopback, sessions, activate,
community, router_id, address_families, local_as, replace_global_as ]
node_copy: [ local_as, replace_global_as ]
link: [ advertise ]
Expand Down Expand Up @@ -295,6 +295,7 @@ devices:
local_as: True
vrf_local_as: True
local_as_ibgp: True
activate_af: True
initial:
ipv4:
unnumbered: False
Expand Down Expand Up @@ -342,6 +343,7 @@ devices:
local_as: True
vrf_local_as: True
local_as_ibgp: True
activate_af: True
initial:
ipv4:
unnumbered: True
Expand Down Expand Up @@ -422,6 +424,7 @@ devices:
bgp:
local_as: True
vrf_local_as: True
activate_af: True
initial:
system_mtu: True
ipv4:
Expand Down
13 changes: 13 additions & 0 deletions tests/integration/bgp/local-as/leaf-spine.yml
Original file line number Diff line number Diff line change
@@ -1,15 +1,28 @@
---
message: |
This topology creates a leaf-and-spine topology with EBGP underlay sessions
and IBGP sessions between loopback interfaces.
You should be able to ping between all loopback interfaces. IPv4 IBGP
neighbor sessions are configured but will probably be idle (no AF configured
on the transport session).
All IPv4 BGP routes should be EBGP routes.
defaults.device: eos

module: [ bgp ]

bgp.as: 65000
bgp.activate:
ipv4: [ ebgp ]

nodes:
s1:
bgp.local_as: 65101
bgp.rr: True
s2:
bgp.local_as: 65102
bgp.rr: True
l1:
bgp.local_as: 65201
l2:
Expand Down
26 changes: 22 additions & 4 deletions tests/topology/expected/6pe.yml
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,10 @@ nodes:
ipv4: true
ipv6: true
neighbors:
- as: 65000
- activate:
ipv4: true
ipv6: true
as: 65000
ifindex: 1
ipv4: 172.31.0.2
ipv6: 2001:db8:2::2
Expand Down Expand Up @@ -221,7 +224,10 @@ nodes:
ipv4: true
ipv6: true
neighbors:
- as: 65000
- activate:
ipv4: true
ipv6: true
as: 65000
ifindex: 1
ipv4: 172.31.1.2
ipv6: 2001:db8:2:1::2
Expand Down Expand Up @@ -331,11 +337,17 @@ nodes:
ipv6: true
neighbors:
- 6pe: true
activate:
ipv4: true
ipv6: true
as: 65000
ipv4: 10.0.0.2
name: pe2
type: ibgp
- as: 65001
- activate:
ipv4: true
ipv6: true
as: 65001
ifindex: 1
ipv4: 172.31.0.1
ipv6: 2001:db8:2::1
Expand Down Expand Up @@ -416,11 +428,17 @@ nodes:
ipv6: true
neighbors:
- 6pe: true
activate:
ipv4: true
ipv6: true
as: 65000
ipv4: 10.0.0.1
name: pe1
type: ibgp
- as: 65002
- activate:
ipv4: true
ipv6: true
as: 65002
ifindex: 1
ipv4: 172.31.1.1
ipv6: 2001:db8:2:1::1
Expand Down
48 changes: 36 additions & 12 deletions tests/topology/expected/addressing-ipv6-only.yml
Original file line number Diff line number Diff line change
Expand Up @@ -119,15 +119,21 @@ nodes:
- extended
ipv6: true
neighbors:
- as: 65000
- activate:
ipv6: true
as: 65000
ipv6: 2001:db8:0:15::1
name: r2
type: ibgp
- as: 65000
- activate:
ipv6: true
as: 65000
ipv6: 2001:db8:0:2a::1
name: r3
type: ibgp
- as: 65000
- activate:
ipv6: true
as: 65000
ipv6: 2001:db8:0:1::1
name: r4
type: ibgp
Expand Down Expand Up @@ -227,15 +233,21 @@ nodes:
- extended
ipv6: true
neighbors:
- as: 65000
- activate:
ipv6: true
as: 65000
ipv6: 2001:db8:0:7::1
name: r1
type: ibgp
- as: 65000
- activate:
ipv6: true
as: 65000
ipv6: 2001:db8:0:2a::1
name: r3
type: ibgp
- as: 65000
- activate:
ipv6: true
as: 65000
ipv6: 2001:db8:0:1::1
name: r4
type: ibgp
Expand Down Expand Up @@ -332,15 +344,21 @@ nodes:
- extended
ipv6: true
neighbors:
- as: 65000
- activate:
ipv6: true
as: 65000
ipv6: 2001:db8:0:7::1
name: r1
type: ibgp
- as: 65000
- activate:
ipv6: true
as: 65000
ipv6: 2001:db8:0:15::1
name: r2
type: ibgp
- as: 65000
- activate:
ipv6: true
as: 65000
ipv6: 2001:db8:0:1::1
name: r4
type: ibgp
Expand Down Expand Up @@ -415,15 +433,21 @@ nodes:
- extended
ipv6: true
neighbors:
- as: 65000
- activate:
ipv6: true
as: 65000
ipv6: 2001:db8:0:7::1
name: r1
type: ibgp
- as: 65000
- activate:
ipv6: true
as: 65000
ipv6: 2001:db8:0:15::1
name: r2
type: ibgp
- as: 65000
- activate:
ipv6: true
as: 65000
ipv6: 2001:db8:0:2a::1
name: r3
type: ibgp
Expand Down
8 changes: 6 additions & 2 deletions tests/topology/expected/bgp-anycast.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@ nodes:
- extended
ipv4: true
neighbors:
- as: 65000
- activate:
ipv4: true
as: 65000
ipv4: 10.0.0.2
name: l2
type: ibgp
Expand Down Expand Up @@ -111,7 +113,9 @@ nodes:
- extended
ipv4: true
neighbors:
- as: 65000
- activate:
ipv4: true
as: 65000
ipv4: 10.0.0.1
name: l1
type: ibgp
Expand Down
Loading

0 comments on commit 97890e2

Please sign in to comment.