]> git.puffer.fish Git - matthieu/frr.git/commitdiff
tests: adding bgp admin distance topotests.
authornguggarigoud <nguggarigoud@vmware.com>
Tue, 23 Aug 2022 07:35:11 +0000 (00:35 -0700)
committernguggarigoud <nguggarigoud@vmware.com>
Mon, 29 Aug 2022 06:34:52 +0000 (23:34 -0700)
This has bgp admin topotest automation suit.

Signed-off-by: nguggarigoud <nguggarigoud@vmware.com>
tests/topotests/bgp_distance_change/bgp_admin_dist.json [new file with mode: 0755]
tests/topotests/bgp_distance_change/bgp_admin_dist_vrf.json [new file with mode: 0755]
tests/topotests/bgp_distance_change/test_bgp_admin_dist.py [new file with mode: 0755]
tests/topotests/bgp_distance_change/test_bgp_admin_dist_vrf.py [new file with mode: 0755]
tests/topotests/lib/bgp.py
tests/topotests/lib/common_config.py

diff --git a/tests/topotests/bgp_distance_change/bgp_admin_dist.json b/tests/topotests/bgp_distance_change/bgp_admin_dist.json
new file mode 100755 (executable)
index 0000000..e6a20a6
--- /dev/null
@@ -0,0 +1,402 @@
+{
+   "address_types": [
+      "ipv4",
+      "ipv6"
+   ],
+   "ipv4base": "10.0.0.0",
+   "ipv4mask": 30,
+   "ipv6base": "fd00::",
+   "ipv6mask": 64,
+   "link_ip_start": {
+      "ipv4": "10.0.0.0",
+      "v4mask": 30,
+      "ipv6": "fd00::",
+      "v6mask": 64
+   },
+   "lo_prefix": {
+      "ipv4": "1.0.",
+      "v4mask": 32,
+      "ipv6": "2001:DB8:F::",
+      "v6mask": 128
+   },
+   "routers": {
+      "r1": {
+         "links": {
+            "lo": {
+               "ipv4": "auto",
+               "ipv6": "auto",
+               "type": "loopback"
+            },
+            "r2": {
+               "ipv4": "auto",
+               "ipv6": "auto"
+            },
+            "r3": {
+               "ipv4": "auto",
+               "ipv6": "auto"
+            }
+         },
+         "bgp": {
+            "local_as": "100",
+            "address_family": {
+               "ipv4": {
+                  "unicast": {
+                     "neighbor": {
+                        "r2": {
+                           "dest_link": {
+                              "r1": {}
+                           }
+                        },
+                        "r3": {
+                           "dest_link": {
+                              "r1": {}
+                           }
+                        }
+                     },
+                     "redistribute": [
+                        {
+                           "redist_type": "static"
+                        },
+                        {
+                           "redist_type": "connected"
+                        }
+                     ]
+                  }
+               },
+               "ipv6": {
+                  "unicast": {
+                     "neighbor": {
+                        "r2": {
+                           "dest_link": {
+                              "r1": {}
+                           }
+                        },
+                        "r3": {
+                           "dest_link": {
+                              "r1": {}
+                           }
+                        }
+                     },
+                     "redistribute": [
+                        {
+                           "redist_type": "static"
+                        },
+                        {
+                           "redist_type": "connected"
+                        }
+                     ]
+                  }
+               }
+            }
+         },
+         "static_routes": [
+            {
+               "network": "192.168.22.1/32",
+               "no_of_ip": 2,
+               "next_hop": "10.0.0.2"
+            },
+            {
+               "network": "fc07:1::1/128",
+               "no_of_ip": 2,
+               "next_hop": "fd00::2"
+            },
+            {
+               "network": "192.168.21.1/32",
+               "no_of_ip": 2,
+               "next_hop": "blackhole"
+            },
+            {
+               "network": "fc07:150::1/128",
+               "no_of_ip": 2,
+               "next_hop": "blackhole"
+            }
+         ]
+      },
+      "r2": {
+         "links": {
+            "lo": {
+               "ipv4": "auto",
+               "ipv6": "auto",
+               "type": "loopback"
+            },
+            "r1": {
+               "ipv4": "auto",
+               "ipv6": "auto"
+            },
+            "r3": {
+               "ipv4": "auto",
+               "ipv6": "auto"
+            }
+         },
+         "bgp": {
+            "local_as": "100",
+            "address_family": {
+               "ipv4": {
+                  "unicast": {
+                     "neighbor": {
+                        "r1": {
+                           "dest_link": {
+                              "r2": {}
+                           }
+                        },
+                        "r3": {
+                           "dest_link": {
+                              "r2": {}
+                           }
+                        }
+                     },
+                     "redistribute": [
+                        {
+                           "redist_type": "static"
+                        },
+                        {
+                           "redist_type": "connected"
+                        }
+                     ]
+                  }
+               },
+               "ipv6": {
+                  "unicast": {
+                     "neighbor": {
+                        "r1": {
+                           "dest_link": {
+                              "r2": {}
+                           }
+                        },
+                        "r3": {
+                           "dest_link": {
+                              "r2": {}
+                           }
+                        }
+                     },
+                     "redistribute": [
+                        {
+                           "redist_type": "static"
+                        },
+                        {
+                           "redist_type": "connected"
+                        }
+                     ]
+                  }
+               }
+            }
+         }
+      },
+      "r3": {
+         "links": {
+            "lo": {
+               "ipv4": "auto",
+               "ipv6": "auto",
+               "type": "loopback"
+            },
+            "r1": {
+               "ipv4": "auto",
+               "ipv6": "auto"
+            },
+            "r2": {
+               "ipv4": "auto",
+               "ipv6": "auto"
+            },
+            "r4": {
+               "ipv4": "auto",
+               "ipv6": "auto"
+            },
+            "r5": {
+               "ipv4": "auto",
+               "ipv6": "auto"
+            }
+         },
+         "bgp": {
+            "local_as": "100",
+            "address_family": {
+               "ipv4": {
+                  "unicast": {
+                     "neighbor": {
+                        "r1": {
+                           "dest_link": {
+                              "r3": {}
+                           }
+                        },
+                        "r2": {
+                           "dest_link": {
+                              "r3": {}
+                           }
+                        },
+                        "r4": {
+                           "dest_link": {
+                              "r3": {}
+                           }
+                        },
+                        "r5": {
+                           "dest_link": {
+                              "r3": {}
+                           }
+                        }
+                     }
+                  }
+               },
+               "ipv6": {
+                  "unicast": {
+                     "neighbor": {
+                        "r1": {
+                           "dest_link": {
+                              "r3": {}
+                           }
+                        },
+                        "r2": {
+                           "dest_link": {
+                              "r3": {}
+                           }
+                        },
+                        "r4": {
+                           "dest_link": {
+                              "r3": {}
+                           }
+                        },
+                        "r5": {
+                           "dest_link": {
+                              "r3": {}
+                           }
+                        }
+                     }
+                  }
+               }
+            }
+         }
+      },
+      "r4": {
+         "links": {
+            "lo": {
+               "ipv4": "auto",
+               "ipv6": "auto",
+               "type": "loopback"
+            },
+            "r3": {
+               "ipv4": "auto",
+               "ipv6": "auto"
+            }
+         },
+         "bgp": {
+            "local_as": "200",
+            "address_family": {
+               "ipv4": {
+                  "unicast": {
+                     "neighbor": {
+                        "r3": {
+                           "dest_link": {
+                              "r4": {}
+                           }
+                        }
+                     },
+                     "redistribute": [
+                        {
+                           "redist_type": "static"
+                        },
+                        {
+                           "redist_type": "connected"
+                        }
+                     ]
+                  }
+               },
+               "ipv6": {
+                  "unicast": {
+                     "neighbor": {
+                        "r3": {
+                           "dest_link": {
+                              "r4": {}
+                           }
+                        }
+                     },
+                     "redistribute": [
+                        {
+                           "redist_type": "static"
+                        },
+                        {
+                           "redist_type": "connected"
+                        }
+                     ]
+                  }
+               }
+            }
+         }
+      },
+      "r5": {
+         "links": {
+            "lo": {
+               "ipv4": "auto",
+               "ipv6": "auto",
+               "type": "loopback"
+            },
+            "r3": {
+               "ipv4": "auto",
+               "ipv6": "auto"
+            }
+         },
+         "bgp": {
+            "local_as": "300",
+            "address_family": {
+               "ipv4": {
+                  "unicast": {
+                     "neighbor": {
+                        "r3": {
+                           "dest_link": {
+                              "r5": {}
+                           }
+                        }
+                     },
+                     "redistribute": [
+                        {
+                           "redist_type": "static"
+                        },
+                        {
+                           "redist_type": "connected"
+                        }
+                     ]
+                  }
+               },
+               "ipv6": {
+                  "unicast": {
+                     "neighbor": {
+                        "r3": {
+                           "dest_link": {
+                              "r5": {}
+                           }
+                        }
+                     },
+                     "redistribute": [
+                        {
+                           "redist_type": "static"
+                        },
+                        {
+                           "redist_type": "connected"
+                        }
+                     ]
+                  }
+               }
+            }
+         },
+         "static_routes": [
+            {
+               "network": "192.168.20.1/32",
+               "no_of_ip": 2,
+               "next_hop": "blackhole"
+            },
+            {
+               "network": "fc07:50::1/128",
+               "no_of_ip": 2,
+               "next_hop": "blackhole"
+            },
+            {
+               "network": "192.168.21.1/32",
+               "no_of_ip": 2,
+               "next_hop": "blackhole"
+            },
+            {
+               "network": "fc07:150::1/128",
+               "no_of_ip": 2,
+               "next_hop": "blackhole"
+            }
+         ]
+      }
+   }
+}
\ No newline at end of file
diff --git a/tests/topotests/bgp_distance_change/bgp_admin_dist_vrf.json b/tests/topotests/bgp_distance_change/bgp_admin_dist_vrf.json
new file mode 100755 (executable)
index 0000000..23afa2c
--- /dev/null
@@ -0,0 +1,429 @@
+{
+   "address_types": [
+      "ipv4",
+      "ipv6"
+   ],
+   "ipv4base": "10.0.0.0",
+   "ipv4mask": 30,
+   "ipv6base": "fd00::",
+   "ipv6mask": 64,
+   "link_ip_start": {
+      "ipv4": "10.0.0.0",
+      "v4mask": 30,
+      "ipv6": "fd00::",
+      "v6mask": 64
+   },
+   "lo_prefix": {
+      "ipv4": "1.0.",
+      "v4mask": 32,
+      "ipv6": "2001:DB8:F::",
+      "v6mask": 128
+   },
+   "routers": {
+      "r1": {
+         "links": {
+            "lo": {
+               "ipv4": "auto",
+               "ipv6": "auto",
+               "type": "loopback",
+               "vrf": "RED"
+            },
+            "r2": {
+               "ipv4": "auto",
+               "ipv6": "auto",
+               "vrf": "RED"
+            },
+            "r3": {
+               "ipv4": "auto",
+               "ipv6": "auto",
+               "vrf": "RED"
+            }
+         },
+         "vrfs": [
+            {
+               "name": "RED",
+               "id": "1"
+            }
+         ],
+         "bgp": [{
+            "local_as": "100",
+               "vrf": "RED",
+
+            "address_family": {
+               "ipv4": {
+                  "unicast": {
+                     "neighbor": {
+                        "r2": {
+                           "dest_link": {
+                              "r1": {}
+                           }
+                        },
+                        "r3": {
+                           "dest_link": {
+                              "r1": {}
+                           }
+                        }
+                     },
+                     "redistribute": [
+                        {
+                           "redist_type": "static"
+                        },
+                        {
+                           "redist_type": "connected"
+                        }
+                     ]
+                  }
+               },
+               "ipv6": {
+                  "unicast": {
+                     "neighbor": {
+                        "r2": {
+                           "dest_link": {
+                              "r1": {}
+                           }
+                        },
+                        "r3": {
+                           "dest_link": {
+                              "r1": {}
+                           }
+                        }
+                     },
+                     "redistribute": [
+                        {
+                           "redist_type": "static"
+                        },
+                        {
+                           "redist_type": "connected"
+                        }
+                     ]
+                  }
+               }
+            }
+         }],
+         "static_routes": [
+            {
+               "network": "192.168.22.1/32",
+               "no_of_ip": 2,
+               "next_hop": "10.0.0.2",
+               "vrf": "RED"
+            },
+            {
+               "network": "fc07:1::1/128",
+               "no_of_ip": 2,
+               "next_hop": "fd00::2",
+               "vrf": "RED"
+            },
+            {
+               "network": "192.168.21.1/32",
+               "no_of_ip": 2,
+               "next_hop": "blackhole",
+               "vrf": "RED"
+            },
+            {
+               "network": "fc07:150::1/128",
+               "no_of_ip": 2,
+               "next_hop": "blackhole",
+               "vrf": "RED"
+            }
+         ]
+      },
+      "r2": {
+         "links": {
+            "lo": {
+               "ipv4": "auto",
+               "ipv6": "auto",
+               "type": "loopback",
+               "vrf": "RED"
+            },
+            "r1": {
+               "ipv4": "auto",
+               "ipv6": "auto",
+               "vrf": "RED"
+            },
+            "r3": {
+               "ipv4": "auto",
+               "ipv6": "auto",
+               "vrf": "RED"
+            }
+         },
+         "vrfs": [
+            {
+               "name": "RED",
+               "id": "1"
+            }
+         ],
+         "bgp": [{
+            "local_as": "100",
+               "vrf": "RED",
+            "address_family": {
+               "ipv4": {
+                  "unicast": {
+                     "neighbor": {
+                        "r1": {
+                           "dest_link": {
+                              "r2": {}
+                           }
+                        },
+                        "r3": {
+                           "dest_link": {
+                              "r2": {}
+                           }
+                        }
+                     }
+                  }
+               },
+               "ipv6": {
+                  "unicast": {
+                     "neighbor": {
+                        "r1": {
+                           "dest_link": {
+                              "r2": {}
+                           }
+                        },
+                        "r3": {
+                           "dest_link": {
+                              "r2": {}
+                           }
+                        }
+                     }
+                  }
+               }
+            }
+         }]
+      },
+      "r3": {
+         "links": {
+            "lo": {
+               "ipv4": "auto",
+               "ipv6": "auto",
+               "type": "loopback",
+               "vrf": "RED"
+            },
+            "r1": {
+               "ipv4": "auto",
+               "ipv6": "auto",
+               "vrf": "RED"
+            },
+            "r2": {
+               "ipv4": "auto",
+               "ipv6": "auto",
+               "vrf": "RED"
+            },
+            "r4": {
+               "ipv4": "auto",
+               "ipv6": "auto",
+               "vrf": "RED"
+            },
+            "r5": {
+               "ipv4": "auto",
+               "ipv6": "auto",
+               "vrf": "RED"
+            }
+         },
+         "vrfs": [
+            {
+               "name": "RED",
+               "id": "1"
+            }
+         ],
+         "bgp": [{
+            "local_as": "100",
+               "vrf": "RED",
+            "address_family": {
+               "ipv4": {
+                  "unicast": {
+                     "neighbor": {
+                        "r1": {
+                           "dest_link": {
+                              "r3": {}
+                           }
+                        },
+                        "r2": {
+                           "dest_link": {
+                              "r3": {}
+                           }
+                        },
+                        "r4": {
+                           "dest_link": {
+                              "r3": {}
+                           }
+                        },
+                        "r5": {
+                           "dest_link": {
+                              "r3": {}
+                           }
+                        }
+                     }
+                  }
+               },
+               "ipv6": {
+                  "unicast": {
+                     "neighbor": {
+                        "r1": {
+                           "dest_link": {
+                              "r3": {}
+                           }
+                        },
+                        "r2": {
+                           "dest_link": {
+                              "r3": {}
+                           }
+                        },
+                        "r4": {
+                           "dest_link": {
+                              "r3": {}
+                           }
+                        },
+                        "r5": {
+                           "dest_link": {
+                              "r3": {}
+                           }
+                        }
+                     }
+                  }
+               }
+            }
+         }]
+      },
+      "r4": {
+         "links": {
+            "lo": {
+               "ipv4": "auto",
+               "ipv6": "auto",
+               "type": "loopback",
+               "vrf": "RED"
+            },
+            "r3": {
+               "ipv4": "auto",
+               "ipv6": "auto",
+               "vrf": "RED"
+            }
+         },
+         "vrfs": [
+            {
+               "name": "RED",
+               "id": "1"
+            }
+         ],
+         "bgp": [{
+            "local_as": "200",
+               "vrf": "RED",
+            "address_family": {
+               "ipv4": {
+                  "unicast": {
+                     "neighbor": {
+                        "r3": {
+                           "dest_link": {
+                              "r4": {}
+                           }
+                        }
+                     }
+                  }
+               },
+               "ipv6": {
+                  "unicast": {
+                     "neighbor": {
+                        "r3": {
+                           "dest_link": {
+                              "r4": {}
+                           }
+                        }
+                     }
+                  }
+               }
+            }
+         }]
+      },
+      "r5": {
+         "links": {
+            "lo": {
+               "ipv4": "auto",
+               "ipv6": "auto",
+               "type": "loopback",
+               "vrf": "RED"
+            },
+            "r3": {
+               "ipv4": "auto",
+               "ipv6": "auto",
+               "vrf": "RED"
+            }
+         },
+         "vrfs": [
+            {
+               "name": "RED",
+               "id": "1"
+            }
+         ],
+         "bgp": [{
+            "local_as": "300",
+               "vrf": "RED",
+            "address_family": {
+               "ipv4": {
+                  "unicast": {
+                     "neighbor": {
+                        "r3": {
+                           "dest_link": {
+                              "r5": {}
+                           }
+                        }
+                     },
+                     "redistribute": [
+                        {
+                           "redist_type": "static"
+                        },
+                        {
+                           "redist_type": "connected"
+                        }
+                     ]
+                  }
+               },
+               "ipv6": {
+                  "unicast": {
+                     "neighbor": {
+                        "r3": {
+                           "dest_link": {
+                              "r5": {}
+                           }
+                        }
+                     },
+                     "redistribute": [
+                        {
+                           "redist_type": "static"
+                        },
+                        {
+                           "redist_type": "connected"
+                        }
+                     ]
+                  }
+               }
+            }
+         }],
+         "static_routes": [
+            {
+               "network": "192.168.20.1/32",
+               "no_of_ip": 2,
+               "next_hop": "blackhole",
+               "vrf": "RED"
+            },
+            {
+               "network": "fc07:50::1/128",
+               "no_of_ip": 2,
+               "next_hop": "blackhole",
+               "vrf": "RED"
+            },
+            {
+               "network": "192.168.21.1/32",
+               "no_of_ip": 2,
+               "next_hop": "blackhole",
+               "vrf": "RED"
+            },
+            {
+               "network": "fc07:150::1/128",
+               "no_of_ip": 2,
+               "next_hop": "blackhole",
+               "vrf": "RED"
+            }
+         ]
+      }
+   }
+}
\ No newline at end of file
diff --git a/tests/topotests/bgp_distance_change/test_bgp_admin_dist.py b/tests/topotests/bgp_distance_change/test_bgp_admin_dist.py
new file mode 100755 (executable)
index 0000000..90c3d22
--- /dev/null
@@ -0,0 +1,1282 @@
+#!/usr/bin/env python
+
+#
+# Copyright (c) 2022 by VMware, Inc. ("VMware")
+# Used Copyright (c) 2018 by Network Device Education Foundation,
+# Inc. ("NetDEF") in this file.
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND VMWARE DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+import sys
+import time
+import pytest
+import inspect
+import os
+
+
+"""Following tests are covered to test bgp admin distance functionality.
+TC_1:
+    Verify bgp admin distance functionality when static route is
+    configured same as ebgp learnt route
+
+TC_2:
+    Verify ebgp admin distance functionality with ECMP.
+
+TC_3:
+    Verify ibgp admin distance functionality when static route is
+    configured same as bgp learnt route.
+TC_4:
+    Verify ibgp admin distance functionality with ECMP.
+
+TC_7: Chaos - Verify bgp admin distance functionality with chaos.
+"""
+
+#################################
+# TOPOLOGY
+#################################
+"""
+
+                    +-------+
+         +--------- |  R2   |
+         |          +-------+
+         |iBGP           |
+     +-------+           |
+     |  R1   |           |iBGP
+     +-------+           |
+         |               |
+         |    iBGP   +-------+   eBGP   +-------+
+         +---------- |  R3   |----------|  R4   |
+                     +-------+          +-------+
+                        |
+                        |eBGP
+                        |
+                    +-------+
+                    |  R5   |
+                    +-------+
+
+
+"""
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+sys.path.append(os.path.join(CWD, "../lib/"))
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib.topogen import Topogen, get_topogen
+
+# Required to instantiate the topology builder class.
+from lib.common_config import (
+    start_topology,
+    write_test_header,
+    step,
+    write_test_footer,
+    create_static_routes,
+    verify_rib,
+    create_route_maps,
+    create_prefix_lists,
+    check_address_types,
+    reset_config_on_routers,
+    check_router_status,
+    stop_router,
+    kill_router_daemons,
+    start_router_daemons,
+    start_router,
+    get_frr_ipv6_linklocal,
+    verify_fib_routes,
+)
+from lib.topolog import logger
+from lib.bgp import (
+    verify_bgp_convergence,
+    create_router_bgp,
+    verify_best_path_as_per_admin_distance,
+    clear_bgp,
+)
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib.topogen import Topogen, get_topogen
+from lib.topojson import build_config_from_json
+from lib.topolog import logger
+
+# Global variables
+topo = None
+bgp_convergence = False
+pytestmark = [pytest.mark.bgpd, pytest.mark.staticd]
+
+NETWORK = {
+    "ipv4": [
+        "192.168.20.1/32",
+        "192.168.20.2/32",
+        "192.168.21.1/32",
+        "192.168.21.2/32",
+        "192.168.22.1/32",
+        "192.168.22.2/32",
+    ],
+    "ipv6": [
+        "fc07:50::1/128",
+        "fc07:50::2/128",
+        "fc07:150::1/128",
+        "fc07:150::2/128",
+        "fc07:1::1/128",
+        "fc07:1::2/128",
+    ],
+}
+
+ADDR_TYPES = check_address_types()
+
+
+def setup_module(mod):
+    """
+    Sets up the pytest environment
+
+    * `mod`: module name
+    """
+
+    global topo
+
+    testsuite_run_time = time.asctime(time.localtime(time.time()))
+    logger.info("Testsuite start time: {}".format(testsuite_run_time))
+    logger.info("=" * 40)
+
+    logger.info("Running setup_module to create topology")
+
+    # This function initiates the topology build with Topogen...
+    json_file = "{}/bgp_admin_dist.json".format(CWD)
+    tgen = Topogen(json_file, mod.__name__)
+    global topo
+    topo = tgen.json_topo
+
+    # Starting topology, create tmp files which are loaded to routers
+    #  to start deamons and then start routers
+    start_topology(tgen)
+
+    # Creating configuration from JSON
+    build_config_from_json(tgen, topo)
+
+    # Checking BGP convergence
+    global bgp_convergence
+    global ADDR_TYPES
+
+    # Don't run this test if we have any failure.
+    if tgen.routers_have_failure():
+        pytest.skip(tgen.errors)
+
+    # Api call verify whether BGP is converged
+    bgp_convergence = verify_bgp_convergence(tgen, topo)
+    assert bgp_convergence is True, "setup_module :Failed \n Error:" " {}".format(
+        bgp_convergence
+    )
+    logger.info("Running setup_module() done")
+
+
+def teardown_module(mod):
+    """teardown_module.
+
+    Teardown the pytest environment.
+    * `mod`: module name
+    """
+    logger.info("Running teardown_module to delete topology")
+    tgen = get_topogen()
+
+    # Stop toplogy and Remove tmp files
+    tgen.stop_topology()
+
+    logger.info(
+        "Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
+    )
+    logger.info("=" * 40)
+
+
+#####################################################
+# Tests starting
+#####################################################
+def test_bgp_admin_distance_ebgp_ecmp_p0():
+    """
+    TC: 2
+    Verify ebgp admin distance functionality with ECMP.
+    """
+    tgen = get_topogen()
+    global bgp_convergence
+
+    if bgp_convergence is not True:
+        pytest.skip("skipping test case because of BGP Convergence failure at setup")
+
+    # test case name
+    tc_name = inspect.stack()[0][3]
+    write_test_header(tc_name)
+    if tgen.routers_have_failure():
+        check_router_status(tgen)
+
+    step("Configure base config as per the topology")
+    reset_config_on_routers(tgen)
+
+    step("Configure static route  in R4 and R5, redistribute in bgp")
+
+    for addr_type in ADDR_TYPES:
+
+        input_dict = {
+            "r4": {
+                "static_routes": [{"network": NETWORK[addr_type], "next_hop": "Null0"}]
+            }
+        }
+
+        result = create_static_routes(tgen, input_dict)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    for addr_type in ADDR_TYPES:
+
+        input_dict = {
+            "r5": {
+                "static_routes": [{"network": NETWORK[addr_type], "next_hop": "Null0"}]
+            }
+        }
+
+        result = create_static_routes(tgen, input_dict)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step("Verify that route is learnt in DUT via ebgp")
+
+    # Verifying RIB routes
+    protocol = "bgp"
+    input_dict = topo["routers"]
+    dut = "r3"
+    nhop = {"ipv4": [], "ipv6": []}
+    nhop["ipv4"].append(topo["routers"]["r4"]["links"]["r3"]["ipv4"].split("/")[0])
+    nhop["ipv4"].append(topo["routers"]["r5"]["links"]["r3"]["ipv4"].split("/")[0])
+    nhop["ipv6"].append(get_frr_ipv6_linklocal(tgen, "r4", "r3-r4-eth1"))
+    nhop["ipv6"].append(get_frr_ipv6_linklocal(tgen, "r5", "r1-r3-eth1"))
+
+    for addr_type in ADDR_TYPES:
+        input_dict = {
+            "r3": {
+                "static_routes": [
+                    {"network": NETWORK[addr_type][0], "next_hop": "Null0"}
+                ]
+            }
+        }
+        result4 = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
+        assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result4
+        )
+
+    step("Configure the static route  in R3 (Dut).")
+
+    for addr_type in ADDR_TYPES:
+
+        input_dict = {
+            "r3": {
+                "static_routes": [
+                    {"network": NETWORK[addr_type][0], "next_hop": "Null0"}
+                ]
+            }
+        }
+
+        result = create_static_routes(tgen, input_dict)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step("Verify that static route is selected as best route in zebra.")
+
+    # Verifying RIB routes
+    protocol = "static"
+    dut = "r3"
+
+    for addr_type in ADDR_TYPES:
+        input_dict = {
+            "r3": {
+                "static_routes": [
+                    {"network": NETWORK[addr_type][0], "next_hop": "Null0"}
+                ]
+            }
+        }
+
+        result4 = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
+        assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result4
+        )
+
+    step(" Configure the admin distance of 254 to static route  in R3.")
+
+    for addr_type in ADDR_TYPES:
+
+        input_dict = {
+            "r3": {
+                "static_routes": [
+                    {
+                        "network": NETWORK[addr_type][0],
+                        "next_hop": "Null0",
+                        "admin_distance": 254,
+                    }
+                ]
+            }
+        }
+
+        result = create_static_routes(tgen, input_dict)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step("Verify that bgp routes are selected as best routes in zebra.")
+    protocol = "bgp"
+    dut = "r3"
+
+    for addr_type in ADDR_TYPES:
+        input_dict = {
+            "r3": {
+                "static_routes": [
+                    {"network": NETWORK[addr_type][0], "next_hop": "Null0"}
+                ]
+            }
+        }
+        result4 = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
+        assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result4
+        )
+
+    input_dict_1 = {
+        "r3": {
+            "bgp": {
+                "local_as": 100,
+                "address_family": {
+                    "ipv4": {
+                        "unicast": {
+                            "distance": {"ebgp": 254, "ibgp": 254, "local": 254}
+                        }
+                    },
+                    "ipv6": {
+                        "unicast": {
+                            "distance": {"ebgp": 254, "ibgp": 254, "local": 254}
+                        }
+                    },
+                },
+            }
+        }
+    }
+
+    result = create_router_bgp(tgen, topo, input_dict_1)
+    assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+    step("Verify that bgp routes are selected as best routes in zebra.")
+    # Verifying RIB routes
+    protocol = "bgp"
+    dut = "r3"
+
+    for addr_type in ADDR_TYPES:
+        input_dict = {
+            "r3": {
+                "static_routes": [
+                    {"network": NETWORK[addr_type][0], "next_hop": "Null0"}
+                ]
+            }
+        }
+        result4 = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
+        assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result4
+        )
+
+    step("Configure bgp admin distance 10 with CLI in dut.")
+    input_dict_1 = {
+        "r3": {
+            "bgp": {
+                "local_as": 100,
+                "address_family": {
+                    "ipv4": {
+                        "unicast": {"distance": {"ebgp": 10, "ibgp": 254, "local": 254}}
+                    },
+                    "ipv6": {
+                        "unicast": {"distance": {"ebgp": 10, "ibgp": 254, "local": 254}}
+                    },
+                },
+            }
+        }
+    }
+
+    result = create_router_bgp(tgen, topo, input_dict_1)
+    assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+    step("Verify ebgp routes have admin distance of 10 in dut.")
+
+    protocol = "bgp"
+    input_dict = topo["routers"]
+    dut = "r3"
+
+    for addr_type in ADDR_TYPES:
+        input_dict = {
+            "r3": {
+                "static_routes": [
+                    {"network": NETWORK[addr_type][0], "next_hop": "Null0"}
+                ]
+            }
+        }
+        result4 = verify_rib(
+            tgen, addr_type, dut, input_dict, protocol=protocol, admin_distance=10
+        )
+        assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result4
+        )
+
+    step(
+        "Configure route map with weight as 200 and apply to one of the "
+        "neighbor (R4 neighbor)."
+    )
+
+    # Create Prefix list
+    input_dict_2 = {
+        "r3": {
+            "prefix_lists": {
+                "ipv4": {
+                    "pf_ls_1": [
+                        {
+                            "seqid": 10,
+                            "network": NETWORK["ipv4"][0],
+                            "le": "32",
+                            "action": "permit",
+                        }
+                    ]
+                },
+                "ipv6": {
+                    "pf_ls_1_ipv6": [
+                        {
+                            "seqid": 100,
+                            "network": NETWORK["ipv6"][0],
+                            "le": "128",
+                            "action": "permit",
+                        }
+                    ]
+                },
+            }
+        }
+    }
+    result = create_prefix_lists(tgen, input_dict_2)
+    assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+    # Create route map
+    input_dict_3 = {
+        "r3": {
+            "route_maps": {
+                "RMAP_WEIGHT": [
+                    {
+                        "action": "permit",
+                        "match": {"ipv4": {"prefix_lists": "pf_ls_1"}},
+                        "set": {"weight": 200},
+                    },
+                    {
+                        "action": "permit",
+                        "match": {"ipv6": {"prefix_lists": "pf_ls_1_ipv6"}},
+                        "set": {"weight": 200},
+                    },
+                ]
+            }
+        }
+    }
+    result = create_route_maps(tgen, input_dict_3)
+    assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+    # Configure neighbor for route map
+    input_dict_4 = {
+        "r3": {
+            "bgp": {
+                "address_family": {
+                    "ipv4": {
+                        "unicast": {
+                            "neighbor": {
+                                "r4": {
+                                    "dest_link": {
+                                        "r3": {
+                                            "route_maps": [
+                                                {
+                                                    "name": "RMAP_WEIGHT",
+                                                    "direction": "in",
+                                                }
+                                            ]
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    },
+                    "ipv6": {
+                        "unicast": {
+                            "neighbor": {
+                                "r4": {
+                                    "dest_link": {
+                                        "r3": {
+                                            "route_maps": [
+                                                {
+                                                    "name": "RMAP_WEIGHT",
+                                                    "direction": "in",
+                                                }
+                                            ]
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    },
+                }
+            }
+        }
+    }
+    result = create_router_bgp(tgen, topo, input_dict_4)
+    assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+    step("Verify that bgp route is selected as best on by zebra in r3.")
+
+    protocol = "bgp"
+    dut = "r3"
+
+    for addr_type in ADDR_TYPES:
+        input_dict = {
+            "r3": {
+                "static_routes": [
+                    {"network": NETWORK[addr_type][0], "next_hop": "Null0"}
+                ]
+            }
+        }
+        result4 = verify_rib(
+            tgen, addr_type, dut, input_dict, protocol=protocol, admin_distance=10
+        )
+        assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result4
+        )
+
+    step("Static route should not be selected as best route.")
+    protocol = "static"
+    dut = "r3"
+
+    for addr_type in ADDR_TYPES:
+        input_dict = {
+            "r3": {
+                "static_routes": [
+                    {"network": NETWORK[addr_type][0], "next_hop": "Null0"}
+                ]
+            }
+        }
+        result4 = verify_fib_routes(
+            tgen, addr_type, dut, input_dict, protocol=protocol, expected=False
+        )
+        assert (
+            result4 is not True
+        ), "Testcase {} : Failed. Wrong route is selected as best route.\n Error: {}".format(
+            tc_name, result4
+        )
+
+    step("Reconfigure the static route without admin distance")
+
+    for addr_type in ADDR_TYPES:
+
+        input_dict = {
+            "r3": {
+                "static_routes": [
+                    {
+                        "network": NETWORK[addr_type][0],
+                        "next_hop": "Null0",
+                        "admin_distance": 254,
+                        "delete": True,
+                    }
+                ]
+            }
+        }
+
+        result = create_static_routes(tgen, input_dict)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    for addr_type in ADDR_TYPES:
+        input_dict = {
+            "r3": {
+                "static_routes": [
+                    {"network": NETWORK[addr_type][0], "next_hop": "Null0"}
+                ]
+            }
+        }
+
+        result = create_static_routes(tgen, input_dict)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step("Verify that static route is installed as best route.")
+    protocol = "static"
+    dut = "r3"
+
+    for addr_type in ADDR_TYPES:
+        input_dict = {
+            "r3": {
+                "static_routes": [
+                    {"network": NETWORK[addr_type][0], "next_hop": "Null0"}
+                ]
+            }
+        }
+        result4 = verify_rib(
+            tgen, addr_type, dut, input_dict, protocol=protocol, fib=True
+        )
+        assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result4
+        )
+
+    step("Unconfigure the static route in R3.")
+
+    for addr_type in ADDR_TYPES:
+        input_dict = {
+            "r3": {
+                "static_routes": [
+                    {
+                        "network": NETWORK[addr_type][0],
+                        "next_hop": "Null0",
+                        "delete": True,
+                    }
+                ]
+            }
+        }
+
+        result = create_static_routes(tgen, input_dict)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step("Verify that bgp route is selected as best on by zebra in r3.")
+
+    protocol = "bgp"
+    dut = "r3"
+
+    for addr_type in ADDR_TYPES:
+        input_dict = {
+            "r3": {
+                "static_routes": [
+                    {"network": NETWORK[addr_type][0], "next_hop": "Null0"}
+                ]
+            }
+        }
+        result4 = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
+        assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result4
+        )
+
+    step("Un configure the route map on R3.")
+
+    # Configure neighbor for route map
+    input_dict_4 = {
+        "r3": {
+            "bgp": {
+                "address_family": {
+                    "ipv4": {
+                        "unicast": {
+                            "neighbor": {
+                                "r4": {
+                                    "dest_link": {
+                                        "r3": {
+                                            "route_maps": [
+                                                {
+                                                    "name": "RMAP_WEIGHT",
+                                                    "direction": "in",
+                                                    "delete": True,
+                                                }
+                                            ]
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    },
+                    "ipv6": {
+                        "unicast": {
+                            "neighbor": {
+                                "r4": {
+                                    "dest_link": {
+                                        "r3": {
+                                            "route_maps": [
+                                                {
+                                                    "name": "RMAP_WEIGHT",
+                                                    "direction": "in",
+                                                    "delete": True,
+                                                }
+                                            ]
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    },
+                }
+            }
+        }
+    }
+    result = create_router_bgp(tgen, topo, input_dict_4)
+    assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+    step("verify bgp routes installed in zebra.")
+
+    # Verifying RIB routes
+    protocol = "bgp"
+    input_dict = topo["routers"]
+    dut = "r3"
+    for addr_type in ADDR_TYPES:
+        input_dict = {
+            "r3": {
+                "static_routes": [
+                    {"network": NETWORK[addr_type][0], "next_hop": "Null0"}
+                ]
+            }
+        }
+        result4 = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
+        assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result4
+        )
+
+    write_test_footer(tc_name)
+
+
+def test_bgp_admin_distance_ibgp_p0():
+    """
+    TC: 3
+    Verify bgp admin distance functionality when static route is
+    configured same as ibgp learnt route
+    """
+    tgen = get_topogen()
+    global bgp_convergence
+
+    if bgp_convergence is not True:
+        pytest.skip("skipping test case because of BGP Convergence failure at setup")
+
+    # test case name
+    tc_name = inspect.stack()[0][3]
+    write_test_header(tc_name)
+    if tgen.routers_have_failure():
+        check_router_status(tgen)
+
+    step("Configure base config as per the topology")
+    reset_config_on_routers(tgen)
+
+    step("Configure bgp admin distance 200 with CLI in dut.")
+
+    input_dict_1 = {
+        "r3": {
+            "bgp": {
+                "local_as": 100,
+                "address_family": {
+                    "ipv4": {
+                        "unicast": {
+                            "distance": {"ebgp": 200, "ibgp": 200, "local": 200}
+                        }
+                    },
+                    "ipv6": {
+                        "unicast": {
+                            "distance": {"ebgp": 200, "ibgp": 200, "local": 200}
+                        }
+                    },
+                },
+            }
+        }
+    }
+
+    result = create_router_bgp(tgen, topo, input_dict_1)
+    assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+    step("Verify bgp routes have admin distance of 200 in dut.")
+    # Verifying best path
+    dut = "r3"
+    attribute = "admin_distance"
+
+    input_dict = {
+        "ipv4": {
+            "r3": {
+                "static_routes": [
+                    {
+                        "network": "192.168.22.1/32",
+                        "admin_distance": 200,
+                    },
+                    {
+                        "network": "192.168.22.2/32",
+                        "admin_distance": 200,
+                    },
+                ]
+            }
+        },
+        "ipv6": {
+            "r3": {
+                "static_routes": [
+                    {
+                        "network": "fc07:1::1/128",
+                        "admin_distance": 200,
+                    },
+                    {
+                        "network": "fc07:1::2/128",
+                        "admin_distance": 200,
+                    },
+                ]
+            }
+        },
+    }
+
+    for addr_type in ADDR_TYPES:
+        result = verify_best_path_as_per_admin_distance(
+            tgen, addr_type, dut, input_dict[addr_type], attribute
+        )
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step("Modify the admin distance value to 150.")
+
+    input_dict_1 = {
+        "r3": {
+            "bgp": {
+                "local_as": 100,
+                "address_family": {
+                    "ipv4": {
+                        "unicast": {
+                            "distance": {"ebgp": 150, "ibgp": 150, "local": 150}
+                        }
+                    },
+                    "ipv6": {
+                        "unicast": {
+                            "distance": {"ebgp": 150, "ibgp": 150, "local": 150}
+                        }
+                    },
+                },
+            }
+        }
+    }
+
+    result = create_router_bgp(tgen, topo, input_dict_1)
+    assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+    step("Verify bgp routes have admin distance of 150 in dut.")
+    # Verifying best path
+    dut = "r3"
+    attribute = "admin_distance"
+
+    input_dict = {
+        "ipv4": {
+            "r3": {
+                "static_routes": [
+                    {
+                        "network": "192.168.22.1/32",
+                        "admin_distance": 150,
+                    },
+                    {
+                        "network": "192.168.22.2/32",
+                        "admin_distance": 150,
+                    },
+                ]
+            }
+        },
+        "ipv6": {
+            "r3": {
+                "static_routes": [
+                    {
+                        "network": "fc07:1::1/128",
+                        "admin_distance": 150,
+                    },
+                    {
+                        "network": "fc07:1::2/128",
+                        "admin_distance": 150,
+                    },
+                ]
+            }
+        },
+    }
+
+    for addr_type in ADDR_TYPES:
+        result = verify_best_path_as_per_admin_distance(
+            tgen, addr_type, dut, input_dict[addr_type], attribute
+        )
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step("Un configure the admin distance value on DUT")
+
+    input_dict_1 = {
+        "r3": {
+            "bgp": {
+                "local_as": 100,
+                "address_family": {
+                    "ipv4": {
+                        "unicast": {
+                            "distance": {
+                                "ebgp": 150,
+                                "ibgp": 150,
+                                "local": 150,
+                                "delete": True,
+                            }
+                        }
+                    },
+                    "ipv6": {
+                        "unicast": {
+                            "distance": {
+                                "ebgp": 150,
+                                "ibgp": 150,
+                                "local": 150,
+                                "delete": True,
+                            }
+                        }
+                    },
+                },
+            }
+        }
+    }
+
+    result = create_router_bgp(tgen, topo, input_dict_1)
+    assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+    step("Verify bgp routes have default admin distance in dut.")
+    # Verifying best path
+    dut = "r3"
+    attribute = "admin_distance"
+
+    input_dict = {
+        "ipv4": {
+            "r3": {
+                "static_routes": [
+                    {
+                        "network": "192.168.22.1/32",
+                        "admin_distance": 20,
+                    },
+                    {
+                        "network": "192.168.22.2/32",
+                        "admin_distance": 20,
+                    },
+                ]
+            }
+        },
+        "ipv6": {
+            "r3": {
+                "static_routes": [
+                    {
+                        "network": "fc07:1::1/128",
+                        "admin_distance": 20,
+                    },
+                    {
+                        "network": "fc07:1::2/128",
+                        "admin_distance": 20,
+                    },
+                ]
+            }
+        },
+    }
+
+    for addr_type in ADDR_TYPES:
+        result = verify_best_path_as_per_admin_distance(
+            tgen, addr_type, dut, input_dict[addr_type], attribute
+        )
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step(
+        "Learn the same route via ebgp and ibgp peer. Configure admin "
+        "distance of 200 in DUT for both ebgp and ibgp peer. "
+    )
+
+    step("Verify that ebgp route is preferred over ibgp.")
+
+    # Verifying RIB routes
+    protocol = "bgp"
+    input_dict = topo["routers"]
+
+    for addr_type in ADDR_TYPES:
+        result4 = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
+        assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result4
+        )
+
+    step("Configure static route  Without any admin distance")
+
+    for addr_type in ADDR_TYPES:
+
+        input_dict = {
+            "r3": {
+                "static_routes": [{"network": NETWORK[addr_type], "next_hop": "Null0"}]
+            }
+        }
+
+        result = create_static_routes(tgen, input_dict)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step("Verify that zebra selects static route.")
+    protocol = "static"
+
+    for addr_type in ADDR_TYPES:
+
+        input_dict = {
+            "r3": {
+                "static_routes": [{"network": NETWORK[addr_type], "next_hop": "Null0"}]
+            }
+        }
+
+        result4 = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
+        assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result4
+        )
+
+    step("Configure static route  with admin distance of 253")
+    for addr_type in ADDR_TYPES:
+
+        input_dict = {
+            "r3": {
+                "static_routes": [
+                    {
+                        "network": NETWORK[addr_type],
+                        "next_hop": "Null0",
+                        "admin_distance": 253,
+                    }
+                ]
+            }
+        }
+
+        result = create_static_routes(tgen, input_dict)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step("Verify that zebra selects bgp route.")
+    protocol = "bgp"
+
+    for addr_type in ADDR_TYPES:
+        result4 = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
+        assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result4
+        )
+
+    step("Configure admin distance of 254 in bgp for route.")
+
+    input_dict_1 = {
+        "r3": {
+            "bgp": {
+                "local_as": 100,
+                "address_family": {
+                    "ipv4": {
+                        "unicast": {
+                            "distance": {"ebgp": 254, "ibgp": 254, "local": 254}
+                        }
+                    },
+                    "ipv6": {
+                        "unicast": {
+                            "distance": {"ebgp": 254, "ibgp": 254, "local": 254}
+                        }
+                    },
+                },
+            }
+        }
+    }
+
+    result = create_router_bgp(tgen, topo, input_dict_1)
+    assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+    step("Verify that zebra selects static route.")
+    protocol = "static"
+
+    for addr_type in ADDR_TYPES:
+        result4 = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
+        assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result4
+        )
+
+    step("Delete the static route.")
+    for addr_type in ADDR_TYPES:
+
+        input_dict = {
+            "r3": {
+                "static_routes": [
+                    {
+                        "network": NETWORK[addr_type],
+                        "next_hop": "Null0",
+                        "admin_distance": 253,
+                        "delete": True,
+                    }
+                ]
+            }
+        }
+
+        result = create_static_routes(tgen, input_dict)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step("Verify that zebra selects bgp route.")
+    protocol = "bgp"
+
+    for addr_type in ADDR_TYPES:
+        result4 = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
+        assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result4
+        )
+
+    write_test_footer(tc_name)
+
+
+def test_bgp_admin_distance_chaos_p2():
+    """
+    TC: 7
+    Chaos - Verify bgp admin distance functionality with chaos.
+    """
+    tgen = get_topogen()
+    global bgp_convergence
+
+    if bgp_convergence is not True:
+        pytest.skip("skipping test case because of BGP Convergence failure at setup")
+
+    # test case name
+    tc_name = inspect.stack()[0][3]
+    write_test_header(tc_name)
+    if tgen.routers_have_failure():
+        check_router_status(tgen)
+
+    step("Configure base config as per the topology")
+    reset_config_on_routers(tgen)
+
+    step("Configure bgp admin distance 200 with CLI in dut.")
+
+    input_dict_1 = {
+        "r3": {
+            "bgp": {
+                "local_as": 100,
+                "address_family": {
+                    "ipv4": {
+                        "unicast": {
+                            "distance": {"ebgp": 200, "ibgp": 200, "local": 200}
+                        }
+                    },
+                    "ipv6": {
+                        "unicast": {
+                            "distance": {"ebgp": 200, "ibgp": 200, "local": 200}
+                        }
+                    },
+                },
+            }
+        }
+    }
+
+    result = create_router_bgp(tgen, topo, input_dict_1)
+    assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+    step("Verify bgp routes have admin distance of 200 in dut.")
+    # Verifying best path
+    dut = "r3"
+    attribute = "admin_distance"
+
+    input_dict = {
+        "ipv4": {
+            "r3": {
+                "static_routes": [
+                    {
+                        "network": NETWORK["ipv4"][0],
+                        "admin_distance": 200,
+                    },
+                    {
+                        "network": NETWORK["ipv4"][1],
+                        "admin_distance": 200,
+                    },
+                ]
+            }
+        },
+        "ipv6": {
+            "r3": {
+                "static_routes": [
+                    {
+                        "network": NETWORK["ipv6"][0],
+                        "admin_distance": 200,
+                    },
+                    {
+                        "network": NETWORK["ipv6"][1],
+                        "admin_distance": 200,
+                    },
+                ]
+            }
+        },
+    }
+
+    for addr_type in ADDR_TYPES:
+        result = verify_best_path_as_per_admin_distance(
+            tgen, addr_type, dut, input_dict[addr_type], attribute
+        )
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step("Restart frr on R3")
+    stop_router(tgen, "r3")
+    start_router(tgen, "r3")
+
+    bgp_convergence = verify_bgp_convergence(tgen, topo)
+    assert bgp_convergence is True, "Testcase {} : Failed \n Error: {}".format(
+        tc_name, bgp_convergence
+    )
+
+    step("Verify ebgp and ibgp routes have admin distance of 200 in dut.")
+    for addr_type in ADDR_TYPES:
+        result = verify_best_path_as_per_admin_distance(
+            tgen, addr_type, dut, input_dict[addr_type], attribute
+        )
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step("Restart bgpd process on R3")
+    kill_router_daemons(tgen, "r3", ["bgpd"])
+    start_router_daemons(tgen, "r3", ["bgpd"])
+
+    bgp_convergence = verify_bgp_convergence(tgen, topo)
+    assert bgp_convergence is True, "Testcase {} : Failed \n Error: {}".format(
+        tc_name, bgp_convergence
+    )
+
+    step("Verify ebgp and ibgp routes have admin distance of 200 in dut.")
+    for addr_type in ADDR_TYPES:
+        result = verify_best_path_as_per_admin_distance(
+            tgen, addr_type, dut, input_dict[addr_type], attribute
+        )
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step("Clear BGP")
+    for rtr in topo["routers"]:
+        clear_bgp(tgen, "ipv4", rtr)
+        clear_bgp(tgen, "ipv6", rtr)
+
+    bgp_convergence = verify_bgp_convergence(tgen, topo)
+    assert bgp_convergence is True, "Testcase {} : Failed \n Error: {}".format(
+        tc_name, bgp_convergence
+    )
+
+    step("Verify that zebra selects bgp route.")
+    protocol = "bgp"
+
+    for addr_type in ADDR_TYPES:
+        result4 = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
+        assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result4
+        )
+
+    write_test_footer(tc_name)
+
+
+if __name__ == "__main__":
+    args = ["-s"] + sys.argv[1:]
+    sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_distance_change/test_bgp_admin_dist_vrf.py b/tests/topotests/bgp_distance_change/test_bgp_admin_dist_vrf.py
new file mode 100755 (executable)
index 0000000..559dc93
--- /dev/null
@@ -0,0 +1,900 @@
+#!/usr/bin/env python
+
+#
+# Copyright (c) 2022 by VMware, Inc. ("VMware")
+# Used Copyright (c) 2018 by Network Device Education Foundation,
+# Inc. ("NetDEF") in this file.
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND VMWARE DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+import sys
+import time
+import pytest
+import inspect
+import os
+
+"""Following tests are covered to test bgp admin distance functionality.
+TC_5:
+        Verify bgp admin distance functionality when static route is configured
+        same as bgp learnt route in user vrf.
+
+TC_6:   Verify bgp admin distance functionality with ECMP in user vrf.
+
+TC_7:
+        Verify bgp admin distance functionality when routes are
+        imported between VRFs.
+"""
+
+#################################
+# TOPOLOGY
+#################################
+"""
+
+                    +-------+
+         +--------- |  R2   |
+         |          +-------+
+         |iBGP           |
+     +-------+           |
+     |  R1   |           |iBGP
+     +-------+           |
+         |               |
+         |    iBGP   +-------+   eBGP   +-------+
+         +---------- |  R3   |----------|  R4   |
+                     +-------+          +-------+
+                        |
+                        |eBGP
+                        |
+                    +-------+
+                    |  R5   |
+                    +-------+
+
+
+"""
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+sys.path.append(os.path.join(CWD, "../lib/"))
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib.topogen import Topogen, get_topogen
+
+# Required to instantiate the topology builder class.
+from lib.common_config import (
+    start_topology,
+    write_test_header,
+    step,
+    write_test_footer,
+    create_static_routes,
+    verify_rib,
+    check_address_types,
+    reset_config_on_routers,
+    check_router_status,
+)
+from lib.topolog import logger
+from lib.bgp import (
+    verify_bgp_convergence,
+    create_router_bgp,
+    verify_best_path_as_per_admin_distance,
+)
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib.topogen import Topogen, get_topogen
+from lib.topojson import build_config_from_json
+from lib.topolog import logger
+
+# Global variables
+topo = None
+bgp_convergence = False
+pytestmark = [pytest.mark.bgpd, pytest.mark.staticd]
+
+NETWORK = {
+    "ipv4": [
+        "192.168.20.1/32",
+        "192.168.20.2/32",
+        "192.168.21.1/32",
+        "192.168.21.2/32",
+        "192.168.22.1/32",
+        "192.168.22.2/32",
+    ],
+    "ipv6": [
+        "fc07:50::1/128",
+        "fc07:50::2/128",
+        "fc07:150::1/128",
+        "fc07:150::2/128",
+        "fc07:1::1/128",
+        "fc07:1::2/128",
+    ],
+}
+ADDR_TYPES = check_address_types()
+
+
+def setup_module(mod):
+    """
+    Sets up the pytest environment
+
+    * `mod`: module name
+    """
+
+    global topo
+
+    testsuite_run_time = time.asctime(time.localtime(time.time()))
+    logger.info("Testsuite start time: {}".format(testsuite_run_time))
+    logger.info("=" * 40)
+
+    logger.info("Running setup_module to create topology")
+
+    # This function initiates the topology build with Topogen...
+    json_file = "{}/bgp_admin_dist_vrf.json".format(CWD)
+    tgen = Topogen(json_file, mod.__name__)
+    global topo
+    topo = tgen.json_topo
+
+    # Starting topology, create tmp files which are loaded to routers
+    #  to start deamons and then start routers
+    start_topology(tgen)
+
+    # Creating configuration from JSON
+    build_config_from_json(tgen, topo)
+
+    # Checking BGP convergence
+    global bgp_convergence
+    global ADDR_TYPES
+
+    # Don't run this test if we have any failure.
+    if tgen.routers_have_failure():
+        pytest.skip(tgen.errors)
+
+    # Api call verify whether BGP is converged
+    bgp_convergence = verify_bgp_convergence(tgen, topo)
+    assert bgp_convergence is True, "setup_module :Failed \n Error:" " {}".format(
+        bgp_convergence
+    )
+    logger.info("Running setup_module() done")
+
+
+def teardown_module(mod):
+    """teardown_module.
+
+    Teardown the pytest environment.
+    * `mod`: module name
+    """
+    logger.info("Running teardown_module to delete topology")
+    tgen = get_topogen()
+
+    # Stop toplogy and Remove tmp files
+    tgen.stop_topology()
+
+    logger.info(
+        "Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
+    )
+    logger.info("=" * 40)
+
+
+#####################################################
+# Tests starting
+#####################################################
+
+
+def test_bgp_admin_distance_ebgp_vrf_p0():
+    """
+    TC: 5
+    Verify bgp admin distance functionality when static route is
+    configured same as ebgp learnt route
+    """
+    tgen = get_topogen()
+    global bgp_convergence
+
+    if bgp_convergence is not True:
+        pytest.skip("skipping test case because of BGP Convergence failure at setup")
+
+    # test case name
+    tc_name = inspect.stack()[0][3]
+    write_test_header(tc_name)
+    if tgen.routers_have_failure():
+        check_router_status(tgen)
+
+    step("Configure base config as per the topology")
+    reset_config_on_routers(tgen)
+
+    step("Configure bgp admin distance 200 with CLI in dut.")
+
+    input_dict_1 = {
+        "r3": {
+            "bgp": [
+                {
+                    "vrf": "RED",
+                    "local_as": 100,
+                    "address_family": {
+                        "ipv4": {
+                            "unicast": {
+                                "distance": {"ebgp": 200, "ibgp": 200, "local": 200}
+                            }
+                        },
+                        "ipv6": {
+                            "unicast": {
+                                "distance": {"ebgp": 200, "ibgp": 200, "local": 200}
+                            }
+                        },
+                    },
+                }
+            ]
+        }
+    }
+
+    result = create_router_bgp(tgen, topo, input_dict_1)
+    assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+    step("Verify bgp routes have admin distance of 200 in dut.")
+    # Verifying best path
+    dut = "r3"
+    attribute = "admin_distance"
+
+    input_dict = {
+        "ipv4": {
+            "r3": {
+                "static_routes": [
+                    {
+                        "network": NETWORK["ipv4"][0],
+                        "admin_distance": 200,
+                        "vrf": "RED",
+                    },
+                    {
+                        "network": NETWORK["ipv4"][1],
+                        "admin_distance": 200,
+                        "vrf": "RED",
+                    },
+                ]
+            }
+        },
+        "ipv6": {
+            "r3": {
+                "static_routes": [
+                    {
+                        "network": NETWORK["ipv6"][0],
+                        "admin_distance": 200,
+                        "vrf": "RED",
+                    },
+                    {
+                        "network": NETWORK["ipv6"][1],
+                        "admin_distance": 200,
+                        "vrf": "RED",
+                    },
+                ]
+            }
+        },
+    }
+
+    for addr_type in ADDR_TYPES:
+        result = verify_best_path_as_per_admin_distance(
+            tgen, addr_type, dut, input_dict[addr_type], attribute, vrf="RED"
+        )
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step("Modify the admin distance value to 150.")
+
+    input_dict_1 = {
+        "r3": {
+            "bgp": [
+                {
+                    "local_as": 100,
+                    "address_family": {
+                        "ipv4": {
+                            "unicast": {
+                                "distance": {"ebgp": 150, "ibgp": 150, "local": 150}
+                            }
+                        },
+                        "ipv6": {
+                            "unicast": {
+                                "distance": {"ebgp": 150, "ibgp": 150, "local": 150}
+                            }
+                        },
+                    },
+                }
+            ]
+        }
+    }
+
+    result = create_router_bgp(tgen, topo, input_dict_1)
+    assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+    step("Verify bgp routes have admin distance of 150 in dut.")
+    # Verifying best path
+    dut = "r3"
+    attribute = "admin_distance"
+
+    input_dict = {
+        "ipv4": {
+            "r3": {
+                "static_routes": [
+                    {
+                        "network": NETWORK["ipv4"][0],
+                        "admin_distance": 150,
+                        "vrf": "RED",
+                    },
+                    {
+                        "network": NETWORK["ipv4"][1],
+                        "admin_distance": 150,
+                        "vrf": "RED",
+                    },
+                ]
+            }
+        },
+        "ipv6": {
+            "r3": {
+                "static_routes": [
+                    {
+                        "network": NETWORK["ipv6"][0],
+                        "admin_distance": 150,
+                        "vrf": "RED",
+                    },
+                    {
+                        "network": NETWORK["ipv6"][1],
+                        "admin_distance": 150,
+                        "vrf": "RED",
+                    },
+                ]
+            }
+        },
+    }
+
+    for addr_type in ADDR_TYPES:
+        result = verify_best_path_as_per_admin_distance(
+            tgen, addr_type, dut, input_dict[addr_type], attribute, vrf="RED"
+        )
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step("Un configure the admin distance value on DUT")
+
+    input_dict_1 = {
+        "r3": {
+            "bgp": [
+                {
+                    "local_as": 100,
+                    "address_family": {
+                        "ipv4": {
+                            "unicast": {
+                                "distance": {
+                                    "ebgp": 150,
+                                    "ibgp": 150,
+                                    "local": 150,
+                                    "delete": True,
+                                }
+                            }
+                        },
+                        "ipv6": {
+                            "unicast": {
+                                "distance": {
+                                    "ebgp": 150,
+                                    "ibgp": 150,
+                                    "local": 150,
+                                    "delete": True,
+                                }
+                            }
+                        },
+                    },
+                }
+            ]
+        }
+    }
+
+    result = create_router_bgp(tgen, topo, input_dict_1)
+    assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+    step("Verify bgp routes have default admin distance in dut.")
+    # Verifying best path
+    dut = "r3"
+    attribute = "admin_distance"
+
+    input_dict = {
+        "ipv4": {
+            "r3": {
+                "static_routes": [
+                    {"network": NETWORK["ipv4"][0], "admin_distance": 20, "vrf": "RED"},
+                    {"network": NETWORK["ipv4"][1], "admin_distance": 20, "vrf": "RED"},
+                ]
+            }
+        },
+        "ipv6": {
+            "r3": {
+                "static_routes": [
+                    {"network": NETWORK["ipv6"][0], "admin_distance": 20, "vrf": "RED"},
+                    {"network": NETWORK["ipv6"][1], "admin_distance": 20, "vrf": "RED"},
+                ]
+            }
+        },
+    }
+
+    for addr_type in ADDR_TYPES:
+        result = verify_best_path_as_per_admin_distance(
+            tgen, addr_type, dut, input_dict[addr_type], attribute, vrf="RED"
+        )
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step("Configure static route  Without any admin distance")
+
+    for addr_type in ADDR_TYPES:
+        # Create Static routes
+        input_dict = {
+            "r3": {
+                "static_routes": [
+                    {"network": NETWORK[addr_type], "next_hop": "Null0", "vrf": "RED"}
+                ]
+            }
+        }
+
+        result = create_static_routes(tgen, input_dict)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step("Verify that zebra selects static route.")
+    protocol = "static"
+    # dual stack changes
+    for addr_type in ADDR_TYPES:
+        input_dict = {
+            "r3": {
+                "static_routes": [
+                    {"network": NETWORK[addr_type], "next_hop": "Null0", "vrf": "RED"}
+                ]
+            }
+        }
+        result4 = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
+        assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result4
+        )
+
+    step("Configure static route  with admin distance of 253")
+    for addr_type in ADDR_TYPES:
+        # Create Static routes
+        input_dict = {
+            "r3": {
+                "static_routes": [
+                    {
+                        "network": NETWORK[addr_type],
+                        "next_hop": "Null0",
+                        "admin_distance": 253,
+                        "vrf": "RED",
+                    }
+                ]
+            }
+        }
+
+        result = create_static_routes(tgen, input_dict)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step("Verify that zebra selects bgp route.")
+    protocol = "bgp"
+
+    for addr_type in ADDR_TYPES:
+        input_dict = {
+            "r3": {
+                "static_routes": [
+                    {
+                        "network": NETWORK[addr_type],
+                        "next_hop": "Null0",
+                        "admin_distance": 253,
+                        "vrf": "RED",
+                    }
+                ]
+            }
+        }
+        result4 = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
+        assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result4
+        )
+
+    step("Configure admin distance of 254 in bgp for route  .")
+
+    input_dict_1 = {
+        "r3": {
+            "bgp": [
+                {
+                    "local_as": 100,
+                    "address_family": {
+                        "ipv4": {
+                            "unicast": {
+                                "distance": {"ebgp": 254, "ibgp": 254, "local": 254}
+                            }
+                        },
+                        "ipv6": {
+                            "unicast": {
+                                "distance": {"ebgp": 254, "ibgp": 254, "local": 254}
+                            }
+                        },
+                    },
+                }
+            ]
+        }
+    }
+
+    result = create_router_bgp(tgen, topo, input_dict_1)
+    assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+    step("Verify that zebra selects static route.")
+    protocol = "static"
+    # dual stack changes
+    for addr_type in ADDR_TYPES:
+        input_dict = {
+            "r3": {
+                "static_routes": [
+                    {
+                        "network": NETWORK[addr_type],
+                        "next_hop": "Null0",
+                        "admin_distance": 253,
+                        "vrf": "RED",
+                    }
+                ]
+            }
+        }
+
+        result4 = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
+        assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result4
+        )
+
+    step("Configure admin distance of 255 in bgp for route  in vrf red")
+
+    input_dict_1 = {
+        "r3": {
+            "bgp": [
+                {
+                    "local_as": 100,
+                    "address_family": {
+                        "ipv4": {
+                            "unicast": {
+                                "distance": {"ebgp": 255, "ibgp": 255, "local": 255}
+                            }
+                        },
+                        "ipv6": {
+                            "unicast": {
+                                "distance": {"ebgp": 255, "ibgp": 255, "local": 255}
+                            }
+                        },
+                    },
+                }
+            ]
+        }
+    }
+
+    result = create_router_bgp(tgen, topo, input_dict_1)
+    assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+    step("Verify that zebra selects static route.")
+    protocol = "static"
+    # dual stack changes
+    for addr_type in ADDR_TYPES:
+        input_dict = {
+            "r3": {
+                "static_routes": [
+                    {
+                        "network": NETWORK[addr_type],
+                        "next_hop": "Null0",
+                        "admin_distance": 253,
+                        "vrf": "RED",
+                    }
+                ]
+            }
+        }
+
+        result4 = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
+        assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result4
+        )
+
+    step("Delete the static route.")
+    for addr_type in ADDR_TYPES:
+        # Create Static routes
+        input_dict = {
+            "r3": {
+                "static_routes": [
+                    {
+                        "network": NETWORK[addr_type],
+                        "next_hop": "Null0",
+                        "admin_distance": 253,
+                        "delete": True,
+                        "vrf": "RED",
+                    }
+                ]
+            }
+        }
+
+        result = create_static_routes(tgen, input_dict)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step("Verify that zebra selects bgp route.")
+    protocol = "bgp"
+    # dual stack changes
+    for addr_type in ADDR_TYPES:
+        result4 = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
+        assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result4
+        )
+
+    write_test_footer(tc_name)
+
+
+def test_bgp_admin_distance_ebgp_with_imported_rtes_vrf_p0():
+    """
+    TC: 5
+    Verify bgp admin distance functionality when static route is configured
+    same as bgp learnt route in user vrf.
+    """
+    tgen = get_topogen()
+    global bgp_convergence
+
+    if bgp_convergence is not True:
+        pytest.skip("skipping test case because of BGP Convergence failure at setup")
+
+    # test case name
+    tc_name = inspect.stack()[0][3]
+    write_test_header(tc_name)
+    if tgen.routers_have_failure():
+        check_router_status(tgen)
+
+    step("Configure base config as per the topology")
+    reset_config_on_routers(tgen)
+    step("Configure bgp admin distance 200 with CLI in dut.")
+    step(" Import route from vrf to default vrf")
+    input_dict_1 = {
+        "r3": {
+            "bgp": [
+                {
+                    "vrf": "RED",
+                    "local_as": 100,
+                    "address_family": {
+                        "ipv4": {
+                            "unicast": {
+                                "distance": {"ebgp": 200, "ibgp": 200, "local": 200}
+                            }
+                        },
+                        "ipv6": {
+                            "unicast": {
+                                "distance": {"ebgp": 200, "ibgp": 200, "local": 200}
+                            }
+                        },
+                    },
+                },
+                {
+                    "local_as": 100,
+                    "address_family": {
+                        "ipv4": {
+                            "unicast": {
+                                "distance": {"ebgp": 200, "ibgp": 200, "local": 200},
+                                "import": {"vrf": "RED"},
+                            }
+                        },
+                        "ipv6": {
+                            "unicast": {
+                                "distance": {"ebgp": 200, "ibgp": 200, "local": 200},
+                                "import": {
+                                    "vrf": "RED",
+                                },
+                            }
+                        },
+                    },
+                },
+            ]
+        }
+    }
+
+    result = create_router_bgp(tgen, topo, input_dict_1)
+    assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+    step("Verify bgp routes have admin distance of 200 in dut.")
+    # Verifying best path
+    dut = "r3"
+    attribute = "admin_distance"
+
+    input_dict = {
+        "ipv4": {
+            "r3": {
+                "static_routes": [
+                    {
+                        "network": NETWORK["ipv4"][0],
+                        "admin_distance": 200,
+                        "vrf": "RED",
+                    },
+                    {
+                        "network": NETWORK["ipv4"][1],
+                        "admin_distance": 200,
+                        "vrf": "RED",
+                    },
+                ]
+            }
+        },
+        "ipv6": {
+            "r3": {
+                "static_routes": [
+                    {
+                        "network": NETWORK["ipv6"][0],
+                        "admin_distance": 200,
+                        "vrf": "RED",
+                    },
+                    {
+                        "network": NETWORK["ipv6"][1],
+                        "admin_distance": 200,
+                        "vrf": "RED",
+                    },
+                ]
+            }
+        },
+    }
+
+    for addr_type in ADDR_TYPES:
+        result = verify_best_path_as_per_admin_distance(
+            tgen, addr_type, dut, input_dict[addr_type], attribute, vrf="RED"
+        )
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step(
+        "Verify that routes are getting imported without any issues and "
+        "routes are calculated and installed in rib."
+    )
+
+    input_dict = {
+        "ipv4": {
+            "r3": {
+                "static_routes": [
+                    {
+                        "network": NETWORK["ipv4"][0],
+                        "admin_distance": 200,
+                    },
+                    {
+                        "network": NETWORK["ipv4"][1],
+                        "admin_distance": 200,
+                    },
+                ]
+            }
+        },
+        "ipv6": {
+            "r3": {
+                "static_routes": [
+                    {
+                        "network": NETWORK["ipv6"][0],
+                        "admin_distance": 200,
+                    },
+                    {
+                        "network": NETWORK["ipv6"][1],
+                        "admin_distance": 200,
+                    },
+                ]
+            }
+        },
+    }
+
+    step("Verify that zebra selects bgp route.")
+    protocol = "bgp"
+    # dual stack changes
+    for addr_type in ADDR_TYPES:
+        result4 = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
+        assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result4
+        )
+
+    step(" Un configure import route vrf red inside default vrf.")
+    input_dict_1 = {
+        "r3": {
+            "bgp": [
+                {
+                    "vrf": "RED",
+                    "local_as": 100,
+                    "address_family": {
+                        "ipv4": {
+                            "unicast": {
+                                "distance": {"ebgp": 200, "ibgp": 200, "local": 200}
+                            }
+                        },
+                        "ipv6": {
+                            "unicast": {
+                                "distance": {"ebgp": 200, "ibgp": 200, "local": 200}
+                            }
+                        },
+                    },
+                },
+                {
+                    "local_as": 100,
+                    "address_family": {
+                        "ipv4": {
+                            "unicast": {
+                                "distance": {"ebgp": 200, "ibgp": 200, "local": 200},
+                                "import": {"vrf": "RED", "delete": True},
+                            }
+                        },
+                        "ipv6": {
+                            "unicast": {
+                                "distance": {"ebgp": 200, "ibgp": 200, "local": 200},
+                                "import": {"vrf": "RED", "delete": True},
+                            }
+                        },
+                    },
+                },
+            ]
+        }
+    }
+
+    result = create_router_bgp(tgen, topo, input_dict_1)
+    assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+    input_dict = {
+        "ipv4": {
+            "r3": {
+                "static_routes": [
+                    {
+                        "network": NETWORK["ipv4"][0],
+                        "admin_distance": 200,
+                    },
+                    {
+                        "network": NETWORK["ipv4"][1],
+                        "admin_distance": 200,
+                    },
+                ]
+            }
+        },
+        "ipv6": {
+            "r3": {
+                "static_routes": [
+                    {
+                        "network": NETWORK["ipv6"][0],
+                        "admin_distance": 200,
+                    },
+                    {
+                        "network": NETWORK["ipv6"][1],
+                        "admin_distance": 200,
+                    },
+                ]
+            }
+        },
+    }
+
+    step("Verify that route withdrawal happens properly.")
+    protocol = "bgp"
+    # dual stack changes
+    for addr_type in ADDR_TYPES:
+        result4 = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict[addr_type],
+            protocol=protocol,
+            expected=False,
+        )
+        assert (
+            result4 is not True
+        ), "Testcase {} : Failed \n Route is not withdrawn. Error: {}".format(
+            tc_name, result4
+        )
+
+    write_test_footer(tc_name)
+
+
+if __name__ == "__main__":
+    args = ["-s"] + sys.argv[1:]
+    sys.exit(pytest.main(args))
index 341ec25a19d980d0e61b8709173ff27274702163..7ab36c4fcdd39a6de5e3852603467c5c26b265a6 100644 (file)
@@ -491,6 +491,25 @@ def __create_bgp_unicast_neighbor(
                         cmd = "no {}".format(cmd)
                     config_data.append(cmd)
 
+        admin_dist_data = addr_data.setdefault("distance", {})
+        if admin_dist_data:
+            if len(admin_dist_data) < 2:
+                logger.debug(
+                    "Router %s: pass the admin distance values for "
+                    "ebgp, ibgp and local routes",
+                    router,
+                )
+            cmd = "distance bgp {} {} {}".format(
+                admin_dist_data["ebgp"],
+                admin_dist_data["ibgp"],
+                admin_dist_data["local"],
+            )
+
+            del_action = admin_dist_data.setdefault("delete", False)
+            if del_action:
+                cmd = "no distance bgp"
+            config_data.append(cmd)
+
         import_vrf_data = addr_data.setdefault("import", {})
         if import_vrf_data:
             cmd = "import vrf {}".format(import_vrf_data["vrf"])
@@ -2662,7 +2681,7 @@ def verify_best_path_as_per_bgp_attribute(
 
 @retry(retry_timeout=10)
 def verify_best_path_as_per_admin_distance(
-    tgen, addr_type, router, input_dict, attribute, expected=True
+    tgen, addr_type, router, input_dict, attribute, expected=True, vrf=None
 ):
     """
     API is to verify best path according to admin distance for given
@@ -2678,6 +2697,7 @@ def verify_best_path_as_per_admin_distance(
     * `input_dict`: defines different routes with different admin distance
                     to calculate for which route best path is selected
     * `expected` : expected results from API, by-default True
+    * `vrf`: Pass vrf name check for perticular vrf.
 
     Usage
     -----
@@ -2710,9 +2730,14 @@ def verify_best_path_as_per_admin_distance(
 
     # Show ip route cmd
     if addr_type == "ipv4":
-        command = "show ip route json"
+        command = "show ip route"
+    else:
+        command = "show ipv6 route"
+
+    if vrf:
+        command = "{} vrf {} json".format(command, vrf)
     else:
-        command = "show ipv6 route json"
+        command = "{} json".format(command)
 
     for routes_from_router in input_dict.keys():
         sh_ip_route_json = router_list[routes_from_router].vtysh_cmd(
index fa33b02ed154d8bcfa184599e7afbc1c20d8f9d1..5f4c2807151ecc4a817473b29d4d5ee11096aae4 100644 (file)
@@ -3339,6 +3339,7 @@ def verify_rib(
     metric=None,
     fib=None,
     count_only=False,
+    admin_distance=None,
 ):
     """
     Data will be read from input_dict or input JSON file, API will generate
@@ -3611,6 +3612,30 @@ def verify_rib(
                                     )
                                     return errormsg
 
+                            if admin_distance is not None:
+                                if "distance" not in rib_routes_json[st_rt][0]:
+                                    errormsg = (
+                                        "[DUT: {}]: admin distance is"
+                                        " not present for"
+                                        " route {} in RIB \n".format(dut, st_rt)
+                                    )
+                                    return errormsg
+
+                                if (
+                                    admin_distance
+                                    != rib_routes_json[st_rt][0]["distance"]
+                                ):
+                                    errormsg = (
+                                        "[DUT: {}]: admin distance value "
+                                        "{} is not matched for "
+                                        "route {} in RIB \n".format(
+                                            dut,
+                                            admin_distance,
+                                            st_rt,
+                                        )
+                                    )
+                                    return errormsg
+
                             if metric is not None:
                                 if "metric" not in rib_routes_json[st_rt][0]:
                                     errormsg = (
@@ -3764,7 +3789,7 @@ def verify_rib(
 
 
 @retry(retry_timeout=12)
-def verify_fib_routes(tgen, addr_type, dut, input_dict, next_hop=None):
+def verify_fib_routes(tgen, addr_type, dut, input_dict, next_hop=None, protocol=None):
     """
     Data will be read from input_dict or input JSON file, API will generate
     same prefixes, which were redistributed by either create_static_routes() or
@@ -3822,6 +3847,9 @@ def verify_fib_routes(tgen, addr_type, dut, input_dict, next_hop=None):
             found_routes = []
             missing_routes = []
 
+            if protocol:
+                command = "{} {}".format(command, protocol)
+
             if "static_routes" in input_dict[routerInput]:
                 static_routes = input_dict[routerInput]["static_routes"]
 
@@ -5039,7 +5067,7 @@ def verify_ip_nht(tgen, input_dict):
 
         for nh in nh_list:
             if nh in show_ip_nht:
-                nht = run_frr_cmd(rnode, f"show ip nht {nh}")
+                nht = run_frr_cmd(rnode, "show ip nht {}".format(nh))
                 if "unresolved" in nht:
                     errormsg = "Nexthop {} became unresolved on {}".format(nh, router)
                     return errormsg