Feature (contd.): Device Emulation - fixed problems in code and in test case for multi-tagged vlans

This commit is contained in:
Srivats P 2015-12-14 21:04:58 +05:30
parent cb1e16976d
commit ad1fb5fc37
3 changed files with 90 additions and 14 deletions

View File

@ -324,22 +324,62 @@ void DeviceManager::enumerateDevices(
OstEmul::VlanEmulation pbVlan = deviceGroup->GetExtension(OstEmul::encap)
.vlan();
int numTags = pbVlan.stack_size();
int vlanCount = 1;
int n = 1;
QList<int> vlanCount;
OstEmul::MacEmulation mac = deviceGroup->GetExtension(OstEmul::mac);
OstEmul::Ip4Emulation ip4 = deviceGroup->GetExtension(OstEmul::ip4);
for (int i = 0; i < numTags; i++)
vlanCount *= pbVlan.stack(i).count();
/*
* vlanCount[] stores the number of unique vlans at each tag level
* e.g. for a 3-tag config with 2, 3, 4 vlans at each level respectively
* vlanCount = [24, 12, 4]
* 0 - 0, 0, 0
* 1 - 0, 0, 1
* 2 - 0, 0, 2
* 3 - 0, 0, 3
* 4 - 0, 1, 0
* 5 - 0, 1, 1
* 6 - 0, 1, 2
* 7 - 0, 1, 3
* 8 - 0, 2, 0
* 9 - 0, 2, 1
* 10 - 0, 2, 2
* 11 - 0, 2, 3
* 12 - 1, 0, 0
* 13 - 1, 0, 1
* 14 - 1, 0, 2
* 15 - 1, 0, 3
* 16 - 1, 1, 0
* 17 - 1, 1, 1
* 18 - 1, 1, 2
* 19 - 1, 1, 3
* 21 - 1, 2, 0
* 21 - 1, 2, 1
* 22 - 1, 2, 2
* 23 - 1, 2, 3
*
* Note that vlanCount[0] repesents total-number-of-vlans
*
* Another way to think about this is that at a particular vlan tag
* level, we need to repeat a particular vlan-id as many times as the
* next level's count before we can increment the vlan-id at that level
*
* We use this list to calculate the vlan ids for each tag level for
* all the vlans.
*
* For implementation convenience we append a '1' as the last element
*/
vlanCount.append(n);
for (int i = numTags - 1; i >= 0 ; i--) {
n *= pbVlan.stack(i).count();
vlanCount.prepend(n);
}
// If we have no vlans, we still have the non-vlan-segmented LAN
if (vlanCount == 0)
vlanCount = 1;
for (int i = 0; i < vlanCount; i++) {
for (int i = 0; i < vlanCount.at(0); i++) {
for (int j = 0; j < numTags; j++) {
OstEmul::VlanEmulation::Vlan vlan = pbVlan.stack(j);
quint16 vlanAdd = i*vlan.step();
quint16 vlanAdd = (i/vlanCount.at(j+1) % vlan.count())*vlan.step();
dk.setVlan(j, vlan.vlan_tag() + vlanAdd);
}

View File

@ -946,7 +946,40 @@ void PcapPort::EmulationTransceiver::run()
int flags = PCAP_OPENFLAG_PROMISCUOUS;
char errbuf[PCAP_ERRBUF_SIZE] = "";
struct bpf_program bpf;
const char *capture_filter = "arp or (vlan and arp)";
#if 0
/*
Ideally we should use the below filter, but the 'vlan' capture filter
in libpcap is implemented as a kludge. From the pcap-filter man page -
vlan [vlan_id]
Note that the first vlan keyword encountered in expression changes
the decoding offsets for the remainder of expression on the
assumption that the packet is a VLAN packet.
The vlan [vlan_id] expression may be used more than once, to filter on
VLAN hierarchies. Each use of that expression increments the filter
offsets by 4.
See https://ask.wireshark.org/questions/31953/unusual-behavior-with-stacked-vlan-tags-and-capture-filter
So we use the modified filter expression that works as we intend. If ever
libpcap changes their implementation, this will need to change as well.
*/
const char *capture_filter =
"arp or "
"(vlan and arp) or "
"(vlan and vlan and arp) or "
"(vlan and vlan and vlan and arp) or "
"(vlan and vlan and vlan and vlan and arp)";
#else
const char *capture_filter =
"arp or "
"(vlan and arp) or "
"(vlan and arp) or "
"(vlan and arp) or "
"(vlan and arp)";
#endif
const int optimize = 1;
qDebug("In %s", __PRETTY_FUNCTION__);

View File

@ -624,6 +624,7 @@ def test_multiEmulDevPerVlan(request, drone, ports, dut, dut_ports, stream_id,
for i in range(num_vlans):
s = stream_cfg.stream.add()
s.stream_id.id = stream_id.stream_id[i].id
s.core.name = 'stream ' + str(s.stream_id.id)
s.core.is_enabled = True
s.core.ordinal = i
s.control.packets_per_sec = 100
@ -635,10 +636,11 @@ def test_multiEmulDevPerVlan(request, drone, ports, dut, dut_ports, stream_id,
p.Extensions[mac].dst_mac_mode = Mac.e_mm_resolve
p.Extensions[mac].src_mac_mode = Mac.e_mm_resolve
for vcfg in vlan_cfg:
ids = dut_vlans.vlans[i].split('.')
for id in ids:
p = s.protocol.add()
p.protocol_id.id = ost_pb.Protocol.kVlanFieldNumber
p.Extensions[vlan].vlan_tag = vcfg['base']+(i % vcfg['count'])
p.Extensions[vlan].vlan_tag = int(id)
p = s.protocol.add()
p.protocol_id.id = ost_pb.Protocol.kEth2FieldNumber
@ -658,7 +660,7 @@ def test_multiEmulDevPerVlan(request, drone, ports, dut, dut_ports, stream_id,
p = s.protocol.add()
p.protocol_id.id = ost_pb.Protocol.kPayloadFieldNumber
log.info('configuring tx_stream %d' % stream_id.stream_id[0].id)
log.info('configuring tx_stream %d' % stream_id.stream_id[i].id)
drone.modifyStream(stream_cfg)
@ -708,7 +710,7 @@ def test_multiEmulDevPerVlan(request, drone, ports, dut, dut_ports, stream_id,
log.info('dumping Rx 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)')
log.info('dumping Rx capture buffer (all pkts - vlans only)')
cap_pkts = subprocess.check_output([tshark, '-nr', 'capture.pcap',
'-Tfields', '-eframe.number', '-evlan.id'])
print(cap_pkts)
@ -734,6 +736,7 @@ def test_multiEmulDevPerVlan(request, drone, ports, dut, dut_ports, stream_id,
for dev_cfg, device in zip(device_config, devices):
resolved = False
for arp in device.arp:
# TODO: print all configured vlans, not just the first
# TODO: pretty print ip and mac
print('v%d|%08x: %08x %012x' %
(dev_cfg.vlan[0] & 0xffff, dev_cfg.ip4, arp.ip4, arp.mac))