diff --git a/common/uint128.h b/common/uint128.h
new file mode 100644
index 0000000..d91ea44
--- /dev/null
+++ b/common/uint128.h
@@ -0,0 +1,83 @@
+/*
+Copyright (C) 2015 Srivats P.
+
+This file is part of "Ostinato"
+
+This is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see
+*/
+
+#ifndef _UINT128_H
+#define _UINT128_H
+
+#include
+#include
+
+class UInt128
+{
+public:
+ UInt128();
+ UInt128(quint64 hi, quint64 lo);
+
+ quint8* toArray() const;
+
+ UInt128 operator+(const UInt128 &other);
+ UInt128 operator*(const uint &other);
+
+private:
+ quint64 hi_;
+ quint64 lo_;
+ quint8 array_[16];
+};
+
+inline UInt128::UInt128()
+{
+ // Do nothing - value will be garbage like any other uint
+}
+
+inline UInt128::UInt128(quint64 hi, quint64 lo)
+{
+ hi_ = hi;
+ lo_ = lo;
+}
+
+inline quint8* UInt128::toArray() const
+{
+ *(quint64*)(array_ + 0) = qToBigEndian(hi_);
+ *(quint64*)(array_ + 8) = qToBigEndian(lo_);
+
+ return (quint8*)array_;
+}
+
+inline UInt128 UInt128::operator+(const UInt128 &other)
+{
+ UInt128 sum;
+
+ sum.lo_ = lo_ + other.lo_;
+ sum.hi_ = hi_ + other.hi_ + (sum.lo_ < lo_);
+
+ return sum;
+}
+
+inline UInt128 UInt128::operator*(const uint &other)
+{
+ UInt128 product;
+
+ // FIXME
+ product.hi_ = 0;
+ product.lo_ = lo_ * other;
+
+ return product;
+}
+
+#endif
diff --git a/server/device.cpp b/server/device.cpp
index fa495da..8549bb5 100644
--- a/server/device.cpp
+++ b/server/device.cpp
@@ -45,9 +45,13 @@ Device::Device(DeviceManager *deviceManager)
vlan_[i] = 0;
numVlanTags_ = 0;
mac_ = 0;
- ip4_ = 0;
+
+ ip4_ = ip4Gateway_ = 0;
ip4PrefixLength_ = 0;
+ ip6_ = ip6Gateway_ = UInt128(0, 0);
+ ip6PrefixLength_ = 0;
+
clearKey();
}
@@ -91,20 +95,33 @@ void Device::setIp4(quint32 address, int prefixLength, quint32 gateway)
ip4Gateway_ = gateway;
}
+void Device::setIp6(UInt128 address, int prefixLength, UInt128 gateway)
+{
+ ip6_ = address;
+ ip6PrefixLength_ = prefixLength;
+ ip6Gateway_ = gateway;
+}
+
void Device::getConfig(OstEmul::Device *deviceConfig)
{
for (int i = 0; i < numVlanTags_; i++)
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 0 // FIXME
+ deviceConfig->set_ip6(ip6_);
+ deviceConfig->set_ip6_prefix_length(ip6PrefixLength_);
+ deviceConfig->set_ip6_default_gateway(ip6Gateway_);
+#endif
}
QString Device::config()
{
- return QString("")
+ return QString("")
.arg((vlan_[0] >> 16) != kVlanTpid ?
QString("0x%1-%2")
.arg(vlan_[0] >> 16, 4, kBaseHex, QChar('0'))
@@ -131,7 +148,9 @@ QString Device::config()
.arg(vlan_[3] & 0xFFFF))
.arg(mac_, 12, kBaseHex, QChar('0'))
.arg(QHostAddress(ip4_).toString())
- .arg(ip4PrefixLength_);
+ .arg(ip4PrefixLength_)
+ .arg(QHostAddress(ip6_.toArray()).toString())
+ .arg(ip6PrefixLength_);
}
DeviceKey Device::key()
@@ -234,6 +253,9 @@ void Device::resolveNeighbor(PacketBuffer *pktBuf)
break;
case 0x86dd: // IPv6
+ sendNeighborSolicit(pktBuf);
+ break;
+
default:
break;
}
@@ -591,6 +613,13 @@ void Device::receiveIcmp4(PacketBuffer *pktBuf)
qDebug("Sent ICMP Echo Reply");
}
+// Send NS for the IPv6 packet in pktBuf
+// pktBuf points to start of IP header
+void Device::sendNeighborSolicit(PacketBuffer *pktBuf)
+{
+ // TODO
+}
+
bool operator<(const DeviceKey &a1, const DeviceKey &a2)
{
int i = 0;
diff --git a/server/device.h b/server/device.h
index 267130a..32d848c 100644
--- a/server/device.h
+++ b/server/device.h
@@ -22,6 +22,7 @@ along with this program. If not, see
#include "../common/emulproto.pb.h"
#include "../common/protocol.pb.h"
+#include "../common/uint128.h"
#include
#include
@@ -45,6 +46,7 @@ public:
quint64 mac();
void setMac(quint64 mac);
void setIp4(quint32 address, int prefixLength, quint32 gateway);
+ void setIp6(UInt128 address, int prefixLength, UInt128 gateway);
void getConfig(OstEmul::Device *deviceConfig);
QString config();
@@ -73,6 +75,9 @@ private: // methods
void receiveIcmp4(PacketBuffer *pktBuf);
+ void sendNeighborSolicit(PacketBuffer *pktBuf);
+ void sendIp6(PacketBuffer *pktBuf);
+
private: // data
static const int kMaxVlan = 4;
@@ -81,10 +86,15 @@ private: // data
int numVlanTags_;
quint32 vlan_[kMaxVlan];
quint64 mac_;
+
quint32 ip4_;
int ip4PrefixLength_;
quint32 ip4Gateway_;
+ UInt128 ip6_;
+ int ip6PrefixLength_;
+ UInt128 ip6Gateway_;
+
DeviceKey key_;
QHash arpTable;
diff --git a/server/devicemanager.cpp b/server/devicemanager.cpp
index f28e4e5..5df1391 100644
--- a/server/devicemanager.cpp
+++ b/server/devicemanager.cpp
@@ -31,6 +31,11 @@ along with this program. If not, see
#define __STDC_FORMAT_MACROS
#include
+inline UInt128 UINT128(OstEmul::Ip6Address x)
+{
+ return UInt128(x.hi(), x.lo());
+}
+
const quint64 kBcastMac = 0xffffffffffffULL;
// XXX: Port owning DeviceManager already uses locks, so we don't use any
@@ -125,7 +130,18 @@ bool DeviceManager::modifyDeviceGroup(const OstProto::DeviceGroup *deviceGroup)
}
enumerateDevices(myDeviceGroup, kDelete);
+
myDeviceGroup->CopyFrom(*deviceGroup);
+ // If mac step is 0, silently override to 1 - otherwise we won't have
+ // unique DeviceKeys
+ if (myDeviceGroup->GetExtension(OstEmul::mac).step() == 0)
+ myDeviceGroup->MutableExtension(OstEmul::mac)->set_step(1);
+ // Default value for ip6 step should be 1 (not 0)
+ if (myDeviceGroup->HasExtension(OstEmul::ip6)
+ && !myDeviceGroup->GetExtension(OstEmul::ip6).has_step())
+ myDeviceGroup->MutableExtension(OstEmul::ip6)
+ ->mutable_step()->set_lo(1);
+
enumerateDevices(myDeviceGroup, kAdd);
return true;
@@ -329,6 +345,7 @@ void DeviceManager::enumerateDevices(
OstEmul::MacEmulation mac = deviceGroup->GetExtension(OstEmul::mac);
OstEmul::Ip4Emulation ip4 = deviceGroup->GetExtension(OstEmul::ip4);
+ OstEmul::Ip6Emulation ip6 = deviceGroup->GetExtension(OstEmul::ip6);
/*
* vlanCount[] stores the number of unique vlans at each tag level
@@ -410,11 +427,15 @@ void DeviceManager::enumerateDevices(
Device *device;
quint64 macAdd = k * mac.step();
quint32 ip4Add = k * ip4.step();
+ 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()));
// TODO: fill in other pbDevice data
diff --git a/test/emultest.py b/test/emultest.py
index e4da1dd..5a114e1 100644
--- a/test/emultest.py
+++ b/test/emultest.py
@@ -88,8 +88,8 @@ class ip6_address(ipaddress.IPv6Interface):
# we assume gateway is the lowest IP host address in the network
gateway = self.network.network_address + 1
self.gateway = emul.Ip6Address()
- self.ip6.hi = int(gateway) >> 64
- self.ip6.lo = int(gateway) & 0xffffffffffffffff
+ self.gateway.hi = int(gateway) >> 64
+ self.gateway.lo = int(gateway) & 0xffffffffffffffff
# ================================================================= #
# ----------------------------------------------------------------- #