Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion netsim/daemons/bird.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ features:
2octet: [ standard ]
import: [ ospf, connected, static, vrf ]
bfd: true
default_originate: true
default_originate: static
gtsm: true
passive: true
password: true
Expand Down
1 change: 0 additions & 1 deletion netsim/daemons/bird/bgp.j2
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
{% if 'router_id' in bgp %}
router id {{ bgp.router_id }};
{% endif %}
{{ bgp_config.bgp_default_originate_routes(bgp) }}
{{ bgp_config.bgp_advertise_list('bgp_advertise',bgp.advertise) }}
{{ bgp_config.bgp_prefixes_function('bgp_prefixes',bgp,'bgp_advertise',bgp.import|default([]),True) }}
{{ bgp_config.bgp_export_filters('bgp_export_','bgp_prefixes') }}
Expand Down
27 changes: 4 additions & 23 deletions netsim/daemons/bird/bgp.macros.j2
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,6 @@
accept;
{% endmacro %}

{#
# bgp_default_originate_routes: Render reject static routes used to originate default routes toward selected BGP neighbors.
#}
{% macro bgp_default_originate_routes(bgp_data) %}
{% for ngb in bgp_data.neighbors|default([]) if ngb.default_originate|default(False) %}
{% if loop.first %}
{% for _af in ['ipv4','ipv6'] if _af in af %}
protocol static static_bgp_default_{{ _af }} {
{{ _af }};
route {{ '0.0.0.0/0' if _af=='ipv4' else '::/0' }} reject;
}
{% endfor %}
{% endif %}
{% endfor %}
{% endmacro %}

{#
# bgp_advertise_list: Render BIRD prefix-set definitions for the configured advertise list.
#}
Expand All @@ -55,17 +39,14 @@ define {{ list_name }}_{{ pfx_af }} = [
#}
{% macro bgp_prefixes_function(func_name,bgp_data,list_name,import_list,include_default_static) %}
function {{ func_name }}( bool originate_default ) {
if net.len = 0 && !originate_default
then reject "Don't originate default route";
if net.len = 0
then if !originate_default
then reject "Don't originate default route";
else accept "BGP default route origination: ",net;

if source ~ [ RTS_BGP ]
then accept "BGP route:", net;

{% if include_default_static %}
if proto ~ "static_bgp_default*"
then accept "BGP prefix origination:", net;

{% endif %}
{% for proto in import_list|default([]) %}
if source ~ [ {{ netlab_import_map[proto] }} ]
then accept "{{ proto }} route:", net;
Expand Down
53 changes: 52 additions & 1 deletion netsim/extra/bgp.session/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from box import Box, BoxList

from netsim import api, modules
from netsim.data import append_to_list
from netsim.data import append_to_list, get_box
from netsim.utils import log
from netsim.utils import routing as _bgp

Expand Down Expand Up @@ -156,6 +156,56 @@ def process_bfd_requests(ndata: Box, topology: Box) -> None:
log.IncorrectValue,
_config_name)

'''
Check whether a node originating a default route needs static default route(s)
'''
BGP_DEFAULT = {
'ipv4': { 'ipv4': '0.0.0.0/0', 'floating': True, 'nexthop.discard': True },
'ipv6': { 'ipv6': '::/0', 'floating': True, 'nexthop.discard': True }}

def process_default_requests(ndata: Box, topology: Box) -> None:
if _bgp.get_device_bgp_feature('default_originate',ndata,topology) != 'static':
return # The node does not need static routes to originate default

for ngb in _bgp.neighbors(ndata):
if not 'default_originate' in ngb: # Does the neighbor need a BGP default route?
continue # Nope? Cool

route_list = [ # Find relevant static routes based on neighbor AFs
BGP_DEFAULT[af] for af in log.AF_LIST if af in ngb
]
Comment on lines +174 to +176

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably not applicable, but I nevertheless rewrote the SR creation code

if not route_list:
continue

append_to_list(ndata,'module','routing') # Activate the routing module in the node
append_to_list(topology,'module','routing') # ... assuming the developer setting BGP features was sane ;)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hope this doesn't activate the routing module on all nodes in the topology?

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Of course not. This is done late in the process (well after the topology.module is copied into node.module). The same two calls are used to add static routes to hosts.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In that case, what breaks if we don’t set this? Why is this necessary?

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In that case, what breaks if we don’t set this? Why is this necessary?

The static routes are not configured 🤷🏻‍♂️


# Get VRF (or global) data and its static routes
#
ngb_vrf = ngb.get('_src_vrf',None)
routes = ndata.get('routing.static',[])

for sr_data in route_list: # Iterate over routes that have to be added
for af in log.AF_LIST: # We have to check all AFs
if af not in sr_data: # Is this AF relevant for the current entry?
continue

# Get existing route(s) where the AF prefix matches what we need
have_routes = [ r for r in routes if af in r and r[af] == sr_data[af] ]
if ngb_vrf is None: # Filter the routes we found based on the VRF
have_routes = [ r for r in have_routes if 'vrf' not in r ]
else:
have_routes = [ r for r in have_routes if r.get('vrf',None) == ngb_vrf ]
if have_routes: # Did the user specify their own default route(s)?
continue # Cool, nothing to do ;)

# No per-AF default route in the target VRF yet, add it
#
sr_final = sr_data # Assume we can use the static route data as-is
if ngb_vrf: # But if we have a VRF neighbor, we have to add VRF info
sr_final = get_box({'vrf': ngb_vrf}) + sr_data
append_to_list(ndata,'routing.static',sr_final)

'''
Zap a BGP neighbor: remove all usable IP addresses, local_if and ifindex
'''
Expand Down Expand Up @@ -288,6 +338,7 @@ def post_transform(topology: Box) -> None:
copy_local_attributes(ndata,topology)
process_tcpao_secrets(ndata,topology)
process_bfd_requests(ndata,topology)
process_default_requests(ndata,topology)
have_rs = process_rs_requests(ndata,topology) or have_rs

# We need to do the RS-related EBGP session cleanup in a second pass
Expand Down
Loading