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