Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
B
bcc
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
bcc
Commits
ffaee08c
Commit
ffaee08c
authored
Jul 11, 2015
by
Brenden Blanco
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #83 from iovisor/yhs_dev
Yhs dev
parents
0fa99f4d
00eb0883
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
222 additions
and
273 deletions
+222
-273
examples/simulation.py
examples/simulation.py
+32
-10
tests/cc/simulation.py
tests/cc/simulation.py
+1
-0
tests/cc/test_brb.c
tests/cc/test_brb.c
+12
-15
tests/cc/test_brb.py
tests/cc/test_brb.py
+84
-127
tests/cc/test_brb2.c
tests/cc/test_brb2.c
+1
-1
tests/cc/test_brb2.py
tests/cc/test_brb2.py
+92
-120
No files found.
examples/simulation.py
View file @
ffaee08c
import
atexit
import
subprocess
from
pyroute2
import
IPRoute
,
NetNS
,
IPDB
,
NSPopen
from
pyroute2
import
IPRoute
,
NetNS
,
IPDB
,
NSPopen
class
Simulation
(
object
):
class
Simulation
(
object
):
...
@@ -14,15 +14,22 @@ class Simulation(object):
...
@@ -14,15 +14,22 @@ class Simulation(object):
self
.
processes
=
[]
self
.
processes
=
[]
self
.
released
=
False
self
.
released
=
False
# helper function to create a namespace and a veth connecting it
# helper function to add additional ifc to namespace
def
_create_ns
(
self
,
name
,
in_ifc
=
None
,
out_ifc
=
None
,
ipaddr
=
None
,
# if called directly outside Simulation class, "ifc_base_name" should be
macaddr
=
None
,
fn
=
None
,
cmd
=
None
,
action
=
"ok"
):
# different from "name", the "ifc_base_name" and "name" are the same for
# the first ifc created by namespace
def
_ns_add_ifc
(
self
,
name
,
ns_ifc
,
ifc_base_name
,
in_ifc
=
None
,
out_ifc
=
None
,
ipaddr
=
None
,
macaddr
=
None
,
fn
=
None
,
cmd
=
None
,
action
=
"ok"
,
disable_ipv6
=
False
):
if
name
in
self
.
ipdbs
:
ns_ipdb
=
self
.
ipdbs
[
name
]
else
:
ns_ipdb
=
IPDB
(
nl
=
NetNS
(
name
))
ns_ipdb
=
IPDB
(
nl
=
NetNS
(
name
))
if
in_ifc
:
if
in_ifc
:
in_ifname
=
in_ifc
.
ifname
in_ifname
=
in_ifc
.
ifname
else
:
else
:
out_ifc
=
self
.
ipdb
.
create
(
ifname
=
"%sa"
%
name
,
kind
=
"veth"
,
out_ifc
=
self
.
ipdb
.
create
(
ifname
=
"%sa"
%
ifc_base_
name
,
kind
=
"veth"
,
peer
=
"%sb"
%
name
).
commit
()
peer
=
"%sb"
%
ifc_base_
name
).
commit
()
in_ifc
=
self
.
ipdb
.
interfaces
[
out_ifc
.
peer
]
in_ifc
=
self
.
ipdb
.
interfaces
[
out_ifc
.
peer
]
in_ifname
=
in_ifc
.
ifname
in_ifname
=
in_ifc
.
ifname
with
in_ifc
as
v
:
with
in_ifc
as
v
:
...
@@ -31,21 +38,36 @@ class Simulation(object):
...
@@ -31,21 +38,36 @@ class Simulation(object):
in_ifc
=
ns_ipdb
.
interfaces
[
in_ifname
]
in_ifc
=
ns_ipdb
.
interfaces
[
in_ifname
]
if
out_ifc
:
out_ifc
.
up
().
commit
()
if
out_ifc
:
out_ifc
.
up
().
commit
()
with
in_ifc
as
v
:
with
in_ifc
as
v
:
v
.
ifname
=
"eth0"
v
.
ifname
=
ns_ifc
if
ipaddr
:
v
.
add_ip
(
"%s"
%
ipaddr
)
if
ipaddr
:
v
.
add_ip
(
"%s"
%
ipaddr
)
if
macaddr
:
v
.
address
=
macaddr
if
macaddr
:
v
.
address
=
macaddr
v
.
up
()
v
.
up
()
# if required, disable ipv6 before attaching the filter
if
disable_ipv6
:
subprocess
.
call
([
"sysctl"
,
"-q"
,
"-w"
,
"net.ipv6.conf."
+
out_ifc
.
ifname
+
".disable_ipv6=1"
])
nsp
=
NSPopen
(
ns_ipdb
.
nl
.
netns
,
[
"sysctl"
,
"-q"
,
"-w"
,
"net.ipv6.conf."
+
ns_ifc
+
".disable_ipv6=1"
])
nsp
.
wait
();
nsp
.
release
()
if
fn
and
out_ifc
:
if
fn
and
out_ifc
:
self
.
ipdb
.
nl
.
tc
(
"add"
,
"ingress"
,
out_ifc
[
"index"
],
"ffff:"
)
self
.
ipdb
.
nl
.
tc
(
"add"
,
"ingress"
,
out_ifc
[
"index"
],
"ffff:"
)
self
.
ipdb
.
nl
.
tc
(
"add-filter"
,
"bpf"
,
out_ifc
[
"index"
],
":1"
,
self
.
ipdb
.
nl
.
tc
(
"add-filter"
,
"bpf"
,
out_ifc
[
"index"
],
":1"
,
fd
=
fn
.
fd
,
name
=
fn
.
name
,
parent
=
"ffff:"
,
fd
=
fn
.
fd
,
name
=
fn
.
name
,
parent
=
"ffff:"
,
action
=
action
,
classid
=
1
)
action
=
action
,
classid
=
1
)
self
.
ipdbs
[
ns_ipdb
.
nl
.
netns
]
=
ns_ipdb
self
.
namespaces
.
append
(
ns_ipdb
.
nl
)
if
cmd
:
if
cmd
:
self
.
processes
.
append
(
NSPopen
(
ns_ipdb
.
nl
.
netns
,
cmd
))
self
.
processes
.
append
(
NSPopen
(
ns_ipdb
.
nl
.
netns
,
cmd
))
return
(
ns_ipdb
,
out_ifc
,
in_ifc
)
return
(
ns_ipdb
,
out_ifc
,
in_ifc
)
# helper function to create a namespace and a veth connecting it
def
_create_ns
(
self
,
name
,
in_ifc
=
None
,
out_ifc
=
None
,
ipaddr
=
None
,
macaddr
=
None
,
fn
=
None
,
cmd
=
None
,
action
=
"ok"
,
disable_ipv6
=
False
):
(
ns_ipdb
,
out_ifc
,
in_ifc
)
=
self
.
_ns_add_ifc
(
name
,
"eth0"
,
name
,
in_ifc
,
out_ifc
,
ipaddr
,
macaddr
,
fn
,
cmd
,
action
,
disable_ipv6
)
self
.
ipdbs
[
ns_ipdb
.
nl
.
netns
]
=
ns_ipdb
self
.
namespaces
.
append
(
ns_ipdb
.
nl
)
return
(
ns_ipdb
,
out_ifc
,
in_ifc
)
def
release
(
self
):
def
release
(
self
):
if
self
.
released
:
return
if
self
.
released
:
return
self
.
released
=
True
self
.
released
=
True
...
...
tests/cc/simulation.py
0 → 120000
View file @
ffaee08c
..
/
..
/
examples
/
simulation
.
py
\ No newline at end of file
tests/cc/test_brb.c
View file @
ffaee08c
...
@@ -101,13 +101,12 @@ int pem(struct __sk_buff *skb) {
...
@@ -101,13 +101,12 @@ int pem(struct __sk_buff *skb) {
}
}
}
}
return
0
;
return
1
;
}
}
static
int
br_common
(
struct
__sk_buff
*
skb
,
int
which_br
)
__attribute__
((
always_inline
));
static
int
br_common
(
struct
__sk_buff
*
skb
,
int
which_br
)
__attribute__
((
always_inline
));
static
int
br_common
(
struct
__sk_buff
*
skb
,
int
which_br
)
{
static
int
br_common
(
struct
__sk_buff
*
skb
,
int
which_br
)
{
u8
*
cursor
=
0
;
u8
*
cursor
=
0
;
bpf_metadata_t
meta
=
{};
u16
proto
;
u16
proto
;
u16
arpop
;
u16
arpop
;
eth_addr_t
dmac
;
eth_addr_t
dmac
;
...
@@ -118,20 +117,16 @@ static int br_common(struct __sk_buff *skb, int which_br) {
...
@@ -118,20 +117,16 @@ static int br_common(struct __sk_buff *skb, int which_br) {
bpf_dest_t
*
dest_p
;
bpf_dest_t
*
dest_p
;
u32
index
,
*
rtrif_p
;
u32
index
,
*
rtrif_p
;
if
(
skb
->
tc_index
==
0
)
{
skb
->
tc_index
=
1
;
skb
->
cb
[
0
]
=
skb
->
cb
[
1
]
=
0
;
meta
.
prog_id
=
meta
.
rx_port_id
=
0
;
}
else
{
meta
.
prog_id
=
skb
->
cb
[
0
];
meta
.
rx_port_id
=
skb
->
cb
[
1
];
}
struct
ethernet_t
*
ethernet
=
cursor_advance
(
cursor
,
sizeof
(
*
ethernet
));
struct
ethernet_t
*
ethernet
=
cursor_advance
(
cursor
,
sizeof
(
*
ethernet
));
/* handle ethernet packet header */
{
{
dmac
.
addr
=
ethernet
->
dst
;
dmac
.
addr
=
ethernet
->
dst
;
if
(
meta
.
prog_id
!=
0
)
{
/* skb->tc_index may be preserved accross router namespace if router simply rewrite packet
/* send to the router */
* and send it back.
*/
if
(
skb
->
tc_index
==
1
)
{
/* packet from pem, send to the router, set tc_index to 2 */
skb
->
tc_index
=
2
;
if
(
dmac
.
addr
==
0xffffffffffffULL
)
{
if
(
dmac
.
addr
==
0xffffffffffffULL
)
{
index
=
0
;
index
=
0
;
if
(
which_br
==
1
)
if
(
which_br
==
1
)
...
@@ -149,9 +144,11 @@ static int br_common(struct __sk_buff *skb, int which_br) {
...
@@ -149,9 +144,11 @@ static int br_common(struct __sk_buff *skb, int which_br) {
if
(
rtrif_p
)
if
(
rtrif_p
)
bpf_clone_redirect
(
skb
,
*
rtrif_p
,
0
);
bpf_clone_redirect
(
skb
,
*
rtrif_p
,
0
);
}
}
return
0
;
return
1
;
}
}
/* set the tc_index to 1 so pem knows it is from internal */
skb
->
tc_index
=
1
;
switch
(
ethernet
->
type
)
{
switch
(
ethernet
->
type
)
{
case
ETH_P_IP
:
goto
ip
;
case
ETH_P_IP
:
goto
ip
;
case
ETH_P_ARP
:
goto
arp
;
case
ETH_P_ARP
:
goto
arp
;
...
@@ -217,7 +214,7 @@ xmit:
...
@@ -217,7 +214,7 @@ xmit:
}
}
EOP:
EOP:
return
0
;
return
1
;
}
}
int
br1
(
struct
__sk_buff
*
skb
)
{
int
br1
(
struct
__sk_buff
*
skb
)
{
...
...
tests/cc/test_brb.py
View file @
ffaee08c
...
@@ -61,68 +61,31 @@
...
@@ -61,68 +61,31 @@
# 8:
# 8:
# 8: OK
# 8: OK
from
ctypes
import
c_u
byte
,
c_ushort
,
c_uint
,
c_ulonglong
,
Structure
from
ctypes
import
c_u
int
from
netaddr
import
IPAddress
,
EUI
from
netaddr
import
IPAddress
,
EUI
from
bpf
import
BPF
from
bpf
import
BPF
from
pyroute2
import
IPRoute
from
pyroute2
import
IPRoute
,
NetNS
,
IPDB
,
NSPopen
from
socket
import
socket
,
AF_INET
,
SOCK_DGRAM
import
sys
import
sys
from
time
import
sleep
from
time
import
sleep
from
unittest
import
main
,
TestCase
from
unittest
import
main
,
TestCase
import
subprocess
from
simulation
import
Simulation
import
struct
arg1
=
sys
.
argv
.
pop
(
1
)
arg1
=
sys
.
argv
.
pop
(
1
)
ipr
=
IPRoute
()
ipdb
=
IPDB
(
nl
=
ipr
)
sim
=
Simulation
(
ipdb
)
class
TestBPFSocket
(
TestCase
):
class
TestBPFSocket
(
TestCase
):
def
setup_vm_ns
(
self
,
ns
,
veth_in
,
veth_out
):
subprocess
.
call
([
"ip"
,
"link"
,
"add"
,
veth_in
,
"type"
,
"veth"
,
"peer"
,
"name"
,
veth_out
])
subprocess
.
call
([
"ip"
,
"netns"
,
"add"
,
ns
])
subprocess
.
call
([
"ip"
,
"link"
,
"set"
,
veth_in
,
"netns"
,
ns
])
subprocess
.
call
([
"ip"
,
"netns"
,
"exec"
,
ns
,
"ip"
,
"link"
,
"set"
,
veth_in
,
"name"
,
"eth0"
])
subprocess
.
call
([
"ip"
,
"link"
,
"set"
,
veth_out
,
"up"
])
def
config_vm_ns
(
self
,
ns
,
ip_addr
,
net_mask
,
ip_gw
):
subprocess
.
call
([
"ip"
,
"netns"
,
"exec"
,
ns
,
"ip"
,
"addr"
,
"add"
,
ip_addr
+
"/24"
,
"dev"
,
"eth0"
])
subprocess
.
call
([
"ip"
,
"netns"
,
"exec"
,
ns
,
"ip"
,
"link"
,
"set"
,
"eth0"
,
"up"
])
subprocess
.
call
([
"ip"
,
"netns"
,
"exec"
,
ns
,
"ip"
,
"route"
,
"add"
,
net_mask
+
"/24"
,
"via"
,
ip_gw
])
def
setup_router_ns
(
self
,
ns
,
veth1_in
,
veth1_out
,
veth2_in
,
veth2_out
):
subprocess
.
call
([
"ip"
,
"netns"
,
"add"
,
ns
])
subprocess
.
call
([
"ip"
,
"link"
,
"add"
,
veth1_in
,
"type"
,
"veth"
,
"peer"
,
"name"
,
veth1_out
])
subprocess
.
call
([
"ip"
,
"link"
,
"set"
,
veth1_in
,
"netns"
,
ns
])
subprocess
.
call
([
"ip"
,
"netns"
,
"exec"
,
ns
,
"ip"
,
"link"
,
"set"
,
veth1_in
,
"name"
,
"eth0"
])
subprocess
.
call
([
"ip"
,
"link"
,
"add"
,
veth2_in
,
"type"
,
"veth"
,
"peer"
,
"name"
,
veth2_out
])
subprocess
.
call
([
"ip"
,
"link"
,
"set"
,
veth2_in
,
"netns"
,
ns
])
subprocess
.
call
([
"ip"
,
"netns"
,
"exec"
,
ns
,
"ip"
,
"link"
,
"set"
,
veth2_in
,
"name"
,
"eth1"
])
subprocess
.
call
([
"ip"
,
"link"
,
"set"
,
veth1_out
,
"up"
])
subprocess
.
call
([
"ip"
,
"link"
,
"set"
,
veth2_out
,
"up"
])
def
config_router_ns
(
self
,
ns
,
ip_eth0
,
ip_eth1
):
subprocess
.
call
([
"ip"
,
"netns"
,
"exec"
,
ns
,
"ip"
,
"addr"
,
"add"
,
ip_eth0
+
"/24"
,
"dev"
,
"eth0"
])
subprocess
.
call
([
"ip"
,
"netns"
,
"exec"
,
ns
,
"ip"
,
"link"
,
"set"
,
"eth0"
,
"up"
])
subprocess
.
call
([
"ip"
,
"netns"
,
"exec"
,
ns
,
"ip"
,
"addr"
,
"add"
,
ip_eth1
+
"/24"
,
"dev"
,
"eth1"
])
subprocess
.
call
([
"ip"
,
"netns"
,
"exec"
,
ns
,
"ip"
,
"link"
,
"set"
,
"eth1"
,
"up"
])
def
set_default_const
(
self
):
def
set_default_const
(
self
):
self
.
ns1
=
"ns1"
self
.
ns1
=
"ns1"
self
.
ns1_eth_in
=
"v1"
self
.
ns1_eth_out
=
"v2"
self
.
ns2
=
"ns2"
self
.
ns2
=
"ns2"
self
.
ns2_eth_in
=
"v3"
self
.
ns2_eth_out
=
"v4"
self
.
ns_router
=
"ns_router"
self
.
ns_router
=
"ns_router"
self
.
nsrtr_eth0_in
=
"v10"
self
.
nsrtr_eth0_out
=
"v11"
self
.
nsrtr_eth1_in
=
"v12"
self
.
nsrtr_eth1_out
=
"v13"
self
.
vm1_ip
=
"100.1.1.1"
self
.
vm1_ip
=
"100.1.1.1"
self
.
vm2_ip
=
"200.1.1.1"
self
.
vm2_ip
=
"200.1.1.1"
self
.
vm1_rtr_ip
=
"100.1.1.254"
self
.
vm1_rtr_ip
=
"100.1.1.254"
self
.
vm2_rtr_ip
=
"200.1.1.254"
self
.
vm2_rtr_ip
=
"200.1.1.254"
self
.
vm1_rtr_mask
=
"100.1.1.0"
self
.
vm1_rtr_mask
=
"100.1.1.0
/24
"
self
.
vm2_rtr_mask
=
"200.1.1.0"
self
.
vm2_rtr_mask
=
"200.1.1.0
/24
"
def
get_table
(
self
,
b
):
def
get_table
(
self
,
b
):
self
.
jump
=
b
.
get_table
(
"jump"
)
self
.
jump
=
b
.
get_table
(
"jump"
)
...
@@ -141,29 +104,15 @@ class TestBPFSocket(TestCase):
...
@@ -141,29 +104,15 @@ class TestBPFSocket(TestCase):
self
.
br2_rtr
=
b
.
get_table
(
"br2_rtr"
)
self
.
br2_rtr
=
b
.
get_table
(
"br2_rtr"
)
def
connect_ports
(
self
,
prog_id_pem
,
prog_id_br
,
curr_pem_pid
,
curr_br_pid
,
def
connect_ports
(
self
,
prog_id_pem
,
prog_id_br
,
curr_pem_pid
,
curr_br_pid
,
ip
,
br_dest_map
,
br_mac_map
,
br_dest_map
,
br_mac_map
,
ifindex
,
vm_mac
,
vm_ip
):
ns_eth_out
,
vm_mac
,
vm_ip
):
self
.
pem_dest
[
c_uint
(
curr_pem_pid
)]
=
self
.
pem_dest
.
Leaf
(
prog_id_br
,
curr_br_pid
)
self
.
pem_dest
[
c_uint
(
curr_pem_pid
)]
=
self
.
pem_dest
.
Leaf
(
prog_id_br
,
curr_br_pid
)
br_dest_map
[
c_uint
(
curr_br_pid
)]
=
br_dest_map
.
Leaf
(
prog_id_pem
,
curr_pem_pid
)
br_dest_map
[
c_uint
(
curr_br_pid
)]
=
br_dest_map
.
Leaf
(
prog_id_pem
,
curr_pem_pid
)
ifindex
=
ip
.
link_lookup
(
ifname
=
ns_eth_out
)[
0
]
self
.
pem_port
[
c_uint
(
curr_pem_pid
)]
=
c_uint
(
ifindex
)
self
.
pem_port
[
c_uint
(
curr_pem_pid
)]
=
c_uint
(
ifindex
)
self
.
pem_ifindex
[
c_uint
(
ifindex
)]
=
c_uint
(
curr_pem_pid
)
self
.
pem_ifindex
[
c_uint
(
ifindex
)]
=
c_uint
(
curr_pem_pid
)
mac_addr
=
br_mac_map
.
Key
(
int
(
EUI
(
vm_mac
.
decode
())))
mac_addr
=
br_mac_map
.
Key
(
int
(
EUI
(
vm_mac
.
decode
())))
br_mac_map
[
mac_addr
]
=
c_uint
(
curr_br_pid
)
br_mac_map
[
mac_addr
]
=
c_uint
(
curr_br_pid
)
def
attach_filter
(
self
,
ip
,
ifname
,
fd
,
name
):
ifindex
=
ip
.
link_lookup
(
ifname
=
ifname
)[
0
]
ip
.
tc
(
"add"
,
"ingress"
,
ifindex
,
"ffff:"
)
ip
.
tc
(
"add-filter"
,
"bpf"
,
ifindex
,
":1"
,
fd
=
fd
,
name
=
name
,
parent
=
"ffff:"
,
action
=
"drop"
,
classid
=
1
)
def
config_maps
(
self
):
def
config_maps
(
self
):
b
=
BPF
(
src_file
=
arg1
,
debug
=
0
)
pem_fn
=
b
.
load_func
(
"pem"
,
BPF
.
SCHED_CLS
)
br1_fn
=
b
.
load_func
(
"br1"
,
BPF
.
SCHED_CLS
)
br2_fn
=
b
.
load_func
(
"br2"
,
BPF
.
SCHED_CLS
)
ip
=
IPRoute
()
# program id
# program id
prog_id_pem
=
1
prog_id_pem
=
1
prog_id_br1
=
2
prog_id_br1
=
2
...
@@ -173,89 +122,97 @@ class TestBPFSocket(TestCase):
...
@@ -173,89 +122,97 @@ class TestBPFSocket(TestCase):
curr_pem_pid
=
0
curr_pem_pid
=
0
curr_br1_pid
=
0
curr_br1_pid
=
0
curr_br2_pid
=
0
curr_br2_pid
=
0
self
.
get_table
(
b
)
# configure jump table
# configure jump table
self
.
jump
[
c_uint
(
prog_id_pem
)]
=
c_uint
(
pem_fn
.
fd
)
self
.
jump
[
c_uint
(
prog_id_pem
)]
=
c_uint
(
self
.
pem_fn
.
fd
)
self
.
jump
[
c_uint
(
prog_id_br1
)]
=
c_uint
(
br1_fn
.
fd
)
self
.
jump
[
c_uint
(
prog_id_br1
)]
=
c_uint
(
self
.
br1_fn
.
fd
)
self
.
jump
[
c_uint
(
prog_id_br2
)]
=
c_uint
(
br2_fn
.
fd
)
self
.
jump
[
c_uint
(
prog_id_br2
)]
=
c_uint
(
self
.
br2_fn
.
fd
)
# connect pem and br1
# connect pem and br1
curr_pem_pid
=
curr_pem_pid
+
1
curr_pem_pid
=
curr_pem_pid
+
1
curr_br1_pid
=
curr_br1_pid
+
1
curr_br1_pid
=
curr_br1_pid
+
1
self
.
connect_ports
(
prog_id_pem
,
prog_id_br1
,
curr_pem_pid
,
curr_br1_pid
,
self
.
connect_ports
(
prog_id_pem
,
prog_id_br1
,
curr_pem_pid
,
curr_br1_pid
,
ip
,
self
.
br1_dest
,
self
.
br1_mac
,
self
.
br1_dest
,
self
.
br1_mac
,
self
.
ns1_eth_out
,
self
.
vm1_mac
,
self
.
vm1_ip
)
self
.
ns1_eth_out
.
index
,
self
.
vm1_mac
,
self
.
vm1_ip
)
# connect pem and br2
# connect pem and br2
curr_pem_pid
=
curr_pem_pid
+
1
curr_pem_pid
=
curr_pem_pid
+
1
curr_br2_pid
=
curr_br2_pid
+
1
curr_br2_pid
=
curr_br2_pid
+
1
self
.
connect_ports
(
prog_id_pem
,
prog_id_br2
,
curr_pem_pid
,
curr_br2_pid
,
self
.
connect_ports
(
prog_id_pem
,
prog_id_br2
,
curr_pem_pid
,
curr_br2_pid
,
ip
,
self
.
br2_dest
,
self
.
br2_mac
,
self
.
br2_dest
,
self
.
br2_mac
,
self
.
ns2_eth_out
,
self
.
vm2_mac
,
self
.
vm2_ip
)
self
.
ns2_eth_out
.
index
,
self
.
vm2_mac
,
self
.
vm2_ip
)
# connect <br1, rtr> and <br2, rtr>
# connect <br1, rtr> and <br2, rtr>
ifindex
=
ip
.
link_lookup
(
ifname
=
self
.
nsrtr_eth0_out
)[
0
]
self
.
br1_rtr
[
c_uint
(
0
)]
=
c_uint
(
self
.
nsrtr_eth0_out
.
index
)
self
.
br1_rtr
[
c_uint
(
0
)]
=
c_uint
(
ifindex
)
self
.
br2_rtr
[
c_uint
(
0
)]
=
c_uint
(
self
.
nsrtr_eth1_out
.
index
)
ifindex
=
ip
.
link_lookup
(
ifname
=
self
.
nsrtr_eth1_out
)[
0
]
self
.
br2_rtr
[
c_uint
(
0
)]
=
c_uint
(
ifindex
)
# tc filter setup with bpf programs attached
def
test_brb
(
self
):
self
.
attach_filter
(
ip
,
self
.
ns1_eth_out
,
pem_fn
.
fd
,
pem_fn
.
name
)
try
:
self
.
attach_filter
(
ip
,
self
.
ns2_eth_out
,
pem_fn
.
fd
,
pem_fn
.
name
)
b
=
BPF
(
src_file
=
arg1
,
debug
=
0
)
self
.
attach_filter
(
ip
,
self
.
nsrtr_eth0_out
,
br1_fn
.
fd
,
br1_fn
.
name
)
self
.
pem_fn
=
b
.
load_func
(
"pem"
,
BPF
.
SCHED_CLS
)
self
.
attach_filter
(
ip
,
self
.
nsrtr_eth1_out
,
br2_fn
.
fd
,
br2_fn
.
name
)
self
.
br1_fn
=
b
.
load_func
(
"br1"
,
BPF
.
SCHED_CLS
)
self
.
br2_fn
=
b
.
load_func
(
"br2"
,
BPF
.
SCHED_CLS
)
def
setUp
(
self
):
self
.
get_table
(
b
)
# set up the environment
# set up the topology
self
.
set_default_const
()
self
.
set_default_const
()
self
.
setup_vm_ns
(
self
.
ns1
,
self
.
ns1_eth_in
,
self
.
ns1_eth_out
)
(
ns1_ipdb
,
self
.
ns1_eth_out
,
_
)
=
sim
.
_create_ns
(
self
.
ns1
,
ipaddr
=
self
.
vm1_ip
+
'/24'
,
self
.
setup_vm_ns
(
self
.
ns2
,
self
.
ns2_eth_in
,
self
.
ns2_eth_out
)
fn
=
self
.
pem_fn
,
action
=
'drop'
,
self
.
config_vm_ns
(
self
.
ns1
,
self
.
vm1_ip
,
self
.
vm2_rtr_mask
,
self
.
vm1_rtr_ip
)
disable_ipv6
=
True
)
self
.
config_vm_ns
(
self
.
ns2
,
self
.
vm2_ip
,
self
.
vm1_rtr_mask
,
self
.
vm2_rtr_ip
)
(
ns2_ipdb
,
self
.
ns2_eth_out
,
_
)
=
sim
.
_create_ns
(
self
.
ns2
,
ipaddr
=
self
.
vm2_ip
+
'/24'
,
self
.
setup_router_ns
(
self
.
ns_router
,
self
.
nsrtr_eth0_in
,
self
.
nsrtr_eth0_out
,
fn
=
self
.
pem_fn
,
action
=
'drop'
,
self
.
nsrtr_eth1_in
,
self
.
nsrtr_eth1_out
)
disable_ipv6
=
True
)
self
.
config_router_ns
(
self
.
ns_router
,
self
.
vm1_rtr_ip
,
self
.
vm2_rtr_ip
)
ns1_ipdb
.
routes
.
add
({
'dst'
:
self
.
vm2_rtr_mask
,
'gateway'
:
self
.
vm1_rtr_ip
}).
commit
()
ns2_ipdb
.
routes
.
add
({
'dst'
:
self
.
vm1_rtr_mask
,
'gateway'
:
self
.
vm2_rtr_ip
}).
commit
()
# get vm mac address
self
.
vm1_mac
=
ns1_ipdb
.
interfaces
[
'eth0'
].
address
self
.
vm1_mac
=
subprocess
.
check_output
([
"ip"
,
"netns"
,
"exec"
,
self
.
ns1
,
"cat"
,
"/sys/class/net/eth0/address"
])
self
.
vm2_mac
=
ns2_ipdb
.
interfaces
[
'eth0'
].
address
self
.
vm1_mac
=
self
.
vm1_mac
.
strip
()
self
.
vm2_mac
=
subprocess
.
check_output
([
"ip"
,
"netns"
,
"exec"
,
self
.
ns2
,
"cat"
,
"/sys/class/net/eth0/address"
])
(
_
,
self
.
nsrtr_eth0_out
,
_
)
=
sim
.
_create_ns
(
self
.
ns_router
,
ipaddr
=
self
.
vm1_rtr_ip
+
'/24'
,
self
.
vm2_mac
=
self
.
vm2_mac
.
strip
()
fn
=
self
.
br1_fn
,
action
=
'drop'
,
disable_ipv6
=
True
)
# load the program and configure maps
(
rt_ipdb
,
self
.
nsrtr_eth1_out
,
_
)
=
sim
.
_ns_add_ifc
(
self
.
ns_router
,
"eth1"
,
"ns_router2"
,
ipaddr
=
self
.
vm2_rtr_ip
+
'/24'
,
fn
=
self
.
br2_fn
,
action
=
'drop'
,
disable_ipv6
=
True
)
nsp
=
NSPopen
(
rt_ipdb
.
nl
.
netns
,
[
"sysctl"
,
"-w"
,
"net.ipv4.ip_forward=1"
])
nsp
.
wait
();
nsp
.
release
()
# configure maps
self
.
config_maps
()
self
.
config_maps
()
def
test_brb
(
self
):
# our bridge is not smart enough, so send arping for router learning to prevent router
# our bridge is not smart enough, so send arping for router learning to prevent router
# from sending out arp request
# from sending out arp request
subprocess
.
call
([
"ip"
,
"netns"
,
"exec"
,
self
.
ns1
,
"arping"
,
"-w"
,
"1"
,
"-c"
,
"1"
,
"-I"
,
"eth0"
,
nsp
=
NSPopen
(
ns1_ipdb
.
nl
.
netns
,
self
.
vm1_rtr_ip
])
[
"arping"
,
"-w"
,
"1"
,
"-c"
,
"1"
,
"-I"
,
"eth0"
,
self
.
vm1_rtr_ip
])
subprocess
.
call
([
"ip"
,
"netns"
,
"exec"
,
self
.
ns2
,
"arping"
,
"-w"
,
"1"
,
"-c"
,
"1"
,
"-I"
,
"eth0"
,
nsp
.
wait
();
nsp
.
release
()
self
.
vm2_rtr_ip
])
nsp
=
NSPopen
(
ns2_ipdb
.
nl
.
netns
,
[
"arping"
,
"-w"
,
"1"
,
"-c"
,
"1"
,
"-I"
,
"eth0"
,
self
.
vm2_rtr_ip
])
nsp
.
wait
();
nsp
.
release
()
# ping
# ping
subprocess
.
call
([
"ip"
,
"netns"
,
"exec"
,
self
.
ns1
,
"ping"
,
self
.
vm2_ip
,
"-c"
,
"2"
])
nsp
=
NSPopen
(
ns1_ipdb
.
nl
.
netns
,
[
"ping"
,
self
.
vm2_ip
,
"-c"
,
"2"
])
# minimum one arp reply, 5 icmp reply
nsp
.
wait
();
nsp
.
release
()
self
.
assertGreater
(
self
.
pem_stats
[
c_uint
(
0
)].
value
,
5
)
# pem_stats only counts pem->bridge traffic, each VM has 4: arping/arp request/2 icmp request
# total 8 packets should be counted
self
.
assertEqual
(
self
.
pem_stats
[
c_uint
(
0
)].
value
,
8
)
# iperf, run server on the background
nsp_server
=
NSPopen
(
ns2_ipdb
.
nl
.
netns
,
[
"iperf"
,
"-s"
,
"-xSC"
])
subprocess
.
Popen
([
"ip"
,
"netns"
,
"exec"
,
self
.
ns2
,
"iperf"
,
"-s"
,
"-xSCD"
])
sleep
(
1
)
sleep
(
1
)
subprocess
.
call
([
"ip"
,
"netns"
,
"exec"
,
self
.
ns1
,
"iperf"
,
"-c"
,
self
.
vm2_ip
,
"-t"
,
"1"
,
"-xSC"
])
nsp
=
NSPopen
(
ns1_ipdb
.
nl
.
netns
,
[
"iperf"
,
"-c"
,
self
.
vm2_ip
,
"-t"
,
"1"
,
"-xSC"
])
subprocess
.
call
([
"ip"
,
"netns"
,
"exec"
,
self
.
ns2
,
"killall"
,
"iperf"
])
nsp
.
wait
();
nsp
.
release
()
nsp_server
.
kill
();
nsp_server
.
wait
();
nsp_server
.
release
()
# netperf, run server on the background
nsp_server
=
NSPopen
(
ns2_ipdb
.
nl
.
netns
,
[
"netserver"
,
"-D"
])
subprocess
.
Popen
([
"ip"
,
"netns"
,
"exec"
,
self
.
ns2
,
"netserver"
])
sleep
(
1
)
sleep
(
1
)
subprocess
.
call
([
"ip"
,
"netns"
,
"exec"
,
self
.
ns1
,
"netperf"
,
"-l"
,
"1"
,
"-H"
,
self
.
vm2_ip
,
"--"
,
"-m"
,
"65160"
])
nsp
=
NSPopen
(
ns1_ipdb
.
nl
.
netns
,
[
"netperf"
,
"-l"
,
"1"
,
"-H"
,
self
.
vm2_ip
,
"--"
,
"-m"
,
"65160"
])
subprocess
.
call
([
"ip"
,
"netns"
,
"exec"
,
self
.
ns1
,
"netperf"
,
"-l"
,
"1"
,
"-H"
,
self
.
vm2_ip
,
"-t"
,
"TCP_RR"
])
nsp
.
wait
();
nsp
.
release
()
subprocess
.
call
([
"ip"
,
"netns"
,
"exec"
,
self
.
ns2
,
"killall"
,
"netserver"
])
nsp
=
NSPopen
(
ns1_ipdb
.
nl
.
netns
,
[
"netperf"
,
"-l"
,
"1"
,
"-H"
,
self
.
vm2_ip
,
"-t"
,
"TCP_RR"
])
nsp
.
wait
();
nsp
.
release
()
# cleanup, tear down the veths and namespaces
nsp_server
.
kill
();
nsp_server
.
wait
();
nsp_server
.
release
()
subprocess
.
call
([
"ip"
,
"netns"
,
"del"
,
self
.
ns1
])
subprocess
.
call
([
"ip"
,
"netns"
,
"del"
,
self
.
ns2
])
finally
:
subprocess
.
call
([
"ip"
,
"netns"
,
"del"
,
self
.
ns_router
])
sim
.
release
()
ipdb
.
release
()
if
__name__
==
"__main__"
:
if
__name__
==
"__main__"
:
...
...
tests/cc/test_brb2.c
View file @
ffaee08c
...
@@ -24,5 +24,5 @@ int pem(struct __sk_buff *skb) {
...
@@ -24,5 +24,5 @@ int pem(struct __sk_buff *skb) {
bpf_clone_redirect
(
skb
,
*
ifindex_p
,
0
);
bpf_clone_redirect
(
skb
,
*
ifindex_p
,
0
);
}
}
return
0
;
return
1
;
}
}
tests/cc/test_brb2.py
View file @
ffaee08c
...
@@ -54,72 +54,41 @@
...
@@ -54,72 +54,41 @@
# 9:
# 9:
# 9: OK
# 9: OK
from
ctypes
import
c_ubyte
,
c_ushort
,
c_uint
,
c_ulonglong
,
Structure
from
ctypes
import
c_uint
from
netaddr
import
IPAddress
from
bpf
import
BPF
from
bpf
import
BPF
from
pyroute2
import
IPRoute
from
pyroute2
import
IPRoute
,
NetNS
,
IPDB
,
NSPopen
from
socket
import
socket
,
AF_INET
,
SOCK_DGRAM
import
sys
import
sys
from
time
import
sleep
from
time
import
sleep
from
unittest
import
main
,
TestCase
from
unittest
import
main
,
TestCase
import
subprocess
import
subprocess
from
simulation
import
Simulation
arg1
=
sys
.
argv
.
pop
(
1
)
arg1
=
sys
.
argv
.
pop
(
1
)
ipr
=
IPRoute
()
ipdb
=
IPDB
(
nl
=
ipr
)
sim
=
Simulation
(
ipdb
)
class
TestBPFSocket
(
TestCase
):
class
TestBPFSocket
(
TestCase
):
def
setup_vm_ns
(
self
,
ns
,
veth_in
,
veth_out
):
def
setup_br
(
self
,
br
,
veth_rt_2_br
,
veth_pem_2_br
,
veth_br_2_pem
):
subprocess
.
call
([
"ip"
,
"link"
,
"add"
,
veth_in
,
"type"
,
"veth"
,
"peer"
,
"name"
,
veth_out
])
# create veth which connecting pem and br
subprocess
.
call
([
"ip"
,
"netns"
,
"add"
,
ns
])
with
ipdb
.
create
(
ifname
=
veth_pem_2_br
,
kind
=
"veth"
,
peer
=
veth_br_2_pem
)
as
v
:
subprocess
.
call
([
"ip"
,
"link"
,
"set"
,
veth_in
,
"netns"
,
ns
])
v
.
up
()
subprocess
.
call
([
"ip"
,
"netns"
,
"exec"
,
ns
,
"ip"
,
"link"
,
"set"
,
veth_in
,
"name"
,
"eth0"
])
ipdb
.
interfaces
[
veth_br_2_pem
].
up
().
commit
()
subprocess
.
call
([
"ip"
,
"link"
,
"set"
,
veth_out
,
"up"
])
subprocess
.
call
([
"sysctl"
,
"-q"
,
"-w"
,
"net.ipv6.conf."
+
veth_pem_2_br
+
".disable_ipv6=1"
])
subprocess
.
call
([
"sysctl"
,
"-q"
,
"-w"
,
"net.ipv6.conf."
+
veth_br_2_pem
+
".disable_ipv6=1"
])
def
config_vm_ns
(
self
,
ns
,
ip_addr
,
net_mask
,
ip_gw
):
subprocess
.
call
([
"ip"
,
"netns"
,
"exec"
,
ns
,
"ip"
,
"addr"
,
"add"
,
ip_addr
+
"/24"
,
"dev"
,
"eth0"
])
subprocess
.
call
([
"ip"
,
"netns"
,
"exec"
,
ns
,
"ip"
,
"link"
,
"set"
,
"eth0"
,
"up"
])
subprocess
.
call
([
"ip"
,
"netns"
,
"exec"
,
ns
,
"route"
,
"add"
,
"-net"
,
net_mask
+
"/24"
,
"gw"
,
ip_gw
])
def
setup_router_ns
(
self
,
ns
,
veth1_in
,
veth1_out
,
veth2_in
,
veth2_out
):
subprocess
.
call
([
"ip"
,
"netns"
,
"add"
,
ns
])
subprocess
.
call
([
"ip"
,
"link"
,
"add"
,
veth1_in
,
"type"
,
"veth"
,
"peer"
,
"name"
,
veth1_out
])
subprocess
.
call
([
"ip"
,
"link"
,
"set"
,
veth1_in
,
"netns"
,
ns
])
subprocess
.
call
([
"ip"
,
"netns"
,
"exec"
,
ns
,
"ip"
,
"link"
,
"set"
,
veth1_in
,
"name"
,
"eth0"
])
subprocess
.
call
([
"ip"
,
"link"
,
"add"
,
veth2_in
,
"type"
,
"veth"
,
"peer"
,
"name"
,
veth2_out
])
subprocess
.
call
([
"ip"
,
"link"
,
"set"
,
veth2_in
,
"netns"
,
ns
])
subprocess
.
call
([
"ip"
,
"netns"
,
"exec"
,
ns
,
"ip"
,
"link"
,
"set"
,
veth2_in
,
"name"
,
"eth1"
])
subprocess
.
call
([
"ip"
,
"link"
,
"set"
,
veth1_out
,
"up"
])
subprocess
.
call
([
"ip"
,
"link"
,
"set"
,
veth2_out
,
"up"
])
def
config_router_ns
(
self
,
ns
,
ip_eth0
,
ip_eth1
):
subprocess
.
call
([
"ip"
,
"netns"
,
"exec"
,
ns
,
"ip"
,
"addr"
,
"add"
,
ip_eth0
+
"/24"
,
"dev"
,
"eth0"
])
subprocess
.
call
([
"ip"
,
"netns"
,
"exec"
,
ns
,
"ip"
,
"link"
,
"set"
,
"eth0"
,
"up"
])
subprocess
.
call
([
"ip"
,
"netns"
,
"exec"
,
ns
,
"ip"
,
"addr"
,
"add"
,
ip_eth1
+
"/24"
,
"dev"
,
"eth1"
])
subprocess
.
call
([
"ip"
,
"netns"
,
"exec"
,
ns
,
"ip"
,
"link"
,
"set"
,
"eth1"
,
"up"
])
def
setup_br
(
self
,
br
,
veth_rt_2_br
):
# set up the bridge and add router interface as one of its slaves
subprocess
.
call
([
"ip"
,
"link"
,
"add"
,
"name"
,
br
,
"type"
,
"bridge"
])
subprocess
.
call
([
"ip"
,
"link"
,
"set"
,
"dev"
,
veth_rt_2_br
,
"master"
,
br
])
subprocess
.
call
([
"ip"
,
"link"
,
"set"
,
br
,
"up"
])
def
br_add_pem_link
(
self
,
br
,
veth_pem_2_br
,
veth_br_2_pem
):
# set up the bridge and add router interface as one of its slaves
subprocess
.
call
([
"ip"
,
"link"
,
"add"
,
veth_pem_2_br
,
"type"
,
"veth"
,
"peer"
,
"name"
,
veth_br_2_pem
])
with
ipdb
.
create
(
ifname
=
br
,
kind
=
"bridge"
)
as
br1
:
subprocess
.
call
([
"ip"
,
"link"
,
"set"
,
"dev"
,
veth_pem_2_br
,
"master"
,
br
])
br1
.
add_port
(
ipdb
.
interfaces
[
veth_pem_2_br
])
subprocess
.
call
([
"ip"
,
"link"
,
"set"
,
veth_pem_2_br
,
"up"
])
br1
.
add_port
(
ipdb
.
interfaces
[
veth_rt_2_br
])
subprocess
.
call
([
"ip"
,
"link"
,
"set"
,
veth_br_2_pem
,
"up"
])
br1
.
up
()
subprocess
.
call
([
"sysctl"
,
"-q"
,
"-w"
,
"net.ipv6.conf."
+
br
+
".disable_ipv6=1"
])
def
set_default_const
(
self
):
def
set_default_const
(
self
):
self
.
ns1
=
"ns1"
self
.
ns1
=
"ns1"
self
.
ns1_eth_in
=
"v1"
self
.
ns1_eth_out
=
"v2"
self
.
ns2
=
"ns2"
self
.
ns2
=
"ns2"
self
.
ns2_eth_in
=
"v3"
self
.
ns2_eth_out
=
"v4"
self
.
ns_router
=
"ns_router"
self
.
ns_router
=
"ns_router"
self
.
nsrtr_eth0_in
=
"v10"
self
.
nsrtr_eth0_out
=
"v11"
self
.
nsrtr_eth1_in
=
"v12"
self
.
nsrtr_eth1_out
=
"v13"
self
.
br1
=
"br1"
self
.
br1
=
"br1"
self
.
veth_pem_2_br1
=
"v20"
self
.
veth_pem_2_br1
=
"v20"
self
.
veth_br1_2_pem
=
"v21"
self
.
veth_br1_2_pem
=
"v21"
...
@@ -131,88 +100,91 @@ class TestBPFSocket(TestCase):
...
@@ -131,88 +100,91 @@ class TestBPFSocket(TestCase):
self
.
vm2_ip
=
"200.1.1.1"
self
.
vm2_ip
=
"200.1.1.1"
self
.
vm1_rtr_ip
=
"100.1.1.254"
self
.
vm1_rtr_ip
=
"100.1.1.254"
self
.
vm2_rtr_ip
=
"200.1.1.254"
self
.
vm2_rtr_ip
=
"200.1.1.254"
self
.
vm1_rtr_mask
=
"100.1.1.0"
self
.
vm1_rtr_mask
=
"100.1.1.0
/24
"
self
.
vm2_rtr_mask
=
"200.1.1.0"
self
.
vm2_rtr_mask
=
"200.1.1.0
/24
"
def
attach_filter
(
self
,
i
p
,
i
fname
,
fd
,
name
):
def
attach_filter
(
self
,
ifname
,
fd
,
name
):
ifindex
=
ip
.
link_lookup
(
ifname
=
ifname
)[
0
]
ifindex
=
ip
db
.
interfaces
[
ifname
].
index
ip
.
tc
(
"add"
,
"ingress"
,
ifindex
,
"ffff:"
)
ip
r
.
tc
(
"add"
,
"ingress"
,
ifindex
,
"ffff:"
)
ip
.
tc
(
"add-filter"
,
"bpf"
,
ifindex
,
":1"
,
fd
=
fd
,
name
=
name
,
ip
r
.
tc
(
"add-filter"
,
"bpf"
,
ifindex
,
":1"
,
fd
=
fd
,
name
=
name
,
parent
=
"ffff:"
,
action
=
"drop"
,
classid
=
1
)
parent
=
"ffff:"
,
action
=
"drop"
,
classid
=
1
)
def
config_maps
(
self
):
def
config_maps
(
self
):
b
=
BPF
(
src_file
=
arg1
,
debug
=
0
)
pem_fn
=
b
.
load_func
(
"pem"
,
BPF
.
SCHED_CLS
)
self
.
pem_dest
=
b
.
get_table
(
"pem_dest"
)
self
.
pem_stats
=
b
.
get_table
(
"pem_stats"
)
ip
=
IPRoute
()
# pem just relays packets between VM and its corresponding
# pem just relays packets between VM and its corresponding
# slave link in the bridge interface
# slave link in the bridge interface
ns1_ifindex
=
ip
.
link_lookup
(
ifname
=
self
.
ns1_eth_out
)[
0
]
ns1_ifindex
=
self
.
ns1_eth_out
.
index
ns2_ifindex
=
ip
.
link_lookup
(
ifname
=
self
.
ns2_eth_out
)[
0
]
ns2_ifindex
=
self
.
ns2_eth_out
.
index
br1_ifindex
=
ip
.
link_lookup
(
ifname
=
self
.
veth_br1_2_pem
)[
0
]
br1_ifindex
=
ip
db
.
interfaces
[
self
.
veth_br1_2_pem
].
index
br2_ifindex
=
ip
.
link_lookup
(
ifname
=
self
.
veth_br2_2_pem
)[
0
]
br2_ifindex
=
ip
db
.
interfaces
[
self
.
veth_br2_2_pem
].
index
self
.
pem_dest
[
c_uint
(
ns1_ifindex
)]
=
c_uint
(
br1_ifindex
)
self
.
pem_dest
[
c_uint
(
ns1_ifindex
)]
=
c_uint
(
br1_ifindex
)
self
.
pem_dest
[
c_uint
(
br1_ifindex
)]
=
c_uint
(
ns1_ifindex
)
self
.
pem_dest
[
c_uint
(
br1_ifindex
)]
=
c_uint
(
ns1_ifindex
)
self
.
pem_dest
[
c_uint
(
ns2_ifindex
)]
=
c_uint
(
br2_ifindex
)
self
.
pem_dest
[
c_uint
(
ns2_ifindex
)]
=
c_uint
(
br2_ifindex
)
self
.
pem_dest
[
c_uint
(
br2_ifindex
)]
=
c_uint
(
ns2_ifindex
)
self
.
pem_dest
[
c_uint
(
br2_ifindex
)]
=
c_uint
(
ns2_ifindex
)
# tc filter setup with bpf programs attached
# tc filter setup with bpf programs attached
self
.
attach_filter
(
ip
,
self
.
ns1_eth_out
,
pem_fn
.
fd
,
pem_fn
.
name
)
self
.
attach_filter
(
self
.
veth_br1_2_pem
,
self
.
pem_fn
.
fd
,
self
.
pem_fn
.
name
)
self
.
attach_filter
(
ip
,
self
.
ns2_eth_out
,
pem_fn
.
fd
,
pem_fn
.
name
)
self
.
attach_filter
(
self
.
veth_br2_2_pem
,
self
.
pem_fn
.
fd
,
self
.
pem_fn
.
name
)
self
.
attach_filter
(
ip
,
self
.
veth_br1_2_pem
,
pem_fn
.
fd
,
pem_fn
.
name
)
self
.
attach_filter
(
ip
,
self
.
veth_br2_2_pem
,
pem_fn
.
fd
,
pem_fn
.
name
)
def
setUp
(
self
):
def
test_brb2
(
self
):
try
:
b
=
BPF
(
src_file
=
arg1
,
debug
=
0
)
self
.
pem_fn
=
b
.
load_func
(
"pem"
,
BPF
.
SCHED_CLS
)
self
.
pem_dest
=
b
.
get_table
(
"pem_dest"
)
self
.
pem_stats
=
b
.
get_table
(
"pem_stats"
)
# set up the environment
# set up the topology
self
.
set_default_const
()
self
.
set_default_const
()
self
.
setup_vm_ns
(
self
.
ns1
,
self
.
ns1_eth_in
,
self
.
ns1_eth_out
)
(
ns1_ipdb
,
self
.
ns1_eth_out
,
_
)
=
sim
.
_create_ns
(
self
.
ns1
,
ipaddr
=
self
.
vm1_ip
+
'/24'
,
self
.
setup_vm_ns
(
self
.
ns2
,
self
.
ns2_eth_in
,
self
.
ns2_eth_out
)
fn
=
self
.
pem_fn
,
action
=
'drop'
,
self
.
config_vm_ns
(
self
.
ns1
,
self
.
vm1_ip
,
self
.
vm2_rtr_mask
,
self
.
vm1_rtr_ip
)
disable_ipv6
=
True
)
self
.
config_vm_ns
(
self
.
ns2
,
self
.
vm2_ip
,
self
.
vm1_rtr_mask
,
self
.
vm2_rtr_ip
)
(
ns2_ipdb
,
self
.
ns2_eth_out
,
_
)
=
sim
.
_create_ns
(
self
.
ns2
,
ipaddr
=
self
.
vm2_ip
+
'/24'
,
self
.
setup_router_ns
(
self
.
ns_router
,
self
.
nsrtr_eth0_in
,
self
.
nsrtr_eth0_out
,
fn
=
self
.
pem_fn
,
action
=
'drop'
,
self
.
nsrtr_eth1_in
,
self
.
nsrtr_eth1_out
)
disable_ipv6
=
True
)
self
.
config_router_ns
(
self
.
ns_router
,
self
.
vm1_rtr_ip
,
self
.
vm2_rtr_ip
)
ns1_ipdb
.
routes
.
add
({
'dst'
:
self
.
vm2_rtr_mask
,
'gateway'
:
self
.
vm1_rtr_ip
}).
commit
()
ns2_ipdb
.
routes
.
add
({
'dst'
:
self
.
vm1_rtr_mask
,
'gateway'
:
self
.
vm2_rtr_ip
}).
commit
()
# for each VM connecting to pem, there will be a corresponding veth
# connecting to the bridge
(
_
,
self
.
nsrtr_eth0_out
,
_
)
=
sim
.
_create_ns
(
self
.
ns_router
,
ipaddr
=
self
.
vm1_rtr_ip
+
'/24'
,
self
.
setup_br
(
self
.
br1
,
self
.
nsrtr_eth0_out
)
disable_ipv6
=
True
)
self
.
br_add_pem_link
(
self
.
br1
,
self
.
veth_pem_2_br1
,
self
.
veth_br1_2_pem
)
(
rt_ipdb
,
self
.
nsrtr_eth1_out
,
_
)
=
sim
.
_ns_add_ifc
(
self
.
ns_router
,
"eth1"
,
"ns_router2"
,
self
.
setup_br
(
self
.
br2
,
self
.
nsrtr_eth1_out
)
ipaddr
=
self
.
vm2_rtr_ip
+
'/24'
,
self
.
br_add_pem_link
(
self
.
br2
,
self
.
veth_pem_2_br2
,
self
.
veth_br2_2_pem
)
disable_ipv6
=
True
)
# enable ip forwarding in router ns
nsp
=
NSPopen
(
rt_ipdb
.
nl
.
netns
,
[
"sysctl"
,
"-w"
,
"net.ipv4.ip_forward=1"
])
nsp
.
wait
();
nsp
.
release
()
# for each VM connecting to pem, there will be a corresponding veth connecting to the bridge
self
.
setup_br
(
self
.
br1
,
self
.
nsrtr_eth0_out
.
ifname
,
self
.
veth_pem_2_br1
,
self
.
veth_br1_2_pem
)
self
.
setup_br
(
self
.
br2
,
self
.
nsrtr_eth1_out
.
ifname
,
self
.
veth_pem_2_br2
,
self
.
veth_br2_2_pem
)
# load the program and configure maps
# load the program and configure maps
self
.
config_maps
()
self
.
config_maps
()
def
test_brb2
(
self
):
# ping
# ping
subprocess
.
call
([
"ip"
,
"netns"
,
"exec"
,
self
.
ns1
,
"ping"
,
self
.
vm2_ip
,
"-c"
,
"2"
]
)
nsp
=
NSPopen
(
ns1_ipdb
.
nl
.
netns
,
[
"ping"
,
self
.
vm2_ip
,
"-c"
,
"2"
]);
nsp
.
wait
();
nsp
.
release
(
)
# minimum one arp request/reply, 5 icmp request/reply
# one arp request/reply, 2 icmp request/reply per VM, total 6 packets per VM, 12 packets total
self
.
assertGreater
(
self
.
pem_stats
[
c_uint
(
0
)].
value
,
11
)
self
.
assertEqual
(
self
.
pem_stats
[
c_uint
(
0
)].
value
,
12
)
# iperf, run server on the background
nsp_server
=
NSPopen
(
ns2_ipdb
.
nl
.
netns
,
[
"iperf"
,
"-s"
,
"-xSC"
])
subprocess
.
Popen
([
"ip"
,
"netns"
,
"exec"
,
self
.
ns2
,
"iperf"
,
"-s"
,
"-xSCD"
])
sleep
(
1
)
sleep
(
1
)
subprocess
.
call
([
"ip"
,
"netns"
,
"exec"
,
self
.
ns1
,
"iperf"
,
"-c"
,
self
.
vm2_ip
,
"-t"
,
"1"
,
"-xSC"
])
nsp
=
NSPopen
(
ns1_ipdb
.
nl
.
netns
,
[
"iperf"
,
"-c"
,
self
.
vm2_ip
,
"-t"
,
"1"
,
"-xSC"
])
subprocess
.
call
([
"ip"
,
"netns"
,
"exec"
,
self
.
ns2
,
"killall"
,
"iperf"
])
nsp
.
wait
();
nsp
.
release
()
nsp_server
.
kill
();
nsp_server
.
wait
();
nsp_server
.
release
()
# netperf, run server on the background
nsp_server
=
NSPopen
(
ns2_ipdb
.
nl
.
netns
,
[
"netserver"
,
"-D"
])
subprocess
.
Popen
([
"ip"
,
"netns"
,
"exec"
,
self
.
ns2
,
"netserver"
])
sleep
(
1
)
sleep
(
1
)
subprocess
.
call
([
"ip"
,
"netns"
,
"exec"
,
self
.
ns1
,
"netperf"
,
"-l"
,
"1"
,
"-H"
,
self
.
vm2_ip
,
"--"
,
"-m"
,
"65160"
])
nsp
=
NSPopen
(
ns1_ipdb
.
nl
.
netns
,
[
"netperf"
,
"-l"
,
"1"
,
"-H"
,
self
.
vm2_ip
,
"--"
,
"-m"
,
"65160"
])
subprocess
.
call
([
"ip"
,
"netns"
,
"exec"
,
self
.
ns1
,
"netperf"
,
"-l"
,
"1"
,
"-H"
,
self
.
vm2_ip
,
"-t"
,
"TCP_RR"
])
nsp
.
wait
();
nsp
.
release
()
subprocess
.
call
([
"ip"
,
"netns"
,
"exec"
,
self
.
ns2
,
"killall"
,
"netserver"
])
nsp
=
NSPopen
(
ns1_ipdb
.
nl
.
netns
,
[
"netperf"
,
"-l"
,
"1"
,
"-H"
,
self
.
vm2_ip
,
"-t"
,
"TCP_RR"
])
nsp
.
wait
();
nsp
.
release
()
# cleanup, tear down the veths and namespaces
nsp_server
.
kill
();
nsp_server
.
wait
();
nsp_server
.
release
()
subprocess
.
call
([
"ip"
,
"link"
,
"del"
,
self
.
veth_br1_2_pem
])
subprocess
.
call
([
"ip"
,
"link"
,
"del"
,
self
.
veth_br2_2_pem
])
finally
:
subprocess
.
call
([
"ip"
,
"link"
,
"del"
,
self
.
br1
])
if
self
.
br1
in
ipdb
.
interfaces
:
ipdb
.
interfaces
[
self
.
br1
].
remove
().
commit
()
subprocess
.
call
([
"ip"
,
"link"
,
"del"
,
self
.
br2
])
if
self
.
br2
in
ipdb
.
interfaces
:
ipdb
.
interfaces
[
self
.
br2
].
remove
().
commit
()
subprocess
.
call
([
"ip"
,
"netns"
,
"del"
,
self
.
ns1
])
if
self
.
veth_pem_2_br1
in
ipdb
.
interfaces
:
ipdb
.
interfaces
[
self
.
veth_pem_2_br1
].
remove
().
commit
()
subprocess
.
call
([
"ip"
,
"netns"
,
"del"
,
self
.
ns2
])
if
self
.
veth_pem_2_br2
in
ipdb
.
interfaces
:
ipdb
.
interfaces
[
self
.
veth_pem_2_br2
].
remove
().
commit
()
subprocess
.
call
([
"ip"
,
"netns"
,
"del"
,
self
.
ns_router
])
sim
.
release
()
ipdb
.
release
()
if
__name__
==
"__main__"
:
if
__name__
==
"__main__"
:
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a 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