Statistics
| Branch: | Revision:

iof-tools / confFileGenerator / Node.py @ 163b30ce

History | View | Annotate | Download (6.79 KB)

1
#!/usr/bin/env python
2
# -*- coding: utf-8 -*-
3

    
4
# This program is free software: you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation, either version 3 of the License, or
7
# (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License
15
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
#
17
# Copyright (C) 2019  Mattia Milani <mattia.milani@studenti.unitn.it>
18

    
19
import ipaddress
20
from os.path import join
21

    
22
from constants import *
23
import os.path
24

    
25

    
26
BRIDGE = "br-iof"
27
BRIDGE_CONF = """
28
exists=`brctl show | grep {bridge}`
29
if [ -z "$exists" ]; then
30
    brctl addbr {bridge}
31
fi
32
brctl stp   {bridge} off
33
ip link set dev {bridge} up
34
""".format(bridge=BRIDGE)
35

    
36
NS_CONF = """
37
ip netns add ns{host}
38
ip netns exec ns{host} ip link set lo up
39
"""
40

    
41
TAP_CONF = """
42
# create a port pair
43
ip link add tap{host} type veth peer name br-tap{host}
44
# attach one side to linuxbridge
45
brctl addif {bridge} br-tap{host}
46
# attach the other side to namespace
47
ip link set tap{host} netns ns{host}
48
# set the ports to up
49
ip netns exec ns{host} ip link set dev tap{host} up
50
ip link set dev br-tap{host} up
51
"""
52

    
53
IP_CONF = """
54
ip netns exec ns{host} ip addr add {ip}/30 dev tap{host}
55
"""
56

    
57
IF_BRIDGE = """
58
ip link set {interface} up
59
brctl addif {bridge} {interface}
60
"""
61

    
62

    
63
class Node:
64
    nodeIpAddr_network = ipaddress.ip_network(u'200.0.0.0/8')
65
    counter_node = 1
66
    # ATTENTION if you would like to change the network 100.0.0.0/8 also change it in the conf file commonFilters.conf
67
    # otherwise the configuration probably would drop all update packets.
68
    nodeIpNetworks_network = list(ipaddress.ip_network(u'100.0.0.0/8').subnets(new_prefix=24))
69
    counter_networks = 1
70
    ClientList = []
71

    
72
    def __init__(self, name, node_type, out_folder, mrai='0',
73
                 interface="enp0s9"):
74
        self.name = name
75
        self.type = node_type
76
        self.mrai = int(float(mrai)*1000)
77
        self.intf = interface
78

    
79
        if self.type == "C":
80
            Node.ClientList.append(int(self.name)+1)
81

    
82
        self.outFolder = out_folder
83
        self.mainOutFileName = "bgp_h_" + str(self.name) + ".conf"
84
        self.sessionExporterFile_name = "bgpSessionExporter_h_" + str(name) + ".conf"
85
        if Node.counter_node < Node.nodeIpAddr_network.num_addresses - 1:
86
            self.router_addr = Node.nodeIpAddr_network[Node.counter_node]
87
            Node.counter_node += 1
88
        else:
89
            raise ValueError('No more addresses for routers')
90

    
91
        # Templates bases
92
        with open(BIRD_TEMPLATE_PATH, "r") as bird_file:
93
            self.bird_template = bird_file.read()
94
        with open(BGP_SESSION_EXPORTER_TEMPLATE_PATH, "r") as bgp_file:
95
            self.bgp_session_exporter = bgp_file.read()
96

    
97
        self.mainOutFile = open(self.outFolder + self.mainOutFileName, 'w+')
98
        self.sessionExporterFile = None
99
        self.exporting_proto_name = "static_bgp"
100
        self.exportedNetworks = []
101
        self.exportedNetworks_str = ""
102
        self.log_file_name = "log_h_" + str(self.name) + ".log"
103

    
104
        self.eth_dict = {}
105
        self.customer = {}
106
        self.peer = {}
107
        self.servicer = {}
108

    
109
        self.write_main_file()
110

    
111
    def __str__(self):
112
        return "{" + str(self.name) + "," + str(self.router_addr) + "}"
113

    
114
    def add_customer(self, node):
115
        self.customer[node.name] = node
116

    
117
    def add_peer(self, node):
118
        self.peer[node.name] = node
119

    
120
    def add_servicer(self, node):
121
        self.servicer[node.name] = node
122

    
123
    def get_customers_addresses(self):
124
        addr_list = []
125
        for node in self.customer.values():
126
            addr_list.append(str(node.get_external_addr(self)))
127
        return addr_list
128

    
129
    def add_addr_to_export(self):
130
        if Node.counter_networks < len(Node.nodeIpNetworks_network):
131
            self.exportedNetworks.append(Node.nodeIpNetworks_network[Node.counter_networks])
132
            Node.counter_networks += 1
133
        else:
134
            raise ValueError('No more networks free')
135
        self.delete_export_file()
136

    
137
        self.exportedNetworks_str += "route " + str(self.exportedNetworks[-1]) + " via \"lo\";\n\t\t\t"
138

    
139
        self.write_export_file()
140
        self.include_in_main(self.sessionExporterFile_name)
141

    
142
    def write_main_file(self):
143
        # Write the template inside the file
144
        open(self.outFolder + self.log_file_name, "a").close()
145
        self.mainOutFile.write(
146
            self.bird_template.format(log_file_path="./"+self.log_file_name, log_mode=LOG_MODE,
147
                                      dbg_mode=DBG_MODE, dbg_commands_mode=DBG_COMMANDS_MODE, addr=self.router_addr,
148
                                      kernel_conf_path=KERNEL_CONF_PATH,
149
                                      direct_conf_path=DIRECT_CONF_PATH,
150
                                      device_conf_path=DEVICE_CONF_PATH,
151
                                      filter_conf_path=FILTER_CONF_PATH,
152
                                      bgp_session_export_path="", bgp_session_path=""))
153

    
154
    def write_network_configuration(self):
155
        host = self.name
156
        output = "{}_conf.sh".format(host)
157
        # TODO: before this: assign this AS to one testbed node
158
        # TODO: read interface name from device configuration
159
        with open(join(self.outFolder, output), "w") as out_file:
160
            out_file.write(BRIDGE_CONF)
161
            out_file.write(NS_CONF.format(host=host))
162
            out_file.write(TAP_CONF.format(host=host, bridge=BRIDGE))
163
            out_file.write(IF_BRIDGE.format(bridge=BRIDGE, interface=self.intf))
164
            for _,ip in self.eth_dict.items():
165
                out_file.write(IP_CONF.format(host=host, ip=str(ip)))
166

    
167
    def delete_export_file(self):
168
        if os.path.isfile(self.outFolder + self.sessionExporterFile_name):
169
            os.remove(self.outFolder + self.sessionExporterFile_name)
170

    
171
    def write_export_file(self):
172
        self.sessionExporterFile = open(self.outFolder + self.sessionExporterFile_name, "w+")
173
        self.sessionExporterFile.write(self.bgp_session_exporter.format(session_protocol_name=self.exporting_proto_name,
174
                                                                        addr_to_export=self.exportedNetworks_str))
175

    
176
    def include_in_main(self, file_name):
177
        self.mainOutFile.write("include  \"./" + file_name + "\";\n")
178

    
179
    def set_new_external_addr(self, neighbor_node, addr):
180
        self.eth_dict[str(neighbor_node.name)] = addr
181

    
182
    def get_external_addr(self, neighbor_node):
183
        if str(neighbor_node.name) in self.eth_dict.keys():
184
            return self.eth_dict[str(neighbor_node.name)]
185
        return None