Scalability tests and log improvement

Change-Id: I510002ea48ecc17e86d771e85c79b85cadf08f32
diff --git a/Fabric/Tests/scalability.py b/Fabric/Tests/scalability.py
index 9292a08..5197446 100755
--- a/Fabric/Tests/scalability.py
+++ b/Fabric/Tests/scalability.py
@@ -13,3 +13,576 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+
+"""
+Check README file
+"""
+
+from oftest import config
+import logging
+import oftest.base_tests as base_tests
+import ofp
+import os
+import time
+import json
+from oftest.testutils import *
+from accton_util import *
+from oftest.utils import *
+from oftest.ofdpa_utils import *
+from accton_util import *
+
+# Number of xconnections created per port
+xcon_num = 64
+
+# Number of seconds to wait after switch restart
+rest_num = 300
+
+#### Global variable  # defined globally to check whether base_config was executed or not
+BASE_RUN = False
+
+
+#####
+##Test cases assumes the ONOS controller is Running and Fabric SWitch is configured to use ONOS as the SDN Controller
+## Test cases assumes ONOS controller is in a clean state
+## Test cases assumes Fabric switch is in clean state without any flows or group entries from a previous configuration. Its a good idea to reload the Fabric switch before starting the test cases.
+## Refer to the test plan for more details
+
+class FabricSW_Scale_Base_TC_0005(base_tests.SimpleDataPlane):
+    """
+    This Test case defines the base configuration which will serve as a pre-requisite on top of which other test cases are executed.
+    """
+    ### Read config parameters from JSON file 'global_vars.json'
+    ROOT_DIR = os.path.dirname(os.path.realpath(__file__))
+    with open(ROOT_DIR + '/' + 'global_vars.json') as f:
+        data = json.load(f)
+
+    onos_server_ip = data['onos_server_ip']
+    onos_user = data['onos_user']
+    onos_passwd = data['onos_passwd']
+    switch_ip = data['switch_ip']
+    switch_user = data['switch_user']
+    switch_passwd = data['switch_passwd']
+
+    def runTest(self):
+        global BASE_RUN
+        try:
+            if len(config[ "port_map" ]) < 4:
+                logging.info("Port count less than 4, can't run this case")
+                assert False, "Port count less than 4, can't run this case"
+                return
+
+            base_config(self)
+            onos_flow_group_dump(self)
+            switch_flow_group_dump(self)
+            time.sleep(2)
+            verify_traffic(self)
+
+        finally:
+            BASE_RUN = True
+            logging.info("End of Test")
+
+
+class FabricSW_Scale_Base_TC_0010(base_tests.SimpleDataPlane):
+    """
+    Verify that with scaled up flow configurations, rebooting the switch restores all flows and handles traffic as expected.
+    """
+    ### Read config parameters from JSON file 'global_vars.json'
+    ROOT_DIR = os.path.dirname(os.path.realpath(__file__))
+    with open(ROOT_DIR + '/' + 'global_vars.json') as f:
+        data = json.load(f)
+
+    switch_ip = data['switch_ip']
+    switch_user = data['switch_user']
+    switch_passwd = data['switch_passwd']
+
+    def runTest(self):
+        global BASE_RUN
+        try:
+            if len( config[ "port_map" ] ) < 4:
+                logging.info( "Port count less than 4, can't run this case")
+                assert False, "Port count less than 4, can't run this case"
+                return
+
+            if BASE_RUN == False:
+                logging.info("Test FabricSW_Scale_Base_TC_0010 cannot be executed. FabricSW_Scale_Base_TC_0005 is a pre-requisite to this test case,"
+                              " Please execute FabricSW_Scale_Base_TC_0005 before FabricSW_Scale_Base_TC_0010")
+                assert False, "Test FabricSW_Scale_Base_TC_0010 cannot be executed. FabricSW_Scale_Base_TC_0005 is a pre-requisite to this test case," \
+                              " Please execute FabricSW_Scale_Base_TC_0005 before FabricSW_Scale_Base_TC_0010"
+                return
+
+            # Reboot switch
+            logging.info("Restarting switch")
+            print("Restarting switch")
+            switch_restart(self)
+            logging.info("Switch is restarting, wait for 300 secs")
+            time.sleep(rest_num)
+            logging.info("Switch is restarted")
+
+            #Verify traffic after switch reboot
+            logging.info("Verify traffic")
+            verify_traffic(self)
+            time.sleep(2)
+
+        finally:
+            logging.info("End of Test")
+
+
+class FabricSW_Scale_Base_TC_0015(base_tests.SimpleDataPlane):
+    """
+    Verify that with scaled up flow configurations, after flapping the data port multiple times the switch restores all flows and handles traffic as expected.
+    """
+    ### Read config parameters from JSON file 'global_vars.json'
+    ROOT_DIR = os.path.dirname(os.path.realpath(__file__))
+    with open(ROOT_DIR + '/' + 'global_vars.json') as f:
+        data = json.load(f)
+
+    switch_ip = data['switch_ip']
+    switch_user = data['switch_user']
+    switch_passwd = data['switch_passwd']
+
+    def runTest(self):
+        global BASE_RUN
+        try:
+            if len( config[ "port_map" ] ) < 4:
+                logging.info( "Port count less than 4, can't run this case" )
+                assert False, "Port count less than 4, can't run this case"
+                return
+
+            if BASE_RUN == False:
+                logging.info("Test FabricSW_Scale_Base_TC_0015 cannot be executed. FabricSW_Scale_Base_TC_0005 is a pre-requisite to this test case,"
+                              " Please execute FabricSW_Scale_Base_TC_0005 before FabricSW_Scale_Base_TC_0015")
+                assert False, "Test FabricSW_Scale_Base_TC_0015 cannot be executed. FabricSW_Scale_Base_TC_0005 is a pre-requisite to this test case," \
+                              " Please execute FabricSW_Scale_Base_TC_0005 before FabricSW_Scale_Base_TC_0015"
+                return
+
+            ports = sorted(config["port_map"].keys())
+            # Flap port1 for 100 iterations
+            logging.info("Flap port1 for 100 iterations with an interval of '2' seconds")
+            for i in range(1, 100):
+                switch_port_enable(self, ports[0], False)
+                time.sleep(2)
+                switch_port_enable(self, ports[0], True)
+                time.sleep(2)
+
+            #Verify traffic after port flapping
+            logging.info("Verify traffic after port flapping")
+            time.sleep(20)
+            verify_traffic(self)
+
+        finally:
+            logging.info("End of Test")
+
+
+class FabricSW_Scale_Base_TC_0020(base_tests.SimpleDataPlane):
+    """
+    Verify that with scaled up flow configurations, after configuring and unconfiguring flows multiple times the switch is stable and handles traffic as expected.
+    """
+
+    ### Read config parameters from JSON file 'global_vars.json'
+    ROOT_DIR = os.path.dirname(os.path.realpath(__file__))
+    with open(ROOT_DIR + '/' + 'global_vars.json') as f:
+        data = json.load(f)
+
+    onos_server_ip = data['onos_server_ip']
+    onos_user = data['onos_user']
+    onos_passwd = data['onos_passwd']
+    onos_port = data['onos_port']
+    switch_ip = data['switch_ip']
+    switch_user = data['switch_user']
+    switch_passwd = data['switch_passwd']
+
+    def runTest(self):
+        global BASE_RUN
+        try:
+            if len( config[ "port_map" ] ) < 4:
+                logging.info( "Port count less than 4, can't run this case")
+                assert False, "Port count less than 4, can't run this case"
+                return
+
+            if BASE_RUN == False:
+                logging.info("Test FabricSW_Scale_Base_TC_0020 cannot be executed. FabricSW_Scale_Base_TC_0005 is a pre-requisite to this test case,"
+                              " Please execute FabricSW_Scale_Base_TC_0005 before FabricSW_Scale_Base_TC_0020")
+                assert False, "Test FabricSW_Scale_Base_TC_0020 cannot be executed. FabricSW_Scale_Base_TC_0005 is a pre-requisite to this test case," \
+                              " Please execute FabricSW_Scale_Base_TC_0005 before FabricSW_Scale_Base_TC_0020"
+                return
+
+            # Un-configure and re-configure of all 'vlan-cross-connect' pairs for 100 iterations with an interval of 5 seconds.
+            logging.info("Un-configure and re-configure of all 'vlan-cross-connect' pairs for 100 iterations with an interval of 5 seconds")
+            for i in range(1, 100):
+                print("Re-create config iteration: ", i)
+                logging.info("Re-create config iteration: {}".format(i))
+                remove_base_config(self)
+                time.sleep(5)
+                base_config(self)
+
+            #Verify traffic after config re-creation
+            logging.info("Verify traffic after config re-creation")
+            time.sleep(2)
+            verify_traffic(self)
+
+        finally:
+            logging.info("End of Test")
+
+
+class FabricSW_Scale_Base_TC_0025(base_tests.SimpleDataPlane):
+    """
+    Verify that with scaled up flow configurations, sending bursts of control traffic (resulting in "Packet_In" messages from switch to controller) the switch is stable and handles traffic as expected.
+    """
+    ### Read config parameters from JSON file 'global_vars.json'
+    ROOT_DIR = os.path.dirname(os.path.realpath(__file__))
+    with open(ROOT_DIR + '/' + 'global_vars.json') as f:
+        data = json.load(f)
+
+    switch_ip = data['switch_ip']
+    switch_user = data['switch_user']
+    switch_passwd = data['switch_passwd']
+    controller_ip = data['controller_ip']
+    controller_port = data['controller_port']
+    onos_server_ip = data['onos_server_ip']
+    onos_user = data['onos_user']
+    onos_passwd = data['onos_passwd']
+    onos_port = data['onos_port']
+
+    def runTest(self):
+        global BASE_RUN
+        try:
+            if len( config[ "port_map" ] ) < 4:
+                logging.info( "Port count less than 4, can't run this case" )
+                assert False, "Port count less than 4, can't run this case"
+                return
+
+            if BASE_RUN == False:
+                logging.info("Test FabricSW_Scale_Base_TC_0025 cannot be executed. FabricSW_Scale_Base_TC_0005 is a pre-requisite to this test case,"
+                              " Please execute FabricSW_Scale_Base_TC_0005 before FabricSW_Scale_Base_TC_0025")
+                assert False, "Test FabricSW_Scale_Base_TC_0025 cannot be executed. FabricSW_Scale_Base_TC_0005 is a pre-requisite to this test case," \
+                              " Please execute FabricSW_Scale_Base_TC_0005 before FabricSW_Scale_Base_TC_0025"
+                return
+
+            # create match
+            match = ofp.match()
+            match.oxm_list.append(ofp.oxm.eth_type(0x0800))
+            match.oxm_list.append(ofp.oxm.ip_proto(1))
+            request = ofp.message.flow_add(table_id=60, cookie=42, match=match, instructions=[
+                ofp.instruction.apply_actions(actions=[
+                    ofp.action.output(port=ofp.OFPP_CONTROLLER, max_len=ofp.OFPCML_NO_BUFFER)]), ],
+                                           buffer_id=ofp.OFP_NO_BUFFER, priority=1)
+            logging.info("Add an ACL table entry to match ICMP packets and send to controller")
+            self.controller.message_send(request)
+
+            # Sent a burst of 64 ICMP packets to data ports 2, 3, and 4.
+            logging.info("Sent a burst of 64 ICMP packets to data ports 2, 3, and 4.")
+            ports = sorted(config["port_map"].keys())
+            # Send ICMP packets to port2
+            pair = [ports[0], ports[1]]
+            tmp_ports = list(pair)
+            tmp_ports.remove(pair[0])
+            logging.info("Creating ICMP packets for port2")
+            # change dest based on port number
+            mac_src = '00:12:34:56:78:%02X' % pair[1]
+            parsed_pkt = simple_icmp_packet(eth_src=mac_src)
+            pkt = str(parsed_pkt)
+
+            for i in range(64):
+                self.dataplane.send(pair[1], pkt)
+                print('ICMP to port1 iteration:', i)
+                verify_packet_in(self, pkt, ports[1], ofp.OFPR_ACTION)
+
+            # Send ICMP packets to port3
+            pair = [ports[0], ports[2]]
+            tmp_ports = list(pair)
+            tmp_ports.remove(pair[0])
+            logging.info("Creating ICMP packets for port3")
+            # change dest based on port number
+            mac_src = '00:12:34:56:78:%02X' % pair[1]
+            parsed_pkt = simple_icmp_packet(eth_src=mac_src)
+            pkt = str(parsed_pkt)
+
+            for i in range(64):
+                self.dataplane.send(pair[1], pkt)
+                print('ICMP to port2 iteration:', i)
+                verify_packet_in(self, pkt, ports[2], ofp.OFPR_ACTION)
+                # time.sleep(2)
+
+            # Send ICMP packets to port4
+            pair = [ports[0], ports[3]]
+            tmp_ports = list(pair)
+            tmp_ports.remove(pair[0])
+            logging.info("Creating ICMP packets for port4")
+            # change dest based on port number
+            mac_src = '00:12:34:56:78:%02X' % pair[1]
+            parsed_pkt = simple_icmp_packet(eth_src=mac_src)
+            pkt = str(parsed_pkt)
+
+            for i in range(64):
+                self.dataplane.send(pair[1], pkt)
+                print('ICMP to port3 iteration: ', i)
+                verify_packet_in(self, pkt, ports[3], ofp.OFPR_ACTION)
+
+        finally:
+            remove_base_config(self)
+            logging.info("End of Test")
+
+def base_config(self):
+    ports = (config["port_map"].keys())
+    datapathid = get_datapathid(self)
+    l = []
+    start, end = 101, (101 + xcon_num)
+    l.extend(range(start, end))
+    # Create flows between port1 and port2
+    logging.info("Configure 64 vlan-cross-connect pair between data ports 1 and 2 for vlan101 to vlan164")
+    for i in l:
+        print('adding xconn port1-2', i)
+        add_onos_xconnect(self, datapathid, i, ports[0], ports[1])
+
+    # Create flows between port1 and port3
+    logging.info("Configure 64 vlan-cross-connect pair between data ports 1 and 3 for vlan201 to vlan264")
+    l = []
+    start, end = 201, (201 + xcon_num)
+    l.extend(range(start, end))
+    for i in l:
+        print('adding xconn port1-3', i)
+        add_onos_xconnect(self, datapathid, i, ports[0], ports[2])
+
+    # Create flows between port1 and port3
+    logging.info("Configure 64 vlan-cross-connect pair between data ports 1 and 4 for vlan301 to vlan364")
+    l = []
+    start, end = 301, (301 + xcon_num)
+    l.extend(range(start, end))
+    for i in l:
+        print('adding xconn port1-4', i)
+        add_onos_xconnect(self, datapathid, i, ports[0], ports[3])
+
+
+def remove_base_config(self):
+    datapathid = get_datapathid(self)
+    l = []
+    start, end = 101, (101 + xcon_num)
+    l.extend(range(start, end))
+    # Remove flows vlan101 - vlan164 between ports 1 and 2
+    logging.info("Remove flows vlan101 - vlan164 between ports 1 and 2")
+    for i in l:
+        remove_onos_xconnect(self, datapathid, i)
+
+    #Removeflows vlan201 - vlan264 between ports 1 and 3
+    logging.info("Remove flows vlan201 - vlan264 between ports 1 and 3")
+    l = []
+    start, end = 201, (201 + xcon_num)
+    l.extend(range(start, end))
+    for i in l:
+        remove_onos_xconnect(self, datapathid, i)
+
+    # Remove flows vlan301 - vlan364 between ports 1 and 4
+    logging.info("Remove flows vlan301 - vlan364 between ports 1 and 4")
+    l = []
+    start, end = 301, (301 + xcon_num)
+    l.extend(range(start, end))
+    for i in l:
+        remove_onos_xconnect(self, datapathid, i)
+
+
+def verify_traffic(self):
+    ports = sorted(config["port_map"].keys())
+
+##### Reverse traffic verification. From BNG to OLT" ########
+    # # Create and send packets between port1 and port2
+    # pair = [ports[0], ports[1]]
+    # packets1 = []
+    # logging.info("Create double tagged vlan packets with outer vlan IDs 101 - 164 between port1 and port2")
+    # # change dest based on port number
+    # mac_src = '00:12:34:56:78:%02X' % ports[0]
+    # l = []
+    # start, end = 101, (101 + xcon_num)
+    # l.extend(range(start, end))
+    # for i in l:
+    #     parsed_pkt = simple_tcp_packet_two_vlan(pktlen=108, out_dl_vlan_enable=True,
+    #                                             out_vlan_vid=i, in_dl_vlan_enable=True, in_vlan_vid=10,
+    #                                             eth_dst='00:12:34:56:78:9a', eth_src=mac_src)
+    #
+    #     pkt = str(parsed_pkt)
+    #     packets1.append(pkt)
+    #
+    # logging.info("Transmit double tagged vlan packets with outer vlan101 - vlan164 to data port1")
+    # logging.info("Verify packets are flooded out of data port 2")
+    # for i in packets1:
+    #     self.dataplane.send(pair[0], i)
+    #     print('verify port1-2, xcon: ', (packets1.index(i)+101))
+    #     verify_packet(self, i, pair[1])
+    #     verify_no_packet(self, i, pair[0])
+
+
+    # time.sleep(1)
+
+##### Reverse traffic verification. From BNG to OLT" ########
+    # # Create and send packets between port1 and port3
+    # pair = [ports[0], ports[2]]
+    # packets2 = []
+    # logging.info("Create double tagged vlan packets with outer vlan IDs 201 - 264 between port1 and port3")
+    # # change dest based on port number
+    # mac_src = '00:12:34:56:78:%02X' % ports[0]
+    # l = []
+    # start, end = 201, (201 + xcon_num)
+    # l.extend(range(start, end))
+    # for i in l:
+    #     parsed_pkt = simple_tcp_packet_two_vlan(pktlen=108, out_dl_vlan_enable=True,
+    #                                             out_vlan_vid=i, in_dl_vlan_enable=True, in_vlan_vid=10,
+    #                                             eth_dst='00:12:34:56:78:9a', eth_src=mac_src)
+    #
+    #     pkt = str(parsed_pkt)
+    #     packets2.append(pkt)
+    #
+    # logging.info("Transmit double tagged vlan packets with outer vlan201 - vlan264 to data port1")
+    # logging.info("Verify packets are flooded out of data port 3")
+    # for i in packets2:
+    #     self.dataplane.send(pair[0], i)
+    #     # verify traffic
+    #     print('verify port1-3, xcon: ', packets2.index(i)+201)
+    #     verify_packet(self, i, pair[1])
+    #     verify_no_packet(self, i, pair[0])
+    #
+    # time.sleep(1)
+
+##### Reverse traffic verification. From BNG to OLT" ########
+    # Create and send packets between port1 and port4
+    # pair = [ports[0], ports[3]]
+    # packets3 = []
+    # logging.info(
+    #     "Create double tagged vlan packets with outer vlan IDs 301 - 364 between port1 and port4")
+    # # change dest based on port number
+    # mac_src = '00:12:34:56:78:%02X' % pair[0]
+    # l = []
+    # start, end = 301, (301 + xcon_num)
+    # l.extend(range(start, end))
+    # for i in l:
+    #     parsed_pkt = simple_tcp_packet_two_vlan(pktlen=108, out_dl_vlan_enable=True,
+    #                                             out_vlan_vid=i, in_dl_vlan_enable=True, in_vlan_vid=10,
+    #                                             eth_dst='00:12:34:56:78:9a', eth_src=mac_src)
+    #
+    #     pkt = str(parsed_pkt)
+    #     packets3.append(pkt)
+    #
+    # logging.info("Transmit double tagged vlan packets with outer vlan301 - vlan364 to data port1")
+    # logging.info("Verify packets are flooded out of data port 4")
+    # for i in packets3:
+    #     self.dataplane.send(pair[0], i)
+    #     # verify traffic
+    #     print('verify port1-4, xcon: ', packets3.index(i)+301)
+    #     verify_packet(self, i, pair[1])
+    #     verify_no_packet(self, i, pair[0])
+    #
+    # time.sleep(1)
+
+    # Create and send packets between port2 and port1
+    pair = [ports[0], ports[1]]
+    packets1 = []
+    logging.info("Create double tagged vlan packets with outer vlan IDs 101 - 164 between port2 and port1")
+    # change dest based on port number
+    mac_src = '00:12:34:56:78:%02X' % ports[1]
+    l = []
+    start, end = 101, (101 + xcon_num)
+    l.extend(range(start, end))
+    for i in l:
+        parsed_pkt = simple_tcp_packet_two_vlan(pktlen=108, out_dl_vlan_enable=True,
+                                                out_vlan_vid=i, in_dl_vlan_enable=True, in_vlan_vid=10,
+                                                eth_dst='00:12:34:56:78:9a', eth_src=mac_src)
+
+        pkt = str(parsed_pkt)
+        packets1.append(pkt)
+
+    logging.info("Transmit double tagged vlan packets with outer vlan101 - vlan164 to data port2")
+    logging.info("Verify packets are flooded out of data port 1")
+    for i in packets1:
+        logging.info("Transmitting packet {}".format(packets1.index(i) + 1))
+        self.dataplane.send(pair[1], i)
+        # verify traffic
+        print('verify port2-1, xcon: ', packets1.index(i)+101)
+        verify_packet(self, i, pair[0])
+        verify_no_packet(self, i, pair[1])
+
+    time.sleep(1)
+
+# # Create and send packets between port3 and port1
+    pair = [ports[0], ports[2]]
+    packets2 = []
+    logging.info("Create double tagged vlan packets with outer vlan IDs 201 - 264 between port3 and port1")
+    # change dest based on port number
+    mac_src = '00:12:34:56:78:%02X' % ports[2]
+    l = []
+    start, end = 201, (201 + xcon_num)
+    l.extend(range(start, end))
+    for i in l:
+        parsed_pkt = simple_tcp_packet_two_vlan(pktlen=108, out_dl_vlan_enable=True,
+                                                out_vlan_vid=i, in_dl_vlan_enable=True, in_vlan_vid=10,
+                                                eth_dst='00:12:34:56:78:9a', eth_src=mac_src)
+
+        pkt = str(parsed_pkt)
+        packets2.append(pkt)
+
+    logging.info("Transmit double tagged vlan packets with outer vlan101 - vlan164 to data port3")
+    logging.info("Verify packets are flooded out of data port 1")
+    for i in packets2:
+        logging.info("Transmitting packet {}".format(packets2.index(i) + 1))
+        self.dataplane.send(pair[1], i)
+        # verify traffic
+        print('verify port3-1, xcon: ', packets2.index(i)+201)
+        verify_packet(self, i, pair[0])
+        verify_no_packet(self, i, pair[1])
+
+    time.sleep(1)
+
+    # Create and send packets between port4 and port1
+    pair = [ports[0], ports[3]]
+    packets3 = []
+    logging.info(
+        "Create double tagged vlan packets with outer vlan IDs 301 - 364 between port4 and port1")
+    # change dest based on port number
+    mac_src = '00:12:34:56:78:%02X' % ports[3]
+    l = []
+    start, end = 301, (301 + xcon_num)
+    l.extend(range(start, end))
+    for i in l:
+        parsed_pkt = simple_tcp_packet_two_vlan(pktlen=108, out_dl_vlan_enable=True,
+                                                out_vlan_vid=i, in_dl_vlan_enable=True, in_vlan_vid=10,
+                                                eth_dst='00:12:34:56:78:9a', eth_src=mac_src)
+
+        pkt = str(parsed_pkt)
+        packets3.append(pkt)
+
+    logging.info("Transmit double tagged vlan packets with outer vlan101 - vlan164 to data port4")
+    logging.info("Verify packets are flooded out of data port 1")
+    for i in packets3:
+        logging.info("Transmitting packet {}".format(packets3.index(i) + 1))
+        self.dataplane.send(pair[1], i)
+        # verify traffic
+        print('verify port4-1, xcon: ', packets3.index(i)+301)
+        verify_packet(self, i, pair[0])
+        verify_no_packet(self, i, pair[1])
+
+
+def get_datapathid(self):
+    feature_reply = get_featureReplay(self)
+    str_datapath_id_f = "{:016x}".format(feature_reply.datapath_id)
+    return str_datapath_id_f
+
+def onos_flow_group_dump(self, logfile_name="ONOS_flow_and_groups_dump.log"):
+    # Dump the created flows and groups from ONOS in a separate file
+    datapathid = get_datapathid(self)
+    log_path = (config["log_dir"])
+    log_file = logfile_name
+    logging.info(
+        "The configured flow and group entries from onos are dumped to " + log_path + '/' + log_file)
+    send_command_to_onos_cli(log_file, "flows -s any " + datapathid, self.onos_server_ip, self.onos_user,
+                             self.onos_passwd, regexp='onos>')
+    send_command_to_onos_cli(log_file, "groups", self.onos_server_ip, self.onos_user, self.onos_passwd, regexp='onos>')
+
+
+def switch_flow_group_dump(self, logfile_name="Switch_flow_and_groups_dump.log"):
+    # Dump the created flows and groups from Openflow Switch in a separate file
+    datapathid = get_datapathid(self)
+    log_path = (config["log_dir"])
+    log_file = logfile_name
+    logging.info(
+        "The configured flow and group entries from switch are dumped to " + log_path + '/' + log_file)
+    send_command_to_switch_cli(log_file, "client_flowtable_dump", self.switch_ip,
+                               self.switch_user, self.switch_passwd, regexp='root@localhost:~#')
+    send_command_to_switch_cli(log_file, "client_grouptable_dump", self.switch_ip,
+                               self.switch_user, self.switch_passwd, regexp='root@localhost:~#')
\ No newline at end of file