Device Emulation (contd.) - added intelligence for single or dual ip stack; fixed pktBuf memory leak

This commit is contained in:
Srivats P 2016-01-01 11:59:31 +05:30
parent aaf6dbcbf2
commit 0b573d572e
4 changed files with 77 additions and 55 deletions

View File

@ -29,6 +29,8 @@ public:
UInt128();
UInt128(quint64 hi, quint64 lo);
quint64 hi64() const;
quint64 lo64() const;
quint8* toArray() const;
UInt128 operator+(const UInt128 &other);
@ -51,6 +53,16 @@ inline UInt128::UInt128(quint64 hi, quint64 lo)
lo_ = lo;
}
inline quint64 UInt128::hi64() const
{
return hi_;
}
inline quint64 UInt128::lo64() const
{
return lo_;
}
inline quint8* UInt128::toArray() const
{
*(quint64*)(array_ + 0) = qToBigEndian<quint64>(hi_);

View File

@ -46,11 +46,8 @@ Device::Device(DeviceManager *deviceManager)
numVlanTags_ = 0;
mac_ = 0;
ip4_ = ip4Gateway_ = 0;
ip4PrefixLength_ = 0;
ip6_ = ip6Gateway_ = UInt128(0, 0);
ip6PrefixLength_ = 0;
hasIp4_ = false;
hasIp6_ = false;
clearKey();
}
@ -93,6 +90,7 @@ void Device::setIp4(quint32 address, int prefixLength, quint32 gateway)
ip4_ = address;
ip4PrefixLength_ = prefixLength;
ip4Gateway_ = gateway;
hasIp4_ = true;
}
void Device::setIp6(UInt128 address, int prefixLength, UInt128 gateway)
@ -100,6 +98,7 @@ void Device::setIp6(UInt128 address, int prefixLength, UInt128 gateway)
ip6_ = address;
ip6PrefixLength_ = prefixLength;
ip6Gateway_ = gateway;
hasIp6_ = true;
}
void Device::getConfig(OstEmul::Device *deviceConfig)
@ -108,49 +107,48 @@ void Device::getConfig(OstEmul::Device *deviceConfig)
deviceConfig->add_vlan(vlan_[i]);
deviceConfig->set_mac(mac_);
deviceConfig->set_ip4(ip4_);
deviceConfig->set_ip4_prefix_length(ip4PrefixLength_);
deviceConfig->set_ip4_default_gateway(ip4Gateway_);
if (hasIp4_) {
deviceConfig->set_ip4(ip4_);
deviceConfig->set_ip4_prefix_length(ip4PrefixLength_);
deviceConfig->set_ip4_default_gateway(ip4Gateway_);
}
#if 0 // FIXME
deviceConfig->set_ip6(ip6_);
deviceConfig->set_ip6_prefix_length(ip6PrefixLength_);
deviceConfig->set_ip6_default_gateway(ip6Gateway_);
#endif
if (hasIp6_) {
deviceConfig->mutable_ip6()->set_hi(ip6_.hi64());
deviceConfig->mutable_ip6()->set_lo(ip6_.lo64());
deviceConfig->set_ip6_prefix_length(ip6PrefixLength_);
deviceConfig->mutable_ip6_default_gateway()->set_hi(ip6Gateway_.hi64());
deviceConfig->mutable_ip6_default_gateway()->set_lo(ip6Gateway_.lo64());
}
}
QString Device::config()
{
return QString("<vlans=%1/%2/%3/%4 mac=%5 ip4=%6/%7 ip6=%8/%9>")
.arg((vlan_[0] >> 16) != kVlanTpid ?
QString config;
for (int i = 0; i < numVlanTags_; i++) {
config.append(i == 0 ? "vlans=" : "|");
config.append(
(vlan_[i] >> 16) != kVlanTpid ?
QString("0x%1-%2")
.arg(vlan_[0] >> 16, 4, kBaseHex, QChar('0'))
.arg(vlan_[0] & 0xFFFF) :
.arg(vlan_[i] >> 16, 4, kBaseHex, QChar('0'))
.arg(vlan_[i] & 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_)
.arg(QHostAddress(ip6_.toArray()).toString())
.arg(ip6PrefixLength_);
.arg(vlan_[i] & 0xFFFF));
}
config.append(QString(" mac=%1")
.arg(mac_, 12, kBaseHex, QChar('0')));
if (hasIp4_)
config.append(QString(" ip4=%1/%2")
.arg(QHostAddress(ip4_).toString())
.arg(ip4PrefixLength_));
if (hasIp6_)
config.append(QString(" ip6=%1/%2")
.arg(QHostAddress(ip6_.toArray()).toString())
.arg(ip6PrefixLength_));
return config;
}
DeviceKey Device::key()
@ -212,11 +210,13 @@ void Device::receivePacket(PacketBuffer *pktBuf)
switch(ethType)
{
case 0x0806: // ARP
receiveArp(pktBuf);
if (hasIp4_)
receiveArp(pktBuf);
break;
case 0x0800: // IPv4
receiveIp4(pktBuf);
if (hasIp4_)
receiveIp4(pktBuf);
break;
case 0x86dd: // IPv6
@ -249,11 +249,13 @@ void Device::resolveNeighbor(PacketBuffer *pktBuf)
switch(ethType)
{
case 0x0800: // IPv4
sendArpRequest(pktBuf);
if (hasIp4_)
sendArpRequest(pktBuf);
break;
case 0x86dd: // IPv6
sendNeighborSolicit(pktBuf);
if (hasIp6_)
sendNeighborSolicit(pktBuf);
break;
default:
@ -278,6 +280,7 @@ void Device::getNeighbors(OstEmul::DeviceNeighborList *neighbors)
}
}
// Are we the source of the given packet?
// We expect pktBuf to point to EthType on entry
bool Device::isOrigin(const PacketBuffer *pktBuf)
{
@ -288,7 +291,7 @@ bool Device::isOrigin(const PacketBuffer *pktBuf)
pktData += 2;
// We know only about IP packets
if (ethType == 0x0800) { // IPv4
if ((ethType == 0x0800) && hasIp4_) { // IPv4
int ipHdrLen = (pktData[0] & 0x0F) << 2;
quint32 srcIp;
@ -306,6 +309,7 @@ bool Device::isOrigin(const PacketBuffer *pktBuf)
return false;
}
// Return the mac address corresponding to the dstIp of the given packet
// We expect pktBuf to point to EthType on entry
quint64 Device::neighborMac(const PacketBuffer *pktBuf)
{
@ -316,7 +320,7 @@ quint64 Device::neighborMac(const PacketBuffer *pktBuf)
pktData += 2;
// We know only about IP packets
if (ethType == 0x0800) { // IPv4
if ((ethType == 0x0800) && hasIp4_) { // IPv4
int ipHdrLen = (pktData[0] & 0x0F) << 2;
quint32 dstIp, tgtIp, mask;

View File

@ -87,10 +87,12 @@ private: // data
quint32 vlan_[kMaxVlan];
quint64 mac_;
bool hasIp4_;
quint32 ip4_;
int ip4PrefixLength_;
quint32 ip4Gateway_;
bool hasIp6_;
UInt128 ip6_;
int ip6PrefixLength_;
UInt128 ip6Gateway_;

View File

@ -188,7 +188,7 @@ void DeviceManager::receivePacket(PacketBuffer *pktBuf)
// All frames we are interested in should be at least 32 bytes
if (pktBuf->length() < 32) {
qWarning("short frame of %d bytes, skipping ...", pktBuf->length());
return;
goto _exit;
}
// Extract dstMac
@ -241,7 +241,7 @@ _eth_type:
device->receivePacket(pktBuf);
_exit:
return;
delete pktBuf;
}
void DeviceManager::transmitPacket(PacketBuffer *pktBuf)
@ -343,6 +343,8 @@ void DeviceManager::enumerateDevices(
int n = 1;
QList<int> vlanCount;
bool hasIp4 = deviceGroup->HasExtension(OstEmul::ip4);
bool hasIp6 = deviceGroup->HasExtension(OstEmul::ip6);
OstEmul::MacEmulation mac = deviceGroup->GetExtension(OstEmul::mac);
OstEmul::Ip4Emulation ip4 = deviceGroup->GetExtension(OstEmul::ip4);
OstEmul::Ip6Emulation ip6 = deviceGroup->GetExtension(OstEmul::ip6);
@ -430,12 +432,14 @@ void DeviceManager::enumerateDevices(
UInt128 ip6Add = UINT128(ip6.step()) * k;
dk.setMac(mac.address() + macAdd);
dk.setIp4(ip4.address() + ip4Add,
ip4.prefix_length(),
ip4.default_gateway());
dk.setIp6(UINT128(ip6.address()) + ip6Add,
ip6.prefix_length(),
UINT128(ip6.default_gateway()));
if (hasIp4)
dk.setIp4(ip4.address() + ip4Add,
ip4.prefix_length(),
ip4.default_gateway());
if (hasIp6)
dk.setIp6(UINT128(ip6.address()) + ip6Add,
ip6.prefix_length(),
UINT128(ip6.default_gateway()));
// TODO: fill in other pbDevice data