Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
emulab
emulab-devel
Commits
b2e4e860
Commit
b2e4e860
authored
Apr 02, 2008
by
Ryan Jackson
Browse files
Added backend for netlink on linux that uses libnl, cleaned up makefile
parent
989c6f7c
Changes
4
Hide whitespace changes
Inline
Side-by-side
event/delay-agent/new/DummynetPipe.cc
View file @
b2e4e860
...
...
@@ -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
::
get
Pipe
(
void
)
struct
dn_pipe
*
DummynetPipe
::
find
Pipe
(
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
event/delay-agent/new/DummynetPipe.hh
View file @
b2e4e860
...
...
@@ -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
event/delay-agent/new/Makefile
View file @
b2e4e860
...
...
@@ -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
../../../../
...
...
event/delay-agent/new/lib.cc
View file @
b2e4e860
...
...
@@ -2,6 +2,9 @@
#include
"lib.hh"
#include
<netlink/netlink.h>
#include
<netlink/route/link.h>
using
namespace
std
;
namespace
g
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment