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 # ================================================================= # # ----------------------------------------------------------------- #