]> git.puffer.fish Git - mirror/frr.git/commitdiff
tests: Add new tests to bgp-basic-functionality-topo1 6925/head
authorKuldeep Kashyap <kashyapk@vmware.com>
Mon, 17 Aug 2020 02:13:04 +0000 (02:13 +0000)
committerKuldeep Kashyap <kashyapk@vmware.com>
Fri, 28 Aug 2020 12:24:20 +0000 (12:24 +0000)
1. Added new tests to bgp-basic-functionality-topo1
3. Execution time increased by 55 sec

Signed-off-by: Kuldeep Kashyap <kashyapk@vmware.com>
tests/topotests/bgp-basic-functionality-topo1/bgp_basic_functionality.json
tests/topotests/bgp-basic-functionality-topo1/test_bgp_basic_functionality.py
tests/topotests/lib/bgp.py
tests/topotests/lib/common_config.py

index c778ae4bedba20a7d201aee9e9f51044a6f6df97..ee1f1b74c016328664ec9cf485e6533a54ddf511 100644 (file)
@@ -1,36 +1,17 @@
 {
+    "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
-    },
+    "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"
-                }
+                "lo": {"ipv4": "auto", "ipv6": "auto", "type": "loopback"},
+                "r2": {"ipv4": "auto", "ipv6": "auto"},
+                "r3": {"ipv4": "auto", "ipv6": "auto"}
             },
             "bgp": {
                 "local_as": "100",
                     "ipv4": {
                         "unicast": {
                             "neighbor": {
-                                "r2": {
-                                    "dest_link": {
-                                        "r1": {}
-                                    }
-                                },
-                                "r3": {
-                                    "dest_link": {
-                                        "r1": {}
-                                    }
-                                }
+                                "r2": {"dest_link": {"r1": {}}},
+                                "r3": {"dest_link": {"r1": {}}}
+                            }
+                        }
+                    },
+                    "ipv6": {
+                        "unicast": {
+                            "neighbor": {
+                                "r2": {"dest_link": {"r1": {}}},
+                                "r3": {"dest_link": {"r1": {}}}
                             }
                         }
                     }
         },
         "r2": {
             "links": {
-                "lo": {
-                    "ipv4": "auto",
-                    "ipv6": "auto",
-                    "type": "loopback"
-                },
-                "r1": {
-                    "ipv4": "auto",
-                    "ipv6": "auto"
-                },
-                "r3": {
-                    "ipv4": "auto",
-                    "ipv6": "auto"
-                }
+                "lo": {"ipv4": "auto", "ipv6": "auto", "type": "loopback"},
+                "r1": {"ipv4": "auto", "ipv6": "auto"},
+                "r3": {"ipv4": "auto", "ipv6": "auto"}
             },
             "bgp": {
                 "local_as": "100",
                     "ipv4": {
                         "unicast": {
                             "neighbor": {
-                                "r1": {
-                                    "dest_link": {
-                                        "r2": {}
-                                    }
-                                },
-                                "r3": {
-                                    "dest_link": {
-                                        "r2": {}
-                                    }
-                                }
+                                "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"
-                },
-                "r1": {
-                    "ipv4": "auto",
-                    "ipv6": "auto"
-                },
-                "r2": {
-                    "ipv4": "auto",
-                    "ipv6": "auto"
-                },
-                "r4": {
-                    "ipv4": "auto",
-                    "ipv6": "auto"
-                }
+                "lo": {"ipv4": "auto", "ipv6": "auto", "type": "loopback"},
+                "r1": {"ipv4": "auto", "ipv6": "auto"},
+                "r2": {"ipv4": "auto", "ipv6": "auto"},
+                "r4": {"ipv4": "auto", "ipv6": "auto"}
             },
             "bgp": {
                 "local_as": "100",
                     "ipv4": {
                         "unicast": {
                             "neighbor": {
-                                "r1": {
-                                    "dest_link": {
-                                        "r3": {}
-                                    }
-                                },
-                                "r2": {
-                                    "dest_link": {
-                                        "r3": {}
-                                    }
-                                },
-                                "r4": {
-                                    "dest_link": {
-                                        "r3": {}
-                                    }
-                                }
+                                "r1": {"dest_link": {"r3": {}}},
+                                "r2": {"dest_link": {"r3": {}}},
+                                "r4": {"dest_link": {"r3": {}}}
+                            }
+                        }
+                    },
+                    "ipv6": {
+                        "unicast": {
+                            "neighbor": {
+                                "r1": {"dest_link": {"r3": {}}},
+                                "r2": {"dest_link": {"r3": {}}},
+                                "r4": {"dest_link": {"r3": {}}}
                             }
                         }
                     }
         },
         "r4": {
             "links": {
-                "lo": {
-                    "ipv4": "auto",
-                    "ipv6": "auto",
-                    "type": "loopback"
-                },
-                "r3": {
-                    "ipv4": "auto",
-                    "ipv6": "auto"
-                }
+                "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": {}
-                                    }
-                                }
-                            }
-                        }
+                        "unicast": {"neighbor": {"r3": {"dest_link": {"r4": {}}}}}
+                    },
+                    "ipv6": {
+                        "unicast": {"neighbor": {"r3": {"dest_link": {"r4": {}}}}}
                     }
                 }
             }
index 3441d68731d6188e4393669b7a73fdff479d715f..69e050caedf17fee4c39b6621e5417306f144a9e 100755 (executable)
@@ -37,6 +37,8 @@ Test steps
 - Verify clear bgp
 - Test bgp convergence with loopback interface
 - Test advertise network using network command
+- Verify routes not installed in zebra when /32 routes received
+   with loopback BGP session subnet
 """
 
 import os
@@ -59,6 +61,7 @@ from lib.topogen import Topogen, get_topogen
 from mininet.topo import Topo
 
 from lib.common_config import (
+    step,
     start_topology,
     write_test_header,
     write_test_footer,
@@ -66,6 +69,13 @@ from lib.common_config import (
     create_static_routes,
     verify_rib,
     verify_admin_distance_for_static_routes,
+    check_address_types,
+    apply_raw_config,
+    addKernelRoute,
+    verify_fib_routes,
+    create_prefix_lists,
+    create_route_maps,
+    verify_bgp_community,
 )
 from lib.topolog import logger
 from lib.bgp import (
@@ -76,6 +86,7 @@ from lib.bgp import (
     verify_as_numbers,
     clear_bgp_and_verify,
     verify_bgp_timers_and_functionality,
+    verify_bgp_rib,
 )
 from lib.topojson import build_topo_from_json, build_config_from_json
 
@@ -90,6 +101,18 @@ except IOError:
 # Global Variable
 KEEPALIVETIMER = 2
 HOLDDOWNTIMER = 6
+r1_ipv4_loopback = "1.0.1.0/24"
+r2_ipv4_loopback = "1.0.2.0/24"
+r3_ipv4_loopback = "1.0.3.0/24"
+r4_ipv4_loopback = "1.0.4.0/24"
+r1_ipv6_loopback = "2001:db8:f::1:0/120"
+r2_ipv6_loopback = "2001:db8:f::2:0/120"
+r3_ipv6_loopback = "2001:db8:f::3:0/120"
+r4_ipv6_loopback = "2001:db8:f::4:0/120"
+NETWORK = {
+    "ipv4": ["100.1.1.1/32", "100.1.1.2/32"],
+    "ipv6": ["100::1/128", "100::2/128"],
+}
 
 
 class CreateTopo(Topo):
@@ -131,7 +154,9 @@ def setup_module(mod):
     # Creating configuration from JSON
     build_config_from_json(tgen, topo)
 
+    global ADDR_TYPES
     global BGP_CONVERGENCE
+    ADDR_TYPES = check_address_types()
     BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo)
     assert BGP_CONVERGENCE is True, "setup_module :Failed \n Error: {}".format(
         BGP_CONVERGENCE
@@ -522,6 +547,243 @@ def test_clear_bgp_and_verify(request):
     write_test_footer(tc_name)
 
 
+def test_BGP_attributes_with_vrf_default_keyword_p0(request):
+    """
+    TC_9:
+    Verify BGP functionality for default vrf with
+    "vrf default" keyword.
+    """
+
+    tc_name = request.node.name
+    write_test_header(tc_name)
+    tgen = get_topogen()
+
+    if tgen.routers_have_failure():
+        pytest.skip(tgen.errors)
+
+    #reset_config_on_routers(tgen)
+
+    step("Configure static routes and redistribute in BGP on R3")
+    for addr_type in ADDR_TYPES:
+        input_dict = {
+            "r3": {
+                "static_routes": [
+                    {
+                        "network": NETWORK[addr_type][0],
+                        "no_of_ip": 4,
+                        "next_hop": "Null0",
+                    }
+                ]
+            }
+        }
+
+        result = create_static_routes(tgen, input_dict)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    input_dict_2 = {
+        "r3": {
+            "bgp": {
+                "address_family": {
+                    "ipv4": {"unicast": {"redistribute": [{"redist_type": "static"}]}},
+                    "ipv6": {"unicast": {"redistribute": [{"redist_type": "static"}]}},
+                }
+            }
+        }
+    }
+    result = create_router_bgp(tgen, topo, input_dict_2)
+    assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+    step(
+        "Create a route-map to match a specific prefix and modify"
+        "BGP attributes for matched prefix"
+    )
+    input_dict_2 = {
+        "r3": {
+            "prefix_lists": {
+                "ipv4": {
+                    "ABC": [
+                        {
+                            "seqid": 10,
+                            "action": "permit",
+                            "network": NETWORK["ipv4"][0],
+                        }
+                    ]
+                },
+                "ipv6": {
+                    "XYZ": [
+                        {
+                            "seqid": 100,
+                            "action": "permit",
+                            "network": NETWORK["ipv6"][0],
+                        }
+                    ]
+                },
+            }
+        }
+    }
+    result = create_prefix_lists(tgen, input_dict_2)
+    assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+    for addr_type in ADDR_TYPES:
+        if addr_type == "ipv4":
+            pf_list = "ABC"
+        else:
+            pf_list = "XYZ"
+
+        input_dict_6 = {
+            "r3": {
+                "route_maps": {
+                    "BGP_ATTR_{}".format(addr_type): [
+                        {
+                            "action": "permit",
+                            "seq_id": 10,
+                            "match": {addr_type: {"prefix_lists": pf_list}},
+                            "set": {
+                                "aspath": {"as_num": 500, "as_action": "prepend"},
+                                "localpref": 500,
+                                "origin": "egp",
+                                "community": {"num": "500:500", "action": "additive"},
+                                "large_community": {
+                                    "num": "500:500:500",
+                                    "action": "additive",
+                                },
+                            },
+                        },
+                        {"action": "permit", "seq_id": 20},
+                    ]
+                },
+                "BGP_ATTR_{}".format(addr_type): [
+                    {
+                        "action": "permit",
+                        "seq_id": 100,
+                        "match": {addr_type: {"prefix_lists": pf_list}},
+                        "set": {
+                            "aspath": {"as_num": 500, "as_action": "prepend"},
+                            "localpref": 500,
+                            "origin": "egp",
+                            "community": {"num": "500:500", "action": "additive"},
+                            "large_community": {
+                                "num": "500:500:500",
+                                "action": "additive",
+                            },
+                        },
+                    },
+                    {"action": "permit", "seq_id": 200},
+                ],
+            }
+        }
+
+        result = create_route_maps(tgen, input_dict_6)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step("Apply the route-map on R3 in outbound direction for peer R4")
+
+    input_dict_7 = {
+        "r3": {
+            "bgp": {
+                "address_family": {
+                    "ipv4": {
+                        "unicast": {
+                            "neighbor": {
+                                "r4": {
+                                    "dest_link": {
+                                        "r3": {
+                                            "route_maps": [
+                                                {
+                                                    "name": "BGP_ATTR_ipv4",
+                                                    "direction": "out",
+                                                }
+                                            ]
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    },
+                    "ipv6": {
+                        "unicast": {
+                            "neighbor": {
+                                "r4": {
+                                    "dest_link": {
+                                        "r3": {
+                                            "route_maps": [
+                                                {
+                                                    "name": "BGP_ATTR_ipv6",
+                                                    "direction": "out",
+                                                }
+                                            ]
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    },
+                }
+            }
+        }
+    }
+
+    result = create_router_bgp(tgen, topo, input_dict_7)
+    assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+    step(
+        "verify modified attributes for specific prefix with 'vrf default'"
+        "keyword on R4"
+    )
+    for addr_type in ADDR_TYPES:
+        dut = "r4"
+        input_dict = {
+            "r3": {
+                "static_routes": [
+                    {
+                        "network": NETWORK[addr_type][0],
+                        "vrf": "default",
+                        "largeCommunity": "500:500:500",
+                    }
+                ]
+            }
+        }
+
+        result = verify_bgp_rib(tgen, addr_type, dut, input_dict)
+        assert result is True, "Testcase  : Failed \n Error: {}".format(tc_name, result)
+        result = verify_rib(tgen, addr_type, dut, input_dict)
+        assert result is True, "Testcase  : Failed \n Error: {}".format(tc_name, result)
+
+    for addr_type in ADDR_TYPES:
+        dut = "r4"
+        input_dict = {
+            "r3": {
+                "static_routes": [
+                    {
+                        "network": NETWORK[addr_type][0],
+                        "vrf": "default",
+                        "community": "500:500",
+                    }
+                ]
+            }
+        }
+
+        result = verify_bgp_rib(tgen, addr_type, dut, input_dict)
+        assert result is True, "Testcase  : Failed \n Error: {}".format(tc_name, result)
+        result = verify_rib(tgen, addr_type, dut, input_dict)
+        assert result is True, "Testcase  : Failed \n Error: {}".format(tc_name, result)
+
+        input_dict_4 = {"largeCommunity": "500:500:500", "community": "500:500"}
+
+        result = verify_bgp_community(
+            tgen, addr_type, dut, [NETWORK[addr_type][0]], input_dict_4
+        )
+        assert result is True, "Test case {} : Should fail \n Error: {}".format(
+            tc_name, result
+        )
+
+    write_test_footer(tc_name)
+
+
 def test_bgp_with_loopback_interface(request):
     """
     Test BGP with loopback interface
@@ -588,6 +850,298 @@ def test_bgp_with_loopback_interface(request):
     write_test_footer(tc_name)
 
 
+def test_bgp_with_loopback_with_same_subnet_p1(request):
+    """
+    Verify routes not installed in zebra when /32 routes received
+    with loopback BGP session subnet
+    """
+
+    tgen = get_topogen()
+    if BGP_CONVERGENCE is not True:
+        pytest.skip("skipped because of BGP Convergence failure")
+
+    # test case name
+    tc_name = request.node.name
+    write_test_header(tc_name)
+
+    # Creating configuration from JSON
+    reset_config_on_routers(tgen)
+    step("Delete BGP seesion created initially")
+    input_dict_r1 = {
+        "r1": {"bgp": {"delete": True}},
+        "r2": {"bgp": {"delete": True}},
+        "r3": {"bgp": {"delete": True}},
+        "r4": {"bgp": {"delete": True}},
+    }
+    result = create_router_bgp(tgen, topo, input_dict_r1)
+    assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+    step("Create BGP session over loop address")
+    topo_modify = deepcopy(topo)
+
+    for routerN in sorted(topo["routers"].keys()):
+        for addr_type in ADDR_TYPES:
+            for bgp_neighbor in topo_modify["routers"][routerN]["bgp"][
+                "address_family"
+            ][addr_type]["unicast"]["neighbor"].keys():
+
+                # Adding ['source_link'] = 'lo' key:value pair
+                topo_modify["routers"][routerN]["bgp"]["address_family"][addr_type][
+                    "unicast"
+                ]["neighbor"][bgp_neighbor]["dest_link"] = {
+                    "lo": {"source_link": "lo", "ebgp_multihop": 2}
+                }
+
+    result = create_router_bgp(tgen, topo_modify["routers"])
+    assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+    step("Disable IPv6 BGP nbr from ipv4 address family")
+    raw_config = {
+        "r1": {
+            "raw_config": [
+                "router bgp {}".format(topo["routers"]["r1"]["bgp"]["local_as"]),
+                "address-family ipv4 unicast",
+                "no neighbor {} activate".format(
+                    topo["routers"]["r2"]["links"]["lo"]["ipv6"].split("/")[0]
+                ),
+                "no neighbor {} activate".format(
+                    topo["routers"]["r3"]["links"]["lo"]["ipv6"].split("/")[0]
+                ),
+            ]
+        },
+        "r2": {
+            "raw_config": [
+                "router bgp {}".format(topo["routers"]["r2"]["bgp"]["local_as"]),
+                "address-family ipv4 unicast",
+                "no neighbor {} activate".format(
+                    topo["routers"]["r1"]["links"]["lo"]["ipv6"].split("/")[0]
+                ),
+                "no neighbor {} activate".format(
+                    topo["routers"]["r3"]["links"]["lo"]["ipv6"].split("/")[0]
+                ),
+            ]
+        },
+        "r3": {
+            "raw_config": [
+                "router bgp {}".format(topo["routers"]["r3"]["bgp"]["local_as"]),
+                "address-family ipv4 unicast",
+                "no neighbor {} activate".format(
+                    topo["routers"]["r1"]["links"]["lo"]["ipv6"].split("/")[0]
+                ),
+                "no neighbor {} activate".format(
+                    topo["routers"]["r2"]["links"]["lo"]["ipv6"].split("/")[0]
+                ),
+                "no neighbor {} activate".format(
+                    topo["routers"]["r4"]["links"]["lo"]["ipv6"].split("/")[0]
+                ),
+            ]
+        },
+        "r4": {
+            "raw_config": [
+                "router bgp {}".format(topo["routers"]["r4"]["bgp"]["local_as"]),
+                "address-family ipv4 unicast",
+                "no neighbor {} activate".format(
+                    topo["routers"]["r3"]["links"]["lo"]["ipv6"].split("/")[0]
+                ),
+            ]
+        },
+    }
+
+    step("Configure kernel routes")
+    result = apply_raw_config(tgen, raw_config)
+    assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+    r1_ipv4_lo = topo["routers"]["r1"]["links"]["lo"]["ipv4"]
+    r1_ipv6_lo = topo["routers"]["r1"]["links"]["lo"]["ipv6"]
+    r2_ipv4_lo = topo["routers"]["r2"]["links"]["lo"]["ipv4"]
+    r2_ipv6_lo = topo["routers"]["r2"]["links"]["lo"]["ipv6"]
+    r3_ipv4_lo = topo["routers"]["r3"]["links"]["lo"]["ipv4"]
+    r3_ipv6_lo = topo["routers"]["r3"]["links"]["lo"]["ipv6"]
+    r4_ipv4_lo = topo["routers"]["r4"]["links"]["lo"]["ipv4"]
+    r4_ipv6_lo = topo["routers"]["r4"]["links"]["lo"]["ipv6"]
+
+    r1_r2 = topo["routers"]["r1"]["links"]["r2"]["ipv6"].split("/")[0]
+    r2_r1 = topo["routers"]["r2"]["links"]["r1"]["ipv6"].split("/")[0]
+    r1_r3 = topo["routers"]["r1"]["links"]["r3"]["ipv6"].split("/")[0]
+    r3_r1 = topo["routers"]["r3"]["links"]["r1"]["ipv6"].split("/")[0]
+    r2_r3 = topo["routers"]["r2"]["links"]["r3"]["ipv6"].split("/")[0]
+    r3_r2 = topo["routers"]["r3"]["links"]["r2"]["ipv6"].split("/")[0]
+    r3_r4 = topo["routers"]["r3"]["links"]["r4"]["ipv6"].split("/")[0]
+    r4_r3 = topo["routers"]["r4"]["links"]["r3"]["ipv6"].split("/")[0]
+
+    r1_r2_ipv4 = topo["routers"]["r1"]["links"]["r2"]["ipv4"].split("/")[0]
+    r2_r1_ipv4 = topo["routers"]["r2"]["links"]["r1"]["ipv4"].split("/")[0]
+    r1_r3_ipv4 = topo["routers"]["r1"]["links"]["r3"]["ipv4"].split("/")[0]
+    r3_r1_ipv4 = topo["routers"]["r3"]["links"]["r1"]["ipv4"].split("/")[0]
+    r2_r3_ipv4 = topo["routers"]["r2"]["links"]["r3"]["ipv4"].split("/")[0]
+    r3_r2_ipv4 = topo["routers"]["r3"]["links"]["r2"]["ipv4"].split("/")[0]
+    r3_r4_ipv4 = topo["routers"]["r3"]["links"]["r4"]["ipv4"].split("/")[0]
+    r4_r3_ipv4 = topo["routers"]["r4"]["links"]["r3"]["ipv4"].split("/")[0]
+
+    r1_r2_intf = topo["routers"]["r1"]["links"]["r2"]["interface"]
+    r2_r1_intf = topo["routers"]["r2"]["links"]["r1"]["interface"]
+    r1_r3_intf = topo["routers"]["r1"]["links"]["r3"]["interface"]
+    r3_r1_intf = topo["routers"]["r3"]["links"]["r1"]["interface"]
+    r2_r3_intf = topo["routers"]["r2"]["links"]["r3"]["interface"]
+    r3_r2_intf = topo["routers"]["r3"]["links"]["r2"]["interface"]
+    r3_r4_intf = topo["routers"]["r3"]["links"]["r4"]["interface"]
+    r4_r3_intf = topo["routers"]["r4"]["links"]["r3"]["interface"]
+
+    ipv4_list = [
+        ("r1", r1_r2_intf, r2_ipv4_loopback),
+        ("r1", r1_r3_intf, r3_ipv4_loopback),
+        ("r2", r2_r1_intf, r1_ipv4_loopback),
+        ("r2", r2_r3_intf, r3_ipv4_loopback),
+        ("r3", r3_r1_intf, r1_ipv4_loopback),
+        ("r3", r3_r2_intf, r2_ipv4_loopback),
+        ("r3", r3_r4_intf, r4_ipv4_loopback),
+        ("r4", r4_r3_intf, r3_ipv4_loopback),
+    ]
+
+    ipv6_list = [
+        ("r1", r1_r2_intf, r2_ipv6_loopback, r2_r1),
+        ("r1", r1_r3_intf, r3_ipv6_loopback, r3_r1),
+        ("r2", r2_r1_intf, r1_ipv6_loopback, r1_r2),
+        ("r2", r2_r3_intf, r3_ipv6_loopback, r3_r2),
+        ("r3", r3_r1_intf, r1_ipv6_loopback, r1_r3),
+        ("r3", r3_r2_intf, r2_ipv6_loopback, r2_r3),
+        ("r3", r3_r4_intf, r4_ipv6_loopback, r4_r3),
+        ("r4", r4_r3_intf, r3_ipv6_loopback, r3_r4),
+    ]
+
+    for dut, intf, loop_addr in ipv4_list:
+        result = addKernelRoute(tgen, dut, intf, loop_addr)
+        assert result is True, "Testcase {}:Failed \n Error: {}".format(tc_name, result)
+
+    for dut, intf, loop_addr, next_hop in ipv6_list:
+        result = addKernelRoute(tgen, dut, intf, loop_addr, next_hop)
+        assert result is True, "Testcase {}:Failed \n Error: {}".format(tc_name, result)
+
+    step("Configure static routes")
+
+    input_dict = {
+        "r1": {
+            "static_routes": [
+                {"network": r2_ipv4_loopback, "next_hop": r2_r1_ipv4},
+                {"network": r3_ipv4_loopback, "next_hop": r3_r1_ipv4},
+                {"network": r2_ipv6_loopback, "next_hop": r2_r1},
+                {"network": r3_ipv6_loopback, "next_hop": r3_r1},
+            ]
+        },
+        "r2": {
+            "static_routes": [
+                {"network": r1_ipv4_loopback, "next_hop": r1_r2_ipv4},
+                {"network": r3_ipv4_loopback, "next_hop": r3_r2_ipv4},
+                {"network": r1_ipv6_loopback, "next_hop": r1_r2},
+                {"network": r3_ipv6_loopback, "next_hop": r3_r2},
+            ]
+        },
+        "r3": {
+            "static_routes": [
+                {"network": r1_ipv4_loopback, "next_hop": r1_r3_ipv4},
+                {"network": r2_ipv4_loopback, "next_hop": r2_r3_ipv4},
+                {"network": r4_ipv4_loopback, "next_hop": r4_r3_ipv4},
+                {"network": r1_ipv6_loopback, "next_hop": r1_r3},
+                {"network": r2_ipv6_loopback, "next_hop": r2_r3},
+                {"network": r4_ipv6_loopback, "next_hop": r4_r3},
+            ]
+        },
+        "r4": {
+            "static_routes": [
+                {"network": r3_ipv4_loopback, "next_hop": r3_r4_ipv4},
+                {"network": r3_ipv6_loopback, "next_hop": r3_r4},
+            ]
+        },
+    }
+    result = create_static_routes(tgen, input_dict)
+    assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+    step("Verify BGP session convergence")
+
+    result = verify_bgp_convergence(tgen, topo_modify)
+    assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+    step("Configure redistribute connected on R2 and R4")
+    input_dict_1 = {
+        "r2": {
+            "bgp": {
+                "address_family": {
+                    "ipv4": {
+                        "unicast": {"redistribute": [{"redist_type": "connected"}]}
+                    },
+                    "ipv6": {
+                        "unicast": {"redistribute": [{"redist_type": "connected"}]}
+                    },
+                }
+            }
+        },
+        "r4": {
+            "bgp": {
+                "address_family": {
+                    "ipv4": {
+                        "unicast": {"redistribute": [{"redist_type": "connected"}]}
+                    },
+                    "ipv6": {
+                        "unicast": {"redistribute": [{"redist_type": "connected"}]}
+                    },
+                }
+            }
+        },
+    }
+
+    result = create_router_bgp(tgen, topo, input_dict_1)
+    assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+    step("Verify Ipv4 and Ipv6 network installed in R1 RIB but not in FIB")
+    input_dict_r1 = {
+        "r1": {
+            "static_routes": [
+                {"network": "1.0.2.17/32"},
+                {"network": "2001:db8:f::2:17/128"},
+            ]
+        }
+    }
+
+    dut = "r1"
+    protocol = "bgp"
+    for addr_type in ADDR_TYPES:
+        result = verify_rib(tgen, addr_type, dut, input_dict_r1, protocol=protocol)
+        assert result is True, "Testcase {} :Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        result = verify_fib_routes(tgen, addr_type, dut, input_dict_r1, expected=False)
+        assert result is not True, "Testcase {} : Failed \n"
+        "Expected behavior: routes should not present in fib \n"
+        "Error: {}".format(tc_name, result)
+
+    step("Verify Ipv4 and Ipv6 network installed in r3 RIB but not in FIB")
+    input_dict_r3 = {
+        "r3": {
+            "static_routes": [
+                {"network": "1.0.4.17/32"},
+                {"network": "2001:db8:f::4:17/128"},
+            ]
+        }
+    }
+    dut = "r3"
+    protocol = "bgp"
+    for addr_type in ADDR_TYPES:
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_r3, protocol=protocol, fib=None
+        )
+        assert result is True, "Testcase {} :Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        result = verify_fib_routes(tgen, addr_type, dut, input_dict_r1, expected=False)
+        assert result is not True, "Testcase {} : Failed \n"
+        "Expected behavior: routes should not present in fib \n"
+        "Error: {}".format(tc_name, result)
+
+    write_test_footer(tc_name)
+
+
 if __name__ == "__main__":
     args = ["-s"] + sys.argv[1:]
     sys.exit(pytest.main(args))
index 7b1eead944f9d1f1e404e9a88bef37d4955235dd..316d4cf414b3c5932fe66bfd99da5cb55d39edb2 100644 (file)
@@ -46,6 +46,7 @@ from lib.common_config import (
 LOGDIR = "/tmp/topotests/"
 TMPDIR = None
 
+
 def create_router_bgp(tgen, topo, input_dict=None, build=False, load_config=True):
     """
     API to configure bgp on router
@@ -1219,11 +1220,17 @@ def verify_bgp_convergence(tgen, topo, dut=None):
                                     no_of_peer += 1
 
                     if no_of_peer == total_peer:
-                        logger.info("[DUT: %s] VRF: %s, BGP is Converged for %s address-family",
-                                    router, vrf, addr_type)
+                        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))
+                        errormsg = (
+                            "[DUT: %s] VRF: %s, BGP is not converged for %s address-family"
+                            % (router, vrf, addr_type)
+                        )
                         return errormsg
 
     logger.debug("Exiting API: verify_bgp_convergence()")
@@ -2553,10 +2560,19 @@ def verify_bgp_rib(tgen, addr_type, dut, input_dict, next_hop=None, aspath=None)
                     missing_routes = []
                     st_found = False
                     nh_found = False
+
                     vrf = static_route.setdefault("vrf", None)
+                    community = static_route.setdefault("community", None)
+                    largeCommunity = static_route.setdefault("largeCommunity", None)
+
                     if vrf:
                         cmd = "{} vrf {} {}".format(command, vrf, addr_type)
 
+                        if community:
+                            cmd = "{} community {}".format(cmd, community)
+
+                        if largeCommunity:
+                            cmd = "{} large-community {}".format(cmd, largeCommunity)
                     else:
                         cmd = "{} {}".format(command, addr_type)
 
index e4d72ea2d7762329f2edf710650d0b6d0e6c1ae8..468af7dc5364700a9d10ad20eefb31a425fd02b6 100644 (file)
@@ -2352,7 +2352,9 @@ def configure_brctl(tgen, topo, input_dict):
                 ):
 
                     ip_cmd_list = []
-                    cmd = "ip link add name {} type bridge stp_state {}".format(brctl_name, stp)
+                    cmd = "ip link add name {} type bridge stp_state {}".format(
+                        brctl_name, stp
+                    )
 
                     logger.info("[DUT: %s]: Running command: %s", dut, cmd)
                     rnode.run(cmd)
@@ -2821,6 +2823,260 @@ def verify_rib(
     return True
 
 
+@retry(attempts=5, wait=2, return_is_str=True, initial_wait=2)
+def verify_fib_routes(tgen, addr_type, dut, input_dict, next_hop=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
+    advertise_networks_using_network_command() and will verify next_hop and
+    each prefix/routes is present in "show ip/ipv6 fib json"
+    command o/p.
+
+    Parameters
+    ----------
+    * `tgen` : topogen object
+    * `addr_type` : ip type, ipv4/ipv6
+    * `dut`: Device Under Test, for which user wants to test the data
+    * `input_dict` : input dict, has details of static routes
+    * `next_hop`[optional]: next_hop which needs to be verified,
+                           default: static
+
+    Usage
+    -----
+    input_routes_r1 = {
+        "r1": {
+            "static_routes": [{
+                "network": ["1.1.1.1/32],
+                "next_hop": "Null0",
+                "vrf": "RED"
+            }]
+        }
+    }
+    result = result = verify_fib_routes(tgen, "ipv4, "r1", input_routes_r1)
+
+    Returns
+    -------
+    errormsg(str) or True
+    """
+
+    logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name))
+
+    router_list = tgen.routers()
+    for routerInput in input_dict.keys():
+        for router, rnode in router_list.iteritems():
+            if router != dut:
+                continue
+
+            logger.info("Checking router %s FIB routes:", router)
+
+            # Verifying RIB routes
+            if addr_type == "ipv4":
+                command = "show ip fib"
+            else:
+                command = "show ipv6 fib"
+
+            found_routes = []
+            missing_routes = []
+
+            if "static_routes" in input_dict[routerInput]:
+                static_routes = input_dict[routerInput]["static_routes"]
+
+                for static_route in static_routes:
+                    if "vrf" in static_route and static_route["vrf"] is not None:
+
+                        logger.info(
+                            "[DUT: {}]: Verifying routes for VRF:"
+                            " {}".format(router, static_route["vrf"])
+                        )
+
+                        cmd = "{} vrf {}".format(command, static_route["vrf"])
+
+                    else:
+                        cmd = "{}".format(command)
+
+                    cmd = "{} json".format(cmd)
+
+                    rib_routes_json = run_frr_cmd(rnode, cmd, isjson=True)
+
+                    # Verifying output dictionary rib_routes_json is not empty
+                    if bool(rib_routes_json) is False:
+                        errormsg = "[DUT: {}]: No route found in fib".format(router)
+                        return errormsg
+
+                    network = static_route["network"]
+                    if "no_of_ip" in static_route:
+                        no_of_ip = static_route["no_of_ip"]
+                    else:
+                        no_of_ip = 1
+
+                    # Generating IPs for verification
+                    ip_list = generate_ips(network, no_of_ip)
+                    st_found = False
+                    nh_found = False
+
+                    for st_rt in ip_list:
+                        st_rt = str(ipaddress.ip_network(unicode(st_rt)))
+
+                        _addr_type = validate_ip_address(st_rt)
+                        if _addr_type != addr_type:
+                            continue
+
+                        if st_rt in rib_routes_json:
+                            st_found = True
+                            found_routes.append(st_rt)
+
+                            if next_hop:
+                                if type(next_hop) is not list:
+                                    next_hop = [next_hop]
+
+                                count = 0
+                                for nh in next_hop:
+                                    for nh_dict in rib_routes_json[st_rt][0][
+                                        "nexthops"
+                                    ]:
+                                        if nh_dict["ip"] != nh:
+                                            continue
+                                        else:
+                                            count += 1
+
+                                if count == len(next_hop):
+                                    nh_found = True
+                                else:
+                                    missing_routes.append(st_rt)
+                                    errormsg = (
+                                        "Nexthop {} is Missing"
+                                        " for route {} in "
+                                        "RIB of router {}\n".format(
+                                            next_hop, st_rt, dut
+                                        )
+                                    )
+                                    return errormsg
+
+                        else:
+                            missing_routes.append(st_rt)
+
+                if len(missing_routes) > 0:
+                    errormsg = "[DUT: {}]: Missing route in FIB:" " {}".format(
+                        dut, missing_routes
+                    )
+                    return errormsg
+
+                if nh_found:
+                    logger.info(
+                        "Found next_hop {} for all routes in RIB"
+                        " of router {}\n".format(next_hop, dut)
+                    )
+
+                if found_routes:
+                    logger.info(
+                        "[DUT: %s]: Verified routes in FIB, found" " routes are: %s\n",
+                        dut,
+                        found_routes,
+                    )
+
+                continue
+
+            if "bgp" in input_dict[routerInput]:
+                if (
+                    "advertise_networks"
+                    not in input_dict[routerInput]["bgp"]["address_family"][addr_type][
+                        "unicast"
+                    ]
+                ):
+                    continue
+
+                found_routes = []
+                missing_routes = []
+                advertise_network = input_dict[routerInput]["bgp"]["address_family"][
+                    addr_type
+                ]["unicast"]["advertise_networks"]
+
+                # Continue if there are no network advertise
+                if len(advertise_network) == 0:
+                    continue
+
+                for advertise_network_dict in advertise_network:
+                    if "vrf" in advertise_network_dict:
+                        cmd = "{} vrf {} json".format(command, static_route["vrf"])
+                    else:
+                        cmd = "{} json".format(command)
+
+                rib_routes_json = run_frr_cmd(rnode, cmd, isjson=True)
+
+                # Verifying output dictionary rib_routes_json is not empty
+                if bool(rib_routes_json) is False:
+                    errormsg = "No route found in rib of router {}..".format(router)
+                    return errormsg
+
+                start_ip = advertise_network_dict["network"]
+                if "no_of_network" in advertise_network_dict:
+                    no_of_network = advertise_network_dict["no_of_network"]
+                else:
+                    no_of_network = 1
+
+                # Generating IPs for verification
+                ip_list = generate_ips(start_ip, no_of_network)
+                st_found = False
+                nh_found = False
+
+                for st_rt in ip_list:
+                    st_rt = str(ipaddress.ip_network(unicode(st_rt)))
+
+                    _addr_type = validate_ip_address(st_rt)
+                    if _addr_type != addr_type:
+                        continue
+
+                    if st_rt in rib_routes_json:
+                        st_found = True
+                        found_routes.append(st_rt)
+
+                        if next_hop:
+                            if type(next_hop) is not list:
+                                next_hop = [next_hop]
+
+                            count = 0
+                            for nh in next_hop:
+                                for nh_dict in rib_routes_json[st_rt][0]["nexthops"]:
+                                    if nh_dict["ip"] != nh:
+                                        continue
+                                    else:
+                                        count += 1
+
+                            if count == len(next_hop):
+                                nh_found = True
+                            else:
+                                missing_routes.append(st_rt)
+                                errormsg = (
+                                    "Nexthop {} is Missing"
+                                    " for route {} in "
+                                    "RIB of router {}\n".format(next_hop, st_rt, dut)
+                                )
+                                return errormsg
+                    else:
+                        missing_routes.append(st_rt)
+
+                if len(missing_routes) > 0:
+                    errormsg = "[DUT: {}]: Missing route in FIB: " "{} \n".format(
+                        dut, missing_routes
+                    )
+                    return errormsg
+
+                if nh_found:
+                    logger.info(
+                        "Found next_hop {} for all routes in RIB"
+                        " of router {}\n".format(next_hop, dut)
+                    )
+
+                if found_routes:
+                    logger.info(
+                        "[DUT: {}]: Verified routes FIB"
+                        ", found routes  are: {}\n".format(dut, found_routes)
+                    )
+
+    logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
+    return True
+
+
 def verify_admin_distance_for_static_routes(tgen, input_dict):
     """
     API to verify admin distance for static routes as defined in input_dict/