]> git.proxmox.com Git - mirror_frr.git/commitdiff
frr-reload: fix bgp nbr remote-as
authorChirag Shah <chirag@nvidia.com>
Thu, 11 Nov 2021 01:22:24 +0000 (17:22 -0800)
committerChirag Shah <chirag@nvidia.com>
Mon, 6 Dec 2021 05:28:11 +0000 (21:28 -0800)
Remove neighbor <> remote-as <> config line,
if the neighbor is part of the peer-group and
peer-group contains remote-as config.

Neighbors which are part of the peer-group
cannot override remote-as.

Fix:
Frr-reload needs to remote 'neighbor <> remote-as <>'
from lines_to_add if its already part of peer-group
and peer-group has remote-as config.

Testing Done:

Before:

Config snippet:
neighbor PEERS peer-group
neighbor PEERS remote-as external
neighbor PEERS timers 3 9
neighbor 10.2.1.1 remote-as external
neighbor 10.2.1.1 peer-group PEERS
neighbor 10.2.1.1 timers 3 9
neighbor 10.2.1.2 remote-as external
neighbor 10.2.1.2 peer-group PEERS

Frr-reload failure:
line 179: Failure to communicate[13] to bgpd, line:  neighbor 10.2.1.1
remote-as external
% Peer-group member cannot override remote-as of peer-group
line 179: Failure to communicate[13] to bgpd, line:  neighbor 10.2.1.2
remote-as external
% Peer-group member cannot override remote-as of peer-group

After:
frr-reload apply the config successfully.

Signed-off-by: Chirag Shah <chirag@nvidia.com>
tools/frr-reload.py

index acd7a240b3f2344c692f31670207937849891bc2..7868c3d41dd4366b89f73427d064e323c7db17fd 100755 (executable)
@@ -762,12 +762,96 @@ def check_for_exit_vrf(lines_to_add, lines_to_del):
     return (lines_to_add, lines_to_del)
 
 
+def bgp_delete_nbr_remote_as_line(lines_to_add):
+    # Handle deletion of neighbor <nbr> remote-as line from
+    # lines_to_add if the nbr is configured with peer-group and
+    # peer-group has remote-as config present.
+    # 'neighbor <nbr> remote-as change on peer is not allowed
+    # if the peer is part of peer-group and peer-group has
+    # remote-as config.
+
+    pg_dict = dict()
+    # Find all peer-group commands; create dict of each peer-group
+    # to store assoicated neighbor as value
+    for ctx_keys, line in lines_to_add:
+        if (
+            ctx_keys[0].startswith("router bgp")
+            and line
+            and line.startswith("neighbor ")
+        ):
+            # {'router bgp 65001': {'PG': [], 'PG1': []},
+            # 'router bgp 65001 vrf vrf1': {'PG': [], 'PG1': []}}
+            if ctx_keys[0] not in pg_dict:
+                pg_dict[ctx_keys[0]] = dict()
+            # find 'neighbor <pg_name> peer-group'
+            re_pg = re.match("neighbor (\S+) peer-group$", line)
+            if re_pg and re_pg.group(1) not in pg_dict[ctx_keys[0]]:
+                pg_dict[ctx_keys[0]][re_pg.group(1)] = {
+                    "nbr": list(),
+                    "remoteas": False,
+                }
+                found_pg_cmd = True
+
+    # Find peer-group with remote-as command, also search neighbor
+    # associated to peer-group and store into peer-group dict
+    for ctx_keys, line in lines_to_add:
+        if (
+            ctx_keys[0].startswith("router bgp")
+            and line
+            and line.startswith("neighbor ")
+        ):
+            if ctx_keys[0] in pg_dict:
+                for pg_key in pg_dict[ctx_keys[0]]:
+                    # Find 'neighbor <pg_name> remote-as'
+                    pg_rmtas = "neighbor %s remote-as (\S+)" % pg_key
+                    re_pg_rmtas = re.search(pg_rmtas, line)
+                    if re_pg_rmtas:
+                        pg_dict[ctx_keys[0]][pg_key]["remoteas"] = True
+
+                    # Find 'neighbor <peer> [interface] peer-group <pg_name>'
+                    nb_pg = "neighbor (\S+) peer-group %s$" % pg_key
+                    re_nbr_pg = re.search(nb_pg, line)
+                    if (
+                        re_nbr_pg
+                        and re_nbr_pg.group(1) not in pg_dict[ctx_keys[0]][pg_key]
+                    ):
+                        pg_dict[ctx_keys[0]][pg_key]["nbr"].append(re_nbr_pg.group(1))
+
+    # Find any neighbor <nbr> remote-as config line check if the nbr
+    # is in the peer group's list of nbrs. Remove 'neighbor <nbr> remote-as <>'
+    # from lines_to_add.
+    lines_to_del_from_add = []
+    for ctx_keys, line in lines_to_add:
+        if (
+            ctx_keys[0].startswith("router bgp")
+            and line
+            and line.startswith("neighbor ")
+        ):
+            nbr_rmtas = "neighbor (\S+) remote-as.*"
+            re_nbr_rmtas = re.search(nbr_rmtas, line)
+            if re_nbr_rmtas and ctx_keys[0] in pg_dict:
+                for pg in pg_dict[ctx_keys[0]]:
+                    if pg_dict[ctx_keys[0]][pg]["remoteas"] == True:
+                        for nbr in pg_dict[ctx_keys[0]][pg]["nbr"]:
+                            if re_nbr_rmtas.group(1) in nbr:
+                                lines_to_del_from_add.append((ctx_keys, line))
+
+    for ctx_keys, line in lines_to_del_from_add:
+        lines_to_add.remove((ctx_keys, line))
+
+
+"""
+This method handles deletion of bgp peer group config.
+The objective is to delete config lines related to peers
+associated with the peer-group and move the peer-group
+config line to the end of the lines_to_del list.
+"""
+
+
 def delete_move_lines(lines_to_add, lines_to_del):
-    """
-    This function handles deletion of bgp peer group config.  The objective is
-    to delete config lines related to peers associated with the peer-group and
-    move the peer-group config line to the end of the lines_to_del list.
-    """
+
+    bgp_delete_nbr_remote_as_line(lines_to_add)
+
     del_dict = dict()
     # Stores the lines to move to the end of the pending list.
     lines_to_del_to_del = []
@@ -860,14 +944,15 @@ def delete_move_lines(lines_to_add, lines_to_del):
             re_pg = re.match("neighbor (\S+) peer-group$", line)
             if re_pg and re_pg.group(1) not in del_dict[ctx_keys[0]]:
                 del_dict[ctx_keys[0]][re_pg.group(1)] = list()
+                found_pg_del_cmd = True
+
+    if found_pg_del_cmd == False:
+        return (lines_to_add, lines_to_del)
 
     for (ctx_keys, line) in lines_to_del_to_app:
         lines_to_del.remove((ctx_keys, line))
         lines_to_del.append((ctx_keys, line))
 
-    if found_pg_del_cmd == False:
-        return (lines_to_add, lines_to_del)
-
     # {'router bgp 65001': {'PG': ['10.1.1.2'], 'PG1': ['10.1.1.21']},
     #  'router bgp 65001 vrf vrf1': {'PG': ['10.1.1.2'], 'PG1': ['10.1.1.21']}}
     for (ctx_keys, line) in lines_to_del: