Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
__pycache__
*.bak
*.ntfl
*.topo.sh
example/*.py
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Nanonet

This repository implements the Nanonet tool, as described [here](https://segment-routing.org/index.php/Testing/Nanonet).

As Python 2 is now deprecated, it was updated in September 2024 to support Python 3 runtime.

## Running the example

- Check the contents of the NTFL example file
```
nanonet $ cat example/example.ntfl
A B 1 0.2 100000
A C 1 0.2 100000
B C 1 0.2 100000
```

- Generate a topology out of this file:
```
nanonet $ ./tools/ntfl2topo.sh example/example.ntfl Test > example/example.py
```

- Create a deployment script out of the topology:
```
nanonet $ ./build example/example.py Test
# Building topology...
# Assigning prefixes...
# Running dijkstra... (3 nodes)
# Running dijkstra for node B (1/3)
# Running dijkstra for node C (2/3)
# Running dijkstra for node A (3/3)
nanonet $
```

You obtain a file named Test.topo.sh that contains all the commands to execute to deploy the topology on linux.

2 changes: 1 addition & 1 deletion addr.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def __init__(self, net, mask, submask):
self.idx_low = self.submask/8 - 1

def next_net(self):
i = self.idx_low
i = int(self.idx_low)

while i >= self.idx_high:
if self.curnet[i] == 0xff:
Expand Down
6 changes: 3 additions & 3 deletions build
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ from net import *
# custom exec inspired by mininet

def usage():
print 'Usage: %s topofile.py toponame [outdir]' % (sys.argv[0])
print('Usage: %s topofile.py toponame [outdir]' % (sys.argv[0]))
sys.exit(-1)

if len(sys.argv) < 3 or len(sys.argv) > 4:
Expand All @@ -23,8 +23,8 @@ topos = {}
sys.path.append('.')

customs = {}
execfile(sys.argv[1], customs, customs)
for name, val in customs.iteritems():
exec(compile(open(sys.argv[1], "rb").read(), sys.argv[1], 'exec'), customs, customs)
for name, val in customs.items():
if name == 'topos':
globals()['topos'].update(val)
else:
Expand Down
Empty file added example/.gitkeep
Empty file.
3 changes: 3 additions & 0 deletions example/example.ntfl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
A B 1 0.2 100000
A C 1 0.2 100000
B C 1 0.2 100000
16 changes: 8 additions & 8 deletions net.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,22 +40,22 @@ def assign(self):
# print e.port2
# print 'For port1 %d and port2 %d' % (e.port1, e.port2)

e.node1.intfs_addr[e.port1] = socket.inet_ntop(socket.AF_INET6, str(a1))+'/'+str(self.linknet.submask)
e.node2.intfs_addr[e.port2] = socket.inet_ntop(socket.AF_INET6, str(a2))+'/'+str(self.linknet.submask)
e.node1.intfs_addr[e.port1] = socket.inet_ntop(socket.AF_INET6, a1)+'/'+str(self.linknet.submask)
e.node2.intfs_addr[e.port2] = socket.inet_ntop(socket.AF_INET6, a2)+'/'+str(self.linknet.submask)

for n in self.topo.nodes:
enet = self.loopnet.next_net()
enet[-1] = 1

n.addr = socket.inet_ntop(socket.AF_INET6, str(enet))+'/'+str(self.loopnet.submask)
n.addr = socket.inet_ntop(socket.AF_INET6, enet)+'/'+str(self.loopnet.submask)

def start(self, netname=None):
print '# Building topology...'
print('# Building topology...')
self.topo.build()
print '# Assigning prefixes...'
print('# Assigning prefixes...')
self.assign()

print '# Running dijkstra... (%d nodes)' % len(self.topo.nodes)
print('# Running dijkstra... (%d nodes)' % len(self.topo.nodes))
self.topo.compute()

if netname is not None:
Expand Down Expand Up @@ -105,7 +105,7 @@ def dump_commands(self, wr=(lambda x: self.call(x)), noroute=False):

if not noroute:
for n in self.topo.nodes:
for dst in n.routes.keys():
for dst in list(n.routes.keys()):
rts = n.routes[dst]
laddr = n.addr.split('/')[0]
if len(rts) == 1:
Expand All @@ -120,7 +120,7 @@ def dump_commands(self, wr=(lambda x: self.call(x)), noroute=False):
for c in host_cmd:
wr('%s' % c)

for n in node_cmd.keys():
for n in list(node_cmd.keys()):
wr('ip netns exec %s bash -c \'%s\'' % (n.name, "; ".join(node_cmd[n])))

def igp_prepare_link_down(self, name1, name2):
Expand Down
6 changes: 3 additions & 3 deletions node.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def __init__(self, name):
self.routes = {}

def add_route(self, r):
if r.dst not in self.routes.keys():
if r.dst not in list(self.routes.keys()):
self.routes[r.dst] = [r]
else:
self.routes[r.dst].append(r)
Expand Down Expand Up @@ -255,7 +255,7 @@ def get_nh_from_paths(self, paths):
def compute_node(self, n):
n.routes = {}
dist, path = self.dijkstra(n)
for t in dist.keys():
for t in list(dist.keys()):
if len(path[t]) == 0:
continue
nh = self.get_nh_from_paths(path[t])
Expand All @@ -268,6 +268,6 @@ def compute_node(self, n):
def compute(self):
cnt = 0
for n in self.nodes:
print '# Running dijkstra for node %s (%d/%d)' % (n.name, cnt+1, len(self.nodes))
print('# Running dijkstra for node %s (%d/%d)' % (n.name, cnt+1, len(self.nodes)))
self.compute_node(n)
cnt += 1