]> git.puffer.fish Git - matthieu/frr.git/commitdiff
tests: Adding lib changes for bgp peer type verification.
authornguggarigoud <nguggarigoud@vmware.com>
Tue, 29 Jun 2021 00:10:17 +0000 (17:10 -0700)
committernguggarigoud <nguggarigoud@vmware.com>
Thu, 15 Jul 2021 12:28:08 +0000 (05:28 -0700)
Signed-off-by: nguggarigoud <nguggarigoud@vmware.com>
tests/topotests/lib/bgp.py
tests/topotests/lib/common_config.py

index a236a916b58c31470520e4a1357f1974a625d18a..2f1f67439f8e92c65d915a00ff07401e5e63e513 100644 (file)
@@ -44,6 +44,7 @@ from lib.common_config import (
     FRRCFG_FILE,
     retry,
     get_ipv6_linklocal_address,
+    get_frr_ipv6_linklocal
 )
 
 LOGDIR = "/tmp/topotests/"
@@ -265,6 +266,11 @@ def __create_bgp_global(tgen, input_dict, router, build=False):
         config_data.append("bgp router-id {}".format(router_id))
 
     config_data.append("no bgp network import-check")
+    bgp_peer_grp_data = bgp_data.setdefault("peer-group", {})
+
+    if "peer-group" in bgp_data and bgp_peer_grp_data:
+        peer_grp_data = __create_bgp_peer_group(tgen, bgp_peer_grp_data, router)
+        config_data.extend(peer_grp_data)
 
     bst_path = bgp_data.setdefault("bestpath", None)
     if bst_path:
@@ -380,6 +386,7 @@ def __create_bgp_unicast_neighbor(
         addr_data = addr_dict["unicast"]
         if addr_data:
             config_data.append("address-family {} unicast".format(addr_type))
+
         advertise_network = addr_data.setdefault("advertise_networks", [])
         for advertise_network_dict in advertise_network:
             network = advertise_network_dict["network"]
@@ -404,14 +411,29 @@ def __create_bgp_unicast_neighbor(
 
                 config_data.append(cmd)
 
+        import_cmd = addr_data.setdefault("import", {})
+        if import_cmd:
+            try:
+                if import_cmd["delete"]:
+                    config_data.append("no import vrf {}".format(import_cmd["vrf"]))
+            except KeyError:
+                config_data.append("import vrf {}".format(import_cmd["vrf"]))
+
         max_paths = addr_data.setdefault("maximum_paths", {})
         if max_paths:
             ibgp = max_paths.setdefault("ibgp", None)
             ebgp = max_paths.setdefault("ebgp", None)
+            del_cmd = max_paths.setdefault("delete", False)
             if ibgp:
-                config_data.append("maximum-paths ibgp {}".format(ibgp))
+                if del_cmd:
+                    config_data.append("no maximum-paths ibgp {}".format(ibgp))
+                else:
+                    config_data.append("maximum-paths ibgp {}".format(ibgp))
             if ebgp:
-                config_data.append("maximum-paths {}".format(ebgp))
+                if del_cmd:
+                    config_data.append("no maximum-paths {}".format(ebgp))
+                else:
+                    config_data.append("maximum-paths {}".format(ebgp))
 
         aggregate_addresses = addr_data.setdefault("aggregate_address", [])
         for aggregate_address in aggregate_addresses:
@@ -649,6 +671,38 @@ def __create_l2vpn_evpn_address_family(
     return config_data
 
 
+def __create_bgp_peer_group(topo, input_dict, router):
+    """
+    Helper API to create neighbor specific configuration
+
+    Parameters
+    ----------
+    * `topo` : json file data
+    * `input_dict` : Input dict data, required when configuring from testcase
+    * `router` : router id to be configured
+    """
+    config_data = []
+    logger.debug("Entering lib API: __create_bgp_peer_group()")
+
+    for grp, grp_dict in input_dict.items():
+        config_data.append("neighbor {} peer-group".format(grp))
+        neigh_cxt = "neighbor {} ".format(grp)
+        update_source = grp_dict.setdefault("update-source", None)
+        remote_as = grp_dict.setdefault("remote-as", None)
+        capability = grp_dict.setdefault("capability", None)
+        if update_source:
+            config_data.append("{} update-source {}".format(neigh_cxt, update_source))
+
+        if remote_as:
+            config_data.append("{} remote-as {}".format(neigh_cxt, remote_as))
+
+        if capability:
+            config_data.append("{} capability {}".format(neigh_cxt, capability))
+
+    logger.debug("Exiting lib API: __create_bgp_peer_group()")
+    return config_data
+
+
 def __create_bgp_neighbor(topo, input_dict, router, addr_type, add_neigh=True):
     """
     Helper API to create neighbor specific configuration
@@ -660,10 +714,9 @@ def __create_bgp_neighbor(topo, input_dict, router, addr_type, add_neigh=True):
     * `input_dict` : Input dict data, required when configuring from testcase
     * `router` : router id to be configured
     """
-
     config_data = []
     logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name))
-
+    tgen = get_topogen()
     bgp_data = input_dict["address_family"]
     neigh_data = bgp_data[addr_type]["unicast"]["neighbor"]
 
@@ -672,35 +725,91 @@ def __create_bgp_neighbor(topo, input_dict, router, addr_type, add_neigh=True):
             nh_details = topo[name]
 
             if "vrfs" in topo[router] or type(nh_details["bgp"]) is list:
-                remote_as = nh_details["bgp"][0]["local_as"]
+                for vrf_data in nh_details["bgp"]:
+                    if "vrf" in nh_details["links"][dest_link] and "vrf" in vrf_data:
+                        if nh_details["links"][dest_link]["vrf"] == vrf_data["vrf"]:
+                            remote_as = vrf_data["local_as"]
+                            break
+                    else:
+                        if "vrf" not in vrf_data:
+                            remote_as = vrf_data["local_as"]
+                            break
+
             else:
                 remote_as = nh_details["bgp"]["local_as"]
 
             update_source = None
 
-            if dest_link in nh_details["links"].keys():
-                ip_addr = nh_details["links"][dest_link][addr_type].split("/")[0]
-            # Loopback interface
-            if "source_link" in peer and peer["source_link"] == "lo":
-                update_source = topo[router]["links"]["lo"][addr_type].split("/")[0]
+            if "neighbor_type" in peer and peer["neighbor_type"] == "unnumbered":
+                ip_addr = nh_details["links"][dest_link]["peer-interface"]
+            elif "neighbor_type" in peer and peer["neighbor_type"] == "link-local":
+                intf = topo[name]["links"][dest_link]["interface"]
+                ip_addr = get_frr_ipv6_linklocal(tgen, name, intf)
+            elif dest_link in nh_details["links"].keys():
+                try:
+                    ip_addr = nh_details["links"][dest_link][addr_type].split("/")[0]
+                except KeyError:
+                    intf = topo[name]["links"][dest_link]["interface"]
+                    ip_addr = get_frr_ipv6_linklocal(tgen, name, intf)
+            if "delete" in peer and peer["delete"]:
+                neigh_cxt = "no neighbor {}".format(ip_addr)
+                config_data.append("{}".format(neigh_cxt))
+                return config_data
+            else:
+                neigh_cxt = "neighbor {}".format(ip_addr)
 
-            neigh_cxt = "neighbor {}".format(ip_addr)
+            if "peer-group" in peer:
+                config_data.append(
+                    "neighbor {} interface peer-group {}".format(
+                        ip_addr, peer["peer-group"]
+                    )
+                )
+
+            # Loopback interface
+            if "source_link" in peer:
+                if peer["source_link"] == "lo":
+                    update_source = topo[router]["links"]["lo"][addr_type].split("/")[0]
+                else:
+                    update_source = topo[router]["links"][peer["source_link"]][
+                        "interface"
+                    ]
+            if "peer-group" not in peer:
+                if "neighbor_type" in peer and peer["neighbor_type"] == "unnumbered":
+                    config_data.append(
+                        "{} interface remote-as {}".format(neigh_cxt, remote_as)
+                    )
+                elif add_neigh:
+                    config_data.append("{} remote-as {}".format(neigh_cxt, remote_as))
 
-            if add_neigh:
-                config_data.append("{} remote-as {}".format(neigh_cxt, remote_as))
             if addr_type == "ipv6":
                 config_data.append("address-family ipv6 unicast")
                 config_data.append("{} activate".format(neigh_cxt))
 
+            if "neighbor_type" in peer and peer["neighbor_type"] == "link-local":
+                config_data.append(
+                    "{} update-source {}".format(
+                        neigh_cxt, nh_details["links"][dest_link]["peer-interface"]
+                    )
+                )
+                config_data.append(
+                    "{} interface {}".format(
+                        neigh_cxt, nh_details["links"][dest_link]["peer-interface"]
+                    )
+                )
+
             disable_connected = peer.setdefault("disable_connected_check", False)
             keep_alive = peer.setdefault("keepalivetimer", 3)
             hold_down = peer.setdefault("holddowntimer", 10)
             password = peer.setdefault("password", None)
             no_password = peer.setdefault("no_password", None)
+            capability = peer.setdefault("capability", None)
             max_hop_limit = peer.setdefault("ebgp_multihop", 1)
+
             graceful_restart = peer.setdefault("graceful-restart", None)
             graceful_restart_helper = peer.setdefault("graceful-restart-helper", None)
             graceful_restart_disable = peer.setdefault("graceful-restart-disable", None)
+            if capability:
+                config_data.append("{} capability {}".format(neigh_cxt, capability))
 
             if update_source:
                 config_data.append(
@@ -718,7 +827,6 @@ def __create_bgp_neighbor(topo, input_dict, router, addr_type, add_neigh=True):
                 config_data.append(
                     "{} timers {} {}".format(neigh_cxt, keep_alive, hold_down)
                 )
-
             if graceful_restart:
                 config_data.append("{} graceful-restart".format(neigh_cxt))
             elif graceful_restart == False:
@@ -768,7 +876,7 @@ def __create_bgp_unicast_address_family(
 
     config_data = []
     logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name))
-
+    tgen = get_topogen()
     bgp_data = input_dict["address_family"]
     neigh_data = bgp_data[addr_type]["unicast"]["neighbor"]
 
@@ -784,16 +892,34 @@ def __create_bgp_unicast_address_family(
                 for destRouterLink, data in sorted(nh_details["links"].items()):
                     if "type" in data and data["type"] == "loopback":
                         if dest_link == destRouterLink:
-                            ip_addr = nh_details["links"][destRouterLink][
-                                addr_type
-                            ].split("/")[0]
+                            ip_addr = (
+                                nh_details["links"][destRouterLink][addr_type]
+                                .split("/")[0]
+                                .lower()
+                            )
 
             # Physical interface
             else:
-                if dest_link in nh_details["links"].keys():
-
-                    ip_addr = nh_details["links"][dest_link][addr_type].split("/")[0]
-                    if addr_type == "ipv4" and bgp_data["ipv6"]:
+                # check the neighbor type if un numbered nbr, use interface.
+                if "neighbor_type" in peer and peer["neighbor_type"] == "unnumbered":
+                    ip_addr = nh_details["links"][dest_link]["peer-interface"]
+                elif "neighbor_type" in peer and peer["neighbor_type"] == "link-local":
+                    intf = topo[peer_name]["links"][dest_link]["interface"]
+                    ip_addr = get_frr_ipv6_linklocal(tgen, peer_name, intf)
+                elif dest_link in nh_details["links"].keys():
+                    try:
+                        ip_addr = nh_details["links"][dest_link][addr_type].split("/")[
+                            0
+                        ]
+                    except KeyError:
+                        intf = topo[peer_name]["links"][dest_link]["interface"]
+                        ip_addr = get_frr_ipv6_linklocal(tgen, peer_name, intf)
+                    if (
+                        addr_type == "ipv4"
+                        and bgp_data["ipv6"]
+                        and check_address_types("ipv6")
+                        and "ipv6" in nh_details["links"][dest_link]
+                    ):
                         deactivate = nh_details["links"][dest_link]["ipv6"].split("/")[
                             0
                         ]
@@ -822,6 +948,7 @@ def __create_bgp_unicast_address_family(
             prefix_lists = peer.setdefault("prefix_lists", {})
             route_maps = peer.setdefault("route_maps", {})
             no_send_community = peer.setdefault("no_send_community", None)
+            capability = peer.setdefault("capability", None)
             allowas_in = peer.setdefault("allowas-in", None)
 
             # next-hop-self
@@ -841,6 +968,11 @@ def __create_bgp_unicast_address_family(
                     "no {} send-community {}".format(neigh_cxt, no_send_community)
                 )
 
+            # capability_ext_nh
+            if capability and addr_type == "ipv6":
+                config_data.append("address-family ipv4 unicast")
+                config_data.append("{} activate".format(neigh_cxt))
+
             if "allowas_in" in peer:
                 allow_as_in = peer["allowas_in"]
                 config_data.append("{} allowas-in {}".format(neigh_cxt, allow_as_in))
@@ -1067,33 +1199,37 @@ def verify_bgp_convergence(tgen, topo, dut=None, expected=True):
     API will verify if BGP is converged with in the given time frame.
     Running "show bgp summary json" command and verify bgp neighbor
     state is established,
+
     Parameters
     ----------
     * `tgen`: topogen object
     * `topo`: input json file data
     * `dut`: device under test
-    * `expected` : expected results from API, by-default True
 
     Usage
     -----
     # To veriry is BGP is converged for all the routers used in
     topology
     results = verify_bgp_convergence(tgen, topo, dut="r1")
+
     Returns
     -------
     errormsg(str) or True
     """
 
-    logger.debug("Entering lib API: verify_bgp_convergence()")
+    result = False
+    logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name))
+    tgen = get_topogen()
     for router, rnode in tgen.routers().items():
-        if dut is not None and dut != router:
+        if 'bgp' not in topo['routers'][router]:
             continue
 
-        if "bgp" not in topo["routers"][router]:
+        if dut is not None and dut != router:
             continue
 
         logger.info("Verifying BGP Convergence on router %s:", router)
-        show_bgp_json = run_frr_cmd(rnode, "show bgp vrf all summary json", isjson=True)
+        show_bgp_json = run_frr_cmd(rnode, "show bgp vrf all summary json",
+                                    isjson=True)
         # Verifying output dictionary show_bgp_json is empty or not
         if not bool(show_bgp_json):
             errormsg = "BGP is not running"
@@ -1115,100 +1251,6 @@ def verify_bgp_convergence(tgen, topo, dut=None, expected=True):
 
             # To find neighbor ip type
             bgp_addr_type = bgp_data["address_family"]
-            if "ipv4" in bgp_addr_type or "ipv6" in bgp_addr_type:
-                for addr_type in bgp_addr_type.keys():
-                    if not check_address_types(addr_type):
-                        continue
-                    total_peer = 0
-
-                    bgp_neighbors = bgp_addr_type[addr_type]["unicast"]["neighbor"]
-
-                    for bgp_neighbor in bgp_neighbors:
-                        total_peer += len(bgp_neighbors[bgp_neighbor]["dest_link"])
-
-                for addr_type in bgp_addr_type.keys():
-                    if not check_address_types(addr_type):
-                        continue
-                    bgp_neighbors = bgp_addr_type[addr_type]["unicast"]["neighbor"]
-
-                    no_of_peer = 0
-                    for bgp_neighbor, peer_data in bgp_neighbors.items():
-                        for dest_link in peer_data["dest_link"].keys():
-                            data = topo["routers"][bgp_neighbor]["links"]
-                            if dest_link in data:
-                                peer_details = peer_data["dest_link"][dest_link]
-                                # for link local neighbors
-                                if (
-                                    "neighbor_type" in peer_details
-                                    and peer_details["neighbor_type"] == "link-local"
-                                ):
-                                    neighbor_ip = get_ipv6_linklocal_address(
-                                        topo["routers"], bgp_neighbor, dest_link
-                                    )
-                                elif "source_link" in peer_details:
-                                    neighbor_ip = topo["routers"][bgp_neighbor][
-                                        "links"
-                                    ][peer_details["source_link"]][addr_type].split(
-                                        "/"
-                                    )[
-                                        0
-                                    ]
-                                elif (
-                                    "neighbor_type" in peer_details
-                                    and peer_details["neighbor_type"] == "unnumbered"
-                                ):
-                                    neighbor_ip = data[dest_link]["peer-interface"]
-                                else:
-                                    neighbor_ip = data[dest_link][addr_type].split("/")[
-                                        0
-                                    ]
-                                nh_state = None
-
-                                if addr_type == "ipv4":
-                                    if "ipv4Unicast" in show_bgp_json[vrf]:
-                                        ipv4_data = show_bgp_json[vrf]["ipv4Unicast"][
-                                            "peers"
-                                        ]
-                                        nh_state = ipv4_data[neighbor_ip]["state"]
-                                else:
-                                    if "ipv6Unicast" in show_bgp_json[vrf]:
-                                        ipv6_data = show_bgp_json[vrf]["ipv6Unicast"][
-                                            "peers"
-                                        ]
-                                        nh_state = ipv6_data[neighbor_ip]["state"]
-                                if nh_state == "Established":
-                                    no_of_peer += 1
-
-                    if "l2vpn" in bgp_addr_type:
-                        if "neighbor" not in bgp_addr_type["l2vpn"]["evpn"]:
-                            if no_of_peer == total_peer:
-                                logger.info(
-                                    "[DUT: %s] VRF: %s, BGP is Converged for %s address-family",
-                                    router,
-                                    vrf,
-                                    addr_type,
-                                )
-                            else:
-                                errormsg = (
-                                    "[DUT: %s] VRF: %s, BGP is not converged for %s address-family"
-                                    % (router, vrf, addr_type)
-                                )
-                                return errormsg
-                    else:
-                        if no_of_peer == total_peer:
-                            logger.info(
-                                "[DUT: %s] VRF: %s, BGP is Converged for %s address-family",
-                                router,
-                                vrf,
-                                addr_type,
-                            )
-                        else:
-                            errormsg = (
-                                "[DUT: %s] VRF: %s, BGP is not converged for %s address-family"
-                                % (router, vrf, addr_type)
-                            )
-                            return errormsg
-
             if "l2vpn" in bgp_addr_type:
                 total_evpn_peer = 0
 
@@ -1224,46 +1266,120 @@ def verify_bgp_convergence(tgen, topo, dut=None, expected=True):
                         data = topo["routers"][bgp_neighbor]["links"]
                         for dest_link in dest_link_dict.keys():
                             if dest_link in data:
-                                peer_details = peer_data[_addr_type][dest_link]
+                                peer_details = \
+                                    peer_data[_addr_type][dest_link]
 
-                                neighbor_ip = data[dest_link][_addr_type].split("/")[0]
+                                neighbor_ip = \
+                                    data[dest_link][_addr_type].split(
+                                        "/")[0]
                                 nh_state = None
 
-                                if (
-                                    "ipv4Unicast" in show_bgp_json[vrf]
-                                    or "ipv6Unicast" in show_bgp_json[vrf]
-                                ):
-                                    errormsg = (
-                                        "[DUT: %s] VRF: %s, "
-                                        "ipv4Unicast/ipv6Unicast"
-                                        " address-family present"
-                                        " under l2vpn" % (router, vrf)
-                                    )
+                                if "ipv4Unicast" in show_bgp_json[vrf] or \
+                                    "ipv6Unicast" in show_bgp_json[vrf]:
+                                    errormsg = ("[DUT: %s] VRF: %s, "
+                                                "ipv4Unicast/ipv6Unicast"
+                                                " address-family present"
+                                                " under l2vpn" % (router,
+                                                                 vrf))
                                     return errormsg
 
-                                l2VpnEvpn_data = show_bgp_json[vrf]["l2VpnEvpn"][
-                                    "peers"
-                                ]
-                                nh_state = l2VpnEvpn_data[neighbor_ip]["state"]
+                                l2VpnEvpn_data = \
+                                    show_bgp_json[vrf]["l2VpnEvpn"][
+                                        "peers"]
+                                nh_state = \
+                                    l2VpnEvpn_data[neighbor_ip]["state"]
 
                                 if nh_state == "Established":
                                     no_of_evpn_peer += 1
 
                 if no_of_evpn_peer == total_evpn_peer:
-                    logger.info(
-                        "[DUT: %s] VRF: %s, BGP is Converged for " "epvn peers",
-                        router,
-                        vrf,
-                    )
+                    logger.info("[DUT: %s] VRF: %s, BGP is Converged for "
+                                "epvn peers", router, vrf)
+                    result = True
                 else:
-                    errormsg = (
-                        "[DUT: %s] VRF: %s, BGP is not converged "
-                        "for evpn peers" % (router, vrf)
-                    )
+                    errormsg = ("[DUT: %s] VRF: %s, BGP is not converged "
+                               "for evpn peers" % (router, vrf))
                     return errormsg
+            else:
+                total_peer = 0
+                for addr_type in bgp_addr_type.keys():
+                    if not check_address_types(addr_type):
+                        continue
 
-    logger.debug("Exiting API: verify_bgp_convergence()")
-    return True
+                    bgp_neighbors = \
+                        bgp_addr_type[addr_type]["unicast"]["neighbor"]
+
+                    for bgp_neighbor in bgp_neighbors:
+                        total_peer += \
+                            len(bgp_neighbors[bgp_neighbor]["dest_link"])
+
+                no_of_peer = 0
+                for addr_type in bgp_addr_type.keys():
+                    if not check_address_types(addr_type):
+                        continue
+                    bgp_neighbors = \
+                        bgp_addr_type[addr_type]["unicast"]["neighbor"]
+
+                    for bgp_neighbor, peer_data in bgp_neighbors.items():
+                            for dest_link in peer_data["dest_link"].\
+                                keys():
+                                data = \
+                                    topo["routers"][bgp_neighbor]["links"]
+                                if dest_link in data:
+                                    peer_details = \
+                                        peer_data['dest_link'][dest_link]
+                                    # for link local neighbors
+                                    if "neighbor_type" in peer_details and \
+                                            peer_details["neighbor_type"] == \
+                                            'link-local':
+                                        intf = topo["routers"][bgp_neighbor][
+                                            "links"][dest_link]["interface"]
+                                        neighbor_ip = get_frr_ipv6_linklocal(
+                                            tgen, bgp_neighbor, intf)
+                                    elif "source_link" in peer_details:
+                                        neighbor_ip = \
+                                            topo["routers"][bgp_neighbor][
+                                                "links"][peer_details[
+                                                    'source_link']][
+                                                    addr_type].\
+                                                        split("/")[0]
+                                    elif "neighbor_type" in peer_details and \
+                                            peer_details["neighbor_type"] == \
+                                            'unnumbered':
+                                        neighbor_ip = \
+                                            data[dest_link]["peer-interface"]
+                                    else:
+                                        neighbor_ip = \
+                                            data[dest_link][addr_type].split(
+                                                "/")[0]
+                                    nh_state = None
+                                    neighbor_ip = neighbor_ip.lower()
+                                    if addr_type == "ipv4":
+                                        ipv4_data = show_bgp_json[vrf][
+                                            "ipv4Unicast"]["peers"]
+                                        nh_state = \
+                                            ipv4_data[neighbor_ip]["state"]
+                                    else:
+                                        ipv6_data = show_bgp_json[vrf][
+                                            "ipv6Unicast"]["peers"]
+                                        if neighbor_ip in ipv6_data:
+                                            nh_state = \
+                                                ipv6_data[neighbor_ip]["state"]
+
+                                    if nh_state == "Established":
+                                        no_of_peer += 1
+
+                if no_of_peer == total_peer and no_of_peer > 0:
+                    logger.info("[DUT: %s] VRF: %s, BGP is Converged",
+                                router, vrf)
+                    result = True
+                else:
+                    errormsg = ("[DUT: %s] VRF: %s, BGP is not converged"
+                        % (router, vrf))
+                    return errormsg
+
+    logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
+    return result
 
 
 @retry(retry_timeout=16)
index 9e60e523d3878498152d33b4d76680e8404afe45..d2f20aa7b331b17d613cfbfef6913caaca47e7d8 100644 (file)
@@ -637,6 +637,7 @@ def load_config_to_router(tgen, routerName, save_bkup=False):
     return True
 
 
+
 def get_frr_ipv6_linklocal(tgen, router, intf=None, vrf=None):
     """
     API to get the link local ipv6 address of a particular interface using
@@ -669,38 +670,48 @@ def get_frr_ipv6_linklocal(tgen, router, intf=None, vrf=None):
         else:
             cmd = "show interface"
 
-        ifaces = router_list[router].run('vtysh -c "{}"'.format(cmd))
-
-        # Fix newlines (make them all the same)
-        ifaces = ("\n".join(ifaces.splitlines()) + "\n").splitlines()
-
-        interface = None
-        ll_per_if_count = 0
-        for line in ifaces:
-            # Interface name
-            m = re_search("Interface ([a-zA-Z0-9-]+) is", line)
-            if m:
-                interface = m.group(1).split(" ")[0]
-                ll_per_if_count = 0
-
-            # Interface ip
-            m1 = re_search("inet6 (fe80[:a-fA-F0-9]+[/0-9]+)", line)
-            if m1:
-                local = m1.group(1)
-                ll_per_if_count += 1
-                if ll_per_if_count > 1:
-                    linklocal += [["%s-%s" % (interface, ll_per_if_count), local]]
-                else:
-                    linklocal += [[interface, local]]
-
-    if linklocal:
-        if intf:
-            return [_linklocal[1] for _linklocal in linklocal if _linklocal[0] == intf][
-                0
-            ].split("/")[0]
-        return linklocal
-    else:
-        errormsg = "Link local ip missing on router {}"
+        linklocal = []
+        if vrf:
+            cmd = "show interface vrf {}".format(vrf)
+        else:
+            cmd = "show interface"
+        for chk_ll in range(0, 60):
+            sleep(1/4)
+            ifaces = router_list[router].run('vtysh -c "{}"'.format(cmd))
+            # Fix newlines (make them all the same)
+            ifaces = ('\n'.join(ifaces.splitlines()) + '\n').splitlines()
+
+            interface = None
+            ll_per_if_count = 0
+            for line in ifaces:
+                # Interface name
+                m = re_search('Interface ([a-zA-Z0-9-]+) is', line)
+                if m:
+                    interface = m.group(1).split(" ")[0]
+                    ll_per_if_count = 0
+
+                # Interface ip
+                m1 = re_search('inet6 (fe80[:a-fA-F0-9]+[\/0-9]+)',
+                              line)
+                if m1:
+                    local = m1.group(1)
+                    ll_per_if_count += 1
+                    if ll_per_if_count > 1:
+                        linklocal += [["%s-%s" %
+                                       (interface, ll_per_if_count), local]]
+                    else:
+                        linklocal += [[interface, local]]
+
+            try:
+                if linklocal:
+                    if intf:
+                        return [_linklocal[1] for _linklocal in linklocal if _linklocal[0]==intf][0].\
+                            split("/")[0]
+                    return linklocal
+            except IndexError:
+                continue
+
+        errormsg = "Link local ip missing on router {}".format(router)
         return errormsg
 
 
@@ -1846,6 +1857,14 @@ def create_interfaces_cfg(tgen, topo, build=False):
                     else:
                         interface_data.append("ipv6 address {}".format(intf_addr))
 
+                # Wait for vrf interfaces to get link local address once they are up
+                if not destRouterLink == 'lo' and 'vrf' in topo[c_router][
+                    'links'][destRouterLink]:
+                    vrf = topo[c_router]['links'][destRouterLink]['vrf']
+                    intf = topo[c_router]['links'][destRouterLink]['interface']
+                    ll = get_frr_ipv6_linklocal(tgen, c_router, intf=intf,
+                                vrf = vrf)
+
                 if "ipv6-link-local" in data:
                     intf_addr = c_data["links"][destRouterLink]["ipv6-link-local"]