tools: frr-reload combine "'router bgp' and line" checks

Signed-off-by: Daniel Walton <dwalton@cumulusnetworks.com>

We had multiple places checking for

    if ctx_keys[0].startswith('router bgp') and line

Combine these into a single check
This commit is contained in:
Daniel Walton 2017-11-10 17:47:13 +00:00
parent c755f5c434
commit 028bcc883f

View File

@ -623,152 +623,154 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del):
for (ctx_keys, line) in lines_to_del: for (ctx_keys, line) in lines_to_del:
deleted = False deleted = False
if ctx_keys[0].startswith('router bgp') and line and line.startswith('neighbor '): if ctx_keys[0].startswith('router bgp') and line:
"""
BGP changed how it displays swpX peers that are part of peer-group. Older
versions of frr would display these on separate lines:
neighbor swp1 interface
neighbor swp1 peer-group FOO
but today we display via a single line if line.startswith('neighbor '):
neighbor swp1 interface peer-group FOO '''
BGP changed how it displays swpX peers that are part of peer-group. Older
versions of frr would display these on separate lines:
neighbor swp1 interface
neighbor swp1 peer-group FOO
This change confuses frr-reload.py so check to see if we are deleting but today we display via a single line
neighbor swp1 interface peer-group FOO neighbor swp1 interface peer-group FOO
and adding This change confuses frr-reload.py so check to see if we are deleting
neighbor swp1 interface neighbor swp1 interface peer-group FOO
neighbor swp1 peer-group FOO
If so then chop the del line and the corresponding add lines and adding
""" neighbor swp1 interface
neighbor swp1 peer-group FOO
re_swpx_int_peergroup = re.search('neighbor (\S+) interface peer-group (\S+)', line) If so then chop the del line and the corresponding add lines
re_swpx_int_v6only_peergroup = re.search('neighbor (\S+) interface v6only peer-group (\S+)', line) '''
if re_swpx_int_peergroup or re_swpx_int_v6only_peergroup: re_swpx_int_peergroup = re.search('neighbor (\S+) interface peer-group (\S+)', line)
swpx_interface = None re_swpx_int_v6only_peergroup = re.search('neighbor (\S+) interface v6only peer-group (\S+)', line)
swpx_peergroup = None
if re_swpx_int_peergroup: if re_swpx_int_peergroup or re_swpx_int_v6only_peergroup:
swpx = re_swpx_int_peergroup.group(1) swpx_interface = None
peergroup = re_swpx_int_peergroup.group(2) swpx_peergroup = None
swpx_interface = "neighbor %s interface" % swpx
elif re_swpx_int_v6only_peergroup:
swpx = re_swpx_int_v6only_peergroup.group(1)
peergroup = re_swpx_int_v6only_peergroup.group(2)
swpx_interface = "neighbor %s interface v6only" % swpx
swpx_peergroup = "neighbor %s peer-group %s" % (swpx, peergroup) if re_swpx_int_peergroup:
found_add_swpx_interface = line_exist(lines_to_add, ctx_keys, swpx_interface) swpx = re_swpx_int_peergroup.group(1)
found_add_swpx_peergroup = line_exist(lines_to_add, ctx_keys, swpx_peergroup) peergroup = re_swpx_int_peergroup.group(2)
tmp_ctx_keys = tuple(list(ctx_keys)) swpx_interface = "neighbor %s interface" % swpx
elif re_swpx_int_v6only_peergroup:
swpx = re_swpx_int_v6only_peergroup.group(1)
peergroup = re_swpx_int_v6only_peergroup.group(2)
swpx_interface = "neighbor %s interface v6only" % swpx
if not found_add_swpx_peergroup: swpx_peergroup = "neighbor %s peer-group %s" % (swpx, peergroup)
tmp_ctx_keys = list(ctx_keys) found_add_swpx_interface = line_exist(lines_to_add, ctx_keys, swpx_interface)
tmp_ctx_keys.append('address-family ipv4 unicast') found_add_swpx_peergroup = line_exist(lines_to_add, ctx_keys, swpx_peergroup)
tmp_ctx_keys = tuple(tmp_ctx_keys) tmp_ctx_keys = tuple(list(ctx_keys))
found_add_swpx_peergroup = line_exist(lines_to_add, tmp_ctx_keys, swpx_peergroup)
if not found_add_swpx_peergroup: if not found_add_swpx_peergroup:
tmp_ctx_keys = list(ctx_keys) tmp_ctx_keys = list(ctx_keys)
tmp_ctx_keys.append('address-family ipv6 unicast') tmp_ctx_keys.append('address-family ipv4 unicast')
tmp_ctx_keys = tuple(tmp_ctx_keys) tmp_ctx_keys = tuple(tmp_ctx_keys)
found_add_swpx_peergroup = line_exist(lines_to_add, tmp_ctx_keys, swpx_peergroup) found_add_swpx_peergroup = line_exist(lines_to_add, tmp_ctx_keys, swpx_peergroup)
if found_add_swpx_interface and found_add_swpx_peergroup: if not found_add_swpx_peergroup:
tmp_ctx_keys = list(ctx_keys)
tmp_ctx_keys.append('address-family ipv6 unicast')
tmp_ctx_keys = tuple(tmp_ctx_keys)
found_add_swpx_peergroup = line_exist(lines_to_add, tmp_ctx_keys, swpx_peergroup)
if found_add_swpx_interface and found_add_swpx_peergroup:
deleted = True
lines_to_del_to_del.append((ctx_keys, line))
lines_to_add_to_del.append((ctx_keys, swpx_interface))
lines_to_add_to_del.append((tmp_ctx_keys, swpx_peergroup))
'''
In 3.0.1 we changed how we display neighbor interface command. Older
versions of frr would display the following:
neighbor swp1 interface
neighbor swp1 remote-as external
neighbor swp1 capability extended-nexthop
but today we display via a single line
neighbor swp1 interface remote-as external
and capability extended-nexthop is no longer needed because we
automatically enable it when the neighbor is of type interface.
This change confuses frr-reload.py so check to see if we are deleting
neighbor swp1 interface remote-as (external|internal|ASNUM)
and adding
neighbor swp1 interface
neighbor swp1 remote-as (external|internal|ASNUM)
neighbor swp1 capability extended-nexthop
If so then chop the del line and the corresponding add lines
'''
re_swpx_int_remoteas = re.search('neighbor (\S+) interface remote-as (\S+)', line)
re_swpx_int_v6only_remoteas = re.search('neighbor (\S+) interface v6only remote-as (\S+)', line)
if re_swpx_int_remoteas or re_swpx_int_v6only_remoteas:
swpx_interface = None
swpx_remoteas = None
if re_swpx_int_remoteas:
swpx = re_swpx_int_remoteas.group(1)
remoteas = re_swpx_int_remoteas.group(2)
swpx_interface = "neighbor %s interface" % swpx
elif re_swpx_int_v6only_remoteas:
swpx = re_swpx_int_v6only_remoteas.group(1)
remoteas = re_swpx_int_v6only_remoteas.group(2)
swpx_interface = "neighbor %s interface v6only" % swpx
swpx_remoteas = "neighbor %s remote-as %s" % (swpx, remoteas)
found_add_swpx_interface = line_exist(lines_to_add, ctx_keys, swpx_interface)
found_add_swpx_remoteas = line_exist(lines_to_add, ctx_keys, swpx_remoteas)
tmp_ctx_keys = tuple(list(ctx_keys))
if found_add_swpx_interface and found_add_swpx_remoteas:
deleted = True
lines_to_del_to_del.append((ctx_keys, line))
lines_to_add_to_del.append((ctx_keys, swpx_interface))
lines_to_add_to_del.append((tmp_ctx_keys, swpx_remoteas))
'''
In 3.0, we made bgp bestpath multipath as-relax command
automatically assume no-as-set since the lack of this option caused
weird routing problems and this problem was peculiar to this
implementation. When the running config is shown in relases after
3.0, the no-as-set is not shown as its the default. This causes
reload to unnecessarily unapply this option to only apply it back
again, causing unnecessary session resets. Handle this.
'''
if 'multipath-relax' in line:
re_asrelax_new = re.search('^bgp\s+bestpath\s+as-path\s+multipath-relax$', line)
old_asrelax_cmd = 'bgp bestpath as-path multipath-relax no-as-set'
found_asrelax_old = line_exist(lines_to_add, ctx_keys, old_asrelax_cmd)
if re_asrelax_new and found_asrelax_old:
deleted = True deleted = True
lines_to_del_to_del.append((ctx_keys, line)) lines_to_del_to_del.append((ctx_keys, line))
lines_to_add_to_del.append((ctx_keys, swpx_interface)) lines_to_add_to_del.append((ctx_keys, old_asrelax_cmd))
lines_to_add_to_del.append((tmp_ctx_keys, swpx_peergroup))
""" '''
In 3.0.1 we changed how we display neighbor interface command. Older If we are modifying the BGP table-map we need to avoid a del/add and
versions of frr would display the following: instead modify the table-map in place via an add. This is needed to
neighbor swp1 interface avoid installing all routes in the RIB the second the 'no table-map'
neighbor swp1 remote-as external is issued.
neighbor swp1 capability extended-nexthop '''
if line.startswith('table-map'):
found_table_map = line_exist(lines_to_add, ctx_keys, 'table-map', False)
but today we display via a single line if found_table_map:
neighbor swp1 interface remote-as external
and capability extended-nexthop is no longer needed because we
automatically enable it when the neighbor is of type interface.
This change confuses frr-reload.py so check to see if we are deleting
neighbor swp1 interface remote-as (external|internal|ASNUM)
and adding
neighbor swp1 interface
neighbor swp1 remote-as (external|internal|ASNUM)
neighbor swp1 capability extended-nexthop
If so then chop the del line and the corresponding add lines
"""
re_swpx_int_remoteas = re.search('neighbor (\S+) interface remote-as (\S+)', line)
re_swpx_int_v6only_remoteas = re.search('neighbor (\S+) interface v6only remote-as (\S+)', line)
if re_swpx_int_remoteas or re_swpx_int_v6only_remoteas:
swpx_interface = None
swpx_remoteas = None
if re_swpx_int_remoteas:
swpx = re_swpx_int_remoteas.group(1)
remoteas = re_swpx_int_remoteas.group(2)
swpx_interface = "neighbor %s interface" % swpx
elif re_swpx_int_v6only_remoteas:
swpx = re_swpx_int_v6only_remoteas.group(1)
remoteas = re_swpx_int_v6only_remoteas.group(2)
swpx_interface = "neighbor %s interface v6only" % swpx
swpx_remoteas = "neighbor %s remote-as %s" % (swpx, remoteas)
found_add_swpx_interface = line_exist(lines_to_add, ctx_keys, swpx_interface)
found_add_swpx_remoteas = line_exist(lines_to_add, ctx_keys, swpx_remoteas)
tmp_ctx_keys = tuple(list(ctx_keys))
if found_add_swpx_interface and found_add_swpx_remoteas:
deleted = True
lines_to_del_to_del.append((ctx_keys, line)) lines_to_del_to_del.append((ctx_keys, line))
lines_to_add_to_del.append((ctx_keys, swpx_interface))
lines_to_add_to_del.append((tmp_ctx_keys, swpx_remoteas))
''' '''
In 3.0, we made bgp bestpath multipath as-relax command More old-to-new config handling. ip import-table no longer accepts
automatically assume no-as-set since the lack of this option caused distance, but we honor the old syntax. But 'show running' shows only
weird routing problems and this problem was peculiar to this the new syntax. This causes an unnecessary 'no import-table' followed
implementation. When the running config is shown in relases after by the same old 'ip import-table' which causes perturbations in
3.0, the no-as-set is not shown as its the default. This causes announced routes leading to traffic blackholes. Fix this issue.
reload to unnecessarily unapply this option to only apply it back
again, causing unnecessary session resets. Handle this.
'''
if ctx_keys[0].startswith('router bgp') and line and 'multipath-relax' in line:
re_asrelax_new = re.search('^bgp\s+bestpath\s+as-path\s+multipath-relax$', line)
old_asrelax_cmd = 'bgp bestpath as-path multipath-relax no-as-set'
found_asrelax_old = line_exist(lines_to_add, ctx_keys, old_asrelax_cmd)
if re_asrelax_new and found_asrelax_old:
deleted = True
lines_to_del_to_del.append((ctx_keys, line))
lines_to_add_to_del.append((ctx_keys, old_asrelax_cmd))
'''
If we are modifying the BGP table-map we need to avoid a del/add and
instead modify the table-map in place via an add. This is needed to
avoid installing all routes in the RIB the second the 'no table-map'
is issued.
'''
if ctx_keys[0].startswith('router bgp') and line and line.startswith('table-map'):
found_table_map = line_exist(lines_to_add, ctx_keys, 'table-map', False)
if found_table_map:
lines_to_del_to_del.append((ctx_keys, line))
'''
More old-to-new config handling. ip import-table no longer accepts
distance, but we honor the old syntax. But 'show running' shows only
the new syntax. This causes an unnecessary 'no import-table' followed
by the same old 'ip import-table' which causes perturbations in
announced routes leading to traffic blackholes. Fix this issue.
''' '''
re_importtbl = re.search('^ip\s+import-table\s+(\d+)$', ctx_keys[0]) re_importtbl = re.search('^ip\s+import-table\s+(\d+)$', ctx_keys[0])
if re_importtbl: if re_importtbl: