Beispiel #1
0
class Drone():
    def __init__(self, host_name='127.0.0.1', port_number=7878, tx_port_list=None, rx_port_list=None):
        self.__drone = DroneProxy(host_name, port_number)
        if tx_port_list:
            self.__tx_port_list = tx_port_list.all_ports
        else:
            self.__tx_port_list = None
        if rx_port_list:
            self.__rx_port_list = rx_port_list.all_ports
        else:
            self.__rx_port_list = None

    def connect(self):
        self.__drone.connect()
        self.tx_port_clear_stats()
        self.rx_port_clear_stats()
        return self

    def disconnect(self):
        self.__drone.disconnect()
        return self

    def add_stream_list(self, stream_list):
        self.current_stream_list = stream_list
        self.__drone.addStream(stream_list.all_streams)
        self.__drone.modifyStream(stream_list.all_streams_configurations)
        return self

    def remove_stream_list(self, stream_id_list):
        self.__drone.deleteStream(stream_id_list)
        return self

    def remove_current_stream_list(self):
        assert(self.current_stream_list)
        self.__drone.deleteStream(self.current_stream_list.all_streams)
        return self

    def fetch_stream_id_list(self):
        assert(self.__tx_port_list)
        stream_id_list = self.__drone.getStreamIdList(self.__tx_port_list.port_id[0])
        return stream_id_list

    def fetch_port_id_list(self):
        port_id_list = self.__drone.getPortIdList()
        return port_id_list

    def get_port_config_list(self):
        port_config_list = self.__drone.getPortConfig(self.fetch_port_id_list())
        return port_config_list

    def start_transmit(self):
        assert(self.__tx_port_list)
        self.tx_port_clear_stats()
        self.__drone.startTransmit(self.__tx_port_list)
        return self

    def wait_for_transmission_complete(self, time_out=None):
        time_start = time.time()
        while True:
            time.sleep(1)
            tx_stats = self.fetch_stats_tx_port()
            print('transmit rate %s bps' % (tx_stats.tx_bps * 8))
            if (not tx_stats.state.is_transmit_on)\
            or (time_out and (time.time() - time_start > time_out)):
                break
            else:
                print('waiting for transmit to finish ,elapsed time %s seconds' % (time.time() - time_start))

        print('transmit total time %s seconds' % (time.time() - time_start))
        return self

    def stop_transmit(self):
        assert(self.__tx_port_list)
        self.__drone.stopTransmit(self.__tx_port_list)
        return self

    def __start_capture(self, port_list):
        assert(port_list)
        self.__drone.startCapture(port_list)

    def __stop_capture(self, port_list):
        assert(port_list)
        self.__drone.stopCapture(port_list)

    def __clear_stats(self, port_list):
        # assert(port)
        if port_list:
            self.__drone.clearStats(port_list)

    def __fetch_stats_port(self, port_list):
        assert(port_list)
        stats = self.__drone.getStats(port_list)
        return stats.port_stats[0]

    def __fetch_capture_buffer(self, port_list, buffer_file_name='capture.pcap'):
        assert(port_list)
        buffer = self.__drone.getCaptureBuffer(port_list.port_id[0])
        self.__drone.saveCaptureBuffer(buffer, buffer_file_name)
        # os.system('tshark -r ' + buffer_file_name)
        # os.remove(buffer_file_name)

    def tx_port_start_capture(self):
        self.__start_capture(self.__tx_port_list)
        return self

    def tx_port_stop_capture(self):
        self.__stop_capture(self.__tx_port_list)
        return self

    def tx_port_clear_stats(self):
        self.__clear_stats(self.__tx_port_list)
        return self

    def rx_port_start_capture(self):
        self.__start_capture(self.__rx_port_list)
        return self

    def rx_port_stop_capture(self):
        self.__stop_capture(self.__rx_port_list)
        return self

    def rx_port_clear_stats(self):
        self.__clear_stats(self.__rx_port_list)
        return self

    def fetch_stats_tx_port(self):
        return self.__fetch_stats_port(self.__tx_port_list)

    def fetch_capture_buffer_tx_port(self):
        self.__fetch_capture_buffer(self.__tx_port_list, buffer_file_name='tx_port_capture.pcap')

    def fetch_stats_rx_port(self):
        return self.__fetch_stats_port(self.__rx_port_list)

    def fetch_capture_buffer_rx_port(self):
        self.__fetch_capture_buffer(self.__rx_port_list, buffer_file_name='rx_port_capture.pcap')
Beispiel #2
0
class Traffic(object):
    """Class for traffic streams"""
    def __init__(self):
        self.drone = DroneProxy('127.0.0.1')
        self.drone.connect()

        self.port_id_list = self.drone.getPortIdList()
        self.port_config_list = self.drone.getPortConfig(self.port_id_list)
        self.tx_port = ost_pb.PortIdList()
        self.rx_port = ost_pb.PortIdList()
        self.interfaces = self._getInterfaces()
        self.addedInterfaces = []
        self.tx_stats = None

    def __del__(self):
        """Cleanup the streams"""
        for interface in self.interfaces:
            self.drone.deleteStream(interface['stream_id_list'])
        self.drone.disconnect()

    def _getInterfaces(self):
        """Create a list of interface dicts which can be used for streams"""
        interfaces = []
        for port in self.port_config_list.port:
            stream_id_list = ost_pb.StreamIdList()
            stream_id_list.stream_id.add().id = 1
            stream_id_list.stream_id.add().id = 2
            stream_id_list.stream_id.add().id = 3
            stream_id_list.stream_id.add().id = 4
            stream_id_list.stream_id.add().id = 5
            stream_id_list.port_id.id = port.port_id.id
            self.drone.addStream(stream_id_list)
            stream_cfg = ost_pb.StreamConfigList()
            stream_cfg.port_id.id = port.port_id.id

            interface = {
                'name': port.name,
                'port_id': port.port_id,
                'port_id_id': port.port_id.id,
                'stream_id_list': stream_id_list,
                'stream_cfg': stream_cfg,
                'stream_id': 1,
            }
            interfaces.append(interface)
        return interfaces

    def _cleanupRun(self):
        """Delete all current streams, so that we can create new
           once for the next run"""
        for interface in self.interfaces:
            stream_id_list = interface['stream_id_list']
            port_id = interface['port_id_id']
            self.drone.deleteStream(stream_id_list)
            self.drone.addStream(stream_id_list)
            stream_cfg = ost_pb.StreamConfigList()
            stream_cfg.port_id.id = port_id
            interface['stream_cfg'] = stream_cfg
            interface['stream_id'] = 1

    def _getInterfaceByName(self, interface_name):
        """Return the interface dict for a given interface name"""
        for interface in self.interfaces:
            if interface['name'] == interface_name:
                return interface
        raise NameError('getInterface called for unknown interface name')

    def _getInterfaceByPortId(self, port_id):
        """Return the interface dict for a given interface name"""
        for interface in self.interfaces:
            if interface['port_id_id'] == port_id:
                return interface
        raise NameError('getInterface called for unknown interface name')

    def _getInterfaceId(self, interface_name):
        """Return the Ostinato ID for an interface name"""
        for interface in self.interfaces:
            if interface['name'] == interface_name:
                return interface['port_id_id']
        raise NameError('getInterfaceId called for unknown interface {0}'.
                        format(interface_name))

    def getInterfaceNames(self):
        """Return a list of interface names which can be used for streams"""
        return [interface['name'] for interface in self.interfaces]

    def addInterface(self, interface_name):
        """Add an interface to the configuration. It will then be used for
           transmit and receive"""
        dbg_print('addInterface({0})'.format(interface_name))
        self.addedInterfaces.append(interface_name)
        port_id = self._getInterfaceId(interface_name)
        self.rx_port.port_id.add().id = port_id
        self.tx_port.port_id.add().id = port_id

    def _getInterfaceMacAddress(self, interface):
        """Return the MAC address of an interface"""
        return 0x001020304000 + interface['port_id_id']

    def _getInterfaceIPAddress(self, interface):
        """Return the IP address of an interface"""
        return 0xc0a83a0a + interface['port_id_id']

    def _addEthernetHeader(self, stream, src_mac, dst_mac):
        """Add an Ethernet header to a stream"""
        proto = stream.protocol.add()
        proto.protocol_id.id = ost_pb.Protocol.kMacFieldNumber
        proto.Extensions[mac].src_mac = src_mac
        proto.Extensions[mac].dst_mac = dst_mac

    def _addEthertypeIP(self, stream):
        """Add an Ethernet Type header for IP to a stream"""
        proto = stream.protocol.add()
        proto.protocol_id.id = ost_pb.Protocol.kEth2FieldNumber
        proto.Extensions[eth2].type = 0x0800
        proto.Extensions[eth2].is_override_type = True

    def _addIPHeader(self, stream, src_ip, dst_ip):
        """Add an IP header to a stream"""
        proto = stream.protocol.add()
        proto.protocol_id.id = ost_pb.Protocol.kIp4FieldNumber
        proto.Extensions[ip4].src_ip = src_ip
        proto.Extensions[ip4].dst_ip = dst_ip

    def _addUdpHeader(self, stream, src_port, dst_port):
        """Add a UDP header to a stream"""
        proto = stream.protocol.add()
        proto.protocol_id.id = ost_pb.Protocol.kUdpFieldNumber
        proto.Extensions[udp].is_override_src_port = True
        proto.Extensions[udp].is_override_dst_port = True
        proto.Extensions[udp].src_port = src_port
        proto.Extensions[udp].dst_port = dst_port

    def _addIGMPHeader(self, stream, igmp_type, group):
        """Add an IGMP header to a stream"""
        proto = stream.protocol.add()
        proto.protocol_id.id = ost_pb.Protocol.kIgmpFieldNumber
        proto.Extensions[igmp].type = igmp_type
        proto.Extensions[igmp].group_address.v4 = group

    def _addIGMPRequestHeader(self, stream, group):
        """Add an IGMP Request header to a stream"""
        self._addIGMPHeader(stream, IGMPv2_REQUEST, group)

    def _addStream(self, stream_cfg, interface, num_packets, packets_per_sec):
        """Add a stream to an interface, and return it"""
        stream = stream_cfg.stream.add()
        stream.stream_id.id = interface['stream_id']
        interface['stream_id'] = interface['stream_id'] + 1
        stream.core.is_enabled = True
        stream.core.frame_len = 128
        stream.control.num_packets = num_packets
        stream.control.packets_per_sec = packets_per_sec
        return stream

    def _addUDPPacketStream(self, stream, src_mac, dst_mac, src_ip, dst_ip):
        """Add a UDP packets to a stream"""
        self._addEthernetHeader(stream, src_mac=src_mac,
                                dst_mac=dst_mac)
        self._addEthertypeIP(stream)
        self._addIPHeader(stream, src_ip=src_ip, dst_ip=dst_ip)
        self._addUdpHeader(stream, 0x1234, 0x4321)

        proto = stream.protocol.add()
        proto.protocol_id.id = ost_pb.Protocol.kPayloadFieldNumber

    def addUDPStream(self, src_interface_name, dst_interface_name,
                     num_packets, packets_per_sec):
        """Add a UDP stream from the source interface to the destination
           interface"""
        dbg_print('addUDPStream({0} {1} {2} {3})'.format(src_interface_name,
                                                         dst_interface_name,
                                                         num_packets,
                                                         packets_per_sec))
        src_interface = self._getInterfaceByName(src_interface_name)
        dst_interface = self._getInterfaceByName(dst_interface_name)
        stream_cfg = src_interface['stream_cfg']
        stream = self._addStream(stream_cfg, src_interface, num_packets,
                                 packets_per_sec)
        src_mac = self._getInterfaceMacAddress(src_interface)
        dst_mac = self._getInterfaceMacAddress(dst_interface)
        src_ip = self._getInterfaceIPAddress(src_interface)
        dst_ip = self._getInterfaceIPAddress(dst_interface)

        self._addUDPPacketStream(stream, src_mac, dst_mac, src_ip, dst_ip)
        self.drone.modifyStream(stream_cfg)

    def addUDPBroadcastStream(self, src_interface_name, num_packets,
                              packets_per_sec):
        """Add a UDP broadcast stream from the source interface to the
           broadcast address"""
        dbg_print('addUDPBroadcastStream({0} {1} {2})'.
                  format(src_interface_name,
                         num_packets,
                         packets_per_sec))
        src_interface = self._getInterfaceByName(src_interface_name)
        stream_cfg = src_interface['stream_cfg']
        stream = self._addStream(stream_cfg, src_interface, num_packets,
                                 packets_per_sec)
        src_mac = self._getInterfaceMacAddress(src_interface)
        dst_mac = 0xffffffffffff
        src_ip = self._getInterfaceIPAddress(src_interface)
        dst_ip = 0xc0a82aff

        self._addUDPPacketStream(stream, src_mac, dst_mac, src_ip, dst_ip)
        self.drone.modifyStream(stream_cfg)

    def addUDPMulticastStream(self, src_interface_name, group_str, num_packets,
                              packets_per_sec):
        """Add a UDP multicast stream from the source interface to the
           group address"""
        dbg_print('addUDPMulticastStream({0} {1} {2} {3})'.
                  format(src_interface_name,
                         group_str,
                         num_packets,
                         packets_per_sec))
        src_interface = self._getInterfaceByName(src_interface_name)
        stream_cfg = src_interface['stream_cfg']
        stream = self._addStream(stream_cfg, src_interface, num_packets,
                                 packets_per_sec)
        src_mac = self._getInterfaceMacAddress(src_interface)
        group = ipaddress.ip_address(group_str.decode())
        dst_mac = 0x01005e000000 + (int(group) & 0x07fffff)
        src_ip = self._getInterfaceIPAddress(src_interface)
        dst_ip = int(group)

        self._addUDPPacketStream(stream, src_mac, dst_mac, src_ip, dst_ip)
        self.drone.modifyStream(stream_cfg)

    def addIGMPRequestStream(self, src_interface_name, group, num_packets,
                             packets_per_sec):
        """Add a IGMP request stream from the source interface to the
           group address"""
        dbg_print('addIGMPStream({0} {1} {2})'.
                  format(src_interface_name, group, num_packets))
        src_interface = self._getInterfaceByName(src_interface_name)
        stream_cfg = src_interface['stream_cfg']
        stream = self._addStream(stream_cfg, src_interface, num_packets,
                                 packets_per_sec)
        src_mac = self._getInterfaceMacAddress(src_interface)
        dst_mac = 0x01005e00001
        src_ip = self._getInterfaceIPAddress(src_interface)
        dst_ip = group

        self._addEthernetHeader(stream, src_mac=src_mac,
                                dst_mac=dst_mac)
        self._addEthertypeIP(stream)
        self._addIPHeader(stream, src_ip=src_ip, dst_ip=dst_ip)
        self._addIGMPRequestHeader(stream, group)

        self.drone.modifyStream(stream_cfg)

    def learningStream(self, interface_name):
        """Create a stream on the interface for bridge learning. Two broadcast
           packets will be sent, so allowing the switch to learn the source
           MAC address on the interface."""
        dbg_print('learningStream({0})'.format(interface_name))
        self.addUDPBroadcastStream(interface_name, 2, 1)

    def learning(self):
        """Perform learning on each port, by sending a couple of packet,
           so that the bridge learns the address on the interface"""
        dbg_print('learning')
        for interface_name in self.addedInterfaces:
            self.learningStream(interface_name)
        frame = inspect.stack()[1][0]
        method = inspect.stack()[1][3]
        test = get_class_from_frame(frame).__name__
        self._run(test, method)

    def _saveCapture(self, testname, methodname, interface_name):
        """Save the capture file for one interface"""
        filename = "{0}-{1}-{2}.pcap".format(testname, methodname,
                                             interface_name)
        interface = self._getInterfaceByName(interface_name)
        buff = self.drone.getCaptureBuffer(interface['port_id'])
        self.drone.saveCaptureBuffer(buff, filename)

    def _saveCaptures(self, testname, methodname):
        """Save the capture files, using the test name as a prefix"""
        for interface_name in self.addedInterfaces:
            self._saveCapture(testname, methodname, interface_name)

    def _run(self, test, method):
        """Do the real work"""
        self.drone.clearStats(self.tx_port)
        self.drone.clearStats(self.rx_port)
        self.drone.startCapture(self.rx_port)
        self.drone.startTransmit(self.tx_port)

        done = False
        while not done:
            done = True
            tx_stats = self.drone.getStats(self.tx_port)
            for port_stats in tx_stats.port_stats:
                if port_stats.state.is_transmit_on:
                    done = False
            time.sleep(1)

        self.drone.stopTransmit(self.tx_port)
        self.drone.stopCapture(self.rx_port)
        self.tx_stats = self.drone.getStats(self.tx_port)
        self._saveCaptures(test, method)
        self._cleanupRun()

    def run(self):
        """Run the streams"""
        dbg_print('run')
        frame = inspect.stack()[1][0]
        method = inspect.stack()[1][3]
        test = get_class_from_frame(frame).__name__
        self._run(test, method)

    def getStats(self, interface_name):
        """Return the interface statistics"""
        dbg_print('getStats({0})'.format(interface_name))
        port_id = self._getInterfaceId(interface_name)
        for port_stats in self.tx_stats.port_stats:
            if port_stats.port_id.id == port_id:
                stats = {
                    'rx_pkts': port_stats.rx_pkts,
                    'rx_pps': port_stats.rx_pps,
                    'rx_bps': port_stats.rx_bps,
                    'tx_pkts': port_stats.tx_pkts,
                    'tx_pps': port_stats.tx_pps,
                    'tx_bps': port_stats.tx_bps,
                    'rx_drops': port_stats.rx_drops,
                    'rx_errors': port_stats.rx_errors,
                    'rx_fifo_errors': port_stats.rx_fifo_errors,
                    'rx_frame_errors': port_stats.rx_frame_errors,
                }
                return stats
p = s.protocol.add()
p.protocol_id.id = ost_pb.Protocol.kIp4FieldNumber
ip = p.Extensions[ip4]
ip.src_ip = int(ip_src, 16)
ip.dst_ip = int(ip_dst, 16)

p = s.protocol.add()
p.protocol_id.id = ost_pb.Protocol.kUdpFieldNumber

s.protocol.add().protocol_id.id = ost_pb.Protocol.kPayloadFieldNumber

drone.modifyStream(stream_cfg)

drone.clearStats(tx_port)

drone.startTransmit(tx_port)

# wait for transmit to finish
try:
    time.sleep(1000)
except KeyboardInterrupt:
    drone.stopTransmit(tx_port)
    drone.stopCapture(tx_port)

    stats = drone.getStats(tx_port)

    print(stats)

    drone.deleteStream(stream_id)
    drone.disconnect()
    # start capture and transmit
    log.info('starting capture')
    drone.startCapture(rx_port)
    log.info('starting transmit')
    drone.startTransmit(tx_port)

    # wait for transmit to finish
    log.info('waiting for transmit to finish ...')
    time.sleep(7)

    # stop transmit and capture
    log.info('stopping transmit')
    drone.stopTransmit(tx_port)
    log.info('stopping capture')
    drone.stopCapture(rx_port)

    # get tx/rx stats
    log.info('retreiving stats')
    tx_stats = drone.getStats(tx_port)
    rx_stats = drone.getStats(rx_port)

    #log.info('--> (tx_stats)' + tx_stats.__str__())
    #log.info('--> (rx_stats)' + rx_stats.__str__())
    log.info('tx pkts = %d, rx pkts = %d' %
             (tx_stats.port_stats[0].tx_pkts, rx_stats.port_stats[0].rx_pkts))

    # retrieve and dump received packets
    log.info('getting Rx capture buffer')
    buff = drone.getCaptureBuffer(rx_port.port_id[0])
    drone.saveCaptureBuffer(buff, 'capture.pcap')