Docs: Add monitoring cluster related documentation
[vswitchperf.git] / core / vswitch_controller_pxp.py
index e3c208a..d36ecdb 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright 2016 Intel Corporation.
+# Copyright 2016-2018 Intel Corporation., Tieto
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
 
 """VSwitch controller for multi VM scenarios with serial or parallel connection
 """
 
 """VSwitch controller for multi VM scenarios with serial or parallel connection
 """
-
-import logging
 import netaddr
 
 from core.vswitch_controller import IVswitchController
 import netaddr
 
 from core.vswitch_controller import IVswitchController
-from vswitches.utils import add_ports_to_flow
 from conf import settings
 
 from conf import settings
 
-_FLOW_TEMPLATE = {
-    'idle_timeout': '0'
-}
-
-_PROTO_TCP = 6
-_PROTO_UDP = 17
-
 class VswitchControllerPXP(IVswitchController):
     """VSwitch controller for PXP deployment scenario.
     """
     def __init__(self, deployment, vswitch_class, traffic):
 class VswitchControllerPXP(IVswitchController):
     """VSwitch controller for PXP deployment scenario.
     """
     def __init__(self, deployment, vswitch_class, traffic):
-        """Initializes up the prerequisites for the PXP deployment scenario.
-
-        :vswitch_class: the vSwitch class to be used.
-        :deployment: the deployment scenario to configure
-        :traffic: dictionary with detailed traffic definition
+        """See IVswitchController for general description
         """
         """
-        self._logger = logging.getLogger(__name__)
-        self._vswitch_class = vswitch_class
-        self._vswitch = vswitch_class()
+        super().__init__(deployment, vswitch_class, traffic)
         self._pxp_topology = 'parallel' if deployment.startswith('pvpv') else 'serial'
         if deployment == 'pvp':
             self._pxp_vm_count = 1
         self._pxp_topology = 'parallel' if deployment.startswith('pvpv') else 'serial'
         if deployment == 'pvp':
             self._pxp_vm_count = 1
@@ -55,9 +39,7 @@ class VswitchControllerPXP(IVswitchController):
 
         self._deployment_scenario = deployment
 
 
         self._deployment_scenario = deployment
 
-        self._traffic = traffic.copy()
         self._bidir = True if self._traffic['bidir'] == 'True' else False
         self._bidir = True if self._traffic['bidir'] == 'True' else False
-        self._logger.debug('Creation using %s', str(self._vswitch_class))
         self._bridge = settings.getValue('VSWITCH_BRIDGE_NAME')
 
     def setup(self):
         self._bridge = settings.getValue('VSWITCH_BRIDGE_NAME')
 
     def setup(self):
@@ -71,8 +53,8 @@ class VswitchControllerPXP(IVswitchController):
             self._vswitch.add_switch(self._bridge)
 
             # create physical ports
             self._vswitch.add_switch(self._bridge)
 
             # create physical ports
-            (_, phy1_number) = self._vswitch.add_phy_port(self._bridge)
-            (_, phy2_number) = self._vswitch.add_phy_port(self._bridge)
+            (phy1, _) = self._vswitch.add_phy_port(self._bridge)
+            (phy2, _) = self._vswitch.add_phy_port(self._bridge)
 
             # create VM ports
             # initialize vport array to requested number of VMs
 
             # create VM ports
             # initialize vport array to requested number of VMs
@@ -86,54 +68,42 @@ class VswitchControllerPXP(IVswitchController):
                 self._logger.debug('Create %s vports for %s. VM with index %s',
                                    nics_nr, vmindex + 1, vmindex)
                 for _ in range(nics_nr):
                 self._logger.debug('Create %s vports for %s. VM with index %s',
                                    nics_nr, vmindex + 1, vmindex)
                 for _ in range(nics_nr):
-                    (_, vport) = self._vswitch.add_vport(self._bridge)
+                    (vport, _) = self._vswitch.add_vport(self._bridge)
                     vm_ports[vmindex].append(vport)
 
                     vm_ports[vmindex].append(vport)
 
-            self._vswitch.del_flow(self._bridge)
-
-            # configure flows according to the TC definition
+            # configure connections according to the TC definition
             if self._pxp_topology == 'serial':
             if self._pxp_topology == 'serial':
-                flow = _FLOW_TEMPLATE.copy()
-                if self._traffic['flow_type'] == 'IP':
-                    flow.update({'dl_type':'0x0800',
-                                 'nw_src':self._traffic['l3']['srcip'],
-                                 'nw_dst':self._traffic['l3']['dstip']})
+                # NOTE: all traffic from VMs is sent to other ports directly
+                # without applying traffic options to avoid issues with MAC swapping
+                # and upper layer mods performed inside guests
 
 
-                # insert flows for phy ports first
+                # insert connections for phy ports first
                 # from 1st PHY to 1st vport of 1st VM
                 # from 1st PHY to 1st vport of 1st VM
-                self._add_flow(flow,
-                               phy1_number,
-                               vm_ports[0][0],
-                               self._bidir)
+                self._vswitch.add_connection(self._bridge, phy1, vm_ports[0][0], self._traffic)
+                self._vswitch.add_connection(self._bridge, vm_ports[0][0], phy1)
                 # from last vport of last VM to 2nd phy
                 # from last vport of last VM to 2nd phy
-                self._add_flow(flow,
-                               vm_ports[self._pxp_vm_count-1][-1],
-                               phy2_number,
-                               self._bidir)
+                self._vswitch.add_connection(self._bridge, vm_ports[self._pxp_vm_count-1][-1], phy2)
+                self._vswitch.add_connection(self._bridge, phy2, vm_ports[self._pxp_vm_count-1][-1], self._traffic)
 
                 # add serial connections among VMs and VM NICs pairs if needed
                 # in case of multiple NICs pairs per VM, the pairs are chained
 
                 # add serial connections among VMs and VM NICs pairs if needed
                 # in case of multiple NICs pairs per VM, the pairs are chained
-                # first, before flow to the next VM is created
+                # first, before connection to the next VM is created
                 for vmindex in range(self._pxp_vm_count):
                     # connect VMs NICs pairs in case of 4 and more NICs per VM
                     connections = [(vm_ports[vmindex][2*(x+1)-1],
                                     vm_ports[vmindex][2*(x+1)])
                                    for x in range(int(len(vm_ports[vmindex])/2)-1)]
                     for connection in connections:
                 for vmindex in range(self._pxp_vm_count):
                     # connect VMs NICs pairs in case of 4 and more NICs per VM
                     connections = [(vm_ports[vmindex][2*(x+1)-1],
                                     vm_ports[vmindex][2*(x+1)])
                                    for x in range(int(len(vm_ports[vmindex])/2)-1)]
                     for connection in connections:
-                        self._add_flow(flow,
-                                       connection[0],
-                                       connection[1],
-                                       self._bidir)
+                        self._vswitch.add_connection(self._bridge, connection[0], connection[1])
+                        self._vswitch.add_connection(self._bridge, connection[1], connection[0])
                     # connect last NICs to the next VM if there is any
                     if self._pxp_vm_count > vmindex + 1:
                     # connect last NICs to the next VM if there is any
                     if self._pxp_vm_count > vmindex + 1:
-                        self._add_flow(flow,
-                                       vm_ports[vmindex][-1],
-                                       vm_ports[vmindex+1][0],
-                                       self._bidir)
+                        self._vswitch.add_connection(self._bridge, vm_ports[vmindex][-1], vm_ports[vmindex+1][0])
+                        self._vswitch.add_connection(self._bridge, vm_ports[vmindex+1][0], vm_ports[vmindex][-1])
             else:
             else:
-                proto = _PROTO_TCP if self._traffic['l3']['proto'].lower() == 'tcp' else _PROTO_UDP
-                dst_mac_value = netaddr.EUI(self._traffic['l2']['dstmac']).value
-                dst_ip_value = netaddr.IPAddress(self._traffic['l3']['dstip']).value
+                mac_value = netaddr.EUI(self._traffic['l2']['dstmac']).value
+                ip_value = netaddr.IPAddress(self._traffic['l3']['dstip']).value
+                port_value = self._traffic['l4']['dstport']
                 # initialize stream index; every NIC pair of every VM uses unique stream
                 stream = 0
                 for vmindex in range(self._pxp_vm_count):
                 # initialize stream index; every NIC pair of every VM uses unique stream
                 stream = 0
                 for vmindex in range(self._pxp_vm_count):
@@ -146,31 +116,33 @@ class VswitchControllerPXP(IVswitchController):
                         port_pairs = [(vm_ports[vmindex][0], vm_ports[vmindex][0])]
 
                     for port_pair in port_pairs:
                         port_pairs = [(vm_ports[vmindex][0], vm_ports[vmindex][0])]
 
                     for port_pair in port_pairs:
-                        flow_p = _FLOW_TEMPLATE.copy()
-                        flow_v = _FLOW_TEMPLATE.copy()
-
-                        # update flow based on trafficgen settings
+                        # override traffic options to ensure, that traffic is
+                        # dispatched among VMs connected in parallel
+                        options = {'multistream':1,
+                                   'stream_type':self._traffic['stream_type'],
+                                   'pre_installed_flows':'Yes'}
+                        # update connection based on trafficgen settings
                         if self._traffic['stream_type'] == 'L2':
                         if self._traffic['stream_type'] == 'L2':
-                            tmp_mac = netaddr.EUI(dst_mac_value + stream)
+                            tmp_mac = netaddr.EUI(mac_value + stream)
                             tmp_mac.dialect = netaddr.mac_unix_expanded
                             tmp_mac.dialect = netaddr.mac_unix_expanded
-                            flow_p.update({'dl_dst':tmp_mac})
+                            options.update({'l2':{'dstmac':tmp_mac}})
                         elif self._traffic['stream_type'] == 'L3':
                         elif self._traffic['stream_type'] == 'L3':
-                            tmp_ip = netaddr.IPAddress(dst_ip_value + stream)
-                            flow_p.update({'dl_type':'0x0800', 'nw_dst':tmp_ip})
+                            tmp_ip = netaddr.IPAddress(ip_value + stream)
+                            options.update({'l3':{'dstip':tmp_ip}})
                         elif self._traffic['stream_type'] == 'L4':
                         elif self._traffic['stream_type'] == 'L4':
-                            flow_p.update({'dl_type':'0x0800', 'nw_proto':proto, 'tp_dst':stream})
+                            options.update({'l3':{'proto':self._traffic['l3']['proto']}})
+                            options.update({'l4':{'dstport':(port_value + stream) % 65536}})
                         else:
                             raise RuntimeError('Unknown stream_type {}'.format(self._traffic['stream_type']))
 
                         else:
                             raise RuntimeError('Unknown stream_type {}'.format(self._traffic['stream_type']))
 
-                        # insert flow to dispatch traffic from physical ports
+                        # insert connection to dispatch traffic from physical ports
                         # to VMs based on stream type; all traffic from VMs is
                         # sent to physical ports to avoid issues with MAC swapping
                         # and upper layer mods performed inside guests
                         # to VMs based on stream type; all traffic from VMs is
                         # sent to physical ports to avoid issues with MAC swapping
                         # and upper layer mods performed inside guests
-                        self._add_flow(flow_p, phy1_number, port_pair[0])
-                        self._add_flow(flow_v, port_pair[1], phy2_number)
-                        if self._bidir:
-                            self._add_flow(flow_p, phy2_number, port_pair[1])
-                            self._add_flow(flow_v, port_pair[0], phy1_number)
+                        self._vswitch.add_connection(self._bridge, phy1, port_pair[0], options)
+                        self._vswitch.add_connection(self._bridge, port_pair[1], phy2)
+                        self._vswitch.add_connection(self._bridge, phy2, port_pair[1], options)
+                        self._vswitch.add_connection(self._bridge, port_pair[0], phy1)
 
                         # every NIC pair needs its own unique traffic stream
                         stream += 1
 
                         # every NIC pair needs its own unique traffic stream
                         stream += 1
@@ -185,37 +157,13 @@ class VswitchControllerPXP(IVswitchController):
         self._logger.debug('Stop using %s', str(self._vswitch_class))
         self._vswitch.stop()
 
         self._logger.debug('Stop using %s', str(self._vswitch_class))
         self._vswitch.stop()
 
-    def _add_flow(self, flow, port1, port2, reverse_flow=False):
-        """ Helper method to insert flow into the vSwitch
-        """
-        self._vswitch.add_flow(self._bridge,
-                               add_ports_to_flow(flow,
-                                                 port1,
-                                                 port2))
-        if reverse_flow:
-            self._vswitch.add_flow(self._bridge,
-                                   add_ports_to_flow(flow,
-                                                     port2,
-                                                     port1))
-
-    def __enter__(self):
-        self.setup()
-
-    def __exit__(self, type_, value, traceback):
-        self.stop()
-
-    def get_vswitch(self):
-        """See IVswitchController for description
-        """
-        return self._vswitch
-
     def get_ports_info(self):
         """See IVswitchController for description
         """
         self._logger.debug('get_ports_info  using %s', str(self._vswitch_class))
         return self._vswitch.get_ports(self._bridge)
 
     def get_ports_info(self):
         """See IVswitchController for description
         """
         self._logger.debug('get_ports_info  using %s', str(self._vswitch_class))
         return self._vswitch.get_ports(self._bridge)
 
-    def dump_vswitch_flows(self):
+    def dump_vswitch_connections(self):
         """See IVswitchController for description
         """
         """See IVswitchController for description
         """
-        self._vswitch.dump_flows(self._bridge)
+        self._vswitch.dump_connections(self._bridge)