forked from NeST-for-Linux/NeST-for-Linux
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathns_helper.py
More file actions
171 lines (151 loc) · 5.11 KB
/
ns_helper.py
File metadata and controls
171 lines (151 loc) · 5.11 KB
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
##########################################
# Note: This script should be run as root
##########################################
import os
import subprocess
# TODO: This module needs to be tested; each function should be seperately tested
def exec_subprocess(cmd, block = True):
temp = subprocess.Popen(cmd.split())
if block:
temp.communicate()
else:
pass
############################################
# CONVENTION:
# - In parameter list, namespace
# names come before interface names.
# - Peers are entities at the ends points of
# the network.
# - Router connects atleast 2 hosts.
# - Host represents either peer or router
# based on context.
############################################
class Error(Exception):
"""Base class for other exceptions"""
pass
class NamespaceAlreadyExists(Error):
"""Raised when the given namespace name
to be added already exists"""
pass
def create_ns(ns_name):
"""
Create namespace with name `ns_name`
if it doesn't already exist
Delt namespace with name `ns_name`
if it doesn't already exist
"""
# try
# if os.path.exist(/vard/netns/ns_name):
# raise NamespaceAlreadyExists
# else:
exec_subprocess('ip netns add ' + ns_name)
# except NamespaceAlreadyExists:
# print("The given namespace already exists")
def delete_ns(ns_name):
"""
Drops the namespace with name `ns_name`
if it already exists.
"""
exec_subprocess('ip netns del ' + ns_name)
def en_ip_forwarding(ns_name):
"""
Enables ip forwarding in the namespace
`ns_name`. Used for routers
"""
exec_subprocess('ip netns exec ' + ns_name + ' sysctl -w net.ipv4.ip_forward=1')
#TODO: delete a veth
def create_veth(dev_name1, dev_name2):
"""
Create a veth interfaces with endpoints
`dev_name1` and `dev_name2`
"""
exec_subprocess('ip link add ' + dev_name1 +' type veth peer name ' + dev_name2)
def add_int_to_ns(ns_name, dev_name):
"""
Add interface `dev_name` to namespace `ns_name`
"""
exec_subprocess('ip link set ' + dev_name + ' netns ' + ns_name)
def set_int_up(ns_name, dev_name):
"""
Set interface `dev_name` in namespace `ns_name` to up
"""
exec_subprocess('ip netns exec ' + ns_name + ' ip link set dev ' + dev_name + ' up')
# Use this function for `high level convinience`
def setup_veth(ns_name1, ns_name2, dev_name1, dev_name2):
"""
Sets up veth connection with interafaces `dev_name1` and
`dev_name2` associated with namespaces `ns_name1` and
`ns_name2` respectively. The interfaces are set up as well.
"""
create_veth(dev_name1, dev_name2)
add_int_to_ns(ns_name1, dev_name1)
add_int_to_ns(ns_name2, dev_name2)
set_int_up(ns_name1, dev_name1)
set_int_up(ns_name2, dev_name2)
def create_peer(peer_name):
"""
Creates a peer with the name `peer_name` and adds it to
the existing topology.
"""
create_ns(peer_name)
def create_router(peer_name):
"""
Creates a peer with the name `peer_name` and adds it to
the existing topology.
"""
create_ns(peer_name)
en_ip_forwarding(peer_name)
def connect(peer_name=None, router_name1=None, router_name2=None):
"""
Connects two namespaces(a peer with a router or two routers) and
returns the created interface names
"""
if(peer_name):
peer_int = peer_name + '-' + router_name1
router_int = router_name1 + '-' + peer_name
setup_veth(peer_name, router_name1, peer_int, router_int)
return (peer_int, router_int)
else:
router1_int = router_name1 + '-' + router_name2
router2_int = router_name2 + '-' + router_name1
setup_veth(router_name1, router_name2, router1_int, router2_int)
return (router1_int, router2_int)
def assign_ip(host_name, dev_name, ip_address):
"""
Assigns ip address `ip_address` to interface
`dev_name` in host `host_name`.
"""
#TODO: Support for ipv6
exec_subprocess('ip netns exec ' + host_name + ' ip address add ' + ip_address + ' dev ' + dev_name)
def add_route(host_name, dest_ip, next_hop_ip, via_int):
"""
Adds a route in routing table of `host_name`.
`dest_ip` is the destination ip for the route.
`next_hop_ip` is the IP of the very next device
(next hop) in the route.
`via_int` is the corresponding interface in the
host.
"""
exec_subprocess('ip netns exec {} ip route add {} via {} dev {}'.format(host_name, dest_ip, next_hop_ip, via_int))
# Only bandwith and latency is considered
# Assuming tc on egress
# Using Netem
def add_traffic_control(host_name, dev_name, rate, latency):
"""
Add traffic control to `host_name`.
`rate` of the bandwidth
`latency` of the link
"""
exec_subprocess('ip netns exec {} tc qdisc add dev {} root netem rate {} latency {}'.format(host_name, dev_name, rate, latency))
if __name__ == '__main__':
n1 = 'red'
n2 = 'blue'
n3 = 'green'
n4 = 'pink'
# create_ns(n1)
# create_ns(n2)
# setup_veth(n1, n2, i1, i2)
create_peer(n3)
create_router(n4)
(int1, int2) = connect(peer_name=n3, router_name1=n4)
assign_ip(n3, int1, '10.0.1.1/24')