blob: 4c89e48d4d0c56042706dad3e79cc068d0ce1db0 [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
24from igraph import *
25from mininet.log import info
26
27
28class LinkInfo:
29 """
30 This class is used to encapsule link information (IP and interface names).
31 """
32
33 def __init__(self, start_intf_name, start_ip, end_intf_name, end_ip):
34 self.start_intf_name = start_intf_name
35 self.start_intf_ip = start_ip
36 self.end_intf_name = end_intf_name
37 self.end_ip = end_ip
38
39
40class IPRoutingHelper:
41 """The routing helper allows to run IP-based evaluations with Mini-NDN. It configures static IP
42 routes to all nodes, which means that all nodes can reach all other nodes in the network
43 reachable, even when relaying is required.
44
45 Usage from Experiment folder: `IPRoutingHelper.calcAllRoutes(self.net)`
46 """
47
48 @staticmethod
49 def findLinkInformation(links, first_node, second_node):
50 """ This method returns link information of a link connecting two nodes.
51
52 :param links: All links in the emulation topology
53 :param first_node: Current node which is looked at
54 :param second_node: Target node (neighbour of first_node)
55 :return: Link information as LinkInfo object, or returns null None if the
56 nodes are not directly connected
57 """
58 for link in links:
59 if link.intf1.node.name == first_node and link.intf2.node.name == second_node:
60 return LinkInfo(link.intf1.name, link.intf1.ip, link.intf2.name, link.intf2.ip)
61 elif link.intf2.node.name == first_node and link.intf1.node.name == second_node:
62 return LinkInfo(link.intf2.name, link.intf2.ip, link.intf1.name, link.intf1.ip)
63
64 return None
65
66 @staticmethod
67 def calcAllRoutes(net):
68 """ Configures IP routes between all nodes in the emulation topology. This is done in three
69 steps:
70
71 1) IP forwarding is enabled on all nodes
72 2) The igraph lib is used to calculate all shortest paths between the nodes
73 3) Route add commands are used to actually configure the ip routes
74
75 :param net:
76 """
77
78 mini_nodes = net.hosts
79 mini_links = net.links
80
81 # Enabling IP forwaring on all nodes
82 info("Configure IP forwarding on all nodes\n")
83 for node in mini_nodes:
84 node.cmd("sysctl -w net.ipv4.ip_forward=1")
85
86 # Calculate igraph to calculate all shortest paths between nodes
87 node_names = [node.name for node in mini_nodes]
88 links = []
89 for link in mini_links:
90 links.append((link.intf1.node.name, link.intf2.node.name))
91 links.append((link.intf2.node.name, link.intf1.node.name))
92
93 networkGraph = Graph()
94 networkGraph = networkGraph.as_directed()
95 for node in node_names:
96 networkGraph.add_vertex(node)
97 for (a, b) in links:
98 networkGraph.add_edges([(a, b), (b, a)])
99
100 named_paths = []
101 for from_node in node_names:
102 for to_node in node_names:
103 if from_node != to_node:
104 paths = networkGraph.get_all_shortest_paths(from_node, to_node)
105 if len(paths) == 0:
106 continue
107 shortest_path = paths[0]
108 shortest_path_with_nodenames = []
109 for node in shortest_path:
110 shortest_path_with_nodenames.append(networkGraph.vs["name"][node])
111 named_paths.append(shortest_path_with_nodenames)
112
113 # Iterate over all paths and configure the routes using the "route add"
114 info("Configure routes on all nodes\n")
115 for path in named_paths:
116 start_node = path[0]
117 end_node = path[-1]
118 mini_start = net.get(start_node)
119 mini_end = net.get(end_node)
120
121 link_info = IPRoutingHelper.findLinkInformation(mini_links, path[0], path[1])
122 start_intf = link_info.start_intf_name
123
124 for intf in mini_end.intfs:
125 addr = mini_end.intfs[intf].ip
126 if len(path) == 2:
127 # For direct connection, configure exit interface
128 info("[{}] route add -host {} dev {}\n".format(start_node, addr, start_intf))
129 mini_start.cmd("route add -host {} dev {}".format(addr, start_intf))
130 elif len(path) > 2:
131 # For longer paths, configure next hop as gateway
132 gateway_ip = link_info.end_ip
133 info("[{}] route add -host {} dev {} gw {}\n"
134 .format(start_node, addr, start_intf, gateway_ip))
135 mini_start.cmd("route add -host {} dev {} gw {}"
136 .format(addr, start_intf, gateway_ip))