def stream(request, drone, ports): global proto_number # add a stream stream_id = ost_pb.StreamIdList() stream_id.port_id.CopyFrom(ports.tx.port_id[0]) stream_id.stream_id.add().id = 1 log.info('adding tx_stream %d' % stream_id.stream_id[0].id) drone.addStream(stream_id) # configure the stream stream_cfg = ost_pb.StreamConfigList() stream_cfg.port_id.CopyFrom(ports.tx.port_id[0]) s = stream_cfg.stream.add() s.stream_id.id = stream_id.stream_id[0].id s.core.is_enabled = True s.control.packets_per_sec = 100 s.control.num_packets = 10 # setup stream protocols as mac:eth2:ip:udp:payload s.ClearField("protocol") protos = request.param.split() for p in protos: s.protocol.add().protocol_id.id = proto_number[p] def fin(): # delete streams log.info('deleting tx_stream %d' % stream_id.stream_id[0].id) drone.deleteStream(stream_id) request.addfinalizer(fin) return stream_cfg
def stream(request, drone, ports): global proto_number # add a stream stream_id = ost_pb.StreamIdList() stream_id.port_id.CopyFrom(ports.tx.port_id[0]) stream_id.stream_id.add().id = 1 log.info('adding tx_stream %d' % stream_id.stream_id[0].id) drone.addStream(stream_id) # configure the stream stream_cfg = ost_pb.StreamConfigList() stream_cfg.port_id.CopyFrom(ports.tx.port_id[0]) s = stream_cfg.stream.add() s.stream_id.id = stream_id.stream_id[0].id s.core.is_enabled = True s.control.packets_per_sec = 100 s.control.num_packets = 10 # XXX: don't setup any stream protocols def fin(): # delete streams log.info('deleting tx_stream %d' % stream_id.stream_id[0].id) drone.deleteStream(stream_id) request.addfinalizer(fin) return stream_cfg
rx_port_number = port.port_id.id if tx_port_number < 0 or rx_port_number < 0: log.warning('loopback port not found') sys.exit(1) print('Using port %d as tx/rx port(s)' % tx_port_number) tx_port = ost_pb.PortIdList() tx_port.port_id.add().id = tx_port_number rx_port = ost_pb.PortIdList() rx_port.port_id.add().id = rx_port_number # add a stream stream_id = ost_pb.StreamIdList() stream_id.port_id.CopyFrom(tx_port.port_id[0]) stream_id.stream_id.add().id = 1 log.info('adding tx_stream %d' % stream_id.stream_id[0].id) drone.addStream(stream_id) # configure the stream stream_cfg = ost_pb.StreamConfigList() stream_cfg.port_id.CopyFrom(tx_port.port_id[0]) s = stream_cfg.stream.add() s.stream_id.id = stream_id.stream_id[0].id s.core.is_enabled = True s.control.num_packets = 10 # setup stream protocols as mac:eth2:ip4:udp:payload p = s.protocol.add()
def test_multiEmulDevPerVlan(request, drone, ports, dut, dut_ports, stream_clear, emul_ports, dgid_list, vlan_cfg, ip_ver): # ----------------------------------------------------------------- # # TESTCASE: Emulate multiple IPv4 device per multiple single-tag VLANs # # +- DUT -+ # .1/ \.1 # / \ # 10.1.1/24 10.1.2/24 # 1234:1/96 1234:2/96 # [vlans] [vlans] # / \ # /.101-103 \.101-103 # Host1(s) Host2(s) # ----------------------------------------------------------------- # num_vlans = 1 for vcfg in vlan_cfg: num_vlans = num_vlans * vcfg['count'] test_multiEmulDevPerVlan.vlan_cfg = vlan_cfg num_devs_per_vlan = 3 has_ip4 = True if 4 in ip_ver else False has_ip6 = True if 6 in ip_ver else False if has_ip4: tx_ip4_base = 0x0a010165 rx_ip4_base = 0x0a010265 if has_ip6: tx_ip6_base = ip6_address('1234:1::65/96') rx_ip6_base = ip6_address('1234:2::65/96') # configure vlans on the DUT dut_vlans(request, dut_ports) assert len(dut_vlans.vlans) == num_vlans vlan_filter = [] for i in range(len(dut_vlans.vlans)): vlan_filter.append('') ids = dut_vlans.vlans[i].split('.') for j in range(len(ids)): filter = '(frame[<ofs>:4]==<tpid>:<id>)' \ .replace('<ofs>', str(12+j*4)) \ .replace('<tpid>', '{:04x}'.format( vlan_cfg[j].get('tpid', 0x8100))) \ .replace('<id>', '{:04x}'.format(int(ids[j]))) if len(vlan_filter[i]) > 0: vlan_filter[i] += ' && ' vlan_filter[i] += filter print i, vlan_filter[i] # configure the tx device(s) devgrp_cfg = ost_pb.DeviceGroupConfigList() devgrp_cfg.port_id.CopyFrom(ports.tx.port_id[0]) dg = devgrp_cfg.device_group.add() dg.device_group_id.id = dgid_list.tx.device_group_id[0].id dg.core.name = "Host1" for vcfg in vlan_cfg: v = dg.encap.Extensions[emul.vlan].stack.add() v.vlan_tag = vcfg['base'] v.count = vcfg['count'] if 'tpid' in vcfg: v.tpid = vcfg['tpid'] if 'step' in vcfg: v.step = vcfg['step'] dg.device_count = num_devs_per_vlan dg.Extensions[emul.mac].address = 0x000102030a01 if has_ip4: ip = dg.Extensions[emul.ip4] ip.address = tx_ip4_base ip.prefix_length = 24 ip.default_gateway = (tx_ip4_base & 0xffffff00) | 0x01 if has_ip6: ip = dg.Extensions[emul.ip6] ip.address.CopyFrom(tx_ip6_base.ip6) ip.prefix_length = tx_ip6_base.prefixlen ip.default_gateway.CopyFrom(tx_ip6_base.gateway) drone.modifyDeviceGroup(devgrp_cfg) # configure the rx device(s) devgrp_cfg = ost_pb.DeviceGroupConfigList() devgrp_cfg.port_id.CopyFrom(ports.rx.port_id[0]) dg = devgrp_cfg.device_group.add() dg.device_group_id.id = dgid_list.rx.device_group_id[0].id dg.core.name = "Host1" for vcfg in vlan_cfg: v = dg.encap.Extensions[emul.vlan].stack.add() v.vlan_tag = vcfg['base'] v.count = vcfg['count'] if 'tpid' in vcfg: v.tpid = vcfg['tpid'] if 'step' in vcfg: v.step = vcfg['step'] dg.device_count = num_devs_per_vlan dg.Extensions[emul.mac].address = 0x000102030b01 if has_ip4: ip = dg.Extensions[emul.ip4] ip.address = rx_ip4_base ip.prefix_length = 24 ip.default_gateway = (rx_ip4_base & 0xffffff00) | 0x01 if has_ip6: ip = dg.Extensions[emul.ip6] ip.address.CopyFrom(rx_ip6_base.ip6) ip.prefix_length = rx_ip6_base.prefixlen ip.default_gateway.CopyFrom(rx_ip6_base.gateway) drone.modifyDeviceGroup(devgrp_cfg) # add the tx stream(s) - we need more than one stream stream_id = ost_pb.StreamIdList() stream_id.port_id.CopyFrom(ports.tx.port_id[0]) for i in range(num_vlans * len(ip_ver)): stream_id.stream_id.add().id = i log.info('adding tx_stream %d' % stream_id.stream_id[i].id) drone.addStream(stream_id) # configure the tx stream(s) stream_cfg = ost_pb.StreamConfigList() stream_cfg.port_id.CopyFrom(ports.tx.port_id[0]) for i in range(num_vlans): for j in range(len(ip_ver)): idx = i * len(ip_ver) + j s = stream_cfg.stream.add() s.stream_id.id = stream_id.stream_id[idx].id s.core.name = 'stream ' + str(s.stream_id.id) s.core.is_enabled = True s.core.ordinal = idx s.core.frame_len = 1024 s.control.packets_per_sec = 100 s.control.num_packets = num_devs_per_vlan # setup stream protocols as mac:vlan:eth2:ip4:udp:payload p = s.protocol.add() p.protocol_id.id = ost_pb.Protocol.kMacFieldNumber p.Extensions[mac].dst_mac_mode = Mac.e_mm_resolve p.Extensions[mac].src_mac_mode = Mac.e_mm_resolve ids = dut_vlans.vlans[i].split('.') for id, idx in zip(ids, range(len(ids))): p = s.protocol.add() p.protocol_id.id = ost_pb.Protocol.kVlanFieldNumber p.Extensions[vlan].vlan_tag = int(id) if 'tpid' in vlan_cfg[idx]: p.Extensions[vlan].tpid = vlan_cfg[idx]['tpid'] p.Extensions[vlan].is_override_tpid = True p = s.protocol.add() p.protocol_id.id = ost_pb.Protocol.kEth2FieldNumber if ip_ver[j] == 4: p = s.protocol.add() p.protocol_id.id = ost_pb.Protocol.kIp4FieldNumber ip = p.Extensions[ip4] ip.src_ip = tx_ip4_base ip.src_ip_mode = Ip4.e_im_inc_host ip.src_ip_count = num_devs_per_vlan ip.dst_ip = rx_ip4_base ip.dst_ip_mode = Ip4.e_im_inc_host ip.dst_ip_count = num_devs_per_vlan elif ip_ver[j] == 6: p = s.protocol.add() p.protocol_id.id = ost_pb.Protocol.kIp6FieldNumber ip = p.Extensions[ip6] ip.src_addr_hi = tx_ip6_base.ip6.hi ip.src_addr_lo = tx_ip6_base.ip6.lo ip.src_addr_mode = Ip6.kIncHost ip.src_addr_count = num_devs_per_vlan ip.src_addr_prefix = tx_ip6_base.prefixlen ip.dst_addr_hi = rx_ip6_base.ip6.hi ip.dst_addr_lo = rx_ip6_base.ip6.lo ip.dst_addr_mode = Ip6.kIncHost ip.dst_addr_count = num_devs_per_vlan ip.dst_addr_prefix = rx_ip6_base.prefixlen else: assert false # unreachable p = s.protocol.add() p.protocol_id.id = ost_pb.Protocol.kUdpFieldNumber p = s.protocol.add() p.protocol_id.id = ost_pb.Protocol.kPayloadFieldNumber log.info('configuring tx_stream %d' % stream_id.stream_id[idx].id) drone.modifyStream(stream_cfg) # clear arp/ndp on DUT for i in range(num_vlans): vrf = 'vrf' + str(i + 1) sudo('ip netns exec ' + vrf + ' ip neigh flush all') arp_cache = sudo('ip netns exec ' + vrf + ' ip neigh show') assert re.search('10.1.[1-2].20[1-5].*lladdr', arp_cache) == None assert re.search('1234:[1-2]::\[\da-f]+.*lladdr', arp_cache) == None # wait for interface to do DAD? Otherwise we don't get replies for NS # FIXME: find alternative to sleep if has_ip6: time.sleep(5) # clear ARP/NDP cache log.info('clearing ARP/NDP cache on tx/rx port') drone.clearDeviceNeighbors(emul_ports) log.info('retrieving ARP/NDP entries on tx port to verify clear') device_list = drone.getDeviceList(emul_ports.port_id[0]) device_config = device_list.Extensions[emul.device] neigh_list = drone.getDeviceNeighbors(emul_ports.port_id[0]) devices = neigh_list.Extensions[emul.device_neighbor] log.info('ARP/NDP Table on tx port') for devcfg, device in zip(device_config, devices): if has_ip4: for arp in device.arp: print('%s: %s %012x' % (str(ipaddress.ip_address( devcfg.ip4)), str(ipaddress.ip_address(arp.ip4)), arp.mac)) assert (len(device.arp) == 0) if has_ip6: for ndp in device.ndp: print('%s: %s %012x' % (str(ip6_address( devcfg.ip6)), str(ip6_address(ndp.ip6)), ndp.mac)) assert (len(device.ndp) == 0) log.info('retrieving ARP/NDP entries on rx port to verify clear') device_list = drone.getDeviceList(emul_ports.port_id[1]) device_config = device_list.Extensions[emul.device] neigh_list = drone.getDeviceNeighbors(emul_ports.port_id[1]) devices = neigh_list.Extensions[emul.device_neighbor] log.info('ARP/NDP Table on rx port') for devcfg, device in zip(device_config, devices): if has_ip4: for arp in device.arp: print('%s: %s %012x' % (str(ipaddress.ip_address( devcfg.ip4)), str(ipaddress.ip_address(arp.ip4)), arp.mac)) assert (len(device.arp) == 0) if has_ip6: for ndp in device.ndp: print('%s: %s %012x' % (str(ip6_address( devcfg.ip6)), str(ip6_address(ndp.ip6)), ndp.mac)) assert (len(device.ndp) == 0) # resolve ARP/NDP on tx/rx ports log.info('resolving Neighbors on tx/rx ports ...') drone.startCapture(emul_ports) drone.resolveDeviceNeighbors(emul_ports) time.sleep(3) drone.stopCapture(emul_ports) # verify ARP/NDP Requests sent out from tx port buff = drone.getCaptureBuffer(emul_ports.port_id[0]) drone.saveCaptureBuffer(buff, 'capture.pcap') log.info('dumping Tx capture buffer (all)') cap_pkts = subprocess.check_output([tshark, '-nr', 'capture.pcap']) print(cap_pkts) log.info('dumping Tx capture buffer (all pkts - vlans only)') cap_pkts = subprocess.check_output([ tshark, '-nr', 'capture.pcap', '-Tfields', '-eframe.number', '-eieee8021ad.id', '-evlan.id' ]) print(cap_pkts) log.info('dumping Tx capture buffer (filtered)') for i in range(num_vlans): for j in range(len(ip_ver)): if ip_ver[j] == 4: filter = vlan_filter[i] + ' && (arp.opcode == 1)' \ ' && (arp.src.proto_ipv4 == 10.1.1.<x>)' \ ' && (arp.dst.proto_ipv4 == 10.1.1.1)' \ ' && !expert.severity' elif ip_ver[j] == 6: filter = vlan_filter[i] + ' && (icmpv6.type == 135)' \ ' && (ipv6.src == 1234:1::<x>)' \ ' && (icmpv6.nd.ns.target_address == 1234:1::1)' \ ' && !expert.severity' for k in range(num_devs_per_vlan): if ip_ver[j] == 4: filter = filter.replace('<x>', str(101 + k)) elif ip_ver[j] == 6: filter = filter.replace('<x>', format(0x65 + k, 'x')) print filter cap_pkts = subprocess.check_output( [tshark, '-nr', 'capture.pcap', '-Y', filter]) print(cap_pkts) assert cap_pkts.count('\n') == 1 # verify ARP/NDP Requests sent out from rx port buff = drone.getCaptureBuffer(emul_ports.port_id[1]) drone.saveCaptureBuffer(buff, 'capture.pcap') log.info('dumping Rx capture buffer (all)') cap_pkts = subprocess.check_output([tshark, '-nr', 'capture.pcap']) print(cap_pkts) log.info('dumping Rx capture buffer (all pkts - vlans only)') cap_pkts = subprocess.check_output([ tshark, '-nr', 'capture.pcap', '-Tfields', '-eframe.number', '-eieee8021ad.id', '-evlan.id' ]) print(cap_pkts) log.info('dumping Rx capture buffer (filtered)') for i in range(num_vlans): for j in range(len(ip_ver)): if ip_ver[j] == 4: filter = vlan_filter[i] + ' && (arp.opcode == 1)' \ ' && (arp.src.proto_ipv4 == 10.1.2.<x>)' \ ' && (arp.dst.proto_ipv4 == 10.1.2.1)' \ ' && !expert.severity' elif ip_ver[j] == 6: filter = vlan_filter[i] + ' && (icmpv6.type == 135)' \ ' && (ipv6.src == 1234:2::<x>)' \ ' && (icmpv6.nd.ns.target_address == 1234:2::1)' \ ' && !expert.severity' for k in range(num_devs_per_vlan): if ip_ver[j] == 4: filter = filter.replace('<x>', str(101 + k)) elif ip_ver[j] == 6: filter = filter.replace('<x>', format(0x65 + k, 'x')) print filter cap_pkts = subprocess.check_output( [tshark, '-nr', 'capture.pcap', '-Y', filter]) print(cap_pkts) assert cap_pkts.count('\n') == 1 # retrieve and verify ARP/NDP Table on tx/rx ports log.info('retrieving ARP/NDP entries on tx port') device_list = drone.getDeviceList(emul_ports.port_id[0]) device_config = device_list.Extensions[emul.device] neigh_list = drone.getDeviceNeighbors(emul_ports.port_id[0]) devices = neigh_list.Extensions[emul.device_neighbor] log.info('ARP/NDP Table on tx port') for devcfg, device in zip(device_config, devices): vlans = '' for v in devcfg.vlan: vlans += str(v & 0xffff) + ' ' if has_ip4: resolved = False for arp in device.arp: print('%s%s: %s %012x' % (vlans, str(ipaddress.ip_address(devcfg.ip4)), str(ipaddress.ip_address(arp.ip4)), arp.mac)) if (arp.ip4 == devcfg.ip4_default_gateway) and (arp.mac): resolved = True assert resolved if has_ip6: resolved = False for ndp in device.ndp: print('%s%s: %s %012x' % (vlans, str(ip6_address( devcfg.ip6)), str(ip6_address(ndp.ip6)), ndp.mac)) if (ndp.ip6 == devcfg.ip6_default_gateway) and (ndp.mac): resolved = True assert resolved log.info('retrieving ARP entries on rx port') device_list = drone.getDeviceList(emul_ports.port_id[1]) device_config = device_list.Extensions[emul.device] neigh_list = drone.getDeviceNeighbors(emul_ports.port_id[1]) devices = neigh_list.Extensions[emul.device_neighbor] log.info('ARP/NDP Table on rx port') for devcfg, device in zip(device_config, devices): vlans = '' for v in devcfg.vlan: vlans += str(v & 0xffff) + ' ' if has_ip4: resolved = False for arp in device.arp: print('%s%s: %s %012x' % (vlans, str(ipaddress.ip_address(devcfg.ip4)), str(ipaddress.ip_address(arp.ip4)), arp.mac)) if (arp.ip4 == devcfg.ip4_default_gateway) and (arp.mac): resolved = True assert resolved if has_ip6: resolved = False for ndp in device.ndp: print('%s%s: %s %012x' % (vlans, str(ip6_address( devcfg.ip6)), str(ip6_address(ndp.ip6)), ndp.mac)) if (ndp.ip6 == devcfg.ip6_default_gateway) and (ndp.mac): resolved = True assert resolved # ping the tx devices from the DUT for i in range(num_vlans): vrf = 'vrf' + str(i + 1) for j in range(num_devs_per_vlan): if has_ip4: out = sudo('ip netns exec ' + vrf + ' ping -c3 10.1.1.' + str(101 + j), warn_only=True) assert '100% packet loss' not in out if has_ip6: out = sudo('ip netns exec ' + vrf + ' ping -6 -c3 1234:1::' + format(101 + j, 'x'), warn_only=True) assert '100% packet loss' not in out # ping the rx devices from the DUT for i in range(num_vlans): vrf = 'vrf' + str(i + 1) for j in range(num_devs_per_vlan): if has_ip4: out = sudo('ip netns exec ' + vrf + ' ping -c3 10.1.2.' + str(101 + j), warn_only=True) assert '100% packet loss' not in out if has_ip6: out = sudo('ip netns exec ' + vrf + ' ping -6 -c3 1234:2::' + format(101 + j, 'x'), warn_only=True) assert '100% packet loss' not in out # we are all set - send data stream(s) drone.startCapture(ports.rx) drone.startTransmit(ports.tx) log.info('waiting for transmit to finish ...') time.sleep(5) drone.stopTransmit(ports.tx) drone.stopCapture(ports.rx) # verify data packets received on rx port buff = drone.getCaptureBuffer(ports.rx.port_id[0]) drone.saveCaptureBuffer(buff, 'capture.pcap') log.info('dumping Rx capture buffer (all)') cap_pkts = subprocess.check_output([tshark, '-nr', 'capture.pcap']) print(cap_pkts) log.info('dumping Rx capture buffer (all pkts - vlans only)') cap_pkts = subprocess.check_output([ tshark, '-nr', 'capture.pcap', '-Tfields', '-eframe.number', '-eieee8021ad.id', '-evlan.id' ]) print(cap_pkts) log.info('dumping Rx capture buffer (filtered)') for i in range(num_vlans): for j in range(num_devs_per_vlan): if has_ip4: filter = vlan_filter[i] + \ ' && (ip.src == 10.1.1.' + str(101+j) + ')' \ ' && (ip.dst == 10.1.2.' + str(101+j) + ')' \ ' && (eth.dst == 00:01:02:03:0b:' + format(1+j, '02x')+')' print('filter: %s' % filter) cap_pkts = subprocess.check_output( [tshark, '-nr', 'capture.pcap', '-Y', filter]) print(cap_pkts) assert cap_pkts.count('\n') == 1 if has_ip6: filter = vlan_filter[i] \ + ' && (ipv6.src == 1234:1::' + format(101+j, 'x') + ')' \ + ' && (ipv6.dst == 1234:2::' + format(101+j, 'x') + ')' \ + ' && (eth.dst == 00:01:02:03:0b:' \ + format(1+j, '02x') + ')' print('filter: %s' % filter) cap_pkts = subprocess.check_output( [tshark, '-nr', 'capture.pcap', '-Y', filter]) print(cap_pkts) assert cap_pkts.count('\n') == 1 os.remove('capture.pcap')
def test_multiEmulDevNoVlan(drone, ports, dut, dut_ports, dut_ip, stream_clear, emul_ports, dgid_list, dev_cfg): # ----------------------------------------------------------------- # # TESTCASE: Emulate multiple IPv4 devices (no vlans) # DUT # /.1 \.1 # / \ # 10.10.1/24 10.10.2/24 # 1234::1/96 1234::2/96 # / \ # /.101-105 \.101-105 # Host1(s) Host2(s) # ----------------------------------------------------------------- # num_devs = 5 has_ip4 = True if 4 in dev_cfg['ip_ver'] else False has_ip6 = True if 6 in dev_cfg['ip_ver'] else False mac_step = dev_cfg['mac_step'] ip_step = dev_cfg['ip_step'] # configure the tx device(s) devgrp_cfg = ost_pb.DeviceGroupConfigList() devgrp_cfg.port_id.CopyFrom(ports.tx.port_id[0]) dg = devgrp_cfg.device_group.add() dg.device_group_id.id = dgid_list.tx.device_group_id[0].id dg.core.name = "Host1" dg.device_count = num_devs dg.Extensions[emul.mac].address = 0x000102030a01 if (mac_step != 1): dg.Extensions[emul.mac].step = mac_step if has_ip4: ip = dg.Extensions[emul.ip4] ip.address = 0x0a0a0165 ip.prefix_length = 24 if (ip_step != 1): ip.step = ip_step ip.default_gateway = 0x0a0a0101 if has_ip6: ip = dg.Extensions[emul.ip6] ip6addr = ip6_address('1234:1::65/96') ip.address.CopyFrom(ip6addr.ip6) ip.prefix_length = ip6addr.prefixlen if (ip_step != 1): ip.step.CopyFrom(ip6_address(ip_step).ip6) ip.default_gateway.CopyFrom(ip6addr.gateway) drone.modifyDeviceGroup(devgrp_cfg) # configure the rx device(s) devgrp_cfg = ost_pb.DeviceGroupConfigList() devgrp_cfg.port_id.CopyFrom(ports.rx.port_id[0]) dg = devgrp_cfg.device_group.add() dg.device_group_id.id = dgid_list.rx.device_group_id[0].id dg.core.name = "Host1" dg.device_count = num_devs dg.Extensions[emul.mac].address = 0x000102030b01 if (mac_step != 1): dg.Extensions[emul.mac].step = mac_step if has_ip4: ip = dg.Extensions[emul.ip4] ip.address = 0x0a0a0265 ip.prefix_length = 24 if (ip_step != 1): ip.step = ip_step ip.default_gateway = 0x0a0a0201 if has_ip6: ip = dg.Extensions[emul.ip6] ip6addr = ip6_address('1234:2::65/96') ip.address.CopyFrom(ip6addr.ip6) ip.prefix_length = ip6addr.prefixlen if (ip_step != 1): ip.step.CopyFrom(ip6_address(ip_step).ip6) ip.default_gateway.CopyFrom(ip6addr.gateway) drone.modifyDeviceGroup(devgrp_cfg) # add the tx stream(s) - we may need more than one stream_id = ost_pb.StreamIdList() stream_id.port_id.CopyFrom(ports.tx.port_id[0]) for i in range(len(dev_cfg['ip_ver'])): stream_id.stream_id.add().id = i log.info('adding tx_stream %d' % stream_id.stream_id[i].id) drone.addStream(stream_id) # configure the tx stream(s) stream_cfg = ost_pb.StreamConfigList() stream_cfg.port_id.CopyFrom(ports.tx.port_id[0]) for i in range(len(dev_cfg['ip_ver'])): s = stream_cfg.stream.add() s.stream_id.id = stream_id.stream_id[i].id s.core.is_enabled = True s.core.frame_len = 1024 s.control.packets_per_sec = 100 s.control.num_packets = 10 # setup stream protocols as mac:eth2:ip:udp:payload p = s.protocol.add() p.protocol_id.id = ost_pb.Protocol.kMacFieldNumber p.Extensions[mac].dst_mac_mode = Mac.e_mm_resolve p.Extensions[mac].src_mac_mode = Mac.e_mm_resolve p = s.protocol.add() p.protocol_id.id = ost_pb.Protocol.kEth2FieldNumber if dev_cfg['ip_ver'][i] == 4: p = s.protocol.add() p.protocol_id.id = ost_pb.Protocol.kIp4FieldNumber ip = None ip = p.Extensions[ip4] ip.src_ip = 0x0a0a0165 if ip_step == 1: ip.src_ip_mode = Ip4.e_im_inc_host ip.src_ip_count = num_devs else: vf = p.variable_field.add() vf.type = ost_pb.VariableField.kCounter32 vf.offset = 12 vf.mask = 0x000000FF vf.value = 0x00000065 vf.step = ip_step vf.mode = ost_pb.VariableField.kIncrement vf.count = num_devs ip.dst_ip = 0x0a0a0265 if ip_step == 1: ip.dst_ip_mode = Ip4.e_im_inc_host ip.dst_ip_count = num_devs else: vf = p.variable_field.add() vf.type = ost_pb.VariableField.kCounter32 vf.offset = 16 vf.mask = 0x000000FF vf.value = 0x00000065 vf.step = ip_step vf.mode = ost_pb.VariableField.kIncrement vf.count = num_devs elif dev_cfg['ip_ver'][i] == 6: p = s.protocol.add() p.protocol_id.id = ost_pb.Protocol.kIp6FieldNumber ip = p.Extensions[ip6] ip6addr = ip6_address('1234:1::65/96') ip.src_addr_hi = ip6addr.ip6.hi ip.src_addr_lo = ip6addr.ip6.lo if ip_step == 1: ip.src_addr_mode = Ip6.kIncHost ip.src_addr_count = num_devs ip.src_addr_prefix = ip6addr.prefixlen else: vf = p.variable_field.add() vf.type = ost_pb.VariableField.kCounter32 vf.offset = 20 vf.mask = 0xFFFFFFFF vf.value = 0x00000065 vf.step = ip_step vf.mode = ost_pb.VariableField.kIncrement vf.count = num_devs ip6addr = ip6_address('1234:2::65/96') ip.dst_addr_hi = ip6addr.ip6.hi ip.dst_addr_lo = ip6addr.ip6.lo if ip_step == 1: ip.dst_addr_mode = Ip6.kIncHost ip.dst_addr_count = num_devs ip.dst_addr_prefix = ip6addr.prefixlen else: vf = p.variable_field.add() vf.type = ost_pb.VariableField.kCounter32 vf.offset = 36 vf.mask = 0xFFFFFFFF vf.value = 0x00000065 vf.step = ip_step vf.mode = ost_pb.VariableField.kIncrement vf.count = num_devs else: assert False # unreachable s.protocol.add().protocol_id.id = ost_pb.Protocol.kUdpFieldNumber s.protocol.add().protocol_id.id = ost_pb.Protocol.kPayloadFieldNumber log.info('configuring tx_stream %d' % stream_id.stream_id[i].id) drone.modifyStream(stream_cfg) # FIXME(needed?): clear tx/rx stats log.info('clearing tx/rx stats') drone.clearStats(ports.tx) drone.clearStats(ports.rx) # clear arp/ndp on DUT sudo('ip neigh flush all') arp_cache = run('ip neigh show') assert re.search('10.10.[1-2].1\d\d.*lladdr', arp_cache) == None assert re.search('1234:[1-2]::\[\da-f]+.*lladdr', arp_cache) == None # wait for interface to do DAD? Otherwise we don't get replies for NS # FIXME: find alternative to sleep time.sleep(5) # clear ARP/NDP cache log.info('clearing ARP/NDP cache on tx/rx port') drone.clearDeviceNeighbors(emul_ports) log.info('retrieving ARP/NDP entries on tx port to verify clear') device_list = drone.getDeviceList(emul_ports.port_id[0]) device_config = device_list.Extensions[emul.device] neigh_list = drone.getDeviceNeighbors(emul_ports.port_id[0]) devices = neigh_list.Extensions[emul.device_neighbor] log.info('ARP/NDP Table on tx port') for devcfg, device in zip(device_config, devices): if has_ip4: for arp in device.arp: print('%s: %s %012x' % (str(ipaddress.ip_address( devcfg.ip4)), str(ipaddress.ip_address(arp.ip4)), arp.mac)) assert (len(device.arp) == 0) if has_ip6: for ndp in device.ndp: print('%s: %s %012x' % (str(ip6_address( devcfg.ip6)), str(ip6_address(ndp.ip6)), ndp.mac)) assert (len(device.ndp) == 0) log.info('retrieving ARP/NDP entries on rx port to verify clear') device_list = drone.getDeviceList(emul_ports.port_id[1]) device_config = device_list.Extensions[emul.device] neigh_list = drone.getDeviceNeighbors(emul_ports.port_id[1]) devices = neigh_list.Extensions[emul.device_neighbor] log.info('ARP/NDP Table on rx port') for devcfg, device in zip(device_config, devices): if has_ip4: for arp in device.arp: print('%s: %s %012x' % (str(ipaddress.ip_address( devcfg.ip4)), str(ipaddress.ip_address(arp.ip4)), arp.mac)) assert (len(device.arp) == 0) if has_ip6: for ndp in device.ndp: print('%s: %s %012x' % (str(ip6_address( devcfg.ip6)), str(ip6_address(ndp.ip6)), ndp.mac)) assert (len(device.ndp) == 0) # resolve ARP/NDP on tx/rx ports log.info('resolving Neighbors on tx/rx ports ...') drone.startCapture(emul_ports) drone.resolveDeviceNeighbors(emul_ports) time.sleep(3) drone.stopCapture(emul_ports) # verify ARP/NDP Requests sent out from tx port buff = drone.getCaptureBuffer(emul_ports.port_id[0]) drone.saveCaptureBuffer(buff, 'capture.pcap') log.info('dumping Tx capture buffer (all)') cap_pkts = subprocess.check_output([tshark, '-nr', 'capture.pcap']) print(cap_pkts) log.info('dumping Tx capture buffer (filtered)') for i in range(len(dev_cfg['ip_ver'])): if dev_cfg['ip_ver'][i] == 4: filter = '(arp.opcode == 1)' \ ' && (arp.src.proto_ipv4 == 10.10.1.<x>)' \ ' && (arp.dst.proto_ipv4 == 10.10.1.1)' \ ' && !expert.severity' elif dev_cfg['ip_ver'][i] == 6: filter = '(icmpv6.type == 135)' \ ' && (ipv6.src == 1234:1::<x>)' \ ' && (icmpv6.nd.ns.target_address == 1234:1::1)' \ ' && !expert.severity' for j in range(num_devs): if dev_cfg['ip_ver'][i] == 4: filter = filter.replace('<x>', str(101 + j * ip_step)) elif dev_cfg['ip_ver'][i] == 6: filter = filter.replace('<x>', format(0x65 + j * ip_step, 'x')) #print filter cap_pkts = subprocess.check_output( [tshark, '-nr', 'capture.pcap', '-Y', filter]) print(cap_pkts) assert cap_pkts.count('\n') == 1 # verify ARP/NDP Requests sent out from rx port buff = drone.getCaptureBuffer(emul_ports.port_id[1]) drone.saveCaptureBuffer(buff, 'capture.pcap') log.info('dumping Rx capture buffer (all)') cap_pkts = subprocess.check_output([tshark, '-nr', 'capture.pcap']) print(cap_pkts) log.info('dumping Rx capture buffer (filtered)') for i in range(len(dev_cfg['ip_ver'])): if dev_cfg['ip_ver'][i] == 4: filter = '(arp.opcode == 1)' \ ' && (arp.src.proto_ipv4 == 10.10.2.<x>)' \ ' && (arp.dst.proto_ipv4 == 10.10.2.1)' \ ' && !expert.severity' elif dev_cfg['ip_ver'][i] == 6: filter = '(icmpv6.type == 135)' \ ' && (ipv6.src == 1234:2::<x>)' \ ' && (icmpv6.nd.ns.target_address == 1234:2::1)' \ ' && !expert.severity' for j in range(num_devs): if dev_cfg['ip_ver'][i] == 4: filter = filter.replace('<x>', str(101 + j * ip_step)) elif dev_cfg['ip_ver'][i] == 6: filter = filter.replace('<x>', format(0x65 + j * ip_step, 'x')) print filter cap_pkts = subprocess.check_output( [tshark, '-nr', 'capture.pcap', '-Y', filter]) print(cap_pkts) assert cap_pkts.count('\n') == 1 # retrieve and verify ARP/NDP Table on tx/rx ports log.info('retrieving ARP/NDP entries on tx port') device_list = drone.getDeviceList(emul_ports.port_id[0]) device_config = device_list.Extensions[emul.device] neigh_list = drone.getDeviceNeighbors(emul_ports.port_id[0]) devices = neigh_list.Extensions[emul.device_neighbor] log.info('ARP/NDP Table on tx port') for devcfg, device in zip(device_config, devices): if has_ip4: resolved = False for arp in device.arp: print('%s: %s %012x' % (str(ipaddress.ip_address( devcfg.ip4)), str(ipaddress.ip_address(arp.ip4)), arp.mac)) if (arp.ip4 == devcfg.ip4_default_gateway) and (arp.mac): resolved = True assert resolved if has_ip6: resolved = False for ndp in device.ndp: print('%s: %s %012x' % (str(ip6_address( devcfg.ip6)), str(ip6_address(ndp.ip6)), ndp.mac)) if (ndp.ip6 == devcfg.ip6_default_gateway) and (ndp.mac): resolved = True assert resolved log.info('retrieving ARP/NDP entries on rx port') device_list = drone.getDeviceList(emul_ports.port_id[1]) device_config = device_list.Extensions[emul.device] neigh_list = drone.getDeviceNeighbors(emul_ports.port_id[1]) devices = neigh_list.Extensions[emul.device_neighbor] log.info('ARP/NDP Table on rx port') for devcfg, device in zip(device_config, devices): if has_ip4: resolved = False for arp in device.arp: print('%s: %s %012x' % (str(ipaddress.ip_address( devcfg.ip4)), str(ipaddress.ip_address(arp.ip4)), arp.mac)) if (arp.ip4 == devcfg.ip4_default_gateway) and (arp.mac): resolved = True assert resolved if has_ip6: resolved = False for ndp in device.ndp: print('%s: %s %012x' % (str(ip6_address( devcfg.ip6)), str(ip6_address(ndp.ip6)), ndp.mac)) if (ndp.ip6 == devcfg.ip6_default_gateway) and (ndp.mac): resolved = True assert resolved # ping the tx devices from the DUT for i in range(num_devs): if has_ip4: out = run('ping -c3 10.10.1.' + str(101 + i * ip_step), warn_only=True) assert '100% packet loss' not in out if has_ip6: out = run('ping -6 -c3 1234:1::' + format(101 + i * ip_step, 'x'), warn_only=True) assert '100% packet loss' not in out # ping the rx devices from the DUT for i in range(num_devs): if has_ip4: out = run('ping -c3 10.10.2.' + str(101 + i * ip_step), warn_only=True) assert '100% packet loss' not in out if has_ip6: out = run('ping -6 -c3 1234:2::' + format(101 + i * ip_step, 'x'), warn_only=True) assert '100% packet loss' not in out # We are all set now - so transmit the stream now drone.startCapture(ports.rx) drone.startTransmit(ports.tx) log.info('waiting for transmit to finish ...') time.sleep(3) drone.stopTransmit(ports.tx) drone.stopCapture(ports.rx) buff = drone.getCaptureBuffer(ports.rx.port_id[0]) drone.saveCaptureBuffer(buff, 'capture.pcap') log.info('dumping Rx capture buffer (all)') cap_pkts = subprocess.check_output([tshark, '-nr', 'capture.pcap']) print(cap_pkts) log.info('dumping Rx capture buffer (filtered)') for i in range(num_devs): if has_ip4: filter = '(ip.src == 10.10.1.' + str(101+i*ip_step) + ')' \ ' && (ip.dst == 10.10.2.' + str(101+i*ip_step) + ')' \ ' && (eth.dst == 00:01:02:03:0b:' \ + format(1+i*mac_step, '02x')+')' print('filter: %s' % filter) cap_pkts = subprocess.check_output( [tshark, '-nr', 'capture.pcap', '-Y', filter]) print(cap_pkts) assert cap_pkts.count('\n') == s.control.num_packets / num_devs if has_ip6: filter = '(ipv6.src == 1234:1::' \ + format(101+i*ip_step, 'x') + ')' \ + ' && (ipv6.dst == 1234:2::' \ + format(101+i*ip_step, 'x') + ')' \ + ' && (eth.dst == 00:01:02:03:0b:' \ + format(1+i*mac_step, '02x') + ')' print('filter: %s' % filter) cap_pkts = subprocess.check_output( [tshark, '-nr', 'capture.pcap', '-Y', filter]) print(cap_pkts) assert cap_pkts.count('\n') == s.control.num_packets / num_devs os.remove('capture.pcap') drone.stopTransmit(ports.tx) run('ip neigh show')
def stream(request, drone, ports, sign_stream_cfg): sscfg = sign_stream_cfg num_streams = sscfg['num_streams'] # add stream(s) stream_id = ost_pb.StreamIdList() stream_id.port_id.CopyFrom(ports.x.port_id[0]) for i in range(num_streams): stream_id.stream_id.add().id = 1 + i log.info('adding X stream(s) ' + str(stream_id)) drone.addStream(stream_id) # configure the stream(s) stream_cfg = ost_pb.StreamConfigList() stream_cfg.port_id.CopyFrom(ports.x.port_id[0]) for i in range(num_streams): s = stream_cfg.stream.add() s.stream_id.id = stream_id.stream_id[i].id s.core.is_enabled = True # On Win32, packets in a seq that take less than 1s to transmit # are transmitted in one shot using pcap_send_queue; this means that # stopTransmit() cannot stop them in the middle of the sequence and # stop will happen only at the pktSeq boundary # Since we want to test cases where stop is trigerred in the middle of # a sequence, we set pps < 1000 # FIXME: for some reason values such as 100pps is also leading to # stop only at seq boundary - need to debug s.control.packets_per_sec = 523 # setup stream protocols p = s.protocol.add() s.control.num_packets = sscfg['num_pkts'][i] p.protocol_id.id = ost_pb.Protocol.kMacFieldNumber p.Extensions[mac].dst_mac_mode = Mac.e_mm_resolve p.Extensions[mac].src_mac_mode = Mac.e_mm_resolve s.protocol.add().protocol_id.id = ost_pb.Protocol.kEth2FieldNumber p = s.protocol.add() if i & 0x1: # odd numbered stream p.protocol_id.id = ost_pb.Protocol.kIp4FieldNumber ip = p.Extensions[ip4] ip.src_ip = 0x0a0a0165 ip.dst_ip = 0x0a0a0265 if sscfg['num_var_pkts'][i]: ip4.src_ip_mode = Ip4.e_im_inc_host ip4.src_ip_count = sscfg['num_var_pkts'][i] s.protocol.add().protocol_id.id = ost_pb.Protocol.kUdpFieldNumber else: # even numbered stream s.core.frame_len = 96 # IPv6 needs a larger frame p.protocol_id.id = ost_pb.Protocol.kIp6FieldNumber ip = p.Extensions[ip6] ip6addr = ip6_address('1234:1::65/96') ip.src_addr_hi = ip6addr.ip6.hi ip.src_addr_lo = ip6addr.ip6.lo ip6addr = ip6_address('1234:2::65/96') ip.dst_addr_hi = ip6addr.ip6.hi ip.dst_addr_lo = ip6addr.ip6.lo if sscfg['num_var_pkts'][i]: ip.dst_addr_mode = Ip6.kIncHost ip.dst_addr_count = sscfg['num_var_pkts'][i] ip.dst_addr_prefix = ip6addr.prefixlen s.protocol.add().protocol_id.id = ost_pb.Protocol.kTcpFieldNumber s.protocol.add().protocol_id.id = ost_pb.Protocol.kPayloadFieldNumber if sscfg['guid'][i] > 0: p = s.protocol.add() p.protocol_id.id = ost_pb.Protocol.kSignFieldNumber p.Extensions[sign].stream_guid = sscfg['guid'][i] if sscfg['loop']: stream_cfg.stream[-1].control.next = ost_pb.StreamControl.e_nw_goto_id drone.modifyStream(stream_cfg) def fin(): # delete streams log.info('deleting tx_stream ' + str(stream_id)) drone.deleteStream(stream_id) request.addfinalizer(fin) return stream_cfg