summaryrefslogtreecommitdiff
path: root/tests/topotests/lib/pim.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/topotests/lib/pim.py')
-rw-r--r--tests/topotests/lib/pim.py249
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()