Skip to content

Commit

Permalink
Implement 'localas_ibgp' on Cisco IOSv/IOS XE (see #368)
Browse files Browse the repository at this point in the history
  • Loading branch information
ipspace committed Sep 8, 2022
1 parent e0f8e9f commit 328edbb
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 5 deletions.
9 changes: 5 additions & 4 deletions netsim/ansible/templates/bgp/ios.macro.j2
Expand Up @@ -8,7 +8,8 @@
{% macro neighbor_global(n,ip) %}
neighbor {{ ip }} remote-as {{ n.as }}
{% if n.local_as is defined %}
neighbor {{ ip }} local-as {{ n.local_as }}{% if n.replace_global_as|default(True) %} no-prepend replace-as{% endif +%}
neighbor {{ ip }} local-as {{ n.local_as }}{%
if n.replace_global_as|default(True) and n.type != 'localas_ibgp' %} no-prepend replace-as{% endif +%}
{% endif %}
neighbor {{ ip }} description {{ n.name }}
{% if n.type == 'ibgp' %}
Expand All @@ -20,14 +21,14 @@
#}
{% macro neighbor_af(n,ip,bgp) %}
neighbor {{ ip }} activate
{% if n.type == 'ibgp' %}
{% if 'ibgp' in n.type %}
{% if bgp.community.ibgp|default([]) %}
neighbor {{ ip }} send-community {{ community(bgp.community.ibgp) }}
{% endif %}
{% if bgp.next_hop_self is defined and bgp.next_hop_self %}
neighbor {{ ip }} next-hop-self
neighbor {{ ip }} next-hop-self{% if n.type == 'localas_ibgp' %} all{% endif +%}
{% endif %}
{% if bgp.rr|default('') and not n.rr|default('') %}
{% if bgp.rr|default('') and (not n.rr|default('') or n.type == 'localas_ibgp') %}
neighbor {{ ip }} route-reflector-client
{% endif %}
{% else %}{# EBGP IPv4 neighbor #}
Expand Down
7 changes: 7 additions & 0 deletions netsim/modules/bgp.py
Expand Up @@ -211,6 +211,13 @@ def build_ebgp_sessions(node: Box, sessions: Box, topology: Box) -> None:
extra_data[k] = local_as_data

session_type = 'localas_ibgp' if neighbor_local_as == node_local_as else 'ebgp'
if session_type == 'localas_ibgp':
if not features.bgp.local_as_ibgp:
common.error(
text=f'You cannot use BGP local-as to create an IBGP session with {ngb_name} on {node.name} (device {node.device})',
category=common.IncorrectValue,
module='bgp')
continue

ebgp_data = bgp_neighbor(neighbor,ngb_ifdata,session_type,sessions,extra_data)
if not ebgp_data is None:
Expand Down
4 changes: 3 additions & 1 deletion netsim/topology-defaults.yml
Expand Up @@ -27,7 +27,7 @@ addressing:
# Global, node and link attributes
attributes:
global: [ addressing,defaults,groups,links,module,name,nodes,plugin,provider ]
internal: [ input,includes,pools,Provider,Plugin ]
internal: [ input,includes,pools,Provider,Plugin,message ]
link: [ bandwidth,bridge,name,prefix,role,type,unnumbered,interfaces,mtu,gateway,vlan_name ]
link_internal: [ linkindex,parentindex ]
link_no_propagate: [ prefix,interfaces,gateway ]
Expand Down Expand Up @@ -294,6 +294,7 @@ devices:
bgp:
local_as: True
vrf_local_as: True
local_as_ibgp: True
initial:
ipv4:
unnumbered: False
Expand Down Expand Up @@ -340,6 +341,7 @@ devices:
bgp:
local_as: True
vrf_local_as: True
local_as_ibgp: True
initial:
ipv4:
unnumbered: True
Expand Down
31 changes: 31 additions & 0 deletions tests/integration/bgp/local-as/ibgp-local-as.yml
@@ -0,0 +1,31 @@
message: |
This lab topology checks the IBGP local-as functionality -- creating BGP direct
session between two autonomous systems and using BGP local-as to make it a
fake IBGP session.
You should be able to see BGP routes from all four loopbacks on E1 and E2, and
ping between loopback interfaces of E1 and E2.
defaults.device: iosv

module: [ bgp,ospf ]

nodes:
r1:
bgp.as: 65000
bgp.rr: True
r2:
bgp.as: 65001
bgp.rr: True
e1:
bgp.as: 65000
e2:
bgp.as: 65001

links:
- r1:
bgp.local_as: 666
r2:
bgp.local_as: 666
bgp.advertise: True
- r1-e1
- r2-e2

0 comments on commit 328edbb

Please sign in to comment.