Commit b2e4e860 authored by Ryan Jackson's avatar Ryan Jackson
Browse files

Added backend for netlink on linux that uses libnl, cleaned up makefile

parent 989c6f7c
......@@ -57,12 +57,18 @@ DummynetPipe::~DummynetPipe()
void DummynetPipe::reset(void)
{
cahr *data;
struct dn_pipe *pipe;
pipe = getPipe();
data = getAllPipes();
if (data == NULL) {
cerr << "Couldn't get dummynet pipes" << endl;
return;
}
pipe = findPipe(data);
if (pipe == NULL)
{
cerr << "Couldn't find pipe for " << dummynetPipeNumber << endl;
cerr << "Couldn't find pipe " << dummynetPipeNumber << endl;
return;
}
......@@ -75,8 +81,6 @@ void DummynetPipe::reset(void)
}
setPipe(pipe);
free(pipe);
}
void DummynetPipe::updateParameter(struct dn_pipe* pipe, Parameter const & newParameter)
......@@ -97,19 +101,24 @@ void DummynetPipe::updateParameter(struct dn_pipe* pipe, Parameter const & newPa
void DummynetPipe::resetParameter(Parameter const & newParameter)
{
char *data;
struct dn_pipe *pipe;
pipe = getPipe();
data = getAllPipes();
if (data == NULL) {
cerr << "Couldn't get dummynet pipes" << endl;
return;
}
pipe = findPipe(data);
if (pipe == NULL)
{
cerr << "Couldn't find pipe " << dummynetPipeNumber << endl;
return;
}
updateParameter(pipe, newParameter);
setPipe(pipe);
free(pipe);
}
char * callGetsockopt(char * data, size_t * count)
......@@ -140,101 +149,204 @@ char * DummynetPipe::getAllPipes(void)
return result;
}
struct dn_pipe * DummynetPipe::getPipe(void)
struct dn_pipe * DummynetPipe::findPipe(char *data)
{
// Find the pipe we care about
// Pass this pipe to the thing which should deal with it.
size_t num_bytes = sizeof(struct dn_pipe);
size_t num_alloc = sizeof(struct dn_pipe);
void * data = NULL;
void * next = NULL;
struct dn_pipe * p = NULL;
struct dn_pipe * pipe = NULL;
struct dn_flow_queue * q = NULL;
struct dn_pipe *p, *pipe;
int l;
pipe = NULL;
p = (struct dn_pipe *) data;
data = malloc(num_bytes);
if(data == NULL)
{
cerr << "malloc: cant allocate memory" << endl;
return 0;
}
while (num_bytes >= num_alloc)
while ( DN_PIPE_NEXT(p) == (struct dn_pipe *)DN_IS_PIPE ) {
{
num_alloc = num_alloc * 2 + 200;
num_bytes = num_alloc ;
if ((data = realloc(data, num_bytes)) == NULL)
{
cerr << "cant alloc memory" << endl;
return 0;
if (dummynetPipeNumber == p->pipe_nr) {
pipe = p;
break;
}
if (getsockopt(dummynetSocket, IPPROTO_IP, IP_DUMMYNET_GET,
data, &num_bytes) < 0)
{
cerr << "error in getsockopt" << endl;
return 0;
}
l = p->fs.rq_elements * sizeof(struct dn_flow_queue) +
sizeof(struct dn_pipe);
p = (struct dn_pipe *)((char *)p + l);
}
next = data;
p = (struct dn_pipe *) data;
pipe = NULL;
return pipe;
}
for ( ; num_bytes >= sizeof(*p) ; p = (struct dn_pipe *)next )
{
if ( DN_PIPE_NEXT(p) != (struct dn_pipe *)DN_IS_PIPE )
break ;
l = sizeof(*p) + p->fs.rq_elements * sizeof(*q) ;
next = (void*)((char *)p + l);
num_bytes -= l ;
if (dummynetPipeNumber != p->pipe_nr)
continue;
q = (struct dn_flow_queue *)(p+1) ;
void DummynetPipe::setPipe(struct dn_pipe *pipe)
{
if (setsockopt(dummynetSocket, IPPROTO_IP, IP_DUMMYNET_CONFIGURE, pipe, sizeof(*pipe))
< 0)
cerr << "IP_DUMMYNET_CONFIGURE setsockopt failed" << endl;
}
#endif
#ifdef LINUX
#if 0
/* grab pipe delay and bandwidth */
link_map[l_index].getParams(p_index).setDelay(p->delay);
link_map[l_index].getParams(p_index).setBandwidth(p->bandwidth);
// NetlinkPipe.cc
/* get flow set parameters*/
get_flowset_params( &(p->fs), l_index, p_index);
#include "lib.hh"
#include "NetlinkPipe.hh"
/* get dynamic queue parameters*/
get_queue_params( &(p->fs), l_index, p_index);
#endif
}
extern "C"
{
#include <sys/types.h>
#include <sys/socket.h>
if ((num_bytes < sizeof(*p) || (DN_PIPE_NEXT(p) != (struct dn_pipe *)DN_IS_PIPE))) {
return NULL;
}
#include <netlink/list.h>
#include <netlink/object.h>
#include <netlink/route/qdisc.h>
#include <netlink/route/sch/plr.h>
#include <netlink/route/sch/delay.h>
#include <netlink/route/sch/htb.h>
}
pipe = (struct dn_pipe*)malloc(l);
if (pipe == NULL) {
cerr << "can't allocate memory" << endl;
return NULL;
}
using namespace std;
memcpy(pipe, p, l);
free(data);
struct rtnl_class * rtnl_class_get(struct nl_cache *, uint32_t);
return pipe;
NetlinkPipe::NetlinkPipe(std::string const & iface, std::string const & pipeno)
{
int ifindex;
interfaceName = iface;
pipeNumber = pipeno;
nl_handle = NULL;
class_cache = NULL;
qdisc_cache = NULL;
link_cache = NULL;
init();
}
int NetlinkPipe::init(void)
{
struct nl_cache *link_cache;
int handle;
string str;
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);
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;
}
class_cache = rtnl_class_alloc_cache(nl_handle, ifindex);
if (class_cache == NULL) {
cerr << "Unable to allocate class cache" << endl;
return -1;
}
handle = g::stringToInt(pipeNumber);
plrHandle = handle << 16;
delayHandle = (handle + 10) << 16;
htbHandle = (handle + 20) << 16;
htbClassHandle = htbHandle + 1;
}
NetlinkPipe::~NetlinkPipe()
{
if (qdisc_cache)
nl_cache_free(qdisc_cache);
if (class_cache)
nl_cache_free(class_cache);
void DummynetPipe::setPipe(struct dn_pipe *pipe)
if (nl_handle)
nl_close(nl_handle);
}
NetlinkPipe::reset(void)
{
if (setsockopt(dummynetSocket, IPPROTO_IP, IP_DUMMYNET_CONFIGURE, pipe, sizeof(*pipe))
< 0)
cerr << "IP_DUMMYNET_CONFIGURE setsockopt failed" << endl;
map<Parameter::ParameterType, Parameter>::iterator pos = g::defaultParameters.begin();
map<Parameter::ParameterType, Parameter>::iterator limit = g::defaultParameters.end();
for (; pos != limit; ++pos)
{
updateParameter(pipe, pos->second);
}
}
NetlinkPipe::resetParameter(Parameter const & newParameter)
{
struct rtnl_qdisc *qdisc;
struct rtnl_class *htbClass;
uint32_t = handle;
qdisc = NULL;
switch(newParameter.getType()) {
case 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());
nl_object_put(htbClass);
break;
case DELAY:
qdisc = rtnl_qdisc_get(qdisc_cache, ifindex, delayHandle);
if (qdisc == NULL) {
cerr "Couldn't find htb class " << delayHandle << endl;
return;
}
rtnl_delay_set_delay(qdisc, newParameter.getValue());
rtnl_qdisc_put(qdisc);
break;
case LOSS:
qdisc = rtnl_qdisc_get(qdisc_cache, ifindex, plrHandle);
if (delay == NULL) {
cerr "Couldn't find htb class " << delayHandle << endl;
return;
}
rtnl_plr_set_plr(qdisc, newParameter.getValue());
rtnl_qdisc_put(qdisc);
break;
}
}
struct rtnl_class * rtnl_class_get(struct nl_cache *cache, uint32_t handle)
{
struct rtnl_class *c;
if (cache->c_ops != &rtnl_class_ops)
return NULL;
nl_list_for_each_entry(c, &cache->c_items, ce_list) {
if (c->c_handle == handle) {
nl_object_get((struct nl_object *) c);
return c;
}
}
return NULL;
}
#endif
......@@ -17,7 +17,8 @@ public:
private:
void updateParameter(struct dn_pipe *pipe, Parameter const & parameter);
void setPipe(struct dn_pipe *pipe);
struct dn_pipe * getPipe(void);
char * getAllPipes(void);
struct dn_pipe * findPipe(char * data);
int dummynetPipeNumber;
int dummynetSocket;
};
......@@ -25,3 +26,39 @@ 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
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 & name);
virtual ~NetlinkPipe();
virtual void reset(void);
virtual void resetParameter(Parameter const & newParameter);
private:
virtual updateParameter(struct dn_pipe *pipe, Parameter const & parameter);
string interfaceName;
string pipeNumber;
int ifindex;
struct nl_handle *nl_handle;
struct nl_cache *qdisc_cache, *class_cache;
uint32_t plrHandle, delayHandle, htbHandle;
};
#endif
#endif
......@@ -2,8 +2,7 @@
all: delay-agent
OBJS = main.o Pipe.o Parameter.o lib.o RootPipe.o linkCallback.o resetCallback.o \
EventPipe.o DummynetPipe.o
OBJS := $(wildcard *.o)
LIBS = -lcrypto -lpubsub
CXXFLAGS = -DELVIN_COMPAT -Wall -I../../lib/ -I../../../../
......
......@@ -2,6 +2,9 @@
#include "lib.hh"
#include <netlink/netlink.h>
#include <netlink/route/link.h>
using namespace std;
namespace g
......
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