Statistics
| Branch: | Revision:

iof-tools / BGPpysim / util / node.py @ de0e8e06

History | View | Annotate | Download (5.43 KB)

1
from util.routing_table import RoutingTable as RT
2
from util.routing_table import Route
3
from util.myqueue import MyQueue as MyQueue
4
from collections import defaultdict
5
from prettytable import PrettyTable
6
from policy import policy
7
import json
8
import code  # code.interact(local=dict(globals(), **locals()))
9
from util.event_log import EventLog
10

    
11

    
12
class Node(object):
13

    
14
    def __init__(self, node_id, sim_dir, node_type='C', prefixes=[]):
15
        self.sim_dir = sim_dir
16
        self.ID = node_id
17
        self.nodeType = node_type
18
        self.RT = RT()
19
        self.rxQueue = MyQueue()
20
        self.neighs = defaultdict(dict)
21
        # self.policies?
22
        self.exportPrefixes = prefixes
23
        # MRAI da configurare, XdestXneigh
24
        self.events_memory = []
25
        self.configure()
26

    
27
    '''
28
    Configure ha 3 compiti:
29
    1. Far capire alla RT che sino i vicini del nodo, per poter
30
    settare gli MRAI x-VICINO, x-destinazione
31
    2. Mettere in canna i primi update da mandare, 
32
      relativi ai prefissi esportati da questo nodo.
33
      Trucco: si mettono gli exportPrefix inizialmente
34
      nella coda di ricezione
35
    3. inizializzare il file log (csv|json)?
36
    '''
37

    
38
    def configure(self):
39
        # far conoscere a RT i negihbour
40
        self.RT.set_neighbours(self.neighs)
41
        # autoricezione prefissi da esportare
42
        for prefix in self.exportPrefixes:
43
            route = Route(prefix, {'AS_PATH': ''})
44
            self_update = (self.ID, route)
45
            self.rxQueue.push(self_update)
46
        # apertura file di log
47
        self.logfile = open(self.sim_dir + "/" + self.ID + "_log.csv", 'a')
48
        self.logfile.write("TIME|EVENT_TYPE|PREFIX|AS_PATH"+'\n')
49

    
50
    def toString(self):
51
        s = PrettyTable()
52
        s.field_names = ["nID", "nTYPE", "NEIGHS", "expPREFIX"]
53
        neighPrint = {}
54
        for n in self.neighs:
55
            neighPrint[n]={}
56
            for k,v in self.neighs[n].items():
57
                if k in ['relation', 'mrai']:
58
                    neighPrint[n][k]=v
59
        s.add_row([self.ID, self.nodeType, '\n'.join(
60
            map(str, neighPrint.items())), ('\n').join(self.exportPrefixes)])
61
        print(s)
62

    
63
    def log(self, evlog):
64
        self.events_memory.append(evlog)
65
        #to_write = json.dumps(event_describer)
66
        self.logfile.write('|'.join([str(evlog.time), evlog.evType,
67
                                     evlog.prefix, evlog.as_path])+'\n')
68

    
69
        '''
70
        - route da annunciare
71
        - vicino a cui mandiamo l'annuncio
72
        '''
73

    
74
    def sendUpdate(self, route, neigh, time):
75
        #print(self.ID, ": sending Update")
76
        try:
77
            mrai = self.RT[route.prefix]['MRAIs'][neigh]
78
            if mrai <= time:  # mrai scaduto! ready2fire!
79
                self.really_send_update(route, neigh, time)
80
            else:
81
                pass  # just wait mrai to fire
82
        except KeyError:
83
            # MRAIs for the couple (prefix, neigh) not found!
84
            # assenza di MRAI per (prefix, neigh) ==> ready2fire
85
            raise Exception("\u001b[31m"+self.ID +
86
                            ": mrai not found for neigh "+neigh)
87

    
88
    def really_send_update(self, route, neigh, time):
89
        '''really send:
90
        1. mettere l'update nel bufferRX del vicino
91
        2. impostare l'MRAI per questa rotta con questo vicino
92
        3. flaggare la rotta come comunicata a questo vicino'''
93
        # 1.
94
        pyneigh = self.neighs[neigh]['pynode']
95
        rt4update = Route(route.prefix, {})
96
        rasp = route.as_path()
97
        newAS_PATH = rasp + ',' + self.ID if rasp != "" else self.ID 
98
        rt4update.attr['AS_PATH'] = newAS_PATH
99
        update = (self.ID, rt4update)
100
        pyneigh.rxQueue.push(update)
101
        # 2. and 3.
102
        #code.interact(local=dict(globals(), **locals()))
103
        self.RT[route.prefix]['MRAIs'][neigh] = time + self.neighs[neigh]['mrai']
104
        self.RT[route.prefix]['SHARED_FLAG'][neigh] = True
105

    
106
    def processRXupdates(self, time):
107
        #print(self.ID, ": processing Received Updates")
108
        while not self.rxQueue.isEmpty():
109
            update = self.rxQueue.pop()
110
            self.log(EventLog(time, 'UpdateRX',
111
                              update[1].prefix, update[1].as_path()))
112
            self.processUpdate(update, time)
113

    
114
    def processUpdate(self, update, time):
115
        sender, route = update
116
        route_preference = policy(self.ID, route)
117

    
118
        # Standard Bellman-Ford to update RT
119
        if route.prefix not in self.RT:
120
            self.RT.install_route(route, sender, route_preference, time)
121
        elif route.prefix in self.RT:
122
            current_preference = self.RT[route.prefix]['PREFERENCE']
123
            if route_preference > current_preference:
124
                self.RT.install_route(route, sender, route_preference, time)
125

    
126
        # Capire se ci sono aggiornamenti da propagare
127
        for neigh in self.neighs:
128
            myNeighIsMy = self.neighs[neigh]['relation']
129
            # vuol dire non gliela ho comunicata
130
            if self.RT[route.prefix]['SHARED_FLAG'][neigh] == False:
131
                # policy propagazione update in base a relazioni tra nodi e loro tipo...
132
                if myNeighIsMy == 'customer':
133
                    '''Da implementare anche, in futuro, la propgazione
134
                    nei seguenti casi:
135
                    - se ho imparato la rotta da un provider OR peer ==> manda ai miei customer
136
                    - se mi arriva da un customer ==> manda a tutti tranne a chi me l'ha mandata'''
137
                    self.sendUpdate(route, neigh, time)