summaryrefslogtreecommitdiff
path: root/tests/topotests/lib/common_config.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/topotests/lib/common_config.py')
-rw-r--r--tests/topotests/lib/common_config.py592
1 files changed, 407 insertions, 185 deletions
diff --git a/tests/topotests/lib/common_config.py b/tests/topotests/lib/common_config.py
index 6a02e50127..81c7ba4d5c 100644
--- a/tests/topotests/lib/common_config.py
+++ b/tests/topotests/lib/common_config.py
@@ -22,20 +22,20 @@ from collections import OrderedDict
from datetime import datetime, timedelta
from time import sleep
from copy import deepcopy
-from subprocess import call
-from subprocess import STDOUT as SUB_STDOUT
-from subprocess import PIPE as SUB_PIPE
-from subprocess import Popen
from functools import wraps
from re import search as re_search
from tempfile import mkdtemp
+import json
+import logging
import os
import sys
import traceback
import socket
+import subprocess
import ipaddress
import platform
+import pytest
try:
# Imports from python2
@@ -235,14 +235,12 @@ def run_frr_cmd(rnode, cmd, isjson=False):
if True:
if isjson:
- logger.debug(ret_data)
- print_data = rnode.vtysh_cmd(cmd.rstrip("json"), isjson=False)
+ print_data = json.dumps(ret_data)
else:
print_data = ret_data
-
logger.info(
- "Output for command [ %s] on router %s:\n%s",
- cmd.rstrip("json"),
+ "Output for command [%s] on router %s:\n%s",
+ cmd,
rnode.name,
print_data,
)
@@ -278,7 +276,8 @@ def apply_raw_config(tgen, input_dict):
True or errormsg
"""
- result = True
+ rlist = []
+
for router_name in input_dict.keys():
config_cmd = input_dict[router_name]["raw_config"]
@@ -290,13 +289,14 @@ def apply_raw_config(tgen, input_dict):
for cmd in config_cmd:
cfg.write("{}\n".format(cmd))
- result = load_config_to_router(tgen, router_name)
+ rlist.append(router_name)
- return result
+ # Load config on all routers
+ return load_config_to_routers(tgen, rlist)
-def create_common_configuration(
- tgen, router, data, config_type=None, build=False, load_config=True
+def create_common_configurations(
+ tgen, config_dict, config_type=None, build=False, load_config=True
):
"""
API to create object of class FRRConfig and also create frr_json.conf
@@ -305,8 +305,8 @@ def create_common_configuration(
Parameters
----------
* `tgen`: tgen object
- * `data`: Configuration data saved in a list.
- * `router` : router id to be configured.
+ * `config_dict`: Configuration data saved in a dict of { router: config-list }
+ * `routers` : list of router id to be configured.
* `config_type` : Syntactic information while writing configuration. Should
be one of the value as mentioned in the config_map below.
* `build` : Only for initial setup phase this is set as True
@@ -316,8 +316,6 @@ def create_common_configuration(
"""
TMPDIR = os.path.join(LOGDIR, tgen.modname)
- fname = "{}/{}/{}".format(TMPDIR, router, FRRCFG_FILE)
-
config_map = OrderedDict(
{
"general_config": "! FRR General Config\n",
@@ -342,27 +340,55 @@ def create_common_configuration(
else:
mode = "w"
- try:
- frr_cfg_fd = open(fname, mode)
- if config_type:
- frr_cfg_fd.write(config_map[config_type])
- for line in data:
- frr_cfg_fd.write("{} \n".format(str(line)))
- frr_cfg_fd.write("\n")
-
- except IOError as err:
- logger.error(
- "Unable to open FRR Config File. error(%s): %s" % (err.errno, err.strerror)
- )
- return False
- finally:
- frr_cfg_fd.close()
+ routers = config_dict.keys()
+ for router in routers:
+ fname = "{}/{}/{}".format(TMPDIR, router, FRRCFG_FILE)
+ try:
+ frr_cfg_fd = open(fname, mode)
+ if config_type:
+ frr_cfg_fd.write(config_map[config_type])
+ for line in config_dict[router]:
+ frr_cfg_fd.write("{} \n".format(str(line)))
+ frr_cfg_fd.write("\n")
+
+ except IOError as err:
+ logger.error(
+ "Unable to open FRR Config '%s': %s" % (fname, str(err))
+ )
+ return False
+ finally:
+ frr_cfg_fd.close()
# If configuration applied from build, it will done at last
+ result = True
if not build and load_config:
- load_config_to_router(tgen, router)
+ result = load_config_to_routers(tgen, routers)
- return True
+ return result
+
+
+def create_common_configuration(
+ tgen, router, data, config_type=None, build=False, load_config=True
+):
+ """
+ API to create object of class FRRConfig and also create frr_json.conf
+ file. It will create interface and common configurations and save it to
+ frr_json.conf and load to router
+ Parameters
+ ----------
+ * `tgen`: tgen object
+ * `data`: Configuration data saved in a list.
+ * `router` : router id to be configured.
+ * `config_type` : Syntactic information while writing configuration. Should
+ be one of the value as mentioned in the config_map below.
+ * `build` : Only for initial setup phase this is set as True
+ Returns
+ -------
+ True or False
+ """
+ return create_common_configurations(
+ tgen, {router: data}, config_type, build, load_config
+ )
def kill_router_daemons(tgen, router, daemons, save_config=True):
@@ -470,110 +496,149 @@ def reset_config_on_routers(tgen, routerName=None):
logger.debug("Entering API: reset_config_on_routers")
+ # Trim the router list if needed
router_list = tgen.routers()
- for rname in ROUTER_LIST:
- if routerName and routerName != rname:
- continue
-
- router = router_list[rname]
- logger.info("Configuring router %s to initial test configuration", rname)
-
- cfg = router.run("vtysh -c 'show running'")
- fname = "{}/{}/frr.sav".format(TMPDIR, rname)
- dname = "{}/{}/delta.conf".format(TMPDIR, rname)
- f = open(fname, "w")
- for line in cfg.split("\n"):
- line = line.strip()
-
- if (
- line == "Building configuration..."
- or line == "Current configuration:"
- or not line
- ):
- continue
- f.write(line)
- f.write("\n")
-
- f.close()
- run_cfg_file = "{}/{}/frr.sav".format(TMPDIR, rname)
- init_cfg_file = "{}/{}/frr_json_initial.conf".format(TMPDIR, rname)
- command = "/usr/lib/frr/frr-reload.py --test --test-reset --input {} {} > {}".format(
- run_cfg_file, init_cfg_file, dname
+ if routerName:
+ if ((routerName not in ROUTER_LIST) or (routerName not in router_list)):
+ logger.debug("Exiting API: reset_config_on_routers: no routers")
+ return True
+ router_list = { routerName: router_list[routerName] }
+
+ delta_fmt = TMPDIR + "/{}/delta.conf"
+ init_cfg_fmt = TMPDIR + "/{}/frr_json_initial.conf"
+ run_cfg_fmt = TMPDIR + "/{}/frr.sav"
+
+ #
+ # Get all running configs in parallel
+ #
+ procs = {}
+ for rname in router_list:
+ logger.info("Fetching running config for router %s", rname)
+ procs[rname] = router_list[rname].popen(
+ ["/usr/bin/env", "vtysh", "-c", "show running-config no-header"],
+ stdin=None,
+ stdout=open(run_cfg_fmt.format(rname), "w"),
+ stderr=subprocess.PIPE,
)
- result = call(command, shell=True, stderr=SUB_STDOUT, stdout=SUB_PIPE)
-
- # Assert if command fail
- if result > 0:
- logger.error("Delta file creation failed. Command executed %s", command)
- with open(run_cfg_file, "r") as fd:
- logger.info(
- "Running configuration saved in %s is:\n%s", run_cfg_file, fd.read()
- )
- with open(init_cfg_file, "r") as fd:
- logger.info(
- "Test configuration saved in %s is:\n%s", init_cfg_file, fd.read()
- )
-
- err_cmd = ["/usr/bin/vtysh", "-m", "-f", run_cfg_file]
- result = Popen(err_cmd, stdout=SUB_PIPE, stderr=SUB_PIPE)
- output = result.communicate()
- for out_data in output:
- temp_data = out_data.decode("utf-8").lower()
- for out_err in ERROR_LIST:
- if out_err.lower() in temp_data:
- logger.error(
- "Found errors while validating data in" " %s", run_cfg_file
- )
- raise InvalidCLIError(out_data)
- raise InvalidCLIError("Unknown error in %s", output)
-
- delta = StringIO()
- with open(dname, "r") as f:
- delta.write(f.read())
-
- output = router.vtysh_multicmd(delta.getvalue(), pretty_output=False)
-
- delta.close()
- delta = StringIO()
- cfg = router.run("vtysh -c 'show running'")
- for line in cfg.split("\n"):
- line = line.strip()
- delta.write(line)
- delta.write("\n")
-
- # Router current configuration to log file or console if
- # "show_router_config" is defined in "pytest.ini"
- if show_router_config:
- logger.info("Configuration on router {} after reset:".format(rname))
- logger.info(delta.getvalue())
- delta.close()
+ for rname, p in procs.items():
+ _, error = p.communicate()
+ if p.returncode:
+ logger.error("Get running config for %s failed %d: %s", rname, p.returncode, error)
+ raise InvalidCLIError("vtysh show running error on {}: {}".format(rname, error))
+
+ #
+ # Get all delta's in parallel
+ #
+ procs = {}
+ for rname in router_list:
+ logger.info("Generating delta for router %s to new configuration", rname)
+ procs[rname] = subprocess.Popen(
+ [ "/usr/lib/frr/frr-reload.py",
+ "--test-reset",
+ "--input",
+ run_cfg_fmt.format(rname),
+ "--test",
+ init_cfg_fmt.format(rname) ],
+ stdin=None,
+ stdout=open(delta_fmt.format(rname), "w"),
+ stderr=subprocess.PIPE,
+ )
+ for rname, p in procs.items():
+ _, error = p.communicate()
+ if p.returncode:
+ logger.error("Delta file creation for %s failed %d: %s", rname, p.returncode, error)
+ raise InvalidCLIError("frr-reload error for {}: {}".format(rname, error))
+
+ #
+ # Apply all the deltas in parallel
+ #
+ procs = {}
+ for rname in router_list:
+ logger.info("Applying delta config on router %s", rname)
+
+ procs[rname] = router_list[rname].popen(
+ ["/usr/bin/env", "vtysh", "-f", delta_fmt.format(rname)],
+ stdin=None,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ )
+ for rname, p in procs.items():
+ output, _ = p.communicate()
+ vtysh_command = "vtysh -f {}".format(delta_fmt.format(rname))
+ if not p.returncode:
+ router_list[rname].logger.info(
+ '\nvtysh config apply => "{}"\nvtysh output <= "{}"'.format(vtysh_command, output)
+ )
+ else:
+ router_list[rname].logger.warning(
+ '\nvtysh config apply failed => "{}"\nvtysh output <= "{}"'.format(vtysh_command, output)
+ )
+ logger.error("Delta file apply for %s failed %d: %s", rname, p.returncode, output)
+
+ # We really need to enable this failure; however, currently frr-reload.py
+ # producing invalid "no" commands as it just preprends "no", but some of the
+ # command forms lack matching values (e.g., final values). Until frr-reload
+ # is fixed to handle this (or all the CLI no forms are adjusted) we can't
+ # fail tests.
+ # raise InvalidCLIError("frr-reload error for {}: {}".format(rname, output))
+
+ #
+ # Optionally log all new running config if "show_router_config" is defined in
+ # "pytest.ini"
+ #
+ if show_router_config:
+ procs = {}
+ for rname in router_list:
+ logger.info("Fetching running config for router %s", rname)
+ procs[rname] = router_list[rname].popen(
+ ["/usr/bin/env", "vtysh", "-c", "show running-config no-header"],
+ stdin=None,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ )
+ for rname, p in procs.items():
+ output, _ = p.communicate()
+ if p.returncode:
+ logger.warning("Get running config for %s failed %d: %s", rname, p.returncode, output)
+ else:
+ logger.info("Configuration on router %s after reset:\n%s", rname, output)
logger.debug("Exiting API: reset_config_on_routers")
return True
-def load_config_to_router(tgen, routerName, save_bkup=False):
+def load_config_to_routers(tgen, routers, save_bkup=False):
"""
- Loads configuration on router from the file FRRCFG_FILE.
+ Loads configuration on routers from the file FRRCFG_FILE.
Parameters
----------
* `tgen` : Topogen object
- * `routerName` : router for which configuration to be loaded
+ * `routers` : routers for which configuration is to be loaded
* `save_bkup` : If True, Saves snapshot of FRRCFG_FILE to FRRCFG_BKUP_FILE
+ Returns
+ -------
+ True or False
"""
- logger.debug("Entering API: load_config_to_router")
+ logger.debug("Entering API: load_config_to_routers")
- router_list = tgen.routers()
- for rname in ROUTER_LIST:
- if routerName and rname != routerName:
+ base_router_list = tgen.routers()
+ router_list = {}
+ for router in routers:
+ if (router not in ROUTER_LIST) or (router not in base_router_list):
continue
+ router_list[router] = base_router_list[router]
+ frr_cfg_file_fmt = TMPDIR + "/{}/" + FRRCFG_FILE
+ frr_cfg_bkup_fmt = TMPDIR + "/{}/" + FRRCFG_BKUP_FILE
+
+ procs = {}
+ for rname in router_list:
router = router_list[rname]
try:
- frr_cfg_file = "{}/{}/{}".format(TMPDIR, rname, FRRCFG_FILE)
- frr_cfg_bkup = "{}/{}/{}".format(TMPDIR, rname, FRRCFG_BKUP_FILE)
+ frr_cfg_file = frr_cfg_file_fmt.format(rname)
+ frr_cfg_bkup = frr_cfg_bkup_fmt.format(rname)
with open(frr_cfg_file, "r+") as cfg:
data = cfg.read()
logger.info(
@@ -583,31 +648,76 @@ def load_config_to_router(tgen, routerName, save_bkup=False):
if save_bkup:
with open(frr_cfg_bkup, "w") as bkup:
bkup.write(data)
-
- output = router.vtysh_multicmd(data, pretty_output=False)
- for out_err in ERROR_LIST:
- if out_err.lower() in output.lower():
- raise InvalidCLIError("%s" % output)
-
- cfg.truncate(0)
-
+ procs[rname] = router_list[rname].popen(
+ ["/usr/bin/env", "vtysh", "-f", frr_cfg_file],
+ stdin=None,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ )
except IOError as err:
- errormsg = (
- "Unable to open config File. error(%s):" " %s",
- (err.errno, err.strerror),
+ logging.error(
+ "Unable to open config File. error(%s): %s",
+ err.errno, err.strerror
)
- return errormsg
+ return False
+ except Exception as error:
+ logging.error("Unable to apply config on %s: %s", rname, str(error))
+ return False
+
+ errors = []
+ for rname, p in procs.items():
+ output, _ = p.communicate()
+ frr_cfg_file = frr_cfg_file_fmt.format(rname)
+ vtysh_command = "vtysh -f " + frr_cfg_file
+ if not p.returncode:
+ router_list[rname].logger.info(
+ '\nvtysh config apply => "{}"\nvtysh output <= "{}"'.format(vtysh_command, output)
+ )
+ else:
+ router_list[rname].logger.error(
+ '\nvtysh config apply failed => "{}"\nvtysh output <= "{}"'.format(vtysh_command, output)
+ )
+ logger.error("Config apply for %s failed %d: %s", rname, p.returncode, output)
+ # We can't thorw an exception here as we won't clear the config file.
+ errors.append(InvalidCLIError("load_config_to_routers error for {}: {}".format(rname, output)))
+
+ # Empty the config file or we append to it next time through.
+ with open(frr_cfg_file, "r+") as cfg:
+ cfg.truncate(0)
+
+ # Router current configuration to log file or console if
+ # "show_router_config" is defined in "pytest.ini"
+ if show_router_config:
+ procs = {}
+ for rname in router_list:
+ procs[rname] = router_list[rname].popen(
+ ["/usr/bin/env", "vtysh", "-c", "show running-config no-header"],
+ stdin=None,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ )
+ for rname, p in procs.items():
+ output, _ = p.communicate()
+ if p.returncode:
+ logger.warning("Get running config for %s failed %d: %s", rname, p.returncode, output)
+ else:
+ logger.info("New configuration for router %s:\n%s", rname,output)
- # Router current configuration to log file or console if
- # "show_router_config" is defined in "pytest.ini"
- if show_router_config:
- logger.info("New configuration for router {}:".format(rname))
- new_config = router.run("vtysh -c 'show running'")
- logger.info(new_config)
+ logger.debug("Exiting API: load_config_to_routers")
+ return not errors
- logger.debug("Exiting API: load_config_to_router")
- return True
+def load_config_to_router(tgen, routerName, save_bkup=False):
+ """
+ Loads configuration on router from the file FRRCFG_FILE.
+
+ Parameters
+ ----------
+ * `tgen` : Topogen object
+ * `routerName` : router for which configuration to be loaded
+ * `save_bkup` : If True, Saves snapshot of FRRCFG_FILE to FRRCFG_BKUP_FILE
+ """
+ return load_config_to_routers(tgen, [routerName], save_bkup)
def get_frr_ipv6_linklocal(tgen, router, intf=None, vrf=None):
@@ -707,8 +817,8 @@ def generate_support_bundle():
bundle_procs[rname] = tgen.net[rname].popen(
"/usr/lib/frr/generate_support_bundle.py",
stdin=None,
- stdout=SUB_PIPE,
- stderr=SUB_PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
)
for rname, rnode in router_list.items():
@@ -944,22 +1054,31 @@ def add_interfaces_to_vlan(tgen, input_dict):
for intf_dict in interfaces:
for interface, data in intf_dict.items():
# Adding interface to VLAN
- cmd = "vconfig add {} {}".format(interface, vlan)
+ vlan_intf = "{}.{}".format(interface, vlan)
+ cmd = "ip link add link {} name {} type vlan id {}".format(
+ interface,
+ vlan_intf,
+ vlan
+ )
logger.info("[DUT: %s]: Running command: %s", dut, cmd)
rnode.run(cmd)
- vlan_intf = "{}.{}".format(interface, vlan)
-
- ip = data["ip"]
- subnet = data["subnet"]
-
# Bringing interface up
- cmd = "ip link set up {}".format(vlan_intf)
+ cmd = "ip link set {} up".format(vlan_intf)
logger.info("[DUT: %s]: Running command: %s", dut, cmd)
rnode.run(cmd)
# Assigning IP address
- cmd = "ifconfig {} {} netmask {}".format(vlan_intf, ip, subnet)
+ ifaddr = ipaddress.ip_interface(
+ u"{}/{}".format(
+ frr_unicode(data["ip"]),
+ frr_unicode(data["subnet"])
+ )
+ )
+
+ cmd = "ip -{0} a flush {1} scope global && ip a add {2} dev {1} && ip l set {1} up".format(
+ ifaddr.version, vlan_intf, ifaddr
+ )
logger.info("[DUT: %s]: Running command: %s", dut, cmd)
rnode.run(cmd)
@@ -1137,6 +1256,8 @@ def create_debug_log_config(tgen, input_dict, build=False):
result = False
try:
+ debug_config_dict = {}
+
for router in input_dict.keys():
debug_config = []
if "debug" in input_dict[router]:
@@ -1167,10 +1288,12 @@ def create_debug_log_config(tgen, input_dict, build=False):
for daemon, debug_logs in disable_logs.items():
for debug_log in debug_logs:
debug_config.append("no {}".format(debug_log))
+ if debug_config:
+ debug_config_dict[router] = debug_config
- result = create_common_configuration(
- tgen, router, debug_config, "debug_log_config", build=build
- )
+ result = create_common_configurations(
+ tgen, debug_config_dict, "debug_log_config", build=build
+ )
except InvalidCLIError:
# Traceback
errormsg = traceback.format_exc()
@@ -1248,11 +1371,14 @@ def create_vrf_cfg(tgen, topo, input_dict=None, build=False):
input_dict = deepcopy(input_dict)
try:
+ config_data_dict = {}
+
for c_router, c_data in input_dict.items():
rnode = tgen.routers()[c_router]
+ config_data = []
+
if "vrfs" in c_data:
for vrf in c_data["vrfs"]:
- config_data = []
del_action = vrf.setdefault("delete", False)
name = vrf.setdefault("name", None)
table_id = vrf.setdefault("id", None)
@@ -1329,9 +1455,12 @@ def create_vrf_cfg(tgen, topo, input_dict=None, build=False):
cmd = "no vni {}".format(del_vni)
config_data.append(cmd)
- result = create_common_configuration(
- tgen, c_router, config_data, "vrf", build=build
- )
+ if config_data:
+ config_data_dict[c_router] = config_data
+
+ result = create_common_configurations(
+ tgen, config_data_dict, "vrf", build=build
+ )
except InvalidCLIError:
# Traceback
@@ -1364,15 +1493,20 @@ def create_interface_in_kernel(
rnode = tgen.routers()[dut]
if create:
- cmd = "sudo ip link add name {} type dummy".format(name)
+ cmd = "ip link show {0} >/dev/null || ip link add {0} type dummy".format(name)
rnode.run(cmd)
- addr_type = validate_ip_address(ip_addr)
- if addr_type == "ipv4":
- cmd = "ifconfig {} {} netmask {}".format(name, ip_addr, netmask)
+ if not netmask:
+ ifaddr = ipaddress.ip_interface(frr_unicode(ip_addr))
else:
- cmd = "ifconfig {} inet6 add {}/{}".format(name, ip_addr, netmask)
-
+ ifaddr = ipaddress.ip_interface(u"{}/{}".format(
+ frr_unicode(ip_addr),
+ frr_unicode(netmask)
+ ))
+ cmd = "ip -{0} a flush {1} scope global && ip a add {2} dev {1} && ip l set {1} up".format(
+ ifaddr.version, name, ifaddr
+ )
+ logger.info("[DUT: %s]: Running command: %s", dut, cmd)
rnode.run(cmd)
if vrf:
@@ -1560,7 +1694,7 @@ def find_interface_with_greater_ip(topo, router, loopback=True, interface=True):
def write_test_header(tc_name):
- """ Display message at beginning of test case"""
+ """Display message at beginning of test case"""
count = 20
logger.info("*" * (len(tc_name) + count))
step("START -> Testcase : %s" % tc_name, reset=True)
@@ -1568,7 +1702,7 @@ def write_test_header(tc_name):
def write_test_footer(tc_name):
- """ Display message at end of test case"""
+ """Display message at end of test case"""
count = 21
logger.info("=" * (len(tc_name) + count))
logger.info("Testcase : %s -> PASSED", tc_name)
@@ -1596,7 +1730,8 @@ def interface_status(tgen, topo, input_dict):
logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name))
try:
- global frr_cfg
+ rlist = []
+
for router in input_dict.keys():
interface_list = input_dict[router]["interface_list"]
@@ -1605,8 +1740,10 @@ def interface_status(tgen, topo, input_dict):
rnode = tgen.routers()[router]
interface_set_status(rnode, intf, status)
- # Load config to router
- load_config_to_router(tgen, router)
+ rlist.append(router)
+
+ # Load config to routers
+ load_config_to_routers(tgen, rlist)
except Exception as e:
errormsg = traceback.format_exc()
@@ -1795,6 +1932,8 @@ def create_interfaces_cfg(tgen, topo, build=False):
topo = deepcopy(topo)
try:
+ interface_data_dict = {}
+
for c_router, c_data in topo.items():
interface_data = []
for destRouterLink, data in sorted(c_data["links"].items()):
@@ -1851,7 +1990,7 @@ def create_interfaces_cfg(tgen, topo, build=False):
"network",
"priority",
"cost",
- "mtu_ignore"
+ "mtu_ignore",
]
if "ospf" in data:
interface_data += _create_interfaces_ospf_cfg(
@@ -1859,12 +1998,14 @@ def create_interfaces_cfg(tgen, topo, build=False):
)
if "ospf6" in data:
interface_data += _create_interfaces_ospf_cfg(
- "ospf6", c_data, data, ospf_keywords
+ "ospf6", c_data, data, ospf_keywords + ["area"]
)
+ if interface_data:
+ interface_data_dict[c_router] = interface_data
- result = create_common_configuration(
- tgen, c_router, interface_data, "interface_config", build=build
- )
+ result = create_common_configurations(
+ tgen, interface_data_dict, "interface_config", build=build
+ )
except InvalidCLIError:
# Traceback
@@ -1923,6 +2064,8 @@ def create_static_routes(tgen, input_dict, build=False):
input_dict = deepcopy(input_dict)
try:
+ static_routes_list_dict = {}
+
for router in input_dict.keys():
if "static_routes" not in input_dict[router]:
errormsg = "static_routes not present in input_dict"
@@ -1978,9 +2121,12 @@ def create_static_routes(tgen, input_dict, build=False):
static_routes_list.append(cmd)
- result = create_common_configuration(
- tgen, router, static_routes_list, "static_route", build=build
- )
+ if static_routes_list:
+ static_routes_list_dict[router] = static_routes_list
+
+ result = create_common_configurations(
+ tgen, static_routes_list_dict, "static_route", build=build
+ )
except InvalidCLIError:
# Traceback
@@ -2037,6 +2183,8 @@ def create_prefix_lists(tgen, input_dict, build=False):
logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name))
result = False
try:
+ config_data_dict = {}
+
for router in input_dict.keys():
if "prefix_lists" not in input_dict[router]:
errormsg = "prefix_lists not present in input_dict"
@@ -2083,9 +2231,12 @@ def create_prefix_lists(tgen, input_dict, build=False):
cmd = "no {}".format(cmd)
config_data.append(cmd)
- result = create_common_configuration(
- tgen, router, config_data, "prefix_list", build=build
- )
+ if config_data:
+ config_data_dict[router] = config_data
+
+ result = create_common_configurations(
+ tgen, config_data_dict, "prefix_list", build=build
+ )
except InvalidCLIError:
# Traceback
@@ -2181,6 +2332,8 @@ def create_route_maps(tgen, input_dict, build=False):
logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name))
input_dict = deepcopy(input_dict)
try:
+ rmap_data_dict = {}
+
for router in input_dict.keys():
if "route_maps" not in input_dict[router]:
logger.debug("route_maps not present in input_dict")
@@ -2458,9 +2611,12 @@ def create_route_maps(tgen, input_dict, build=False):
cmd = "match metric {}".format(metric)
rmap_data.append(cmd)
- result = create_common_configuration(
- tgen, router, rmap_data, "route_maps", build=build
- )
+ if rmap_data:
+ rmap_data_dict[router] = rmap_data
+
+ result = create_common_configurations(
+ tgen, rmap_data_dict, "route_maps", build=build
+ )
except InvalidCLIError:
# Traceback
@@ -2535,6 +2691,8 @@ def create_bgp_community_lists(tgen, input_dict, build=False):
logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name))
input_dict = deepcopy(input_dict)
try:
+ config_data_dict = {}
+
for router in input_dict.keys():
if "bgp_community_lists" not in input_dict[router]:
errormsg = "bgp_community_lists not present in input_dict"
@@ -2571,9 +2729,12 @@ def create_bgp_community_lists(tgen, input_dict, build=False):
config_data.append(cmd)
- result = create_common_configuration(
- tgen, router, config_data, "bgp_community_list", build=build
- )
+ if config_data:
+ config_data_dict[router] = config_data
+
+ result = create_common_configurations(
+ tgen, config_data_dict, "bgp_community_list", build=build
+ )
except InvalidCLIError:
# Traceback
@@ -2906,7 +3067,7 @@ def configure_interface_mac(tgen, input_dict):
rnode = tgen.routers()[dut]
for intf, mac in input_dict[dut].items():
- cmd = "ifconfig {} hw ether {}".format(intf, mac)
+ cmd = "ip link set {} address {}".format(intf, mac)
logger.info("[DUT: %s]: Running command: %s", dut, cmd)
try:
@@ -4550,3 +4711,64 @@ def verify_ip_nht(tgen, input_dict):
logger.debug("Exiting lib API: verify_ip_nht()")
return False
+
+
+def scapy_send_raw_packet(
+ tgen, topo, senderRouter, intf, packet=None, interval=1, count=1
+):
+ """
+ Using scapy Raw() method to send BSR raw packet from one FRR
+ to other
+
+ Parameters:
+ -----------
+ * `tgen` : Topogen object
+ * `topo` : json file data
+ * `senderRouter` : Sender router
+ * `packet` : packet in raw format
+ * `interval` : Interval between the packets
+ * `count` : Number of packets to be sent
+
+ returns:
+ --------
+ errormsg or True
+ """
+
+ global CD
+ result = ""
+ logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name))
+ sender_interface = intf
+ rnode = tgen.routers()[senderRouter]
+
+ for destLink, data in topo["routers"][senderRouter]["links"].items():
+ if "type" in data and data["type"] == "loopback":
+ continue
+
+ if not packet:
+ packet = topo["routers"][senderRouter]["pkt"]["test_packets"][packet][
+ "data"
+ ]
+
+ if interval > 1 or count > 1:
+ cmd = (
+ "nohup /usr/bin/python {}/send_bsr_packet.py '{}' '{}' "
+ "--interval={} --count={} &".format(
+ CD, packet, sender_interface, interval, count
+ )
+ )
+ else:
+ cmd = (
+ "/usr/bin/python {}/send_bsr_packet.py '{}' '{}' "
+ "--interval={} --count={}".format(
+ CD, packet, sender_interface, interval, count
+ )
+ )
+
+ logger.info("Scapy cmd: \n %s", cmd)
+ result = rnode.run(cmd)
+
+ if result == "":
+ return result
+
+ logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
+ return True