Feature (contd.): Device Emulation - Test case and code to support non default vlan TPID

This commit is contained in:
Srivats P 2015-12-20 19:33:02 +05:30
parent 6b5a8105e6
commit 03f427ce91
5 changed files with 83 additions and 16 deletions

View File

@ -51,7 +51,7 @@ Device::Device(DeviceManager *deviceManager)
clearKey();
}
void Device::setVlan(int index, quint16 vlan)
void Device::setVlan(int index, quint16 vlan, quint16 tpid)
{
int ofs;
@ -61,7 +61,7 @@ void Device::setVlan(int index, quint16 vlan)
return;
}
vlan_[index] = vlan;
vlan_[index] = (tpid << 16) | vlan;
ofs = index * sizeof(quint16);
key_[ofs] = vlan >> 8;
@ -105,7 +105,30 @@ void Device::getConfig(OstEmul::Device *deviceConfig)
QString Device::config()
{
return QString("<vlans=%1/%2/%3/%4 mac=%5 ip4=%6/%7>")
.arg(vlan_[0]).arg(vlan_[1]).arg(vlan_[2]).arg(vlan_[3])
.arg((vlan_[0] >> 16) != kVlanTpid ?
QString("0x%1-%2")
.arg(vlan_[0] >> 16, 4, kBaseHex, QChar('0'))
.arg(vlan_[0] & 0xFFFF) :
QString("%1")
.arg(vlan_[0] & 0xFFFF))
.arg((vlan_[1] >> 16) != kVlanTpid ?
QString("0x%1-%2")
.arg(vlan_[1] >> 16, 4, kBaseHex, QChar('0'))
.arg(vlan_[1] & 0xFFFF) :
QString("%1")
.arg(vlan_[1] & 0xFFFF))
.arg((vlan_[2] >> 16) != kVlanTpid ?
QString("0x%1-%2")
.arg(vlan_[2] >> 16, 4, kBaseHex, QChar('0'))
.arg(vlan_[2] & 0xFFFF) :
QString("%1")
.arg(vlan_[2] & 0xFFFF))
.arg((vlan_[3] >> 16) != kVlanTpid ?
QString("0x%1-%2")
.arg(vlan_[3] >> 16, 4, kBaseHex, QChar('0'))
.arg(vlan_[3] & 0xFFFF) :
QString("%1")
.arg(vlan_[3] & 0xFFFF))
.arg(mac_, 12, kBaseHex, QChar('0'))
.arg(QHostAddress(ip4_).toString())
.arg(ip4PrefixLength_);
@ -147,7 +170,7 @@ void Device::encap(PacketBuffer *pktBuf, quint64 dstMac, quint16 type)
*(quint16*)(p + 10) = qToBigEndian(quint16(srcMac & 0xffff));
ofs = 12;
for (int i = 0; i < numVlanTags_; i++) {
*(quint32*)(p + ofs) = qToBigEndian(quint32((0x8100 << 16)|vlan_[i]));
*(quint32*)(p + ofs) = qToBigEndian(vlan_[i]);
ofs += 4;
}
*(quint16*)(p + ofs) = qToBigEndian(type);

View File

@ -35,10 +35,13 @@ class DeviceKey: public QByteArray
class Device
{
public:
static const quint16 kVlanTpid = 0x8100;
public:
Device(DeviceManager *deviceManager);
void setVlan(int index, quint16 vlan);
void setVlan(int index, quint16 vlan, quint16 tpid = kVlanTpid);
quint64 mac();
void setMac(quint64 mac);
void setIp4(quint32 address, int prefixLength, quint32 gateway);
@ -71,7 +74,7 @@ private: // data
DeviceManager *deviceManager_;
int numVlanTags_;
quint16 vlan_[kMaxVlan]; // FIXME: vlan tpid
quint32 vlan_[kMaxVlan];
quint64 mac_;
quint32 ip4_;
int ip4PrefixLength_;

View File

@ -192,7 +192,7 @@ _eth_type:
ethType = qFromBigEndian<quint16>(pktData + offset);
qDebug("%s: ethType 0x%x", __PRETTY_FUNCTION__, ethType);
if (ethType == 0x8100) {
if (tpidList_.contains(ethType)) {
offset += 2;
vlan = qFromBigEndian<quint16>(pktData + offset);
dk.setVlan(idx++, vlan);
@ -296,7 +296,7 @@ _eth_type:
ethType = qFromBigEndian<quint16>(pktData + offset);
qDebug("%s: ethType 0x%x", __PRETTY_FUNCTION__, ethType);
if (ethType == 0x8100) {
if (tpidList_.contains(ethType)) {
offset += 2;
vlan = qFromBigEndian<quint16>(pktData + offset);
dk.setVlan(idx++, vlan);
@ -372,8 +372,30 @@ void DeviceManager::enumerateDevices(
*/
vlanCount.append(n);
for (int i = numTags - 1; i >= 0 ; i--) {
n *= pbVlan.stack(i).count();
OstEmul::VlanEmulation::Vlan vlan = pbVlan.stack(i);
n *= vlan.count();
vlanCount.prepend(n);
// Update TPID list
switch (oper) {
case kAdd:
tpidList_[vlan.tpid()]++;
break;
case kDelete:
tpidList_[vlan.tpid()]--;
if (tpidList_[vlan.tpid()] == 0)
tpidList_.remove(vlan.tpid());
break;
default:
Q_ASSERT(0); // Unreachable
}
}
QHash<quint16, uint>::const_iterator iter = tpidList_.constBegin();
qDebug("Port %s TPID List:", port_->name());
while (iter != tpidList_.constEnd()) {
qDebug("tpid: %x (%d)", iter.key(), iter.value());
iter++;
}
for (int i = 0; i < vlanCount.at(0); i++) {
@ -381,7 +403,7 @@ void DeviceManager::enumerateDevices(
OstEmul::VlanEmulation::Vlan vlan = pbVlan.stack(j);
quint16 vlanAdd = (i/vlanCount.at(j+1) % vlan.count())*vlan.step();
dk.setVlan(j, vlan.vlan_tag() + vlanAdd);
dk.setVlan(j, vlan.vlan_tag() + vlanAdd, vlan.tpid());
}
for (uint k = 0; k < deviceGroup->device_count(); k++) {

View File

@ -71,6 +71,7 @@ private:
QHash<uint, OstProto::DeviceGroup*> deviceGroupList_;
QHash<DeviceKey, Device*> deviceList_;
QMultiHash<DeviceKey, Device*> bcastList_;
QHash<quint16, uint> tpidList_; // Key: TPID, Value: RefCount
};
#endif

View File

@ -261,10 +261,15 @@ def dut_vlans(request, dut_ports):
for dev in devices.rx+devices.tx:
for k in range(vcfg['count']):
vlan_id = vcfg['base'] + k
if 'tpid' in vcfg and vcfg['tpid'] == 0x88a8:
tpid = '802.1ad'
else:
tpid = '802.1q'
dev_name = dev + '.' + str(vlan_id)
sudo('ip link add link ' + dev
+ ' name ' + dev_name
+ ' type vlan id ' + str(vlan_id))
+ ' type vlan id ' + str(vlan_id)
+ ' proto ' + tpid)
sudo('ip link set ' + dev_name + ' up')
if dev in devices.rx:
new_devs.rx.append(dev_name)
@ -549,6 +554,9 @@ def test_multiEmulDevNoVlan(drone, ports, dut, dut_ports, stream_id,
[{'base': 11, 'count': 2},
{'base': 21, 'count': 3}],
[{'base': 11, 'count': 2, 'tpid': 0x88a8},
{'base': 21, 'count': 3}],
[{'base': 11, 'count': 2},
{'base': 21, 'count': 3},
{'base': 31, 'count': 2}],
@ -590,12 +598,15 @@ def test_multiEmulDevPerVlan(request, drone, ports, dut, dut_ports, stream_id,
vlan_filter.append('')
ids = dut_vlans.vlans[i].split('.')
for j in range(len(ids)):
filter = '(frame[<ofs>:4]==8100:<id>)' \
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()
@ -607,6 +618,8 @@ def test_multiEmulDevPerVlan(request, drone, ports, dut, dut_ports, stream_id,
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']
dg.device_count = num_devs_per_vlan
dg.Extensions[emul.mac].address = 0x000102030a01
ip = dg.Extensions[emul.ip4]
@ -626,6 +639,8 @@ def test_multiEmulDevPerVlan(request, drone, ports, dut, dut_ports, stream_id,
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']
dg.device_count = num_devs_per_vlan
dg.Extensions[emul.mac].address = 0x000102030b01
ip = dg.Extensions[emul.ip4]
@ -668,10 +683,13 @@ def test_multiEmulDevPerVlan(request, drone, ports, dut, dut_ports, stream_id,
p.Extensions[mac].src_mac_mode = Mac.e_mm_resolve
ids = dut_vlans.vlans[i].split('.')
for id in ids:
for id, j 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[j]:
p.Extensions[vlan].tpid = vlan_cfg[j]['tpid']
p.Extensions[vlan].is_override_tpid = True
p = s.protocol.add()
p.protocol_id.id = ost_pb.Protocol.kEth2FieldNumber
@ -721,7 +739,7 @@ def test_multiEmulDevPerVlan(request, drone, ports, dut, dut_ports, stream_id,
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', '-evlan.id'])
'-Tfields', '-eframe.number', '-eieee8021ad.id', '-evlan.id'])
print(cap_pkts)
log.info('dumping Tx capture buffer (filtered)')
for i in range(num_vlans):
@ -743,7 +761,7 @@ def test_multiEmulDevPerVlan(request, drone, ports, dut, dut_ports, stream_id,
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', '-evlan.id'])
'-Tfields', '-eframe.number', '-eieee8021ad.id', '-evlan.id'])
print(cap_pkts)
log.info('dumping Rx capture buffer (filtered)')
for i in range(num_vlans):
@ -804,7 +822,7 @@ def test_multiEmulDevPerVlan(request, drone, ports, dut, dut_ports, stream_id,
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', '-evlan.id'])
'-Tfields', '-eframe.number', '-eieee8021ad.id', '-evlan.id'])
print(cap_pkts)
log.info('dumping Rx capture buffer (filtered)')
for i in range(num_vlans):