diff options
Diffstat (limited to 'tests/topotests/lib/pim.py')
| -rw-r--r-- | tests/topotests/lib/pim.py | 249 |
1 files changed, 196 insertions, 53 deletions
diff --git a/tests/topotests/lib/pim.py b/tests/topotests/lib/pim.py index e702e53c00..9d37088218 100644 --- a/tests/topotests/lib/pim.py +++ b/tests/topotests/lib/pim.py @@ -16,24 +16,28 @@ # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE # OF THIS SOFTWARE. -import sys +import datetime import os import re -import datetime +import sys import traceback -import pytest -from time import sleep from copy import deepcopy -from lib.topolog import logger +from time import sleep + # Import common_config to use commomnly used APIs from lib.common_config import ( - create_common_configuration, create_common_configurations, + HostApplicationHelper, + InvalidCLIError, + create_common_configuration, InvalidCLIError, retry, run_frr_cmd, ) +from lib.micronet import get_exec_path +from lib.topolog import logger +from lib.topotest import frr_unicode #### CWD = os.path.dirname(os.path.realpath(__file__)) @@ -95,9 +99,7 @@ def create_pim_config(tgen, topo, input_dict=None, build=False, load_config=True continue if "rp" not in input_dict[router]["pim"]: continue - _add_pim_rp_config( - tgen, topo, input_dict, router, build, config_data_dict - ) + _add_pim_rp_config(tgen, topo, input_dict, router, build, config_data_dict) try: result = create_common_configurations( @@ -149,8 +151,7 @@ def _add_pim_rp_config(tgen, topo, input_dict, router, build, config_data_dict): # ip address of RP if "rp_addr" not in rp_dict and build: logger.error( - "Router %s: 'ip address of RP' not " - "present in input_dict/JSON", + "Router %s: 'ip address of RP' not " "present in input_dict/JSON", router, ) @@ -195,9 +196,7 @@ def _add_pim_rp_config(tgen, topo, input_dict, router, build, config_data_dict): config_data.append(cmd) if prefix_list: - cmd = "ip pim rp {} prefix-list {}".format( - rp_addr, prefix_list - ) + cmd = "ip pim rp {} prefix-list {}".format(rp_addr, prefix_list) if del_action: cmd = "no {}".format(cmd) config_data.append(cmd) @@ -353,9 +352,9 @@ def _enable_disable_pim_config(tgen, topo, input_dict, router, build=False): pim_data = input_dict[router]["pim"] del_action = pim_data.setdefault("delete", False) for t in [ - "join-prune-interval", - "keep-alive-timer", - "register-suppress-time", + "join-prune-interval", + "keep-alive-timer", + "register-suppress-time", ]: if t in pim_data: cmd = "ip pim {} {}".format(t, pim_data[t]) @@ -677,7 +676,14 @@ def verify_igmp_groups(tgen, dut, interface, group_addresses, expected=True): @retry(retry_timeout=60) def verify_upstream_iif( - tgen, dut, iif, src_address, group_addresses, joinState=None, refCount=1, expected=True + tgen, + dut, + iif, + src_address, + group_addresses, + joinState=None, + refCount=1, + expected=True, ): """ Verify upstream inbound interface is updated correctly @@ -830,7 +836,9 @@ def verify_upstream_iif( @retry(retry_timeout=12) -def verify_join_state_and_timer(tgen, dut, iif, src_address, group_addresses, expected=True): +def verify_join_state_and_timer( + tgen, dut, iif, src_address, group_addresses, expected=True +): """ Verify join state is updated correctly and join timer is running with the help of "show ip pim upstream" cli @@ -922,7 +930,8 @@ def verify_join_state_and_timer(tgen, dut, iif, src_address, group_addresses, ex error = ( "[DUT %s]: Verifying join timer for" " (%s,%s) [FAILED]!! " - " Expected: %s, Found: %s", + " Expected: %s, Found: %s" + ) % ( dut, src_address, grp_addr, @@ -950,7 +959,15 @@ def verify_join_state_and_timer(tgen, dut, iif, src_address, group_addresses, ex @retry(retry_timeout=120) def verify_ip_mroutes( - tgen, dut, src_address, group_addresses, iif, oil, return_uptime=False, mwait=0, expected=True + tgen, + dut, + src_address, + group_addresses, + iif, + oil, + return_uptime=False, + mwait=0, + expected=True, ): """ Verify ip mroutes and make sure (*, G)/(S, G) is present in mroutes @@ -1147,7 +1164,15 @@ def verify_ip_mroutes( @retry(retry_timeout=60) def verify_pim_rp_info( - tgen, topo, dut, group_addresses, oif=None, rp=None, source=None, iamrp=None, expected=True + tgen, + topo, + dut, + group_addresses, + oif=None, + rp=None, + source=None, + iamrp=None, + expected=True, ): """ Verify pim rp info by running "show ip pim rp-info" cli @@ -1304,7 +1329,14 @@ def verify_pim_rp_info( @retry(retry_timeout=60) def verify_pim_state( - tgen, dut, iif, oil, group_addresses, src_address=None, installed_fl=None, expected=True + tgen, + dut, + iif, + oil, + group_addresses, + src_address=None, + installed_fl=None, + expected=True, ): """ Verify pim state by running "show ip pim state" cli @@ -1473,7 +1505,9 @@ def verify_pim_interface_traffic(tgen, input_dict): @retry(retry_timeout=40) -def verify_pim_interface(tgen, topo, dut, interface=None, interface_ip=None, expected=True): +def verify_pim_interface( + tgen, topo, dut, interface=None, interface_ip=None, expected=True +): """ Verify all PIM interface are up and running, config is verified using "show ip pim interface" cli @@ -2028,9 +2062,7 @@ def add_rp_interfaces_and_pim_config(tgen, topo, interface, rp, rp_mapping): return result -def scapy_send_bsr_raw_packet( - tgen, topo, senderRouter, receiverRouter, packet=None, interval=1, count=1 -): +def scapy_send_bsr_raw_packet(tgen, topo, senderRouter, receiverRouter, packet=None): """ Using scapy Raw() method to send BSR raw packet from one FRR to other @@ -2042,8 +2074,6 @@ def scapy_send_bsr_raw_packet( * `senderRouter` : Sender router * `receiverRouter` : Receiver router * `packet` : BSR packet in raw format - * `interval` : Interval between the packets - * `count` : Number of packets to be sent returns: -------- @@ -2054,7 +2084,9 @@ def scapy_send_bsr_raw_packet( result = "" logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name)) - rnode = tgen.routers()[senderRouter] + python3_path = tgen.net.get_exec_path(["python3", "python"]) + script_path = os.path.join(CWD, "send_bsr_packet.py") + node = tgen.net[senderRouter] for destLink, data in topo["routers"][senderRouter]["links"].items(): if "type" in data and data["type"] == "loopback": @@ -2065,26 +2097,16 @@ def scapy_send_bsr_raw_packet( packet = topo["routers"][senderRouter]["bsm"]["bsr_packets"][packet]["data"] - if interval > 1 or count > 1: - cmd = ( - "nohup /usr/bin/python {}/send_bsr_packet.py '{}' '{}' " - "--interval={} --count={} &".format( - CWD, packet, sender_interface, interval, count - ) - ) - else: - cmd = ( - "/usr/bin/python {}/send_bsr_packet.py '{}' '{}' " - "--interval={} --count={}".format( - CWD, packet, sender_interface, interval, count - ) - ) - + cmd = [ + python3_path, + script_path, + packet, + sender_interface, + "--interval=1", + "--count=1", + ] logger.info("Scapy cmd: \n %s", cmd) - result = rnode.run(cmd) - - if result == "": - return result + node.cmd_raises(cmd) logger.debug("Exiting lib API: scapy_send_bsr_raw_packet") return True @@ -2157,7 +2179,9 @@ def find_rp_from_bsrp_info(tgen, dut, bsr, grp=None): @retry(retry_timeout=12) -def verify_pim_grp_rp_source(tgen, topo, dut, grp_addr, rp_source, rpadd=None, expected=True): +def verify_pim_grp_rp_source( + tgen, topo, dut, grp_addr, rp_source, rpadd=None, expected=True +): """ Verify pim rp info by running "show ip pim rp-info" cli @@ -2316,7 +2340,9 @@ def verify_pim_bsr(tgen, topo, dut, bsr_ip, expected=True): @retry(retry_timeout=60) -def verify_ip_pim_upstream_rpf(tgen, topo, dut, interface, group_addresses, rp=None, expected=True): +def verify_ip_pim_upstream_rpf( + tgen, topo, dut, interface, group_addresses, rp=None, expected=True +): """ Verify IP PIM upstream rpf, config is verified using "show ip pim neighbor" cli @@ -2514,7 +2540,9 @@ def enable_disable_pim_bsm(tgen, router, intf, enable=True): @retry(retry_timeout=60) -def verify_ip_pim_join(tgen, topo, dut, interface, group_addresses, src_address=None, expected=True): +def verify_ip_pim_join( + tgen, topo, dut, interface, group_addresses, src_address=None, expected=True +): """ Verify ip pim join by running "show ip pim join" cli @@ -3264,7 +3292,9 @@ def get_refCount_for_mroute(tgen, dut, iif, src_address, group_addresses): @retry(retry_timeout=40) -def verify_multicast_flag_state(tgen, dut, src_address, group_addresses, flag, expected=True): +def verify_multicast_flag_state( + tgen, dut, src_address, group_addresses, flag, expected=True +): """ Verify flag state for mroutes and make sure (*, G)/(S, G) are having coorect flags by running "show ip mroute" cli @@ -3422,3 +3452,116 @@ def verify_igmp_interface(tgen, topo, dut, igmp_iface, interface_ip, expected=Tr logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name)) return True + + +class McastTesterHelper(HostApplicationHelper): + def __init__(self, tgen=None): + self.script_path = os.path.join(CWD, "mcast-tester.py") + self.host_conn = {} + self.listen_sock = None + + # # Get a temporary file for socket path + # (fd, sock_path) = tempfile.mkstemp("-mct.sock", "tmp" + str(os.getpid())) + # os.close(fd) + # os.remove(sock_path) + # self.app_sock_path = sock_path + + # # Listen on unix socket + # logger.debug("%s: listening on socket %s", self, self.app_sock_path) + # self.listen_sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM, 0) + # self.listen_sock.settimeout(10) + # self.listen_sock.bind(self.app_sock_path) + # self.listen_sock.listen(10) + + python3_path = get_exec_path(["python3", "python"]) + super(McastTesterHelper, self).__init__( + tgen, + # [python3_path, self.script_path, self.app_sock_path] + [python3_path, self.script_path], + ) + + def __str__(self): + return "McastTesterHelper({})".format(self.script_path) + + def run_join(self, host, join_addrs, join_towards=None, join_intf=None): + """ + Join a UDP multicast group. + + One of join_towards or join_intf MUST be set. + + Parameters: + ----------- + * `host`: host from where IGMP join would be sent + * `join_addrs`: multicast address (or addresses) to join to + * `join_intf`: the interface to bind the join[s] to + * `join_towards`: router whos interface to bind the join[s] to + """ + if not isinstance(join_addrs, list) and not isinstance(join_addrs, tuple): + join_addrs = [join_addrs] + + if join_towards: + join_intf = frr_unicode( + self.tgen.json_topo["routers"][host]["links"][join_towards]["interface"] + ) + else: + assert join_intf + + for join in join_addrs: + self.run(host, [join, join_intf]) + + return True + + def run_traffic(self, host, send_to_addrs, bind_towards=None, bind_intf=None): + """ + Send UDP multicast traffic. + + One of bind_towards or bind_intf MUST be set. + + Parameters: + ----------- + * `host`: host to send traffic from + * `send_to_addrs`: multicast address (or addresses) to send traffic to + * `bind_towards`: Router who's interface the source ip address is got from + """ + if bind_towards: + bind_intf = frr_unicode( + self.tgen.json_topo["routers"][host]["links"][bind_towards]["interface"] + ) + else: + assert bind_intf + + if not isinstance(send_to_addrs, list) and not isinstance(send_to_addrs, tuple): + send_to_addrs = [send_to_addrs] + + for send_to in send_to_addrs: + self.run(host, ["--send=0.7", send_to, bind_intf]) + + return True + + # def cleanup(self): + # super(McastTesterHelper, self).cleanup() + + # if not self.listen_sock: + # return + + # logger.debug("%s: closing listen socket %s", self, self.app_sock_path) + # self.listen_sock.close() + # self.listen_sock = None + + # if os.path.exists(self.app_sock_path): + # os.remove(self.app_sock_path) + + # def started_proc(self, host, p): + # logger.debug("%s: %s: accepting on socket %s", self, host, self.app_sock_path) + # try: + # conn = self.listen_sock.accept() + # return conn + # except Exception as error: + # logger.error("%s: %s: accept on socket failed: %s", self, host, error) + # if p.poll() is not None: + # logger.error("%s: %s: helper app quit: %s", self, host, comm_error(p)) + # raise + + # def stopping_proc(self, host, p, conn): + # logger.debug("%s: %s: closing socket %s", self, host, conn) + # conn[0].close() |
