Device Emulation (contd.) - Implemented IPv6 device creation and deletion

This commit is contained in:
Srivats P 2015-12-31 20:17:56 +05:30
parent ea68b42059
commit aaf6dbcbf2
5 changed files with 149 additions and 6 deletions

83
common/uint128.h Normal file
View File

@ -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 <http://www.gnu.org/licenses/>
*/
#ifndef _UINT128_H
#define _UINT128_H
#include <QtGlobal>
#include <qendian.h>
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<quint64>(hi_);
*(quint64*)(array_ + 8) = qToBigEndian<quint64>(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

View File

@ -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("<vlans=%1/%2/%3/%4 mac=%5 ip4=%6/%7>")
return QString("<vlans=%1/%2/%3/%4 mac=%5 ip4=%6/%7 ip6=%8/%9>")
.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;

View File

@ -22,6 +22,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
#include "../common/emulproto.pb.h"
#include "../common/protocol.pb.h"
#include "../common/uint128.h"
#include <QByteArray>
#include <QHash>
@ -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<quint32, quint64> arpTable;

View File

@ -31,6 +31,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
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

View File

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