Device Emulation (contd.) - Implemented sending of IPv6 Neighbor Solicitation packets for IPv6 resolution
This commit is contained in:
parent
0b573d572e
commit
d9be523827
@ -20,6 +20,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
#ifndef _UINT128_H
|
#ifndef _UINT128_H
|
||||||
#define _UINT128_H
|
#define _UINT128_H
|
||||||
|
|
||||||
|
#include <QHash>
|
||||||
|
|
||||||
#include <QtGlobal>
|
#include <QtGlobal>
|
||||||
#include <qendian.h>
|
#include <qendian.h>
|
||||||
|
|
||||||
@ -33,8 +35,12 @@ public:
|
|||||||
quint64 lo64() const;
|
quint64 lo64() const;
|
||||||
quint8* toArray() const;
|
quint8* toArray() const;
|
||||||
|
|
||||||
UInt128 operator+(const UInt128 &other);
|
bool operator==(const UInt128 &other) const;
|
||||||
UInt128 operator*(const uint &other);
|
UInt128 operator+(const UInt128 &other) const;
|
||||||
|
UInt128 operator*(const uint &other) const;
|
||||||
|
UInt128 operator<<(const int &shift) const;
|
||||||
|
UInt128 operator~() const;
|
||||||
|
UInt128 operator&(const UInt128 &other) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
quint64 hi_;
|
quint64 hi_;
|
||||||
@ -71,7 +77,12 @@ inline quint8* UInt128::toArray() const
|
|||||||
return (quint8*)array_;
|
return (quint8*)array_;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline UInt128 UInt128::operator+(const UInt128 &other)
|
inline bool UInt128::operator==(const UInt128 &other) const
|
||||||
|
{
|
||||||
|
return ((hi_ == other.hi_) && (lo_ == other.lo_));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline UInt128 UInt128::operator+(const UInt128 &other) const
|
||||||
{
|
{
|
||||||
UInt128 sum;
|
UInt128 sum;
|
||||||
|
|
||||||
@ -81,7 +92,7 @@ inline UInt128 UInt128::operator+(const UInt128 &other)
|
|||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline UInt128 UInt128::operator*(const uint &other)
|
inline UInt128 UInt128::operator*(const uint &other) const
|
||||||
{
|
{
|
||||||
UInt128 product;
|
UInt128 product;
|
||||||
|
|
||||||
@ -92,4 +103,49 @@ inline UInt128 UInt128::operator*(const uint &other)
|
|||||||
return product;
|
return product;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline UInt128 UInt128::operator<<(const int &shift) const
|
||||||
|
{
|
||||||
|
UInt128 shifted;
|
||||||
|
|
||||||
|
if (shift < 64)
|
||||||
|
return UInt128((hi_<<shift) | (lo_>>(64-shift)), lo_ << shift);
|
||||||
|
|
||||||
|
return UInt128(hi_<<(shift-64), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline UInt128 UInt128::operator~() const
|
||||||
|
{
|
||||||
|
return UInt128(~hi_, ~lo_);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline UInt128 UInt128::operator&(const UInt128 &other) const
|
||||||
|
{
|
||||||
|
return UInt128(hi_ & other.hi_, lo_ & other.lo_);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <> inline UInt128 qFromBigEndian<UInt128>(const uchar *src)
|
||||||
|
{
|
||||||
|
quint64 hi, lo;
|
||||||
|
|
||||||
|
hi = qFromBigEndian<quint64>(src);
|
||||||
|
lo = qFromBigEndian<quint64>(src+8);
|
||||||
|
|
||||||
|
return UInt128(hi, lo);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <> inline UInt128 qToBigEndian<UInt128>(const UInt128 src)
|
||||||
|
{
|
||||||
|
quint64 hi, lo;
|
||||||
|
|
||||||
|
hi = qToBigEndian<quint64>(src.hi64());
|
||||||
|
lo = qToBigEndian<quint64>(src.lo64());
|
||||||
|
|
||||||
|
return UInt128(hi, lo);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint qHash(const UInt128 &key)
|
||||||
|
{
|
||||||
|
return qHash(key.hi64()) ^ qHash(key.lo64());
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -28,6 +28,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
|
|
||||||
const int kBaseHex = 16;
|
const int kBaseHex = 16;
|
||||||
const quint64 kBcastMac = 0xffffffffffffULL;
|
const quint64 kBcastMac = 0xffffffffffffULL;
|
||||||
|
const quint16 kEthTypeIp4 = 0x0800;
|
||||||
|
const quint16 kEthTypeIp6 = 0x86dd;
|
||||||
|
const int kIp6HdrLen = 40;
|
||||||
|
const quint8 kIpProtoIcmp6 = 58;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NOTE:
|
* NOTE:
|
||||||
@ -37,6 +41,17 @@ const quint64 kBcastMac = 0xffffffffffffULL;
|
|||||||
* (e.g. in a hash)
|
* (e.g. in a hash)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
inline quint32 sumUInt128(UInt128 value)
|
||||||
|
{
|
||||||
|
quint8 *arr = value.toArray();
|
||||||
|
quint32 sum = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < 16; i += 2)
|
||||||
|
sum += qToBigEndian(*((quint16*)(arr + i)));
|
||||||
|
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
Device::Device(DeviceManager *deviceManager)
|
Device::Device(DeviceManager *deviceManager)
|
||||||
{
|
{
|
||||||
deviceManager_ = deviceManager;
|
deviceManager_ = deviceManager;
|
||||||
@ -81,8 +96,8 @@ void Device::setMac(quint64 mac)
|
|||||||
{
|
{
|
||||||
int ofs = kMaxVlan * sizeof(quint16);
|
int ofs = kMaxVlan * sizeof(quint16);
|
||||||
|
|
||||||
mac_ = mac;
|
mac_ = mac & ~(0xffffULL << 48);
|
||||||
memcpy(key_.data() + ofs, (char*)&mac, sizeof(mac));
|
memcpy(key_.data() + ofs, (char*)&mac_, sizeof(mac_));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Device::setIp4(quint32 address, int prefixLength, quint32 gateway)
|
void Device::setIp4(quint32 address, int prefixLength, quint32 gateway)
|
||||||
@ -234,7 +249,7 @@ void Device::transmitPacket(PacketBuffer *pktBuf)
|
|||||||
|
|
||||||
void Device::clearNeighbors()
|
void Device::clearNeighbors()
|
||||||
{
|
{
|
||||||
arpTable.clear();
|
arpTable_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolve the Neighbor IP address for this to-be-transmitted pktBuf
|
// Resolve the Neighbor IP address for this to-be-transmitted pktBuf
|
||||||
@ -268,8 +283,8 @@ void Device::resolveNeighbor(PacketBuffer *pktBuf)
|
|||||||
// Append this device's neighbors to the list
|
// Append this device's neighbors to the list
|
||||||
void Device::getNeighbors(OstEmul::DeviceNeighborList *neighbors)
|
void Device::getNeighbors(OstEmul::DeviceNeighborList *neighbors)
|
||||||
{
|
{
|
||||||
QList<quint32> ipList = arpTable.keys();
|
QList<quint32> ipList = arpTable_.keys();
|
||||||
QList<quint64> macList = arpTable.values();
|
QList<quint64> macList = arpTable_.values();
|
||||||
|
|
||||||
Q_ASSERT(ipList.size() == macList.size());
|
Q_ASSERT(ipList.size() == macList.size());
|
||||||
|
|
||||||
@ -290,12 +305,13 @@ bool Device::isOrigin(const PacketBuffer *pktBuf)
|
|||||||
qDebug("%s: ethType 0x%x", __PRETTY_FUNCTION__, ethType);
|
qDebug("%s: ethType 0x%x", __PRETTY_FUNCTION__, ethType);
|
||||||
pktData += 2;
|
pktData += 2;
|
||||||
|
|
||||||
// We know only about IP packets
|
// We know only about IP packets - adjust for ethType length (2 bytes)
|
||||||
|
// when checking that we have a complete IP header
|
||||||
if ((ethType == 0x0800) && hasIp4_) { // IPv4
|
if ((ethType == 0x0800) && hasIp4_) { // IPv4
|
||||||
int ipHdrLen = (pktData[0] & 0x0F) << 2;
|
int ipHdrLen = (pktData[0] & 0x0F) << 2;
|
||||||
quint32 srcIp;
|
quint32 srcIp;
|
||||||
|
|
||||||
if (pktBuf->length() < ipHdrLen) {
|
if (pktBuf->length() < (ipHdrLen+2)) {
|
||||||
qDebug("incomplete IPv4 header: expected %d, actual %d",
|
qDebug("incomplete IPv4 header: expected %d, actual %d",
|
||||||
ipHdrLen, pktBuf->length());
|
ipHdrLen, pktBuf->length());
|
||||||
return false;
|
return false;
|
||||||
@ -305,6 +321,19 @@ bool Device::isOrigin(const PacketBuffer *pktBuf)
|
|||||||
qDebug("%s: pktSrcIp/selfIp = 0x%x/0x%x", __FUNCTION__, srcIp, ip4_);
|
qDebug("%s: pktSrcIp/selfIp = 0x%x/0x%x", __FUNCTION__, srcIp, ip4_);
|
||||||
return (srcIp == ip4_);
|
return (srcIp == ip4_);
|
||||||
}
|
}
|
||||||
|
else if ((ethType == kEthTypeIp6) && hasIp6_) { // IPv6
|
||||||
|
UInt128 srcIp;
|
||||||
|
if (pktBuf->length() < (kIp6HdrLen+2)) {
|
||||||
|
qDebug("incomplete IPv6 header: expected %d, actual %d",
|
||||||
|
kIp6HdrLen, pktBuf->length()-2);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
srcIp = qFromBigEndian<UInt128>(pktData + 8);
|
||||||
|
qDebug("%s: pktSrcIp6/selfIp6 = %llx-%llx/%llx-%llx", __FUNCTION__,
|
||||||
|
srcIp.hi64(), srcIp.lo64(), ip6_.hi64(), ip6_.lo64());
|
||||||
|
return (srcIp == ip6_);
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -335,7 +364,7 @@ quint64 Device::neighborMac(const PacketBuffer *pktBuf)
|
|||||||
qDebug("dst %x self %x mask %x", dstIp, ip4_, mask);
|
qDebug("dst %x self %x mask %x", dstIp, ip4_, mask);
|
||||||
tgtIp = ((dstIp & mask) == (ip4_ & mask)) ? dstIp : ip4Gateway_;
|
tgtIp = ((dstIp & mask) == (ip4_ & mask)) ? dstIp : ip4Gateway_;
|
||||||
|
|
||||||
return arpTable.value(tgtIp);
|
return arpTable_.value(tgtIp);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -344,6 +373,11 @@ quint64 Device::neighborMac(const PacketBuffer *pktBuf)
|
|||||||
//
|
//
|
||||||
// Private Methods
|
// Private Methods
|
||||||
//
|
//
|
||||||
|
/*
|
||||||
|
* ---------------------------------------------------------
|
||||||
|
* IPv4 related private methods
|
||||||
|
* ---------------------------------------------------------
|
||||||
|
*/
|
||||||
void Device::receiveArp(PacketBuffer *pktBuf)
|
void Device::receiveArp(PacketBuffer *pktBuf)
|
||||||
{
|
{
|
||||||
PacketBuffer *rspPkt;
|
PacketBuffer *rspPkt;
|
||||||
@ -404,7 +438,7 @@ void Device::receiveArp(PacketBuffer *pktBuf)
|
|||||||
switch (opCode)
|
switch (opCode)
|
||||||
{
|
{
|
||||||
case 1: // ARP Request
|
case 1: // ARP Request
|
||||||
arpTable.insert(srcIp, srcMac);
|
arpTable_.insert(srcIp, srcMac);
|
||||||
|
|
||||||
rspPkt = new PacketBuffer;
|
rspPkt = new PacketBuffer;
|
||||||
rspPkt->reserve(encapSize());
|
rspPkt->reserve(encapSize());
|
||||||
@ -432,7 +466,7 @@ void Device::receiveArp(PacketBuffer *pktBuf)
|
|||||||
qPrintable(QHostAddress(tgtIp).toString()));
|
qPrintable(QHostAddress(tgtIp).toString()));
|
||||||
break;
|
break;
|
||||||
case 2: // ARP Response
|
case 2: // ARP Response
|
||||||
arpTable.insert(srcIp, srcMac);
|
arpTable_.insert(srcIp, srcMac);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -462,6 +496,7 @@ void Device::sendArpRequest(PacketBuffer *pktBuf)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: not required - caller is checking for origin anyway
|
||||||
// Extract srcIp first to check quickly that this packet originates
|
// Extract srcIp first to check quickly that this packet originates
|
||||||
// from this device
|
// from this device
|
||||||
srcIp = qFromBigEndian<quint32>(pktData + ipHdrLen - 8);
|
srcIp = qFromBigEndian<quint32>(pktData + ipHdrLen - 8);
|
||||||
@ -480,7 +515,7 @@ void Device::sendArpRequest(PacketBuffer *pktBuf)
|
|||||||
|
|
||||||
// Do we already have a ARP entry (resolved or unresolved)?
|
// Do we already have a ARP entry (resolved or unresolved)?
|
||||||
// FIXME: do we need a timer to resend ARP for unresolved entries?
|
// FIXME: do we need a timer to resend ARP for unresolved entries?
|
||||||
if (arpTable.contains(tgtIp))
|
if (arpTable_.contains(tgtIp))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
reqPkt = new PacketBuffer;
|
reqPkt = new PacketBuffer;
|
||||||
@ -503,7 +538,7 @@ void Device::sendArpRequest(PacketBuffer *pktBuf)
|
|||||||
|
|
||||||
encap(reqPkt, kBcastMac, 0x0806);
|
encap(reqPkt, kBcastMac, 0x0806);
|
||||||
transmitPacket(reqPkt);
|
transmitPacket(reqPkt);
|
||||||
arpTable.insert(tgtIp, 0);
|
arpTable_.insert(tgtIp, 0);
|
||||||
|
|
||||||
qDebug("Sent ARP Request for srcIp/tgtIp=%s/%s",
|
qDebug("Sent ARP Request for srcIp/tgtIp=%s/%s",
|
||||||
qPrintable(QHostAddress(srcIp).toString()),
|
qPrintable(QHostAddress(srcIp).toString()),
|
||||||
@ -567,7 +602,7 @@ void Device::sendIp4Reply(PacketBuffer *pktBuf)
|
|||||||
dstIp = qFromBigEndian<quint32>(pktData + 12); // srcIp in original pkt
|
dstIp = qFromBigEndian<quint32>(pktData + 12); // srcIp in original pkt
|
||||||
srcIp = qFromBigEndian<quint32>(pktData + 16); // dstIp in original pkt
|
srcIp = qFromBigEndian<quint32>(pktData + 16); // dstIp in original pkt
|
||||||
|
|
||||||
if (!arpTable.contains(dstIp))
|
if (!arpTable_.contains(dstIp))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
*(quint32*)(pktData + 12) = qToBigEndian(srcIp);
|
*(quint32*)(pktData + 12) = qToBigEndian(srcIp);
|
||||||
@ -585,7 +620,7 @@ void Device::sendIp4Reply(PacketBuffer *pktBuf)
|
|||||||
sum = (sum & 0xFFFF) + (sum >> 16);
|
sum = (sum & 0xFFFF) + (sum >> 16);
|
||||||
*(quint16*)(pktData + 10) = qToBigEndian(quint16(~sum));
|
*(quint16*)(pktData + 10) = qToBigEndian(quint16(~sum));
|
||||||
|
|
||||||
encap(pktBuf, arpTable.value(dstIp), 0x0800);
|
encap(pktBuf, arpTable_.value(dstIp), 0x0800);
|
||||||
transmitPacket(pktBuf);
|
transmitPacket(pktBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -617,11 +652,123 @@ void Device::receiveIcmp4(PacketBuffer *pktBuf)
|
|||||||
qDebug("Sent ICMP Echo Reply");
|
qDebug("Sent ICMP Echo Reply");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ---------------------------------------------------------
|
||||||
|
* IPV6 related private methods
|
||||||
|
* ---------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
// pktBuf should point to start of IP payload
|
||||||
|
bool Device::sendIp6(PacketBuffer *pktBuf, UInt128 dstIp, quint8 protocol)
|
||||||
|
{
|
||||||
|
int payloadLen = pktBuf->length();
|
||||||
|
uchar *p = pktBuf->push(kIp6HdrLen);
|
||||||
|
quint64 dstMac = kBcastMac;
|
||||||
|
|
||||||
|
if (!p) {
|
||||||
|
qWarning("%s: failed to push %d bytes [0x%p, 0x%p]", __FUNCTION__,
|
||||||
|
kIp6HdrLen, pktBuf->head(), pktBuf->data());
|
||||||
|
goto _error_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ver(4), TrfClass(8), FlowLabel(8)
|
||||||
|
*(quint32*)(p ) = qToBigEndian(quint32(0x60000000));
|
||||||
|
*(quint16*)(p+ 4) = qToBigEndian(quint16(payloadLen));
|
||||||
|
p[6] = protocol;
|
||||||
|
p[7] = 255; // HopLimit
|
||||||
|
memcpy(p+ 8, ip6_.toArray(), 16); // Source IP
|
||||||
|
memcpy(p+24, dstIp.toArray(), 16); // Destination IP
|
||||||
|
|
||||||
|
// In case of mcast, derive dstMac
|
||||||
|
if ((dstIp.hi64() >> 56) == 0xff)
|
||||||
|
dstMac = (quint64(0x3333) << 32) | (dstIp.lo64() & 0xffffffff);
|
||||||
|
|
||||||
|
// FIXME: both these functions should return success/failure
|
||||||
|
encap(pktBuf, dstMac, kEthTypeIp6);
|
||||||
|
transmitPacket(pktBuf);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
_error_exit:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Send NS for the IPv6 packet in pktBuf
|
// Send NS for the IPv6 packet in pktBuf
|
||||||
// pktBuf points to start of IP header
|
// caller is responsible to check that pktBuf originates from this device
|
||||||
|
// pktBuf should point to start of IP header
|
||||||
void Device::sendNeighborSolicit(PacketBuffer *pktBuf)
|
void Device::sendNeighborSolicit(PacketBuffer *pktBuf)
|
||||||
{
|
{
|
||||||
// TODO
|
PacketBuffer *reqPkt;
|
||||||
|
uchar *pktData = pktBuf->data();
|
||||||
|
UInt128 srcIp, dstIp, mask, tgtIp;
|
||||||
|
|
||||||
|
if (pktBuf->length() < kIp6HdrLen) {
|
||||||
|
qDebug("incomplete IPv6 header: expected %d, actual %d",
|
||||||
|
kIp6HdrLen, pktBuf->length());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
srcIp = qFromBigEndian<UInt128>(pktData + 8);
|
||||||
|
dstIp = qFromBigEndian<UInt128>(pktData + 24);
|
||||||
|
|
||||||
|
mask = ~UInt128(0, 0) << (128 - ip6PrefixLength_);
|
||||||
|
qDebug("%s: dst %s src %s mask %s", __FUNCTION__,
|
||||||
|
qPrintable(QHostAddress(dstIp.toArray()).toString()),
|
||||||
|
qPrintable(QHostAddress(srcIp.toArray()).toString()),
|
||||||
|
qPrintable(QHostAddress(mask.toArray()).toString()));
|
||||||
|
tgtIp = ((dstIp & mask) == (srcIp & mask)) ? dstIp : ip6Gateway_;
|
||||||
|
|
||||||
|
// Do we already have a NDP entry (resolved or unresolved)?
|
||||||
|
// FIXME: do we need a timer to resend NS for unresolved entries?
|
||||||
|
if (ndpTable_.contains(tgtIp))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Form the solicited node address to be used as dstIp
|
||||||
|
// ff02::1:ffXX:XXXX/104
|
||||||
|
dstIp = UInt128((quint64(0xff02) << 48),
|
||||||
|
(quint64(0x01ff) << 24) | (tgtIp.lo64() & 0xFFFFFF));
|
||||||
|
|
||||||
|
reqPkt = new PacketBuffer;
|
||||||
|
reqPkt->reserve(encapSize() + kIp6HdrLen);
|
||||||
|
pktData = reqPkt->put(32);
|
||||||
|
if (pktData) {
|
||||||
|
// Calculate checksum first -
|
||||||
|
// start with fixed fields in ICMP Header and IPv6 Pseudo Header ...
|
||||||
|
quint32 sum = 0x8700 + 0x0101 + 32 + kIpProtoIcmp6;
|
||||||
|
|
||||||
|
// then variable fields from ICMP header ...
|
||||||
|
sum += sumUInt128(tgtIp);
|
||||||
|
sum += (mac_ >> 32) + ((mac_ >> 16) & 0xffff) + (mac_ & 0xffff);
|
||||||
|
|
||||||
|
// and variable fields from IPv6 pseudo header
|
||||||
|
sum += sumUInt128(ip6_);
|
||||||
|
sum += sumUInt128(dstIp);
|
||||||
|
|
||||||
|
while(sum >> 16)
|
||||||
|
sum = (sum & 0xFFFF) + (sum >> 16);
|
||||||
|
|
||||||
|
// Type, Code
|
||||||
|
*(quint16*)(pktData ) = qToBigEndian(quint16(0x8700));
|
||||||
|
// Checksum
|
||||||
|
*(quint16*)(pktData+ 2) = qToBigEndian(quint16(~sum));
|
||||||
|
// Reserved
|
||||||
|
*(quint32*)(pktData+ 4) = qToBigEndian(quint32(0));
|
||||||
|
// Target IP
|
||||||
|
memcpy(pktData+ 8, tgtIp.toArray(), 16);
|
||||||
|
// Source Addr TLV + MacAddr
|
||||||
|
*(quint16*)(pktData+24) = qToBigEndian(quint16(0x0101));
|
||||||
|
*(quint32*)(pktData+26) = qToBigEndian(quint32(mac_ >> 16));
|
||||||
|
*(quint16*)(pktData+30) = qToBigEndian(quint16(mac_ & 0xffff));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sendIp6(reqPkt, dstIp , kIpProtoIcmp6))
|
||||||
|
return;
|
||||||
|
|
||||||
|
ndpTable_.insert(tgtIp, 0);
|
||||||
|
|
||||||
|
qDebug("Sent NDP Request for srcIp/tgtIp=%s/%s",
|
||||||
|
qPrintable(QHostAddress(srcIp.toArray()).toString()),
|
||||||
|
qPrintable(QHostAddress(tgtIp.toArray()).toString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator<(const DeviceKey &a1, const DeviceKey &a2)
|
bool operator<(const DeviceKey &a1, const DeviceKey &a2)
|
||||||
|
@ -75,8 +75,9 @@ private: // methods
|
|||||||
|
|
||||||
void receiveIcmp4(PacketBuffer *pktBuf);
|
void receiveIcmp4(PacketBuffer *pktBuf);
|
||||||
|
|
||||||
|
bool sendIp6(PacketBuffer *pktBuf, UInt128 dstIp, quint8 protocol);
|
||||||
|
|
||||||
void sendNeighborSolicit(PacketBuffer *pktBuf);
|
void sendNeighborSolicit(PacketBuffer *pktBuf);
|
||||||
void sendIp6(PacketBuffer *pktBuf);
|
|
||||||
|
|
||||||
private: // data
|
private: // data
|
||||||
static const int kMaxVlan = 4;
|
static const int kMaxVlan = 4;
|
||||||
@ -99,7 +100,8 @@ private: // data
|
|||||||
|
|
||||||
DeviceKey key_;
|
DeviceKey key_;
|
||||||
|
|
||||||
QHash<quint32, quint64> arpTable;
|
QHash<quint32, quint64> arpTable_;
|
||||||
|
QHash<UInt128, quint64> ndpTable_;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool operator<(const DeviceKey &a1, const DeviceKey &a2);
|
bool operator<(const DeviceKey &a1, const DeviceKey &a2);
|
||||||
|
@ -159,6 +159,7 @@ def ports(request, drone):
|
|||||||
def dut(request):
|
def dut(request):
|
||||||
# Enable IP forwarding on the DUT (aka make it a router)
|
# Enable IP forwarding on the DUT (aka make it a router)
|
||||||
sudo('sysctl -w net.ipv4.ip_forward=1')
|
sudo('sysctl -w net.ipv4.ip_forward=1')
|
||||||
|
sudo('sysctl -w net.ipv6.conf.all.forwarding=1')
|
||||||
|
|
||||||
@pytest.fixture(scope='module')
|
@pytest.fixture(scope='module')
|
||||||
def dut_ports(request):
|
def dut_ports(request):
|
||||||
@ -559,20 +560,22 @@ def test_multiEmulDevNoVlan(drone, ports, dut, dut_ports, dut_ip,
|
|||||||
print(cap_pkts)
|
print(cap_pkts)
|
||||||
log.info('dumping Tx capture buffer (filtered)')
|
log.info('dumping Tx capture buffer (filtered)')
|
||||||
for i in range(len(ip_versions)):
|
for i in range(len(ip_versions)):
|
||||||
|
if ip_versions[i] == 'ip4':
|
||||||
|
filter = '(arp.opcode == 1)' \
|
||||||
|
' && (arp.src.proto_ipv4 == 10.10.1.<x>)' \
|
||||||
|
' && (arp.dst.proto_ipv4 == 10.10.1.1)' \
|
||||||
|
' && !expert.severity'
|
||||||
|
elif ip_versions[i] == 'ip6':
|
||||||
|
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):
|
for j in range(num_devs):
|
||||||
if ip_versions[i] == 'ip4':
|
if ip_versions[i] == 'ip4':
|
||||||
filter = '(arp.opcode == 1)' \
|
filter = filter.replace('<x>', str(101+j*ip_step))
|
||||||
' && (arp.src.proto_ipv4 == 10.10.1.' \
|
|
||||||
+ str(101+j*ip_step) + ')' \
|
|
||||||
' && (arp.dst.proto_ipv4 == 10.10.1.1)'
|
|
||||||
elif ip_versions[i] == 'ip6':
|
elif ip_versions[i] == 'ip6':
|
||||||
filter = '(icmpv6.type == 135)' \
|
filter = filter.replace('<x>', format(0x65+j*ip_step, 'x'))
|
||||||
' && (icmpv6.nd.ns.target_address == 1234:1::1)' \
|
#print filter
|
||||||
' && (icmpv6.nd.ns.target_address == 1234:1::' \
|
|
||||||
+ format(0x65+i*ip_step, 'x')+')'
|
|
||||||
print filter
|
|
||||||
else:
|
|
||||||
assert False # unreachable
|
|
||||||
cap_pkts = subprocess.check_output([tshark, '-nr', 'capture.pcap',
|
cap_pkts = subprocess.check_output([tshark, '-nr', 'capture.pcap',
|
||||||
'-Y', filter])
|
'-Y', filter])
|
||||||
print(cap_pkts)
|
print(cap_pkts)
|
||||||
@ -586,19 +589,21 @@ def test_multiEmulDevNoVlan(drone, ports, dut, dut_ports, dut_ip,
|
|||||||
print(cap_pkts)
|
print(cap_pkts)
|
||||||
log.info('dumping Rx capture buffer (filtered)')
|
log.info('dumping Rx capture buffer (filtered)')
|
||||||
for i in range(len(ip_versions)):
|
for i in range(len(ip_versions)):
|
||||||
|
if ip_versions[i] == 'ip4':
|
||||||
|
filter = '(arp.opcode == 1)' \
|
||||||
|
' && (arp.src.proto_ipv4 == 10.10.2.<x>)' \
|
||||||
|
' && (arp.dst.proto_ipv4 == 10.10.2.1)' \
|
||||||
|
' && !expert.severity'
|
||||||
|
elif ip_versions[i] == 'ip6':
|
||||||
|
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):
|
for j in range(num_devs):
|
||||||
if ip_versions[i] == 'ip4':
|
if ip_versions[i] == 'ip4':
|
||||||
filter = '(arp.opcode == 1)' \
|
filter = filter.replace('<x>', str(101+j*ip_step))
|
||||||
' && (arp.src.proto_ipv4 == 10.10.2.' \
|
|
||||||
+ str(101+j*ip_step) + ')' \
|
|
||||||
' && (arp.dst.proto_ipv4 == 10.10.2.1)'
|
|
||||||
elif ip_versions[i] == 'ip6':
|
elif ip_versions[i] == 'ip6':
|
||||||
filter = '(icmpv6.type == 135)' \
|
filter = filter.replace('<x>', format(0x65+j*ip_step, 'x'))
|
||||||
' && (icmpv6.nd.ns.target_address == 1234:2::1)' \
|
|
||||||
' && (icmpv6.nd.ns.target_address == 1234:2::' \
|
|
||||||
+ format(0x65+i*ip_step, 'x')+')'
|
|
||||||
else:
|
|
||||||
assert False # unreachable
|
|
||||||
print filter
|
print filter
|
||||||
cap_pkts = subprocess.check_output([tshark, '-nr', 'capture.pcap',
|
cap_pkts = subprocess.check_output([tshark, '-nr', 'capture.pcap',
|
||||||
'-Y', filter])
|
'-Y', filter])
|
||||||
|
Loading…
Reference in New Issue
Block a user