All new accounts created on Gitlab now require administrator approval. If you invite any collaborators, please let Flux staff know so they can approve the accounts.

Commit 44f10b26 authored by Ryan Jackson's avatar Ryan Jackson

Separated the NetlinkPipe and DummynetPipe implementations.

parent bac0172e
......@@ -204,197 +204,3 @@ void DummynetPipe::setPipe(struct dn_pipe *pipe)
}
#endif
#ifdef LINUX
// NetlinkPipe.cc
#include "lib.hh"
#include "DummynetPipe.hh"
extern "C"
{
#include <sys/types.h>
#include <sys/socket.h>
#include <netlink/list.h>
#include <netlink/object.h>
#include <netlink/route/rtnl.h>
#include <netlink/route/route.h>
#include <netlink/route/link.h>
#include <netlink/route/class.h>
#include <netlink/route/qdisc.h>
#include <netlink/route/sch/plr.h>
#include <netlink/route/sch/delay.h>
#include <netlink/route/sch/htb.h>
}
using namespace std;
NetlinkPipe::NetlinkPipe(std::string const & iface, std::string const & pipeno)
{
cerr << "Creating Netlink Pipe" << endl;
interfaceName = iface;
pipeNumber = pipeno;
nl_handle = NULL;
class_cache = NULL;
qdisc_cache = NULL;
init();
/* test(); */
}
void NetlinkPipe::test(void)
{
Parameter testParam(Parameter::DELAY, 90000);
updateParameter(testParam);
}
int NetlinkPipe::init(void)
{
struct nl_cache *link_cache;
int handle;
string str;
link_cache = NULL;
cerr << "Got pipe number " << pipeNumber << endl;
handle = hexStringToInt(pipeNumber);
nl_handle = nl_handle_alloc();
if (nl_handle == NULL) {
cerr << "Unable to allocate nl_handle" << endl;
return -1;
}
if (nl_connect(nl_handle, NETLINK_ROUTE) < 0) {
cerr << "Unable to allocate Netlink socket" << endl;
return -1;
}
link_cache = rtnl_link_alloc_cache(nl_handle);
if (link_cache == NULL) {
cerr << "Unable to allocate link cache" << endl;
return -1;
}
ifindex = rtnl_link_name2i(link_cache, interfaceName.c_str());
if (ifindex == RTNL_LINK_NOT_FOUND) {
cerr << "Unable to translate link name to ifindex" << endl;
return -1;
}
nl_cache_free(link_cache);
qdisc_cache = rtnl_qdisc_alloc_cache(nl_handle);
if (qdisc_cache == NULL) {
cerr << "Unable to allocate qdisc cache" << endl;
return -1;
}
plrHandle = handle << 16;
delayHandle = (handle + 0x10) << 16;
htbHandle = (handle + 0x20) << 16;
class_cache = rtnl_class_alloc_cache(nl_handle, ifindex);
if (class_cache == NULL) {
cerr << "Unable to allocate class cache" << endl;
return -1;
}
htbClassHandle = htbHandle + 1;
return 0;
}
NetlinkPipe::~NetlinkPipe()
{
if (qdisc_cache)
nl_cache_free(qdisc_cache);
if (class_cache)
nl_cache_free(class_cache);
if (nl_handle)
nl_close(nl_handle);
}
void NetlinkPipe::reset(void)
{
map<Parameter::ParameterType, Parameter>::iterator pos = g::defaultParameters.begin();
map<Parameter::ParameterType, Parameter>::iterator limit = g::defaultParameters.end();
for (; pos != limit; ++pos)
{
updateParameter(pos->second);
}
}
void NetlinkPipe::resetParameter(Parameter const & newParameter)
{
updateParameter(newParameter);
}
void NetlinkPipe::updateParameter(Parameter const & newParameter)
{
struct rtnl_qdisc *qdisc;
struct rtnl_class *htbClass;
int rate;
qdisc = NULL;
switch(newParameter.getType()) {
case Parameter::BANDWIDTH:
rate = newParameter.getValue() * 1000 / 8;
htbClass = rtnl_class_get(class_cache, htbClassHandle);
if (htbClass == NULL) {
cerr << "Couldn't find htb class " << htbClassHandle << endl;
return;
}
rtnl_htb_set_rate(htbClass, rate);
rtnl_htb_set_ceil(htbClass, rate);
rtnl_class_change(nl_handle, htbClass, NULL);
rtnl_class_put(htbClass);
break;
case Parameter::DELAY:
qdisc = rtnl_qdisc_get(qdisc_cache, ifindex, delayHandle);
if (qdisc == NULL) {
cerr << "Couldn't find delay qdisc " << delayHandle << endl;
return;
}
rtnl_delay_set_delay(qdisc, newParameter.getValue() * 1000);
rtnl_qdisc_change(nl_handle, qdisc, NULL);
rtnl_qdisc_put(qdisc);
break;
case Parameter::LOSS:
qdisc = rtnl_qdisc_get(qdisc_cache, ifindex, plrHandle);
if (qdisc == NULL) {
cerr << "Couldn't find plr qdisc " << plrHandle << endl;
return;
}
rtnl_plr_set_plr(qdisc, newParameter.getValue());
rtnl_qdisc_change(nl_handle, qdisc, NULL);
rtnl_qdisc_put(qdisc);
break;
case Parameter::LINK_UP:
uint32_t value;
if (newParameter.getValue()) {
value = 0;
}
else {
value = 0xffffffff;
}
qdisc = rtnl_qdisc_get(qdisc_cache, ifindex, plrHandle);
if (qdisc == NULL) {
cerr << "Couldn't find plr qdisc " << plrHandle << endl;
return;
}
rtnl_plr_set_plr(qdisc, value);
rtnl_qdisc_change(nl_handle, qdisc, NULL);
rtnl_qdisc_put(qdisc);
break;
default:
break;
}
}
#endif
// DummynetPipe.hh
#ifdef FREEBSD
#ifndef DUMMYNET_PIPE_HH_DELAY_AGENT_1
#define DUMMYNET_PIPE_HH_DELAY_AGENT_1
......@@ -25,44 +23,3 @@ private:
};
#endif
#endif
#ifdef LINUX
// NetlinkPipe.hh
// A pipe which implements the system by generating events for the old delay agent.
// TEVC example:
// /usr/testbed/bin/tevc -e project/experiment now agent-name MODIFY BANDWIDTH=3455
// or DELAY=34
// or PLR=0.1
#ifndef NETLINK_PIPE_HH_DELAY_AGENT_1
#define NETLINK_PIPE_HH_DELAY_AGENT_1
#include <stdint.h>
class NetlinkPipe : public RootPipe
{
public:
NetlinkPipe(std::string const & iface, std::string const & pipeno);
virtual ~NetlinkPipe();
virtual void reset(void);
virtual void resetParameter(Parameter const & newParameter);
private:
virtual void updateParameter(Parameter const & newParameter);
virtual int init(void);
virtual void test(void);
std::string interfaceName;
std::string pipeNumber;
int ifindex;
struct nl_handle *nl_handle;
struct nl_cache *qdisc_cache, *class_cache;
uint32_t plrHandle, delayHandle, htbHandle;
uint32_t htbClassHandle;
};
#endif
#endif
......@@ -3,7 +3,6 @@
all: delay-agent
SRCS := $(wildcard *.cc)
OBJS := $(SRCS:%.cc=%.o)
LIBS = -lcrypto -lpubsub
CXXFLAGS = -DELVIN_COMPAT -Wall -I../../lib/ -I../../../../
......@@ -20,16 +19,18 @@ CXXFLAGS += -DLINUX -I../../../../libnl/include
LDFLAGS += -L../../../../libnl/lib -lnl
endif
OBJS := $(SRCS:%.cc=%.o)
CFLAGS = $(CXXFLAGS)
%.o: %.cc
$(CXX) $(CXXFLAGS) -c $< -o $@
delay-agent: $(OBJS) $(COMMON_OBJS) $(EVENT_OBJS) libevent.a
delay-agent: $(OBJS) libevent.a
$(CXX) $(LDFLAGS) -o $@ $^ $(LIBS)
clean:
rm -f *.o *.a delay-agent
rm -f *.a delay-agent $(OBJS)
libevent.a: event.o util.o
$(AR) crv libevent.a event.o util.o
......
// NetlinkPipe.cc
#ifdef LINUX
#include "lib.hh"
#include "NetlinkPipe.hh"
extern "C"
{
#include <sys/types.h>
#include <sys/socket.h>
#include <netlink/list.h>
#include <netlink/object.h>
#include <netlink/route/rtnl.h>
#include <netlink/route/route.h>
#include <netlink/route/link.h>
#include <netlink/route/class.h>
#include <netlink/route/qdisc.h>
#include <netlink/route/sch/plr.h>
#include <netlink/route/sch/delay.h>
#include <netlink/route/sch/htb.h>
}
using namespace std;
NetlinkPipe::NetlinkPipe(std::string const & iface, std::string const & pipeno)
{
interfaceName = iface;
pipeNumber = pipeno;
nl_handle = NULL;
class_cache = NULL;
qdisc_cache = NULL;
init();
/* test(); */
}
void NetlinkPipe::test(void)
{
Parameter testParam(Parameter::LOSS, 50000);
updateParameter(testParam);
}
int NetlinkPipe::init(void)
{
struct nl_cache *link_cache;
int handle;
string str;
link_cache = NULL;
cerr << "Got pipe number " << pipeNumber << endl;
handle = hexStringToInt(pipeNumber);
cerr << "handle: " << handle << endl;
nl_handle = nl_handle_alloc();
if (nl_handle == NULL) {
cerr << "Unable to allocate nl_handle" << endl;
return -1;
}
if (nl_connect(nl_handle, NETLINK_ROUTE) < 0) {
cerr << "Unable to allocate Netlink socket" << endl;
return -1;
}
link_cache = rtnl_link_alloc_cache(nl_handle);
if (link_cache == NULL) {
cerr << "Unable to allocate link cache" << endl;
return -1;
}
ifindex = rtnl_link_name2i(link_cache, interfaceName.c_str());
if (ifindex == RTNL_LINK_NOT_FOUND) {
cerr << "Unable to translate link name to ifindex" << endl;
return -1;
}
nl_cache_free(link_cache);
qdisc_cache = rtnl_qdisc_alloc_cache(nl_handle);
if (qdisc_cache == NULL) {
cerr << "Unable to allocate qdisc cache" << endl;
return -1;
}
plrHandle = handle << 16;
delayHandle = (handle + 0x10) << 16;
htbHandle = (handle + 0x20) << 16;
class_cache = rtnl_class_alloc_cache(nl_handle, ifindex);
if (class_cache == NULL) {
cerr << "Unable to allocate class cache" << endl;
return -1;
}
htbClassHandle = htbHandle + 1;
return 0;
}
NetlinkPipe::~NetlinkPipe()
{
if (qdisc_cache)
nl_cache_free(qdisc_cache);
if (class_cache)
nl_cache_free(class_cache);
if (nl_handle)
nl_close(nl_handle);
}
void NetlinkPipe::reset(void)
{
map<Parameter::ParameterType, Parameter>::iterator pos = g::defaultParameters.begin();
map<Parameter::ParameterType, Parameter>::iterator limit = g::defaultParameters.end();
for (; pos != limit; ++pos)
{
updateParameter(pos->second);
}
}
void NetlinkPipe::resetParameter(Parameter const & newParameter)
{
updateParameter(newParameter);
}
void NetlinkPipe::updateParameter(Parameter const & newParameter)
{
struct rtnl_qdisc *qdisc;
struct rtnl_class *htbClass;
qdisc = NULL;
switch(newParameter.getType()) {
case Parameter::BANDWIDTH:
htbClass = rtnl_class_get(class_cache, htbClassHandle);
if (htbClass == NULL) {
cerr << "Couldn't find htb class " << htbClassHandle << endl;
return;
}
rtnl_htb_set_rate(htbClass, newParameter.getValue());
rtnl_htb_set_ceil(htbClass, newParameter.getValue());
rtnl_class_change(nl_handle, htbClass, NULL);
rtnl_class_put(htbClass);
break;
case Parameter::DELAY:
qdisc = rtnl_qdisc_get(qdisc_cache, ifindex, delayHandle);
if (qdisc == NULL) {
cerr << "Couldn't find delay qdisc " << delayHandle << endl;
return;
}
rtnl_delay_set_delay(qdisc, newParameter.getValue());
rtnl_qdisc_change(nl_handle, qdisc, NULL);
rtnl_qdisc_put(qdisc);
break;
case Parameter::LOSS:
qdisc = rtnl_qdisc_get(qdisc_cache, ifindex, plrHandle);
if (qdisc == NULL) {
cerr << "Couldn't find plr qdisc " << plrHandle << endl;
return;
}
rtnl_plr_set_plr(qdisc, newParameter.getValue());
rtnl_qdisc_change(nl_handle, qdisc, NULL);
rtnl_qdisc_put(qdisc);
break;
case Parameter::LINK_UP:
uint32_t value;
if (newParameter.getValue()) {
value = 1;
}
else {
value = 0x7ffffffff;
}
qdisc = rtnl_qdisc_get(qdisc_cache, ifindex, plrHandle);
if (qdisc == NULL) {
cerr << "Couldn't find plr qdisc " << plrHandle << endl;
return;
}
rtnl_plr_set_plr(qdisc, value);
rtnl_qdisc_change(nl_handle, qdisc, NULL);
rtnl_qdisc_put(qdisc);
break;
default:
break;
}
}
#endif
// NetlinkPipe.hh
// A pipe which implements the system by generating events for the old delay agent.
// TEVC example:
// /usr/testbed/bin/tevc -e project/experiment now agent-name MODIFY BANDWIDTH=3455
// or DELAY=34
// or PLR=0.1
#ifndef NETLINK_PIPE_HH_DELAY_AGENT_1
#define NETLINK_PIPE_HH_DELAY_AGENT_1
#include <stdint.h>
class NetlinkPipe : public RootPipe
{
public:
// 'name' will be prefixed with "new-" plus the original agent's
// name. To call the old agent, simply remove the prefix.
NetlinkPipe(std::string const & iface, std::string const & pipeno);
virtual ~NetlinkPipe();
virtual void reset(void);
virtual void resetParameter(Parameter const & newParameter);
private:
virtual void updateParameter(Parameter const & newParameter);
virtual int init(void);
virtual void test(void);
std::string interfaceName;
std::string pipeNumber;
int ifindex;
struct nl_handle *nl_handle;
struct nl_cache *qdisc_cache, *class_cache;
uint32_t plrHandle, delayHandle, htbHandle;
uint32_t htbClassHandle;
};
#endif
......@@ -5,7 +5,13 @@
#include "Pipe.hh"
#include "EventPipe.hh"
#ifdef FREEBSD
#include "DummynetPipe.hh"
#else
#ifdef LINUX
#include "NetlinkPipe.hh"
#endif
#endif
// Each pipe here is uni-directional. Multiple directions are
// accounted for with multiple pipes.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment