diff options
Diffstat (limited to 'core/vswitch_controller_pxp.py')
-rw-r--r-- | core/vswitch_controller_pxp.py | 136 |
1 files changed, 42 insertions, 94 deletions
diff --git a/core/vswitch_controller_pxp.py b/core/vswitch_controller_pxp.py index e3c208a3..d36ecdba 100644 --- a/core/vswitch_controller_pxp.py +++ b/core/vswitch_controller_pxp.py @@ -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. @@ -14,34 +14,18 @@ """VSwitch controller for multi VM scenarios with serial or parallel connection """ - -import logging import netaddr from core.vswitch_controller import IVswitchController -from vswitches.utils import add_ports_to_flow 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): - """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 @@ -55,9 +39,7 @@ class VswitchControllerPXP(IVswitchController): self._deployment_scenario = deployment - self._traffic = traffic.copy() 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): @@ -71,8 +53,8 @@ class VswitchControllerPXP(IVswitchController): 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 @@ -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): - (_, vport) = self._vswitch.add_vport(self._bridge) + (vport, _) = self._vswitch.add_vport(self._bridge) 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': - 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 - 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 - 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 - # 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: - 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: - 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: - 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): @@ -146,31 +116,33 @@ class VswitchControllerPXP(IVswitchController): 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': - tmp_mac = netaddr.EUI(dst_mac_value + stream) + tmp_mac = netaddr.EUI(mac_value + stream) 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': - 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': - 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'])) - # 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 - 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 @@ -185,37 +157,13 @@ class VswitchControllerPXP(IVswitchController): 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 dump_vswitch_flows(self): + def dump_vswitch_connections(self): """See IVswitchController for description """ - self._vswitch.dump_flows(self._bridge) + self._vswitch.dump_connections(self._bridge) |