blob: 8c2bddf1e98454bb8c6e35cd86f888e56a8cc57c [file] [log] [blame]
Philipp Moll61a2be82019-07-12 08:33:09 +02001# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2#
3# Copyright (C) 2015-2019, The University of Memphis,
4# Arizona Board of Regents,
5# Regents of the University of California.
6#
7# This file is part of Mini-NDN.
8# See AUTHORS.md for a complete list of Mini-NDN authors and contributors.
9#
10# Mini-NDN is free software: you can redistribute it and/or modify
11# it under the terms of the GNU General Public License as published by
12# the Free Software Foundation, either version 3 of the License, or
13# (at your option) any later version.
14#
15# Mini-NDN is distributed in the hope that it will be useful,
16# but WITHOUT ANY WARRANTY; without even the implied warranty of
17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18# GNU General Public License for more details.
19#
20# You should have received a copy of the GNU General Public License
21# along with Mini-NDN, e.g., in COPYING.md file.
22# If not, see <http://www.gnu.org/licenses/>.
23
Ashlesh Gawande6c86e302019-09-17 22:27:05 -050024from igraph import Graph
Philipp Moll61a2be82019-07-12 08:33:09 +020025from mininet.log import info
26
Ashlesh Gawande6c86e302019-09-17 22:27:05 -050027class LinkInfo(object):
Philipp Moll61a2be82019-07-12 08:33:09 +020028 """
29 This class is used to encapsule link information (IP and interface names).
30 """
31
32 def __init__(self, start_intf_name, start_ip, end_intf_name, end_ip):
33 self.start_intf_name = start_intf_name
34 self.start_intf_ip = start_ip
35 self.end_intf_name = end_intf_name
36 self.end_ip = end_ip
37
Ashlesh Gawande6c86e302019-09-17 22:27:05 -050038class IPRoutingHelper(object):
Philipp Moll61a2be82019-07-12 08:33:09 +020039 """The routing helper allows to run IP-based evaluations with Mini-NDN. It configures static IP
40 routes to all nodes, which means that all nodes can reach all other nodes in the network
41 reachable, even when relaying is required.
42
43 Usage from Experiment folder: `IPRoutingHelper.calcAllRoutes(self.net)`
44 """
45
46 @staticmethod
47 def findLinkInformation(links, first_node, second_node):
48 """ This method returns link information of a link connecting two nodes.
49
50 :param links: All links in the emulation topology
51 :param first_node: Current node which is looked at
52 :param second_node: Target node (neighbour of first_node)
53 :return: Link information as LinkInfo object, or returns null None if the
54 nodes are not directly connected
55 """
56 for link in links:
57 if link.intf1.node.name == first_node and link.intf2.node.name == second_node:
58 return LinkInfo(link.intf1.name, link.intf1.ip, link.intf2.name, link.intf2.ip)
59 elif link.intf2.node.name == first_node and link.intf1.node.name == second_node:
60 return LinkInfo(link.intf2.name, link.intf2.ip, link.intf1.name, link.intf1.ip)
61
62 return None
63
64 @staticmethod
65 def calcAllRoutes(net):
66 """ Configures IP routes between all nodes in the emulation topology. This is done in three
67 steps:
68
69 1) IP forwarding is enabled on all nodes
70 2) The igraph lib is used to calculate all shortest paths between the nodes
71 3) Route add commands are used to actually configure the ip routes
72
73 :param net:
74 """
75
76 mini_nodes = net.hosts
77 mini_links = net.links
78
79 # Enabling IP forwaring on all nodes
Ashlesh Gawande6c86e302019-09-17 22:27:05 -050080 info('Configure IP forwarding on all nodes\n')
Philipp Moll61a2be82019-07-12 08:33:09 +020081 for node in mini_nodes:
Ashlesh Gawande6c86e302019-09-17 22:27:05 -050082 node.cmd('sysctl -w net.ipv4.ip_forward=1')
Philipp Moll61a2be82019-07-12 08:33:09 +020083
84 # Calculate igraph to calculate all shortest paths between nodes
85 node_names = [node.name for node in mini_nodes]
86 links = []
87 for link in mini_links:
88 links.append((link.intf1.node.name, link.intf2.node.name))
89 links.append((link.intf2.node.name, link.intf1.node.name))
90
91 networkGraph = Graph()
92 networkGraph = networkGraph.as_directed()
93 for node in node_names:
94 networkGraph.add_vertex(node)
95 for (a, b) in links:
96 networkGraph.add_edges([(a, b), (b, a)])
97
98 named_paths = []
99 for from_node in node_names:
100 for to_node in node_names:
101 if from_node != to_node:
102 paths = networkGraph.get_all_shortest_paths(from_node, to_node)
103 if len(paths) == 0:
104 continue
105 shortest_path = paths[0]
106 shortest_path_with_nodenames = []
107 for node in shortest_path:
Ashlesh Gawande6c86e302019-09-17 22:27:05 -0500108 shortest_path_with_nodenames.append(networkGraph.vs['name'][node])
Philipp Moll61a2be82019-07-12 08:33:09 +0200109 named_paths.append(shortest_path_with_nodenames)
110
Ashlesh Gawande6c86e302019-09-17 22:27:05 -0500111 # Iterate over all paths and configure the routes using the 'route add'
112 info('Configure routes on all nodes\n')
Philipp Moll61a2be82019-07-12 08:33:09 +0200113 for path in named_paths:
114 start_node = path[0]
115 end_node = path[-1]
116 mini_start = net.get(start_node)
117 mini_end = net.get(end_node)
118
119 link_info = IPRoutingHelper.findLinkInformation(mini_links, path[0], path[1])
120 start_intf = link_info.start_intf_name
121
122 for intf in mini_end.intfs:
123 addr = mini_end.intfs[intf].ip
124 if len(path) == 2:
125 # For direct connection, configure exit interface
Ashlesh Gawande6c86e302019-09-17 22:27:05 -0500126 info('[{}] route add -host {} dev {}\n'.format(start_node, addr, start_intf))
127 mini_start.cmd('route add -host {} dev {}'.format(addr, start_intf))
Philipp Moll61a2be82019-07-12 08:33:09 +0200128 elif len(path) > 2:
129 # For longer paths, configure next hop as gateway
130 gateway_ip = link_info.end_ip
Ashlesh Gawande6c86e302019-09-17 22:27:05 -0500131 info('[{}] route add -host {} dev {} gw {}\n'
Philipp Moll61a2be82019-07-12 08:33:09 +0200132 .format(start_node, addr, start_intf, gateway_ip))
Ashlesh Gawande6c86e302019-09-17 22:27:05 -0500133 mini_start.cmd('route add -host {} dev {} gw {}'
Philipp Moll61a2be82019-07-12 08:33:09 +0200134 .format(addr, start_intf, gateway_ip))