~ubuntu-branches/ubuntu/utopic/exabgp/utopic

« back to all changes in this revision

Viewing changes to lib/exabgp/bgp/neighbor.py

  • Committer: Package Import Robot
  • Author(s): Henry-Nicolas Tourneur
  • Date: 2014-03-08 19:07:00 UTC
  • mfrom: (1.1.8)
  • Revision ID: package-import@ubuntu.com-20140308190700-xjbibpg1g6001c9x
Tags: 3.3.1-1
* New upstream release
* Bump python minimal required version (2.7)
* Closes: #726066 Debian packaging improvements proposed by Vincent Bernat
* Closes: #703774 not existent rundir (/var/run/exabgp) after reboot

Show diffs side-by-side

added added

removed removed

Lines of Context:
6
6
Copyright (c) 2009-2013 Exa Networks. All rights reserved.
7
7
"""
8
8
 
 
9
from collections import deque
 
10
 
9
11
from exabgp.protocol.family import AFI
 
12
 
10
13
from exabgp.bgp.message.open.holdtime import HoldTime
11
14
from exabgp.bgp.message.open.capability import AddPath
12
 
from exabgp.bgp.message.update.attribute.id import AttributeID
13
 
 
14
 
from exabgp.structure.api import APIOptions
15
 
 
16
 
from exabgp.rib.watchdog import Watchdog
17
 
 
18
 
from exabgp.structure.log import Logger
 
15
 
 
16
from exabgp.reactor.api.encoding import APIOptions
 
17
 
 
18
from exabgp.rib import RIB
19
19
 
20
20
# The definition of a neighbor (from reading the configuration)
21
21
class Neighbor (object):
22
 
        # This need to be global, all neighbor share the same data !
23
 
        # It allows us to use the information when performing global routing table update calculation
24
 
        watchdog = Watchdog()
25
 
 
26
22
        def __init__ (self):
27
 
                self.logger = Logger()
 
23
                # self.logger should not be used here as long as we do use deepcopy as it contains a Lock
28
24
                self.description = ''
29
25
                self.router_id = None
30
26
                self.local_address = None
37
33
                self.md5 = None
38
34
                self.ttl = None
39
35
                self.group_updates = None
 
36
                self.flush = None
 
37
                self.adjribout = None
40
38
 
41
39
                self.api = APIOptions()
42
40
 
 
41
                self.passive = False
 
42
 
43
43
                # capability
44
44
                self.route_refresh = False
45
45
                self.graceful_restart = False
46
46
                self.multisession = None
47
47
                self.add_path = None
 
48
                self.aigp = None
48
49
 
49
50
                self._families = []
50
 
                self._routes = {}
 
51
                self.rib = None
 
52
 
 
53
                self.operational = None
 
54
                self.asm = dict()
 
55
 
 
56
                self.messages = deque()
 
57
                self.refresh = deque()
 
58
 
 
59
        def make_rib (self):
 
60
                self.rib = RIB(self.name(),self.adjribout,self._families)
 
61
 
 
62
        # will resend all the routes once we reconnect
 
63
        def reset_rib (self):
 
64
                self.rib.reset()
 
65
                self.messages = deque()
 
66
                self.refresh = deque()
 
67
 
 
68
        # back to square one, all the routes are removed
 
69
        def clear_rib (self):
 
70
                self.rib.clear()
 
71
                self.messages = deque()
 
72
                self.refresh = deque()
51
73
 
52
74
        def name (self):
53
75
                if self.multisession:
54
 
                        session = "/ ".join("%s-%s" % (afi,safi) for (afi,safi) in self.families())
 
76
                        session = '/'.join("%s-%s" % (afi.name(),safi.name()) for (afi,safi) in self.families())
55
77
                else:
56
78
                        session = 'in-open'
57
 
                return "%s local-ip %s local-as %s peer-as %s router-id %s family-allowed %s" % (self.peer_address,self.local_address,self.local_as,self.peer_as,self.router_id,session)
 
79
                return "neighbor %s local-ip %s local-as %s peer-as %s router-id %s family-allowed %s" % (self.peer_address,self.local_address,self.local_as,self.peer_as,self.router_id,session)
58
80
 
59
81
        def families (self):
60
82
                # this list() is important .. as we use the function to modify self._families
61
83
                return list(self._families)
62
84
 
63
 
        def every_routes (self):
64
 
                for family in list(self._routes.keys()):
65
 
                        for route in self._routes[family]:
66
 
                                yield route
67
 
 
68
 
        def routes (self):
69
 
                # This function returns a hash and not a list as "in" tests are O(n) with lists and O(1) with hash
70
 
                # and with ten thousands routes this makes an enormous difference (60 seconds to 2)
71
 
 
72
 
                def _routes (self):
73
 
                        for family in list(self._routes.keys()):
74
 
                                for route in self._routes[family]:
75
 
                                        yield route
76
 
 
77
 
                routes = {}
78
 
                for route in self.watchdog.filtered(_routes(self)):
79
 
                        routes[route.index()] = route
80
 
                return routes
81
 
 
82
85
        def add_family (self,family):
 
86
                # the families MUST be sorted for neighbor indexing name to be predictable for API users
83
87
                if not family in self.families():
84
 
                        self._families.append(family)
 
88
                        afi,safi = family
 
89
                        d = dict()
 
90
                        d[afi] = [safi,]
 
91
                        for afi,safi in self._families:
 
92
                                d.setdefault(afi,[]).append(safi)
 
93
                        self._families = [(afi,safi) for afi in sorted(d) for safi in sorted(d[afi])]
85
94
 
86
 
        def remove_family_and_routes (self,family):
 
95
        def remove_family (self,family):
87
96
                if family in self.families():
88
97
                        self._families.remove(family)
89
 
                        if family in self._routes:
90
 
                                del self._routes[family]
91
 
 
92
 
        def add_route (self,route):
93
 
                self.watchdog.integrate(route)
94
 
                self._routes.setdefault((route.nlri.afi,route.nlri.safi),set()).add(route)
95
 
 
96
 
        def remove_route (self,route):
97
 
                try :
98
 
                        removed = False
99
 
                        routes = self._routes[(route.nlri.afi,route.nlri.safi)]
100
 
                        if route.nlri.afi in (AFI.ipv4,AFI.ipv6):
101
 
                                for r in list(routes):
102
 
                                        if r.nlri == route.nlri and \
103
 
                                           r.attributes.get(AttributeID.NEXT_HOP,None) == route.attributes.get(AttributeID.NEXT_HOP,None):
104
 
                                                routes.remove(r)
105
 
                                                removed = True
106
 
                        else:
107
 
                                routes.remove(route)
108
 
                                removed = True
109
 
                except KeyError:
110
 
                        removed = False
111
 
                return removed
112
 
 
113
 
        def set_routes (self,routes):
114
 
                # routes can be a generator for self.everyroutes, if we delete self._families
115
 
                # then the generator will return an empty content when ran, so we can not use add_route
116
 
                f = {}
117
 
                for route in routes:
118
 
                        f.setdefault((route.nlri.afi,route.nlri.safi),set()).add(route)
119
 
                self._routes = f
120
98
 
121
99
        def missing (self):
122
100
                if self.local_address is None: return 'local-address'
134
112
                        self.local_as == other.local_as and \
135
113
                        self.peer_address == other.peer_address and \
136
114
                        self.peer_as == other.peer_as and \
 
115
                        self.passive == other.passive and \
137
116
                        self.hold_time == other.hold_time and \
138
117
                        self.md5 == other.md5 and \
139
118
                        self.ttl == other.ttl and \
141
120
                        self.graceful_restart == other.graceful_restart and \
142
121
                        self.multisession == other.multisession and \
143
122
                        self.add_path == other.add_path and \
 
123
                        self.operational == other.operational and \
144
124
                        self.group_updates == other.group_updates and \
 
125
                        self.flush == other.flush and \
 
126
                        self.adjribout == other.adjribout and \
145
127
                        self.families() == other.families()
146
128
 
147
129
        def __ne__(self, other):
148
130
                return not self.__eq__(other)
149
131
 
150
 
        def pprint (self,with_routes=True):
151
 
                routes=''
152
 
                if with_routes:
153
 
                        routes += '\nstatic { '
154
 
                        for route in self.every_routes():
155
 
                                routes += '\n    %s' % route
156
 
                        route += '\n}'
 
132
        def pprint (self,with_changes=True):
 
133
                changes=''
 
134
                if with_changes:
 
135
                        changes += '\nstatic { '
 
136
                        for changes in self.rib.incoming.queued_changes():
 
137
                                changes += '\n    %s' % changes.extensive()
 
138
                        changes += '\n}'
157
139
 
158
140
                families = ''
159
141
                for afi,safi in self.families():
160
142
                        families += '\n    %s %s;' % (afi.name(),safi.name())
161
143
 
162
144
                _api  = []
163
 
                _api.extend(['    neighbor-changes;\n',] if self.api.neighbor_changes else [])
164
 
                _api.extend(['    receive-packets;\n',]  if self.api.receive_packets else [])
165
 
                _api.extend(['    send-packets;\n',]     if self.api.send_packets else [])
166
 
                _api.extend(['    receive-routes;\n',]   if self.api.receive_routes else [])
 
145
                _api.extend(['    neighbor-changes;\n',]    if self.api.neighbor_changes else [])
 
146
                _api.extend(['    receive-packets;\n',]     if self.api.receive_packets else [])
 
147
                _api.extend(['    send-packets;\n',]        if self.api.send_packets else [])
 
148
                _api.extend(['    receive-routes;\n',]      if self.api.receive_routes else [])
 
149
                _api.extend(['    receive-operational;\n',] if self.api.receive_operational else [])
167
150
                api = ''.join(_api)
168
151
 
169
152
                return """\
172
155
  router-id %s;
173
156
  local-address %s;
174
157
  local-as %s;
175
 
  peer-as %s;
 
158
  peer-as %s;%s
176
159
  hold-time %s;
177
 
%s%s%s
 
160
%s%s%s%s%s
178
161
  capability {
179
 
%s%s%s%s%s  }
 
162
%s%s%s%s%s%s%s  }
180
163
  family {%s
181
164
  }
182
165
  process {
188
171
        self.local_address,
189
172
        self.local_as,
190
173
        self.peer_as,
 
174
        '\n  passive;\n' if self.passive else '',
191
175
        self.hold_time,
192
176
        '  group-updates: %s;\n' % self.group_updates if self.group_updates else '',
 
177
        '  auto-flush: %s;\n' % 'true' if self.flush else 'false',
 
178
        '  adj-rib-out: %s;\n' % 'true' if self.adjribout else 'false',
193
179
        '  md5: %d;\n' % self.ttl if self.ttl else '',
194
180
        '  ttl-security: %d;\n' % self.ttl if self.ttl else '',
195
181
        '    asn4 enable;\n' if self.asn4 else '    asn4 disable;\n',
197
183
        '    graceful-restart %s;\n' % self.graceful_restart if self.graceful_restart else '',
198
184
        '    add-path %s;\n' % AddPath.string[self.add_path] if self.add_path else '',
199
185
        '    multi-session;\n' if self.multisession else '',
 
186
        '    operational;\n' if self.operational else '',
 
187
        '    aigp;\n' if self.aigp else '',
200
188
        families,
201
189
        api,
202
 
        routes
 
190
        changes
203
191
)
204
192
 
205
193
        def __str__ (self):