/*
Copyright (C) 2016 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
*/
#include "devicegroupdialog.h"
#include "port.h"
#include "emulproto.pb.h"
#include "uint128.h"
#include "macedit.h"
#include "ip4edit.h"
#include
#include
enum { kIpNone, kIp4, kIp6, kIpDual };
static QStringList ipStackItems = QStringList()
<< "None" << "IPv4" << "IPv6" << "Dual";
inline UInt128 UINT128(OstEmul::Ip6Address x)
{
return UInt128(x.hi(), x.lo());
}
inline QString IP6STR(OstEmul::Ip6Address ip)
{
return QHostAddress(UINT128(ip).toArray()).toString();
}
DeviceGroupDialog::DeviceGroupDialog(
Port *port,
int deviceGroupIndex,
QWidget *parent,
Qt::WindowFlags flags)
: QDialog(parent, flags), port_(port), index_(deviceGroupIndex)
{
// Setup the Dialog
setupUi(this);
vlanTagCount->setRange(0, kMaxVlanTags);
#if 0 // FIXME: not working
qDebug("vlan def size: %d", vlans->verticalHeader()->defaultSectionSize());
qDebug("vlan min size: %d", vlans->verticalHeader()->minimumSectionSize());
vlans->verticalHeader()->setDefaultSectionSize(
vlans->verticalHeader()->minimumSectionSize());
qDebug("vlan def size: %d", vlans->verticalHeader()->defaultSectionSize());
qDebug("vlan min size: %d", vlans->verticalHeader()->minimumSectionSize());
#endif
ipStack->insertItems(0, ipStackItems);
layout()->setSizeConstraint(QLayout::SetFixedSize);
connect(ip4Address, SIGNAL(textEdited(const QString&)),
this, SLOT(updateIp4Gateway()));
connect(ip4PrefixLength, SIGNAL(valueChanged(const QString&)),
this, SLOT(updateIp4Gateway()));
loadDeviceGroup();
}
void DeviceGroupDialog::accept()
{
storeDeviceGroup();
QDialog::accept();
}
//
// Private Slots
//
void DeviceGroupDialog::on_vlanTagCount_valueChanged(int value)
{
Q_ASSERT((value >= 0) && (value <= kMaxVlanTags));
vlans->setVisible(value > 0);
}
void DeviceGroupDialog::on_ipStack_currentIndexChanged(int index)
{
switch (index) {
case kIpNone:
ip4->hide();
ip6->hide();
break;
case kIp4:
ip4->show();
ip6->hide();
break;
case kIp6:
ip4->hide();
ip6->show();
break;
case kIpDual:
ip4->show();
ip6->show();
break;
default:
Q_ASSERT(false); // Unreachable!
break;
}
}
void DeviceGroupDialog::updateIp4Gateway()
{
quint32 net = ip4Address->value() & (~0 << (32 - ip4PrefixLength->value()));
ip4Gateway->setValue(net | 0x01);
}
void DeviceGroupDialog::loadDeviceGroup()
{
OstProto::DeviceGroup *devGrp = port_->deviceGroupByIndex(index_);
int tagCount = 0;
int totalVlans;
Q_ASSERT(devGrp);
name->setText(QString::fromStdString(devGrp->core().name()));
if (devGrp->has_encap() && devGrp->encap().HasExtension(OstEmul::vlan))
tagCount = devGrp->encap().GetExtension(OstEmul::vlan).stack_size();
vlanTagCount->setValue(tagCount);
// FIXME: vlan table widget
totalVlans = totalVlanCount();
vlanCount->setText(QString::number(totalVlans));
devicePerVlanCount->setValue(devGrp->device_count());
totalDeviceCount->setText(
QString::number(totalVlans * devGrp->device_count()));
OstEmul::MacEmulation mac = devGrp->GetExtension(OstEmul::mac);
if (!mac.has_address()) {
// Mac address as per RFC 4814 Sec 4.2
// (RR & 0xFC):PP:PP:RR:RR:RR
// where RR is a random number, PP:PP is 1-indexed port index
// NOTE: although qrand() return type is a int, the max value
// is RAND_MAX (stdlib.h) which is often 16-bit only, so we
// use two random numbers
quint32 r1 = qrand(), r2 = qrand();
quint64 mac;
mac = quint64(r1 & 0xfc00) << 32
| quint64(port_->id() + 1) << 24
| quint64((r1 & 0xff) << 16 | (r2 & 0xffff));
macAddress->setValue(mac);
}
else
macAddress->setValue(mac.address());
macStep->setValue(mac.step());
OstEmul::Ip4Emulation ip4 = devGrp->GetExtension(OstEmul::ip4);
ip4Address->setValue(ip4.address());
ip4PrefixLength->setValue(ip4.prefix_length());
ip4Step->setValue(ip4.step());
ip4Gateway->setValue(ip4.default_gateway());
OstEmul::Ip6Emulation ip6 = devGrp->GetExtension(OstEmul::ip6);
ip6Address->setText(IP6STR(ip6.address()));
ip6Step->setText(IP6STR(ip6.step()));
ip6Gateway->setText(IP6STR(ip6.default_gateway()));
int stk = kIpNone;
if (devGrp->HasExtension(OstEmul::ip4))
if (devGrp->HasExtension(OstEmul::ip6))
stk = kIpDual;
else
stk = kIp4;
else if (devGrp->HasExtension(OstEmul::ip6))
stk = kIp6;
ipStack->setCurrentIndex(stk);
}
void DeviceGroupDialog::storeDeviceGroup()
{
OstProto::DeviceGroup *devGrp = port_->deviceGroupByIndex(index_);
int tagCount = 0;
Q_ASSERT(devGrp);
devGrp->mutable_core()->set_name(name->text().toStdString());
tagCount = vlanTagCount->value();
// FIXME: vlan table widget
devGrp->set_device_count(devicePerVlanCount->value());
OstEmul::MacEmulation *mac = devGrp->MutableExtension(OstEmul::mac);
mac->set_address(macAddress->value());
mac->set_step(macStep->value());
if (ipStack->currentIndex() == kIp4
|| ipStack->currentIndex() == kIpDual) {
OstEmul::Ip4Emulation *ip4 = devGrp->MutableExtension(OstEmul::ip4);
ip4->set_address(ip4Address->value());
ip4->set_prefix_length(ip4PrefixLength->value());
ip4->set_default_gateway(ip4Gateway->value());
ip4->set_step(ip4Step->value());
if (ipStack->currentIndex() == kIp4)
devGrp->ClearExtension(OstEmul::ip6);
}
if (ipStack->currentIndex() == kIp6
|| ipStack->currentIndex() == kIpDual) {
OstEmul::Ip6Emulation *ip6 = devGrp->MutableExtension(OstEmul::ip6);
Q_IPV6ADDR w;
UInt128 x;
w = QHostAddress(ip6Address->text()).toIPv6Address();
x = UInt128((quint8*)&w);
ip6->mutable_address()->set_hi(x.hi64());
ip6->mutable_address()->set_lo(x.lo64());
ip6->set_prefix_length(ip4PrefixLength->value());
w = QHostAddress(ip6Gateway->text()).toIPv6Address();
x = UInt128((quint8*)&w);
ip6->mutable_default_gateway()->set_hi(x.hi64());
ip6->mutable_default_gateway()->set_lo(x.lo64());
w = QHostAddress(ip6Step->text()).toIPv6Address();
x = UInt128((quint8*)&w);
ip6->mutable_step()->set_hi(x.hi64());
ip6->mutable_step()->set_lo(x.lo64());
if (ipStack->currentIndex() == kIp6)
devGrp->ClearExtension(OstEmul::ip4);
}
if (ipStack->currentIndex() == kIpNone) {
devGrp->ClearExtension(OstEmul::ip4);
devGrp->ClearExtension(OstEmul::ip6);
}
}
int DeviceGroupDialog::totalVlanCount()
{
// FIXME
return 1;
}