Review and rework of GMP and IGMP
This commit is contained in:
parent
d4408f0fc1
commit
dbc7409616
@ -5,7 +5,6 @@ win32:RC_FILE = ostinato.rc
|
|||||||
macx:ICON = icons/logo.icns
|
macx:ICON = icons/logo.icns
|
||||||
QT += network script
|
QT += network script
|
||||||
INCLUDEPATH += "../rpc/" "../common/"
|
INCLUDEPATH += "../rpc/" "../common/"
|
||||||
LIBS += -lprotobuf
|
|
||||||
win32 {
|
win32 {
|
||||||
CONFIG(debug, debug|release) {
|
CONFIG(debug, debug|release) {
|
||||||
LIBS += -L"../common/debug" -lostproto
|
LIBS += -L"../common/debug" -lostproto
|
||||||
@ -25,6 +24,7 @@ win32 {
|
|||||||
LIBS += -L"../rpc" -lpbrpc
|
LIBS += -L"../rpc" -lpbrpc
|
||||||
POST_TARGETDEPS += "../common/libostproto.a" "../rpc/libpbrpc.a"
|
POST_TARGETDEPS += "../common/libostproto.a" "../rpc/libpbrpc.a"
|
||||||
}
|
}
|
||||||
|
LIBS += -lprotobuf
|
||||||
RESOURCES += ostinato.qrc
|
RESOURCES += ostinato.qrc
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
dumpview.h \
|
dumpview.h \
|
||||||
|
131
common/gmp.cpp
131
common/gmp.cpp
@ -22,11 +22,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
#include <QHeaderView>
|
#include <QHeaderView>
|
||||||
#include <qendian.h>
|
#include <qendian.h>
|
||||||
|
|
||||||
|
QHash<int, int> GmpProtocol::frameFieldCountMap;
|
||||||
|
|
||||||
GmpConfigForm::GmpConfigForm(QWidget *parent)
|
GmpConfigForm::GmpConfigForm(QWidget *parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
{
|
{
|
||||||
setupUi(this);
|
setupUi(this);
|
||||||
|
|
||||||
|
// TODO: this should be in subclass
|
||||||
msgTypeCombo->setValueMask(0xFF);
|
msgTypeCombo->setValueMask(0xFF);
|
||||||
msgTypeCombo->addItem(kIgmpV1Query, "IGMPv1 Query");
|
msgTypeCombo->addItem(kIgmpV1Query, "IGMPv1 Query");
|
||||||
msgTypeCombo->addItem(kIgmpV1Report, "IGMPv1 Report");
|
msgTypeCombo->addItem(kIgmpV1Report, "IGMPv1 Report");
|
||||||
@ -70,14 +73,14 @@ void GmpConfigForm::on_msgTypeCombo_currentIndexChanged(int /*index*/)
|
|||||||
case kIgmpV3Query:
|
case kIgmpV3Query:
|
||||||
case kMldV2Query:
|
case kMldV2Query:
|
||||||
asmGroup->hide();
|
asmGroup->hide();
|
||||||
ssmWidget->setCurrentIndex(0);
|
ssmWidget->setCurrentIndex(kSsmQueryPage);
|
||||||
ssmWidget->show();
|
ssmWidget->show();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case kIgmpV3Report:
|
case kIgmpV3Report:
|
||||||
case kMldV2Report:
|
case kMldV2Report:
|
||||||
asmGroup->hide();
|
asmGroup->hide();
|
||||||
ssmWidget->setCurrentIndex(1);
|
ssmWidget->setCurrentIndex(kSsmReportPage);
|
||||||
ssmWidget->show();
|
ssmWidget->show();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -88,6 +91,14 @@ void GmpConfigForm::on_msgTypeCombo_currentIndexChanged(int /*index*/)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GmpConfigForm::on_groupMode_currentIndexChanged(int index)
|
||||||
|
{
|
||||||
|
bool disabled = (index == 0);
|
||||||
|
|
||||||
|
groupCount->setDisabled(disabled);
|
||||||
|
groupPrefix->setDisabled(disabled);
|
||||||
|
}
|
||||||
|
|
||||||
void GmpConfigForm::on_addSource_clicked()
|
void GmpConfigForm::on_addSource_clicked()
|
||||||
{
|
{
|
||||||
QListWidgetItem *item=new QListWidgetItem(_defaultSourceIp);
|
QListWidgetItem *item=new QListWidgetItem(_defaultSourceIp);
|
||||||
@ -113,13 +124,14 @@ void GmpConfigForm::on_addGroupRecord_clicked()
|
|||||||
QListWidgetItem *item = new QListWidgetItem;
|
QListWidgetItem *item = new QListWidgetItem;
|
||||||
|
|
||||||
grpRec["groupRecordType"] = defRec.type()-1;
|
grpRec["groupRecordType"] = defRec.type()-1;
|
||||||
grpRec["groupRecordAddress"] = _defaultSourceIp;
|
grpRec["groupRecordAddress"] = _defaultGroupIp;
|
||||||
grpRec["overrideGroupRecordSourceCount"] = defRec.is_override_source_count();
|
grpRec["overrideGroupRecordSourceCount"] =defRec.is_override_source_count();
|
||||||
grpRec["groupRecordSourceCount"] = defRec.source_count();
|
grpRec["groupRecordSourceCount"] = defRec.source_count();
|
||||||
grpRec["groupRecordSourceList"] = QStringList();
|
grpRec["groupRecordSourceList"] = QStringList();
|
||||||
grpRec["overrideAuxDataLength"] = defRec.is_override_aux_data_length();
|
grpRec["overrideAuxDataLength"] = defRec.is_override_aux_data_length();
|
||||||
grpRec["auxDataLength"] = defRec.aux_data_length();
|
grpRec["auxDataLength"] = defRec.aux_data_length();
|
||||||
grpRec["auxData"] = QString().fromStdString(defRec.aux_data());
|
grpRec["auxData"] = QByteArray().append(
|
||||||
|
QString().fromStdString(defRec.aux_data()));
|
||||||
|
|
||||||
item->setData(Qt::UserRole, grpRec);
|
item->setData(Qt::UserRole, grpRec);
|
||||||
item->setText(QString("%1: %2")
|
item->setText(QString("%1: %2")
|
||||||
@ -167,7 +179,7 @@ void GmpConfigForm::on_groupList_currentItemChanged(QListWidgetItem *current,
|
|||||||
rec["groupRecordSourceCount"] = groupRecordSourceCount->text().toUInt();
|
rec["groupRecordSourceCount"] = groupRecordSourceCount->text().toUInt();
|
||||||
rec["overrideAuxDataLength"] = overrideAuxDataLength->isChecked();
|
rec["overrideAuxDataLength"] = overrideAuxDataLength->isChecked();
|
||||||
rec["auxDataLength"] = auxDataLength->text().toUInt();
|
rec["auxDataLength"] = auxDataLength->text().toUInt();
|
||||||
rec["auxData"] = auxData->text();
|
rec["auxData"] = QByteArray().fromHex(QByteArray().append(auxData->text()));
|
||||||
|
|
||||||
previous->setData(Qt::UserRole, rec);
|
previous->setData(Qt::UserRole, rec);
|
||||||
previous->setText(QString("%1: %2")
|
previous->setText(QString("%1: %2")
|
||||||
@ -196,7 +208,7 @@ _load_current_record:
|
|||||||
rec["groupRecordSourceCount"].toUInt()));
|
rec["groupRecordSourceCount"].toUInt()));
|
||||||
overrideAuxDataLength->setChecked(rec["overrideAuxDataLength"].toBool());
|
overrideAuxDataLength->setChecked(rec["overrideAuxDataLength"].toBool());
|
||||||
auxDataLength->setText(QString().setNum(rec["auxDataLength"].toUInt()));
|
auxDataLength->setText(QString().setNum(rec["auxDataLength"].toUInt()));
|
||||||
auxData->setText(rec["auxData"].toString());
|
auxData->setText(QString(rec["auxData"].toByteArray().toHex()));
|
||||||
|
|
||||||
_exit:
|
_exit:
|
||||||
groupRecord->setEnabled(current != NULL);
|
groupRecord->setEnabled(current != NULL);
|
||||||
@ -254,46 +266,24 @@ int GmpProtocol::fieldCount() const
|
|||||||
|
|
||||||
int GmpProtocol::frameFieldCount() const
|
int GmpProtocol::frameFieldCount() const
|
||||||
{
|
{
|
||||||
int count = 0;
|
int type = msgType();
|
||||||
|
|
||||||
// TODO: optimize!!!!!
|
// frameFieldCountMap contains the frameFieldCounts for each
|
||||||
|
// msgType - this is built on demand and cached for subsequent use
|
||||||
|
|
||||||
|
// lookup if we have already cached ...
|
||||||
|
if (frameFieldCountMap.contains(type))
|
||||||
|
return frameFieldCountMap.value(type);
|
||||||
|
|
||||||
|
// ... otherwise calculate and cache
|
||||||
|
int count = 0;
|
||||||
for (int i = 0; i < FIELD_COUNT; i++)
|
for (int i = 0; i < FIELD_COUNT; i++)
|
||||||
{
|
{
|
||||||
if (fieldFlags(i).testFlag(AbstractProtocol::FrameField))
|
if (fieldFlags(i).testFlag(AbstractProtocol::FrameField))
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
frameFieldCountMap.insert(type, count);
|
||||||
return count;
|
return count;
|
||||||
#if 0
|
|
||||||
switch(msgType())
|
|
||||||
{
|
|
||||||
// IGMP
|
|
||||||
case kIgmpV1Query:
|
|
||||||
case kIgmpV1Report:
|
|
||||||
case kIgmpV2Query:
|
|
||||||
case kIgmpV2Report:
|
|
||||||
case kIgmpV2Leave:
|
|
||||||
return FIELD_COUNT_ASM_ALL;
|
|
||||||
|
|
||||||
case kIgmpV3Query:
|
|
||||||
return FIELD_COUNT_SSM_QUERY;
|
|
||||||
case kIgmpV3Report:
|
|
||||||
return FIELD_COUNT_SSM_REPORT;
|
|
||||||
|
|
||||||
// MLD
|
|
||||||
case kMldV1Query:
|
|
||||||
case kMldV1Report:
|
|
||||||
case kMldV1Done:
|
|
||||||
return FIELD_COUNT_ASM_ALL;
|
|
||||||
|
|
||||||
case kMldV2Query:
|
|
||||||
return FIELD_COUNT_SSM_QUERY;
|
|
||||||
case kMldV2Report:
|
|
||||||
return FIELD_COUNT_SSM_REPORT;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return FIELD_COUNT_ASM_ALL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractProtocol::FieldFlags GmpProtocol::fieldFlags(int index) const
|
AbstractProtocol::FieldFlags GmpProtocol::fieldFlags(int index) const
|
||||||
@ -316,6 +306,7 @@ AbstractProtocol::FieldFlags GmpProtocol::fieldFlags(int index) const
|
|||||||
break;
|
break;
|
||||||
case kMldMrt:
|
case kMldMrt:
|
||||||
case kMldRsvd:
|
case kMldRsvd:
|
||||||
|
// MLD subclass should handle suitably
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case kGroupAddress:
|
case kGroupAddress:
|
||||||
@ -404,13 +395,21 @@ QVariant GmpProtocol::fieldData(int index, FieldAttrib attrib,
|
|||||||
}
|
}
|
||||||
case kChecksum:
|
case kChecksum:
|
||||||
{
|
{
|
||||||
|
switch(attrib)
|
||||||
|
{
|
||||||
|
case FieldName:
|
||||||
|
return QString("Checksum");
|
||||||
|
case FieldBitSize:
|
||||||
|
return 16;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
quint16 cksum = data.is_override_checksum() ?
|
quint16 cksum = data.is_override_checksum() ?
|
||||||
data.checksum() : checksum(streamIndex);
|
data.checksum() : checksum(streamIndex);
|
||||||
|
|
||||||
switch(attrib)
|
switch(attrib)
|
||||||
{
|
{
|
||||||
case FieldName:
|
|
||||||
return QString("Checksum");
|
|
||||||
case FieldValue:
|
case FieldValue:
|
||||||
return cksum;
|
return cksum;
|
||||||
case FieldFrameValue:
|
case FieldFrameValue:
|
||||||
@ -423,14 +422,13 @@ QVariant GmpProtocol::fieldData(int index, FieldAttrib attrib,
|
|||||||
}
|
}
|
||||||
case FieldTextValue:
|
case FieldTextValue:
|
||||||
return QString("0x%1").arg(cksum, 4, BASE_HEX, QChar('0'));
|
return QString("0x%1").arg(cksum, 4, BASE_HEX, QChar('0'));
|
||||||
case FieldBitSize:
|
|
||||||
return 16;
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case kMldMrt:
|
case kMldMrt:
|
||||||
|
case kMldRsvd:
|
||||||
// XXX: Present only in MLD - hence handled by the mld subclass
|
// XXX: Present only in MLD - hence handled by the mld subclass
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -440,7 +438,7 @@ QVariant GmpProtocol::fieldData(int index, FieldAttrib attrib,
|
|||||||
|
|
||||||
case kRsvd1:
|
case kRsvd1:
|
||||||
{
|
{
|
||||||
int rsvd = 0;
|
quint8 rsvd = 0;
|
||||||
|
|
||||||
switch(attrib)
|
switch(attrib)
|
||||||
{
|
{
|
||||||
@ -513,8 +511,8 @@ QVariant GmpProtocol::fieldData(int index, FieldAttrib attrib,
|
|||||||
return QString("%1").arg(qqi);
|
return QString("%1").arg(qqi);
|
||||||
case FieldFrameValue:
|
case FieldFrameValue:
|
||||||
{
|
{
|
||||||
quint8 qqic = qqi; // TODO: derive code from qqi
|
char qqicode = char(qqic(qqi));
|
||||||
return QByteArray(1, char(qqic));
|
return QByteArray(1, qqicode);
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -628,7 +626,7 @@ QVariant GmpProtocol::fieldData(int index, FieldAttrib attrib,
|
|||||||
rec.is_override_aux_data_length();
|
rec.is_override_aux_data_length();
|
||||||
grpRec["auxDataLength"] = rec.aux_data_length();
|
grpRec["auxDataLength"] = rec.aux_data_length();
|
||||||
grpRec["auxData"] = QByteArray().append(
|
grpRec["auxData"] = QByteArray().append(
|
||||||
QString::fromStdString(rec.aux_data())).toHex();
|
QString::fromStdString(rec.aux_data()));
|
||||||
|
|
||||||
grpRecords.append(grpRec);
|
grpRecords.append(grpRec);
|
||||||
}
|
}
|
||||||
@ -641,26 +639,23 @@ QVariant GmpProtocol::fieldData(int index, FieldAttrib attrib,
|
|||||||
{
|
{
|
||||||
OstProto::Gmp::GroupRecord rec = data.group_records(i);
|
OstProto::Gmp::GroupRecord rec = data.group_records(i);
|
||||||
QByteArray rv;
|
QByteArray rv;
|
||||||
|
quint16 srcCount;
|
||||||
|
|
||||||
rv.resize(4);
|
rv.resize(4);
|
||||||
rv[0] = rec.type();
|
rv[0] = rec.type();
|
||||||
rv[1] = rec.is_override_aux_data_length() ?
|
rv[1] = rec.is_override_aux_data_length() ?
|
||||||
rec.aux_data_length() : rec.aux_data().size()/4;
|
rec.aux_data_length() : rec.aux_data().size()/4;
|
||||||
|
|
||||||
if (rec.is_override_source_count())
|
if (rec.is_override_source_count())
|
||||||
{
|
srcCount = rec.source_count();
|
||||||
qToBigEndian(quint16(rec.source_count()),
|
|
||||||
(uchar*)(rv.data()+2));
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
srcCount = rec.sources_size();
|
||||||
qToBigEndian(quint16(rec.sources_size()),
|
qToBigEndian(srcCount, (uchar*)(rv.data()+2));
|
||||||
(uchar*)(rv.data()+2));
|
|
||||||
}
|
|
||||||
|
|
||||||
// group_address => subclass responsibility
|
// group_address => subclass responsibility
|
||||||
// source list => subclass responsibility
|
// source list => subclass responsibility
|
||||||
|
|
||||||
rv.append(QString().fromStdString(rec.aux_data()).toUtf8());
|
rv.append(QString().fromStdString(rec.aux_data()));
|
||||||
|
|
||||||
fv.append(rv);
|
fv.append(rv);
|
||||||
}
|
}
|
||||||
@ -823,6 +818,7 @@ bool GmpProtocol::setFieldData(int index, const QVariant &value,
|
|||||||
}
|
}
|
||||||
case kGroupAddress:
|
case kGroupAddress:
|
||||||
// XXX: Handled by subclass
|
// XXX: Handled by subclass
|
||||||
|
isOk = false;
|
||||||
break;
|
break;
|
||||||
case kRsvd1:
|
case kRsvd1:
|
||||||
isOk = false;
|
isOk = false;
|
||||||
@ -843,7 +839,7 @@ bool GmpProtocol::setFieldData(int index, const QVariant &value,
|
|||||||
}
|
}
|
||||||
case kQqic:
|
case kQqic:
|
||||||
{
|
{
|
||||||
uint qqi = value.toUInt(&isOk); // TODO: QQIC or QQI??
|
uint qqi = value.toUInt(&isOk);
|
||||||
if (isOk)
|
if (isOk)
|
||||||
data.set_qqi(qqi);
|
data.set_qqi(qqi);
|
||||||
break;
|
break;
|
||||||
@ -857,6 +853,7 @@ bool GmpProtocol::setFieldData(int index, const QVariant &value,
|
|||||||
}
|
}
|
||||||
case kSources:
|
case kSources:
|
||||||
// XXX: Handled by subclass
|
// XXX: Handled by subclass
|
||||||
|
isOk = false;
|
||||||
break;
|
break;
|
||||||
case kRsvd2:
|
case kRsvd2:
|
||||||
isOk = false;
|
isOk = false;
|
||||||
@ -889,8 +886,7 @@ bool GmpProtocol::setFieldData(int index, const QVariant &value,
|
|||||||
rec->set_is_override_aux_data_length(
|
rec->set_is_override_aux_data_length(
|
||||||
grpRec["overrideAuxDataLength"].toBool());
|
grpRec["overrideAuxDataLength"].toBool());
|
||||||
rec->set_aux_data_length(grpRec["auxDataLength"].toUInt());
|
rec->set_aux_data_length(grpRec["auxDataLength"].toUInt());
|
||||||
QByteArray ba = QByteArray::fromHex(
|
QByteArray ba = grpRec["auxData"].toByteArray();
|
||||||
grpRec["auxData"].toByteArray());
|
|
||||||
// pad to word boundary
|
// pad to word boundary
|
||||||
if (ba.size() % 4)
|
if (ba.size() % 4)
|
||||||
ba.append(QByteArray(4 - (ba.size() % 4), char(0)));
|
ba.append(QByteArray(4 - (ba.size() % 4), char(0)));
|
||||||
@ -956,12 +952,6 @@ _exit:
|
|||||||
return isOk;
|
return isOk;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
|
||||||
TODO: Return the protocol frame size in bytes\n
|
|
||||||
|
|
||||||
If your protocol has a fixed size - you don't need to reimplement this; the
|
|
||||||
base class implementation is good enough
|
|
||||||
*/
|
|
||||||
int GmpProtocol::protocolFrameSize(int streamIndex) const
|
int GmpProtocol::protocolFrameSize(int streamIndex) const
|
||||||
{
|
{
|
||||||
// TODO: Calculate to reduce processing cost
|
// TODO: Calculate to reduce processing cost
|
||||||
@ -987,8 +977,7 @@ void GmpProtocol::loadConfigWidget()
|
|||||||
configWidget();
|
configWidget();
|
||||||
|
|
||||||
configForm->msgTypeCombo->setValue(fieldData(kType, FieldValue).toUInt());
|
configForm->msgTypeCombo->setValue(fieldData(kType, FieldValue).toUInt());
|
||||||
configForm->maxResponseTime->setText(QString("%1").arg(
|
// XXX: configForm->maxResponseTime set by subclass
|
||||||
data.max_response_time()));
|
|
||||||
configForm->overrideChecksum->setChecked(
|
configForm->overrideChecksum->setChecked(
|
||||||
fieldData(kIsOverrideChecksum, FieldValue).toBool());
|
fieldData(kIsOverrideChecksum, FieldValue).toBool());
|
||||||
configForm->checksum->setText(uintToHexStr(
|
configForm->checksum->setText(uintToHexStr(
|
||||||
@ -1049,7 +1038,7 @@ void GmpProtocol::storeConfigWidget()
|
|||||||
configForm->update();
|
configForm->update();
|
||||||
|
|
||||||
setFieldData(kType, configForm->msgTypeCombo->currentValue());
|
setFieldData(kType, configForm->msgTypeCombo->currentValue());
|
||||||
setFieldData(kMldMrt, configForm->maxResponseTime->text());
|
// XXX: configForm->maxResponseTime handled by subclass
|
||||||
setFieldData(kIsOverrideChecksum,
|
setFieldData(kIsOverrideChecksum,
|
||||||
configForm->overrideChecksum->isChecked());
|
configForm->overrideChecksum->isChecked());
|
||||||
setFieldData(kChecksum,
|
setFieldData(kChecksum,
|
||||||
@ -1077,8 +1066,8 @@ void GmpProtocol::storeConfigWidget()
|
|||||||
QVariantList grpList;
|
QVariantList grpList;
|
||||||
for (int i = 0; i < configForm->groupList->count(); i++)
|
for (int i = 0; i < configForm->groupList->count(); i++)
|
||||||
{
|
{
|
||||||
grpList.append(configForm->groupList->item(i)->data(Qt::UserRole)
|
QVariant grp = configForm->groupList->item(i)->data(Qt::UserRole);
|
||||||
.toMap());
|
grpList.append(grp.toMap());
|
||||||
}
|
}
|
||||||
setFieldData(kGroupRecords, grpList);
|
setFieldData(kGroupRecords, grpList);
|
||||||
|
|
||||||
|
130
common/gmp.h
130
common/gmp.h
@ -25,34 +25,35 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
|
|
||||||
#include "abstractprotocol.h"
|
#include "abstractprotocol.h"
|
||||||
|
|
||||||
enum GmpMsgType
|
#include <QHash>
|
||||||
{
|
|
||||||
kIgmpV1Query = 0x11,
|
|
||||||
kIgmpV1Report = 0x12,
|
|
||||||
|
|
||||||
kIgmpV2Query = 0xFF11,
|
// Both IGMP and MLD use the same msg type value for 'Query' message
|
||||||
kIgmpV2Report = 0x16,
|
// across versions despite the fields being different. To distinguish
|
||||||
kIgmpV2Leave = 0x17,
|
// Query messages of different versions, we use an additional upper byte
|
||||||
|
enum GmpMsgType
|
||||||
|
{
|
||||||
|
// IGMP
|
||||||
|
kIgmpV1Query = 0x11,
|
||||||
|
kIgmpV1Report = 0x12,
|
||||||
|
|
||||||
kIgmpV3Query = 0xFE11,
|
kIgmpV2Query = 0xFF11,
|
||||||
kIgmpV3Report = 0x22,
|
kIgmpV2Report = 0x16,
|
||||||
|
kIgmpV2Leave = 0x17,
|
||||||
|
|
||||||
kMldV1Query = 0x82,
|
kIgmpV3Query = 0xFE11,
|
||||||
kMldV1Report = 0x83,
|
kIgmpV3Report = 0x22,
|
||||||
kMldV1Done = 0x84,
|
|
||||||
|
|
||||||
kMldV2Query = 0xFF82,
|
// MLD
|
||||||
kMldV2Report = 0x8F
|
kMldV1Query = 0x82,
|
||||||
};
|
kMldV1Report = 0x83,
|
||||||
|
kMldV1Done = 0x84,
|
||||||
|
|
||||||
|
kMldV2Query = 0xFF82,
|
||||||
|
kMldV2Report = 0x8F
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
TODO:FIXME
|
Gmp Protocol Frame Format - TODO: for now see the respective RFCs
|
||||||
Gmp Protocol Frame Format -
|
|
||||||
+-----+------+------+------+------+------+
|
|
||||||
| A | B | LEN | CSUM | X | Y |
|
|
||||||
| (3) | (13) | (16) | (16) | (32) | (32) |
|
|
||||||
+-----+------+------+------+------+------+
|
|
||||||
Figures in brackets represent field width in bits
|
|
||||||
*/
|
*/
|
||||||
class GmpProtocol;
|
class GmpProtocol;
|
||||||
|
|
||||||
@ -64,9 +65,16 @@ public:
|
|||||||
~GmpConfigForm();
|
~GmpConfigForm();
|
||||||
void update();
|
void update();
|
||||||
protected:
|
protected:
|
||||||
|
QString _defaultGroupIp;
|
||||||
QString _defaultSourceIp;
|
QString _defaultSourceIp;
|
||||||
|
private:
|
||||||
|
enum {
|
||||||
|
kSsmQueryPage = 0,
|
||||||
|
kSsmReportPage = 1
|
||||||
|
};
|
||||||
private slots:
|
private slots:
|
||||||
void on_msgTypeCombo_currentIndexChanged(int index);
|
void on_msgTypeCombo_currentIndexChanged(int index);
|
||||||
|
void on_groupMode_currentIndexChanged(int index);
|
||||||
void on_addSource_clicked();
|
void on_addSource_clicked();
|
||||||
void on_deleteSource_clicked();
|
void on_deleteSource_clicked();
|
||||||
|
|
||||||
@ -109,24 +117,18 @@ protected:
|
|||||||
// ------------
|
// ------------
|
||||||
// Frame Fields
|
// Frame Fields
|
||||||
// ------------
|
// ------------
|
||||||
|
// Fields used in all ASM and SSM messages, unless otherwise specified
|
||||||
kType = 0,
|
kType = 0,
|
||||||
kRsvdMrtCode,
|
kRsvdMrtCode,
|
||||||
kChecksum,
|
kChecksum,
|
||||||
kMldMrt, // MLD Only (except MLDv2 Report)
|
kMldMrt, // MLD Only (except MLDv2 Report)
|
||||||
kMldRsvd, // MLD Only (except MLDv2 Report)
|
kMldRsvd, // MLD Only (except MLDv2 Report)
|
||||||
|
|
||||||
// Used ONLY in -
|
// Field used in ASM messages
|
||||||
// IGMPv1: Query, Report
|
|
||||||
// IGMPv2: Report, Leave (v2 uses v1 Query only)
|
|
||||||
// IGMPv3: Query
|
|
||||||
// MLDv1: Query, Report, Done
|
|
||||||
// MLDv2: Query
|
|
||||||
kGroupAddress,
|
kGroupAddress,
|
||||||
FIELD_COUNT_ASM_ALL,
|
FIELD_COUNT_ASM_ALL,
|
||||||
|
|
||||||
// Used ONLY in -
|
// Fields used in SSM Query
|
||||||
// IGMPv3: Query
|
|
||||||
// MLDv2: Query
|
|
||||||
kRsvd1 = FIELD_COUNT_ASM_ALL,
|
kRsvd1 = FIELD_COUNT_ASM_ALL,
|
||||||
kSFlag,
|
kSFlag,
|
||||||
kQrv,
|
kQrv,
|
||||||
@ -135,9 +137,7 @@ protected:
|
|||||||
kSources,
|
kSources,
|
||||||
FIELD_COUNT_SSM_QUERY,
|
FIELD_COUNT_SSM_QUERY,
|
||||||
|
|
||||||
// Used ONLY in -
|
// Fields used in SSM Report
|
||||||
// IGMPv3: Report
|
|
||||||
// MLDv2: Report
|
|
||||||
kRsvd2 = FIELD_COUNT_SSM_QUERY,
|
kRsvd2 = FIELD_COUNT_SSM_QUERY,
|
||||||
kGroupRecordCount,
|
kGroupRecordCount,
|
||||||
kGroupRecords,
|
kGroupRecords,
|
||||||
@ -163,30 +163,48 @@ protected:
|
|||||||
OstProto::Gmp data;
|
OstProto::Gmp data;
|
||||||
GmpConfigForm *configForm;
|
GmpConfigForm *configForm;
|
||||||
|
|
||||||
GmpMsgType msgType() const
|
GmpMsgType msgType() const;
|
||||||
{
|
|
||||||
return GmpMsgType(fieldData(kType, FieldValue).toUInt());
|
virtual bool isSsmReport() const;
|
||||||
}
|
virtual bool isQuery() const;
|
||||||
bool isSsmReport() const
|
virtual bool isSsmQuery() const;
|
||||||
{
|
|
||||||
return ((msgType() == kIgmpV3Report)
|
int qqic(int value) const;
|
||||||
|| (msgType() == kMldV2Report ));
|
|
||||||
}
|
|
||||||
bool isQuery() const
|
|
||||||
{
|
|
||||||
return ((msgType() == kIgmpV1Query)
|
|
||||||
|| (msgType() == kIgmpV2Query)
|
|
||||||
|| (msgType() == kIgmpV3Query)
|
|
||||||
|| (msgType() == kMldV1Query )
|
|
||||||
|| (msgType() == kMldV2Query ));
|
|
||||||
}
|
|
||||||
bool isSsmQuery() const
|
|
||||||
{
|
|
||||||
return ((msgType() == kIgmpV3Query)
|
|
||||||
|| (msgType() == kMldV2Query ));
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual quint16 checksum(int streamIndex) const = 0;
|
virtual quint16 checksum(int streamIndex) const = 0;
|
||||||
|
private:
|
||||||
|
static QHash<int, int> frameFieldCountMap;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline GmpMsgType GmpProtocol::msgType() const
|
||||||
|
{
|
||||||
|
return GmpMsgType(fieldData(kType, FieldValue).toUInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool GmpProtocol::isSsmReport() const
|
||||||
|
{
|
||||||
|
return ((msgType() == kIgmpV3Report)
|
||||||
|
|| (msgType() == kMldV2Report ));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool GmpProtocol::isQuery() const
|
||||||
|
{
|
||||||
|
return ((msgType() == kIgmpV1Query)
|
||||||
|
|| (msgType() == kIgmpV2Query)
|
||||||
|
|| (msgType() == kIgmpV3Query)
|
||||||
|
|| (msgType() == kMldV1Query )
|
||||||
|
|| (msgType() == kMldV2Query ));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool GmpProtocol::isSsmQuery() const
|
||||||
|
{
|
||||||
|
return ((msgType() == kIgmpV3Query)
|
||||||
|
|| (msgType() == kMldV2Query ));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int GmpProtocol::qqic(int value) const
|
||||||
|
{
|
||||||
|
return quint8(value); // TODO: if value > 128 convert to mantissa/exp form
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -23,13 +23,14 @@ package OstProto;
|
|||||||
|
|
||||||
// Group Management Protocol (i.e. IGMP and MLD)
|
// Group Management Protocol (i.e. IGMP and MLD)
|
||||||
message Gmp {
|
message Gmp {
|
||||||
// TODO: field numbers and default values
|
//
|
||||||
|
// Common fields for both ASM and SSM messages
|
||||||
optional uint32 type = 1; // TODO: default value
|
//
|
||||||
|
optional uint32 type = 1;
|
||||||
optional bool is_override_rsvd_code = 2;
|
optional bool is_override_rsvd_code = 2;
|
||||||
optional uint32 rsvd_code = 3 [default = 0];
|
optional uint32 rsvd_code = 3;
|
||||||
// MaxRespTime is in milliseconds - MaxRespCode will be derived
|
// MaxRespTime is in milliseconds - MaxRespCode will be derived
|
||||||
optional uint32 max_response_time = 4[default = 100];
|
optional uint32 max_response_time = 4 [default = 100];
|
||||||
optional bool is_override_checksum = 5;
|
optional bool is_override_checksum = 5;
|
||||||
optional uint32 checksum = 6;
|
optional uint32 checksum = 6;
|
||||||
|
|
||||||
@ -39,35 +40,34 @@ message Gmp {
|
|||||||
optional fixed64 v6_lo = 3;
|
optional fixed64 v6_lo = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
// used by
|
//
|
||||||
// IGMPv1: Query, Report
|
// Fields used in ASM messages
|
||||||
// IGMPv2: Report, Leave (v2 uses v1 Query only)
|
//
|
||||||
// MLDv1: Query, Report, Done
|
|
||||||
enum GroupMode {
|
enum GroupMode {
|
||||||
kFixed = 0;
|
kFixed = 0;
|
||||||
kIncrementGroup = 1;
|
kIncrementGroup = 1;
|
||||||
kDecrementGroup = 2;
|
kDecrementGroup = 2;
|
||||||
kRandomGroup = 3;
|
kRandomGroup = 3;
|
||||||
}
|
}
|
||||||
optional IpAddress group_address = 10; // TODO: default value
|
optional IpAddress group_address = 10;
|
||||||
optional GroupMode group_mode = 11 [default = kFixed];
|
optional GroupMode group_mode = 11 [default = kFixed];
|
||||||
optional uint32 group_count = 12 [default = 16];
|
optional uint32 group_count = 12 [default = 16];
|
||||||
optional uint32 group_prefix = 13 [default = 24]; // TODO: verify mcast ip range
|
optional uint32 group_prefix = 13 [default = 24];
|
||||||
|
|
||||||
// used by
|
//
|
||||||
// IGMPv3: Query
|
// Fields used in SSM Query
|
||||||
// MLDv2: Query
|
//
|
||||||
optional bool s_flag = 20;
|
optional bool s_flag = 20;
|
||||||
optional uint32 qrv = 21 [default = 2];
|
optional uint32 qrv = 21 [default = 2];
|
||||||
// QuerierQueryInterval is in seconds - QQIC will be derived
|
// QuerierQueryInterval is in seconds - QQIC will be derived
|
||||||
optional uint32 qqi = 22;
|
optional uint32 qqi = 22 [default = 125];
|
||||||
repeated IpAddress sources = 23;
|
repeated IpAddress sources = 23;
|
||||||
optional bool is_override_source_count = 24;
|
optional bool is_override_source_count = 24;
|
||||||
optional uint32 source_count = 25;
|
optional uint32 source_count = 25;
|
||||||
|
|
||||||
// used by
|
//
|
||||||
// IGMPv3: Report
|
// Fields used in SSM Reports
|
||||||
// MLDv2: Report
|
//
|
||||||
message GroupRecord {
|
message GroupRecord {
|
||||||
enum RecordType {
|
enum RecordType {
|
||||||
kIsInclude = 1;
|
kIsInclude = 1;
|
||||||
@ -79,7 +79,7 @@ message Gmp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
optional RecordType type = 1 [default = kIsInclude];
|
optional RecordType type = 1 [default = kIsInclude];
|
||||||
optional IpAddress group_address = 2; // TODO: default
|
optional IpAddress group_address = 2;
|
||||||
repeated IpAddress sources = 3;
|
repeated IpAddress sources = 3;
|
||||||
optional bool is_override_source_count = 4;
|
optional bool is_override_source_count = 4;
|
||||||
optional uint32 source_count = 5;
|
optional uint32 source_count = 5;
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>497</width>
|
<width>509</width>
|
||||||
<height>355</height>
|
<height>355</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
@ -31,7 +31,7 @@
|
|||||||
<item row="1" column="0" >
|
<item row="1" column="0" >
|
||||||
<widget class="QLabel" name="label_2" >
|
<widget class="QLabel" name="label_2" >
|
||||||
<property name="text" >
|
<property name="text" >
|
||||||
<string>Max Response Time</string>
|
<string>Max Response Time (1/10s)</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="buddy" >
|
<property name="buddy" >
|
||||||
<cstring>maxResponseTime</cstring>
|
<cstring>maxResponseTime</cstring>
|
||||||
@ -155,6 +155,9 @@
|
|||||||
</item>
|
</item>
|
||||||
<item row="1" column="2" >
|
<item row="1" column="2" >
|
||||||
<widget class="QLineEdit" name="groupCount" >
|
<widget class="QLineEdit" name="groupCount" >
|
||||||
|
<property name="enabled" >
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
<property name="sizePolicy" >
|
<property name="sizePolicy" >
|
||||||
<sizepolicy vsizetype="Fixed" hsizetype="Fixed" >
|
<sizepolicy vsizetype="Fixed" hsizetype="Fixed" >
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@ -165,6 +168,9 @@
|
|||||||
</item>
|
</item>
|
||||||
<item row="1" column="3" >
|
<item row="1" column="3" >
|
||||||
<widget class="QLineEdit" name="groupPrefix" >
|
<widget class="QLineEdit" name="groupPrefix" >
|
||||||
|
<property name="enabled" >
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
<property name="sizePolicy" >
|
<property name="sizePolicy" >
|
||||||
<sizepolicy vsizetype="Fixed" hsizetype="Fixed" >
|
<sizepolicy vsizetype="Fixed" hsizetype="Fixed" >
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@ -304,7 +310,7 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QToolButton" name="deleteSource" >
|
<widget class="QToolButton" name="deleteSource" >
|
||||||
<property name="text" >
|
<property name="text" >
|
||||||
<string>--</string>
|
<string>–</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -428,7 +434,7 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QToolButton" name="deleteGroupRecord" >
|
<widget class="QToolButton" name="deleteGroupRecord" >
|
||||||
<property name="text" >
|
<property name="text" >
|
||||||
<string>--</string>
|
<string>–</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -580,7 +586,7 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QToolButton" name="deleteGroupRecordSource" >
|
<widget class="QToolButton" name="deleteGroupRecordSource" >
|
||||||
<property name="text" >
|
<property name="text" >
|
||||||
<string>--</string>
|
<string>–</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
109
common/igmp.cpp
109
common/igmp.cpp
@ -19,37 +19,22 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
|
|
||||||
#include "igmp.h"
|
#include "igmp.h"
|
||||||
|
|
||||||
|
#include "ipv4addressdelegate.h"
|
||||||
|
#include "iputils.h"
|
||||||
|
|
||||||
#include <QHostAddress>
|
#include <QHostAddress>
|
||||||
#include <QItemDelegate>
|
|
||||||
#include <qendian.h>
|
#include <qendian.h>
|
||||||
|
|
||||||
class IpAddressDelegate : public QItemDelegate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
IpAddressDelegate(QObject *parent = 0)
|
|
||||||
: QItemDelegate(parent) { }
|
|
||||||
~IpAddressDelegate() {}
|
|
||||||
QWidget* createEditor(QWidget *parent,
|
|
||||||
const QStyleOptionViewItem &option, const QModelIndex &index) const
|
|
||||||
{
|
|
||||||
QLineEdit *ipEdit;
|
|
||||||
|
|
||||||
ipEdit = static_cast<QLineEdit*>(QItemDelegate::createEditor(
|
|
||||||
parent, option, index));
|
|
||||||
|
|
||||||
ipEdit->setInputMask("009.009.009.009;"); // FIXME: use validator
|
|
||||||
|
|
||||||
return ipEdit;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
IgmpConfigForm::IgmpConfigForm(QWidget *parent)
|
IgmpConfigForm::IgmpConfigForm(QWidget *parent)
|
||||||
: GmpConfigForm(parent)
|
: GmpConfigForm(parent)
|
||||||
{
|
{
|
||||||
|
_defaultGroupIp = "0.0.0.0";
|
||||||
_defaultSourceIp = "0.0.0.0";
|
_defaultSourceIp = "0.0.0.0";
|
||||||
|
|
||||||
sourceList->setItemDelegate(new IpAddressDelegate(this));
|
groupAddress->setInputMask("009.009.009.009;"); // FIXME: use validator
|
||||||
groupRecordSourceList->setItemDelegate(new IpAddressDelegate(this));
|
groupRecordAddress->setInputMask("009.009.009.009;"); // FIXME:use validator
|
||||||
|
sourceList->setItemDelegate(new IPv4AddressDelegate(this));
|
||||||
|
groupRecordSourceList->setItemDelegate(new IPv4AddressDelegate(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
IgmpProtocol::IgmpProtocol(StreamBase *stream, AbstractProtocol *parent)
|
IgmpProtocol::IgmpProtocol(StreamBase *stream, AbstractProtocol *parent)
|
||||||
@ -114,15 +99,19 @@ QVariant IgmpProtocol::fieldData(int index, FieldAttrib attrib,
|
|||||||
{
|
{
|
||||||
case kRsvdMrtCode:
|
case kRsvdMrtCode:
|
||||||
{
|
{
|
||||||
quint8 mrt = 0, mrc = 0;
|
uint mrt = 0;
|
||||||
|
quint8 mrcode = 0;
|
||||||
|
|
||||||
if (msgType() == kIgmpV3Query)
|
if (msgType() == kIgmpV3Query)
|
||||||
{
|
{
|
||||||
mrt = data.max_response_time();
|
mrt = data.max_response_time();
|
||||||
mrc = mrt; // TODO: MR Code
|
mrcode = quint8(mrc(mrt));
|
||||||
}
|
}
|
||||||
else if (msgType() == kIgmpV2Query)
|
else if (msgType() == kIgmpV2Query)
|
||||||
mrc = mrt = data.max_response_time() & 0xFF;
|
{
|
||||||
|
mrt = data.max_response_time();
|
||||||
|
mrcode = mrt & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
switch(attrib)
|
switch(attrib)
|
||||||
@ -137,7 +126,7 @@ QVariant IgmpProtocol::fieldData(int index, FieldAttrib attrib,
|
|||||||
case FieldTextValue:
|
case FieldTextValue:
|
||||||
return QString("%1").arg(mrt);
|
return QString("%1").arg(mrt);
|
||||||
case FieldFrameValue:
|
case FieldFrameValue:
|
||||||
return QByteArray(1, mrc);
|
return QByteArray(1, mrcode);
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -145,14 +134,12 @@ QVariant IgmpProtocol::fieldData(int index, FieldAttrib attrib,
|
|||||||
}
|
}
|
||||||
case kGroupAddress:
|
case kGroupAddress:
|
||||||
{
|
{
|
||||||
quint32 grpIp = data.group_address().v4(); // FIXME
|
quint32 grpIp = ipUtils::ipAddress(
|
||||||
#if 0 // TODO
|
data.group_address().v4(),
|
||||||
getip(
|
data.group_prefix(),
|
||||||
data.group_address().v4(),
|
ipUtils::AddrMode(data.group_mode()),
|
||||||
data.group_mode(),
|
data.group_count(),
|
||||||
data.group_count(),
|
streamIndex);
|
||||||
data.group_prefix());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
switch(attrib)
|
switch(attrib)
|
||||||
{
|
{
|
||||||
@ -225,10 +212,10 @@ QVariant IgmpProtocol::fieldData(int index, FieldAttrib attrib,
|
|||||||
grpRec["groupRecordAddress"] = QHostAddress(
|
grpRec["groupRecordAddress"] = QHostAddress(
|
||||||
rec.group_address().v4()).toString();
|
rec.group_address().v4()).toString();
|
||||||
|
|
||||||
QStringList l;
|
QStringList sl;
|
||||||
for (int j = 0; j < rec.sources_size(); j++)
|
for (int j = 0; j < rec.sources_size(); j++)
|
||||||
l.append(QHostAddress(rec.sources(j).v4()).toString());
|
sl.append(QHostAddress(rec.sources(j).v4()).toString());
|
||||||
grpRec["groupRecordSourceList"] = l;
|
grpRec["groupRecordSourceList"] = sl;
|
||||||
|
|
||||||
grpRecords.replace(i, grpRec);
|
grpRecords.replace(i, grpRec);
|
||||||
}
|
}
|
||||||
@ -273,10 +260,10 @@ QVariant IgmpProtocol::fieldData(int index, FieldAttrib attrib,
|
|||||||
QHostAddress(rec.group_address().v4()).toString()));
|
QHostAddress(rec.group_address().v4()).toString()));
|
||||||
|
|
||||||
str.append("; Sources: ");
|
str.append("; Sources: ");
|
||||||
QStringList l;
|
QStringList sl;
|
||||||
for (int j = 0; j < rec.sources_size(); j++)
|
for (int j = 0; j < rec.sources_size(); j++)
|
||||||
l.append(QHostAddress(rec.sources(j).v4()).toString());
|
sl.append(QHostAddress(rec.sources(j).v4()).toString());
|
||||||
str.append(l.join(", "));
|
str.append(sl.join(", "));
|
||||||
|
|
||||||
recStr.replace("XXX", str);
|
recStr.replace("XXX", str);
|
||||||
list.replace(i, recStr);
|
list.replace(i, recStr);
|
||||||
@ -305,6 +292,13 @@ bool IgmpProtocol::setFieldData(int index, const QVariant &value,
|
|||||||
|
|
||||||
switch (index)
|
switch (index)
|
||||||
{
|
{
|
||||||
|
case kRsvdMrtCode:
|
||||||
|
{
|
||||||
|
uint mrt = value.toUInt(&isOk);
|
||||||
|
if (isOk)
|
||||||
|
data.set_max_response_time(mrt);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case kGroupAddress:
|
case kGroupAddress:
|
||||||
{
|
{
|
||||||
QHostAddress addr(value.toString());
|
QHostAddress addr(value.toString());
|
||||||
@ -343,6 +337,7 @@ bool IgmpProtocol::setFieldData(int index, const QVariant &value,
|
|||||||
|
|
||||||
QStringList srcList = grpRec["groupRecordSourceList"]
|
QStringList srcList = grpRec["groupRecordSourceList"]
|
||||||
.toStringList();
|
.toStringList();
|
||||||
|
rec->clear_sources();
|
||||||
foreach (QString src, srcList)
|
foreach (QString src, srcList)
|
||||||
{
|
{
|
||||||
rec->add_sources()->set_v4(
|
rec->add_sources()->set_v4(
|
||||||
@ -380,48 +375,20 @@ void IgmpProtocol::loadConfigWidget()
|
|||||||
|
|
||||||
configForm->maxResponseTime->setText(
|
configForm->maxResponseTime->setText(
|
||||||
fieldData(kRsvdMrtCode, FieldValue).toString());
|
fieldData(kRsvdMrtCode, FieldValue).toString());
|
||||||
#if 0
|
|
||||||
configForm->igmpA->setText(fieldData(igmp_a, FieldValue).toString());
|
|
||||||
configForm->igmpB->setText(fieldData(igmp_b, FieldValue).toString());
|
|
||||||
|
|
||||||
configForm->igmpPayloadLength->setText(
|
|
||||||
fieldData(igmp_payloadLength, FieldValue).toString());
|
|
||||||
|
|
||||||
configForm->isChecksumOverride->setChecked(
|
|
||||||
fieldData(igmp_is_override_checksum, FieldValue).toBool());
|
|
||||||
configForm->igmpChecksum->setText(uintToHexStr(
|
|
||||||
fieldData(igmp_checksum, FieldValue).toUInt(), 2));
|
|
||||||
|
|
||||||
configForm->igmpX->setText(fieldData(igmp_x, FieldValue).toString());
|
|
||||||
configForm->igmpY->setText(fieldData(igmp_y, FieldValue).toString());
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IgmpProtocol::storeConfigWidget()
|
void IgmpProtocol::storeConfigWidget()
|
||||||
{
|
{
|
||||||
bool isOk;
|
|
||||||
|
|
||||||
GmpProtocol::storeConfigWidget();
|
GmpProtocol::storeConfigWidget();
|
||||||
|
|
||||||
#if 0
|
setFieldData(kRsvdMrtCode, configForm->maxResponseTime->text());
|
||||||
setFieldData(igmp_a, configForm->igmpA->text());
|
|
||||||
setFieldData(igmp_b, configForm->igmpB->text());
|
|
||||||
|
|
||||||
setFieldData(igmp_payloadLength, configForm->igmpPayloadLength->text());
|
|
||||||
setFieldData(igmp_is_override_checksum,
|
|
||||||
configForm->isChecksumOverride->isChecked());
|
|
||||||
setFieldData(igmp_checksum, configForm->igmpChecksum->text().toUInt(&isOk, BASE_HEX));
|
|
||||||
|
|
||||||
setFieldData(igmp_x, configForm->igmpX->text());
|
|
||||||
setFieldData(igmp_y, configForm->igmpY->text());
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
quint16 IgmpProtocol::checksum(int streamIndex) const
|
quint16 IgmpProtocol::checksum(int streamIndex) const
|
||||||
{
|
{
|
||||||
quint16 cks;
|
quint16 cks;
|
||||||
quint32 sum = 0;
|
quint32 sum = 0;
|
||||||
#if 0 // FIXME
|
#if 1 // FIXME
|
||||||
// TODO: add as a new CksumType (CksumIgmp?) and implement in AbsProto
|
// TODO: add as a new CksumType (CksumIgmp?) and implement in AbsProto
|
||||||
cks = protocolFrameCksum(streamIndex, CksumIp);
|
cks = protocolFrameCksum(streamIndex, CksumIp);
|
||||||
sum += (quint16) ~cks;
|
sum += (quint16) ~cks;
|
||||||
|
@ -58,6 +58,13 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual quint16 checksum(int streamIndex) const;
|
virtual quint16 checksum(int streamIndex) const;
|
||||||
|
private:
|
||||||
|
int mrc(int value) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline int IgmpProtocol::mrc(int value) const
|
||||||
|
{
|
||||||
|
return quint8(value); // TODO: if value > 128, convert to mantissa/exp form
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
70
common/iputils.h
Normal file
70
common/iputils.h
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2010 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 _IP_UTILS_H
|
||||||
|
#define _IP_UTILS_H
|
||||||
|
|
||||||
|
namespace ipUtils {
|
||||||
|
enum AddrMode {
|
||||||
|
kFixed = 0,
|
||||||
|
kIncrement = 1,
|
||||||
|
kDecrement = 2,
|
||||||
|
kRandom = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
quint32 ipAddress(quint32 baseIp, int prefix, AddrMode mode, int count,
|
||||||
|
int index)
|
||||||
|
{
|
||||||
|
int u;
|
||||||
|
quint32 mask = ((1<<prefix) - 1) << (32 - prefix);
|
||||||
|
quint32 subnet, host, ip;
|
||||||
|
|
||||||
|
switch(mode)
|
||||||
|
{
|
||||||
|
case kFixed:
|
||||||
|
ip = baseIp;
|
||||||
|
break;
|
||||||
|
case kIncrement:
|
||||||
|
u = index % count;
|
||||||
|
subnet = baseIp & mask;
|
||||||
|
host = (((baseIp & ~mask) + u) &
|
||||||
|
~mask);
|
||||||
|
ip = subnet | host;
|
||||||
|
break;
|
||||||
|
case kDecrement:
|
||||||
|
u = index % count;
|
||||||
|
subnet = baseIp & mask;
|
||||||
|
host = (((baseIp & ~mask) - u) &
|
||||||
|
~mask);
|
||||||
|
ip = subnet | host;
|
||||||
|
break;
|
||||||
|
case kRandom:
|
||||||
|
subnet = baseIp & mask;
|
||||||
|
host = (qrand() & ~mask);
|
||||||
|
ip = subnet | host;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
qWarning("Unhandled mode = %d", mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ipUtils
|
||||||
|
#endif
|
58
common/ipv4addressdelegate.h
Normal file
58
common/ipv4addressdelegate.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2010 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 _IPV4_ADDRESS_DELEGATE
|
||||||
|
#define _IPV4_ADDRESS_DELEGATE
|
||||||
|
|
||||||
|
#include <QItemDelegate>
|
||||||
|
#include <QLineEdit>
|
||||||
|
|
||||||
|
class IPv4AddressDelegate : public QItemDelegate
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
IPv4AddressDelegate(QObject *parent = 0);
|
||||||
|
~IPv4AddressDelegate();
|
||||||
|
|
||||||
|
QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option,
|
||||||
|
const QModelIndex &index) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline IPv4AddressDelegate::IPv4AddressDelegate(QObject *parent)
|
||||||
|
: QItemDelegate(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
inline IPv4AddressDelegate::~IPv4AddressDelegate()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
inline QWidget* IPv4AddressDelegate::createEditor(QWidget *parent,
|
||||||
|
const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
QLineEdit *ipEdit;
|
||||||
|
|
||||||
|
ipEdit = static_cast<QLineEdit*>(QItemDelegate::createEditor(
|
||||||
|
parent, option, index));
|
||||||
|
|
||||||
|
ipEdit->setInputMask("009.009.009.009;"); // FIXME: use validator
|
||||||
|
|
||||||
|
return ipEdit;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
@ -73,6 +73,7 @@ HEADERS += \
|
|||||||
arp.h \
|
arp.h \
|
||||||
ip4.h \
|
ip4.h \
|
||||||
ip6.h \
|
ip6.h \
|
||||||
|
ipv4addressdelegate.h \
|
||||||
ip6over4.h \
|
ip6over4.h \
|
||||||
ip4over6.h \
|
ip4over6.h \
|
||||||
ip4over4.h \
|
ip4over4.h \
|
||||||
|
Loading…
Reference in New Issue
Block a user