-
Notifications
You must be signed in to change notification settings - Fork 0
/
router.bess
130 lines (104 loc) · 3.78 KB
/
router.bess
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# vim: syntax=py
import sys
def exit(code, msg):
print(msg)
sys.exit(code)
import os
def get_env(varname):
try:
var = os.environ[varname]
except KeyError:
exit(1, 'Empty env var {}'.format(varname))
else:
return var
from pyroute2 import IPDB
ipdb = IPDB()
def ips_by_interface(name):
return [ipobj[0] for ipobj in ipdb.interfaces[name]['ipaddr'].ipv4]
def mac_by_interface(name):
return int(ipdb.interfaces[name]['address'].replace(':', ''), 16)
def peer_by_interface(name):
try:
peer_idx = ipdb.interfaces[name]['link']
peer_name = ipdb.interfaces[peer_idx]['ifname']
except:
exit(2, 'veth interface {} does not exist'.format(name))
else:
return peer_name
import socket
def aton(ip):
return socket.inet_aton(ip)
# ====================================================
# Core Setup
# ====================================================
import psutil
bess.add_worker(wid=0, core=int(psutil.Process().cpu_affinity()[0]))
# ====================================================
# Port Setup
# ====================================================
ifname = get_env('IFNAME')
peer = peer_by_interface(ifname)
print('Setting up for port {}'.format(ifname))
intf_kern = PMDPort(name="intf_kern", vdev="net_af_packet0,iface={}".format(peer))
intf_dpdk = PMDPort(name="intf_dpdk", port_id=0)
# ====================================================
# Module Setup
# ====================================================
intf_kern_in::PortInc(port=intf_kern.name)
intf_dpdk_in::PortInc(port=intf_dpdk.name)
classify::BPF()
routes::IPLookup()
merge_intf_kern::Merge()
merge_intf_dpdk::Merge()
intf_kern_out::PortOut(port=intf_kern.name)
intf_dpdk_out::PortOut(port=intf_dpdk.name)
# ====================================================
# Processing pipeline
# ====================================================
# Classify traffic
# 1: Any traffic destined to me
# tcpdump -i foo 'dst host 198.19.0.1 or 198.18.0.1' -d
# (000) ldh [12]
# (001) jeq #0x800 jt 2 jf 4
# (002) ld [30]
# (003) jeq #0xc6130001 jt 9 jf 8
# (004) jeq #0x806 jt 6 jf 5
# (005) jeq #0x8035 jt 6 jf 10
# (006) ld [38]
# (007) jeq #0xc6130001 jt 9 jf 8
# (008) jeq #0xc6120001 jt 9 jf 10
# (009) ret #262144
# (010) ret #0
# 2: IP traffic to be routed
router_ips = ips_by_interface(ifname)
filter1 = {"priority": -1,
"filter": "dst host " + " or ".join(str(x) for x in router_ips), "gate": 1}
filter2 = {"priority": -2, "filter": "ip", "gate": 2}
classify.clear()
classify.add(filters=[filter1, filter2])
intf_dpdk_in -> classify
classify: 0 -> Sink()
classify: 1 -> merge_intf_kern -> intf_kern_out
classify: 2 -> routes
intf_kern_in -> merge_intf_dpdk -> intf_dpdk_out
# ====================================================
# Scheduler config
# ====================================================
# Limit scheduling slow path RX to 1000 times/second
bess.add_tc('schedule_limit',
policy='rate_limit',
resource='count',
limit={'count': 1000})
intf_kern_in.attach_task(parent='schedule_limit')
# ====================================================
# Dynamic config
# ====================================================
# Default route
srcmac = mac_by_interface(ifname)
routes.add(prefix='0.0.0.0', prefix_len=0, gate=0)
routes: 0 \
-> default_route::Update(fields=[{'offset': 0, 'size': 6, 'value': 0xdeadbeefdead},
{'offset': 6, 'size': 6, 'value': srcmac}]) \
-> merge_intf_dpdk
# Add routes and update dst/src MAC accordingly
# TODO - make this dynamic using pyroute2