backing up
[vsorcdistro/.git] / ryu / build / lib.linux-armv7l-2.7 / ryu / services / protocols / bgp / rtconf / neighbors.py
1 # Copyright (C) 2014 Nippon Telegraph and Telephone Corporation.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #    http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12 # implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15
16 """
17  Running or runtime configuration related to bgp peers/neighbors.
18 """
19 from abc import abstractmethod
20 import logging
21 import numbers
22
23 import netaddr
24
25 from ryu.lib import ip
26
27 from ryu.lib.packet.bgp import RF_IPv4_UC
28 from ryu.lib.packet.bgp import RF_IPv6_UC
29 from ryu.lib.packet.bgp import RF_IPv4_VPN
30 from ryu.lib.packet.bgp import RF_IPv6_VPN
31 from ryu.lib.packet.bgp import RF_L2_EVPN
32 from ryu.lib.packet.bgp import RF_IPv4_FLOWSPEC
33 from ryu.lib.packet.bgp import RF_IPv6_FLOWSPEC
34 from ryu.lib.packet.bgp import RF_VPNv4_FLOWSPEC
35 from ryu.lib.packet.bgp import RF_VPNv6_FLOWSPEC
36 from ryu.lib.packet.bgp import RF_L2VPN_FLOWSPEC
37 from ryu.lib.packet.bgp import RF_RTC_UC
38 from ryu.lib.packet.bgp import BGPOptParamCapabilityFourOctetAsNumber
39 from ryu.lib.packet.bgp import BGPOptParamCapabilityEnhancedRouteRefresh
40 from ryu.lib.packet.bgp import BGPOptParamCapabilityMultiprotocol
41 from ryu.lib.packet.bgp import BGPOptParamCapabilityRouteRefresh
42 from ryu.lib.packet.bgp import BGP_CAP_FOUR_OCTET_AS_NUMBER
43 from ryu.lib.packet.bgp import BGP_CAP_ENHANCED_ROUTE_REFRESH
44 from ryu.lib.packet.bgp import BGP_CAP_MULTIPROTOCOL
45 from ryu.lib.packet.bgp import BGP_CAP_ROUTE_REFRESH
46
47 from ryu.services.protocols.bgp.base import OrderedDict
48 from ryu.services.protocols.bgp.constants import STD_BGP_SERVER_PORT_NUM
49 from ryu.services.protocols.bgp.rtconf.base import ADVERTISE_PEER_AS
50 from ryu.services.protocols.bgp.rtconf.base import BaseConf
51 from ryu.services.protocols.bgp.rtconf.base import BaseConfListener
52 from ryu.services.protocols.bgp.rtconf.base import CAP_ENHANCED_REFRESH
53 from ryu.services.protocols.bgp.rtconf.base import CAP_FOUR_OCTET_AS_NUMBER
54 from ryu.services.protocols.bgp.rtconf.base import CAP_MBGP_IPV4
55 from ryu.services.protocols.bgp.rtconf.base import CAP_MBGP_IPV6
56 from ryu.services.protocols.bgp.rtconf.base import CAP_MBGP_VPNV4
57 from ryu.services.protocols.bgp.rtconf.base import CAP_MBGP_VPNV6
58 from ryu.services.protocols.bgp.rtconf.base import CAP_MBGP_EVPN
59 from ryu.services.protocols.bgp.rtconf.base import CAP_MBGP_IPV4FS
60 from ryu.services.protocols.bgp.rtconf.base import CAP_MBGP_IPV6FS
61 from ryu.services.protocols.bgp.rtconf.base import CAP_MBGP_VPNV4FS
62 from ryu.services.protocols.bgp.rtconf.base import CAP_MBGP_VPNV6FS
63 from ryu.services.protocols.bgp.rtconf.base import CAP_MBGP_L2VPNFS
64 from ryu.services.protocols.bgp.rtconf.base import CAP_REFRESH
65 from ryu.services.protocols.bgp.rtconf.base import CAP_RTC
66 from ryu.services.protocols.bgp.rtconf.base import compute_optional_conf
67 from ryu.services.protocols.bgp.rtconf.base import ConfigTypeError
68 from ryu.services.protocols.bgp.rtconf.base import ConfigValueError
69 from ryu.services.protocols.bgp.rtconf.base import ConfWithId
70 from ryu.services.protocols.bgp.rtconf.base import ConfWithIdListener
71 from ryu.services.protocols.bgp.rtconf.base import ConfWithStats
72 from ryu.services.protocols.bgp.rtconf.base import ConfWithStatsListener
73 from ryu.services.protocols.bgp.rtconf.base import HOLD_TIME
74 from ryu.services.protocols.bgp.rtconf.base import MAX_PREFIXES
75 from ryu.services.protocols.bgp.rtconf.base import MULTI_EXIT_DISC
76 from ryu.services.protocols.bgp.rtconf.base import RTC_AS
77 from ryu.services.protocols.bgp.rtconf.base import RuntimeConfigError
78 from ryu.services.protocols.bgp.rtconf.base import SITE_OF_ORIGINS
79 from ryu.services.protocols.bgp.rtconf.base import validate
80 from ryu.services.protocols.bgp.rtconf.base import validate_med
81 from ryu.services.protocols.bgp.rtconf.base import validate_soo_list
82 from ryu.services.protocols.bgp.utils.validation import is_valid_asn
83 from ryu.services.protocols.bgp.info_base.base import Filter
84 from ryu.services.protocols.bgp.info_base.base import PrefixFilter
85 from ryu.services.protocols.bgp.info_base.base import AttributeMap
86
87 LOG = logging.getLogger('bgpspeaker.rtconf.neighbor')
88
89 # Various neighbor settings.
90 REMOTE_AS = 'remote_as'
91 IP_ADDRESS = 'ip_address'
92 REMOTE_PORT = 'remote_port'
93 ENABLED = 'enabled'
94 CHANGES = 'changes'
95 LOCAL_ADDRESS = 'local_address'
96 LOCAL_PORT = 'local_port'
97 LOCAL_AS = 'local_as'
98 PEER_NEXT_HOP = 'peer_next_hop'
99 PASSWORD = 'password'
100 IN_FILTER = 'in_filter'
101 OUT_FILTER = 'out_filter'
102 IS_ROUTE_SERVER_CLIENT = 'is_route_server_client'
103 IS_ROUTE_REFLECTOR_CLIENT = 'is_route_reflector_client'
104 CHECK_FIRST_AS = 'check_first_as'
105 ATTRIBUTE_MAP = 'attribute_map'
106 IS_NEXT_HOP_SELF = 'is_next_hop_self'
107 CONNECT_MODE = 'connect_mode'
108 CONNECT_MODE_ACTIVE = 'active'
109 CONNECT_MODE_PASSIVE = 'passive'
110 CONNECT_MODE_BOTH = 'both'
111
112 # Default value constants.
113 DEFAULT_BGP_PORT = STD_BGP_SERVER_PORT_NUM
114 DEFAULT_CAP_GR_NULL = True
115 DEFAULT_CAP_REFRESH = True
116 DEFAULT_CAP_ENHANCED_REFRESH = False
117 DEFAULT_CAP_FOUR_OCTET_AS_NUMBER = True
118 DEFAULT_CAP_MBGP_IPV4 = True
119 DEFAULT_CAP_MBGP_IPV6 = False
120 DEFAULT_CAP_MBGP_VPNV4 = False
121 DEFAULT_CAP_MBGP_VPNV6 = False
122 DEFAULT_CAP_MBGP_EVPN = False
123 DEFAULT_CAP_MBGP_IPV4FS = False
124 DEFAULT_CAP_MBGP_IPV6FS = False
125 DEFAULT_CAP_MBGP_VPNV4FS = False
126 DEFAULT_CAP_MBGP_VPNV6FS = False
127 DEFAULT_CAP_MBGP_L2VPNFS = False
128 DEFAULT_HOLD_TIME = 40
129 DEFAULT_ENABLED = True
130 DEFAULT_CAP_RTC = False
131 DEFAULT_IN_FILTER = []
132 DEFAULT_OUT_FILTER = []
133 DEFAULT_IS_ROUTE_SERVER_CLIENT = False
134 DEFAULT_IS_ROUTE_REFLECTOR_CLIENT = False
135 DEFAULT_CHECK_FIRST_AS = False
136 DEFAULT_IS_NEXT_HOP_SELF = False
137 DEFAULT_CONNECT_MODE = CONNECT_MODE_BOTH
138
139 # Default value for *MAX_PREFIXES* setting is set to 0.
140 DEFAULT_MAX_PREFIXES = 0
141 DEFAULT_ADVERTISE_PEER_AS = False
142
143
144 @validate(name=ENABLED)
145 def validate_enabled(enabled):
146     if not isinstance(enabled, bool):
147         raise ConfigValueError(desc='Enable property is not an instance of '
148                                'boolean')
149     return enabled
150
151
152 @validate(name=CHANGES)
153 def validate_changes(changes):
154     for k, v in changes.items():
155         if k not in (MULTI_EXIT_DISC, ENABLED, CONNECT_MODE):
156             raise ConfigValueError(desc="Unknown field to change: %s" % k)
157
158         if k == MULTI_EXIT_DISC:
159             validate_med(v)
160         elif k == ENABLED:
161             validate_enabled(v)
162         elif k == CONNECT_MODE:
163             validate_connect_mode(v)
164     return changes
165
166
167 def valid_ip_address(addr):
168     if not ip.valid_ipv4(addr) and not ip.valid_ipv6(addr):
169         return False
170     return True
171
172
173 @validate(name=IP_ADDRESS)
174 def validate_ip_address(ip_address):
175     if not valid_ip_address(ip_address):
176         raise ConfigValueError(desc='Invalid neighbor ip_address: %s' %
177                                ip_address)
178     return str(netaddr.IPAddress(ip_address))
179
180
181 @validate(name=LOCAL_ADDRESS)
182 def validate_local_address(ip_address):
183     if not valid_ip_address(ip_address):
184         raise ConfigValueError(desc='Invalid local ip_address: %s' %
185                                ip_address)
186     return str(netaddr.IPAddress(ip_address))
187
188
189 @validate(name=PEER_NEXT_HOP)
190 def validate_next_hop(ip_address):
191     if not valid_ip_address(ip_address):
192         raise ConfigValueError(desc='Invalid next_hop ip_address: %s' %
193                                ip_address)
194     return str(netaddr.IPAddress(ip_address))
195
196
197 @validate(name=PASSWORD)
198 def validate_password(password):
199     return password
200
201
202 @validate(name=LOCAL_PORT)
203 def validate_local_port(port):
204     if not isinstance(port, numbers.Integral):
205         raise ConfigTypeError(desc='Invalid local port: %s' % port)
206     if port < 1025 or port > 65535:
207         raise ConfigValueError(desc='Invalid local port value: %s, has to be'
208                                ' between 1025 and 65535' % port)
209     return port
210
211
212 @validate(name=REMOTE_AS)
213 def validate_remote_as(asn):
214     if not is_valid_asn(asn):
215         raise ConfigValueError(desc='Invalid remote as value %s' % asn)
216     return asn
217
218
219 @validate(name=REMOTE_PORT)
220 def validate_remote_port(port):
221     if not isinstance(port, numbers.Integral):
222         raise ConfigTypeError(desc='Invalid remote port: %s' % port)
223     return port
224
225
226 def valid_prefix_filter(filter_):
227     policy = filter_.get('policy', None)
228     if policy == 'permit':
229         policy = PrefixFilter.POLICY_PERMIT
230     else:
231         policy = PrefixFilter.POLICY_DENY
232     prefix = filter_['prefix']
233     ge = filter_.get('ge', None)
234     le = filter_.get('le', None)
235     return PrefixFilter(prefix, policy, ge=ge, le=le)
236
237
238 PREFIX_FILTER = 'prefix_filter'
239
240 SUPPORTED_FILTER_VALIDATORS = {
241     PREFIX_FILTER: valid_prefix_filter
242 }
243
244
245 def valid_filter(filter_):
246     if isinstance(filter_, Filter):
247         return filter_
248
249     if not isinstance(filter_, dict):
250         raise ConfigTypeError(desc='Invalid filter: %s' % filter_)
251
252     if 'type' not in filter_:
253         raise ConfigTypeError(desc='Invalid filter: %s, needs \'type\' field'
254                               % filter_)
255
256     if not filter_['type'] in SUPPORTED_FILTER_VALIDATORS:
257         raise ConfigTypeError(desc='Invalid filter type: %s, supported filter'
258                               ' types are %s'
259                               % (filter_['type'],
260                                  list(SUPPORTED_FILTER_VALIDATORS.keys())))
261
262     return SUPPORTED_FILTER_VALIDATORS[filter_['type']](filter_)
263
264
265 def valid_attribute_map(attribute_map):
266     if not isinstance(attribute_map, AttributeMap):
267         raise ConfigTypeError(desc='Invalid AttributeMap: %s' % attribute_map)
268     else:
269         return attribute_map
270
271
272 @validate(name=IN_FILTER)
273 def validate_in_filters(filters):
274     return [valid_filter(filter_) for filter_ in filters]
275
276
277 @validate(name=OUT_FILTER)
278 def validate_out_filters(filters):
279     return [valid_filter(filter_) for filter_ in filters]
280
281
282 @validate(name=ATTRIBUTE_MAP)
283 def validate_attribute_maps(attribute_maps):
284     return [valid_attribute_map(attribute_map)
285             for attribute_map in attribute_maps]
286
287
288 @validate(name=IS_ROUTE_SERVER_CLIENT)
289 def validate_is_route_server_client(is_route_server_client):
290     if not isinstance(is_route_server_client, bool):
291         raise ConfigValueError(desc='Invalid is_route_server_client(%s)' %
292                                is_route_server_client)
293
294     return is_route_server_client
295
296
297 @validate(name=IS_ROUTE_REFLECTOR_CLIENT)
298 def validate_is_route_reflector_client(is_route_reflector_client):
299     if not isinstance(is_route_reflector_client, bool):
300         raise ConfigValueError(desc='Invalid is_route_reflector_client(%s)' %
301                                     is_route_reflector_client)
302
303     return is_route_reflector_client
304
305
306 @validate(name=CHECK_FIRST_AS)
307 def validate_check_first_as(check_first_as):
308     if not isinstance(check_first_as, bool):
309         raise ConfigValueError(desc='Invalid check_first_as(%s)' %
310                                check_first_as)
311
312     return check_first_as
313
314
315 @validate(name=IS_NEXT_HOP_SELF)
316 def validate_is_next_hop_self(is_next_hop_self):
317     if not isinstance(is_next_hop_self, bool):
318         raise ConfigValueError(desc='Invalid is_next_hop_self(%s)' %
319                                is_next_hop_self)
320
321     return is_next_hop_self
322
323
324 @validate(name=CONNECT_MODE)
325 def validate_connect_mode(mode):
326     if mode not in (CONNECT_MODE_ACTIVE,
327                     CONNECT_MODE_PASSIVE,
328                     CONNECT_MODE_BOTH):
329         raise ConfigValueError(desc='Invalid connect_mode(%s)' % mode)
330     return mode
331
332
333 class NeighborConf(ConfWithId, ConfWithStats):
334     """Class that encapsulates one neighbors' configuration."""
335
336     UPDATE_ENABLED_EVT = 'update_enabled_evt'
337     UPDATE_MED_EVT = 'update_med_evt'
338     UPDATE_CONNECT_MODE_EVT = 'update_connect_mode_evt'
339
340     VALID_EVT = frozenset([UPDATE_ENABLED_EVT, UPDATE_MED_EVT,
341                            UPDATE_CONNECT_MODE_EVT])
342     REQUIRED_SETTINGS = frozenset([REMOTE_AS, IP_ADDRESS])
343     OPTIONAL_SETTINGS = frozenset([CAP_REFRESH,
344                                    CAP_ENHANCED_REFRESH,
345                                    CAP_FOUR_OCTET_AS_NUMBER,
346                                    CAP_MBGP_IPV4, CAP_MBGP_IPV6,
347                                    CAP_MBGP_VPNV4, CAP_MBGP_VPNV6,
348                                    CAP_RTC, CAP_MBGP_EVPN,
349                                    CAP_MBGP_IPV4FS, CAP_MBGP_VPNV4FS,
350                                    CAP_MBGP_IPV6FS, CAP_MBGP_VPNV6FS,
351                                    CAP_MBGP_L2VPNFS,
352                                    RTC_AS, HOLD_TIME, REMOTE_PORT,
353                                    ENABLED, MULTI_EXIT_DISC, MAX_PREFIXES,
354                                    ADVERTISE_PEER_AS, SITE_OF_ORIGINS,
355                                    LOCAL_ADDRESS, LOCAL_PORT, LOCAL_AS,
356                                    PEER_NEXT_HOP, PASSWORD,
357                                    IN_FILTER, OUT_FILTER,
358                                    IS_ROUTE_SERVER_CLIENT,
359                                    IS_ROUTE_REFLECTOR_CLIENT,
360                                    CHECK_FIRST_AS,
361                                    IS_NEXT_HOP_SELF, CONNECT_MODE])
362
363     def __init__(self, **kwargs):
364         super(NeighborConf, self).__init__(**kwargs)
365
366     def _init_opt_settings(self, **kwargs):
367         self._settings[CAP_REFRESH] = compute_optional_conf(
368             CAP_REFRESH, DEFAULT_CAP_REFRESH, **kwargs)
369         self._settings[CAP_ENHANCED_REFRESH] = compute_optional_conf(
370             CAP_ENHANCED_REFRESH, DEFAULT_CAP_ENHANCED_REFRESH, **kwargs)
371         self._settings[CAP_FOUR_OCTET_AS_NUMBER] = compute_optional_conf(
372             CAP_FOUR_OCTET_AS_NUMBER,
373             DEFAULT_CAP_FOUR_OCTET_AS_NUMBER, **kwargs)
374         self._settings[CAP_MBGP_IPV4] = compute_optional_conf(
375             CAP_MBGP_IPV4, DEFAULT_CAP_MBGP_IPV4, **kwargs)
376         self._settings[CAP_MBGP_IPV6] = compute_optional_conf(
377             CAP_MBGP_IPV6, DEFAULT_CAP_MBGP_IPV6, **kwargs)
378         self._settings[CAP_MBGP_VPNV4] = compute_optional_conf(
379             CAP_MBGP_VPNV4, DEFAULT_CAP_MBGP_VPNV4, **kwargs)
380         self._settings[CAP_MBGP_EVPN] = compute_optional_conf(
381             CAP_MBGP_EVPN, DEFAULT_CAP_MBGP_EVPN, **kwargs)
382         self._settings[CAP_MBGP_VPNV6] = compute_optional_conf(
383             CAP_MBGP_VPNV6, DEFAULT_CAP_MBGP_VPNV6, **kwargs)
384         self._settings[CAP_MBGP_IPV4FS] = compute_optional_conf(
385             CAP_MBGP_IPV4FS, DEFAULT_CAP_MBGP_IPV4FS, **kwargs)
386         self._settings[CAP_MBGP_IPV6FS] = compute_optional_conf(
387             CAP_MBGP_IPV6FS, DEFAULT_CAP_MBGP_IPV6FS, **kwargs)
388         self._settings[CAP_MBGP_VPNV4FS] = compute_optional_conf(
389             CAP_MBGP_VPNV4FS, DEFAULT_CAP_MBGP_VPNV4FS, **kwargs)
390         self._settings[CAP_MBGP_VPNV6FS] = compute_optional_conf(
391             CAP_MBGP_VPNV6FS, DEFAULT_CAP_MBGP_VPNV6FS, **kwargs)
392         self._settings[CAP_MBGP_L2VPNFS] = compute_optional_conf(
393             CAP_MBGP_L2VPNFS, DEFAULT_CAP_MBGP_L2VPNFS, **kwargs)
394         self._settings[HOLD_TIME] = compute_optional_conf(
395             HOLD_TIME, DEFAULT_HOLD_TIME, **kwargs)
396         self._settings[ENABLED] = compute_optional_conf(
397             ENABLED, DEFAULT_ENABLED, **kwargs)
398         self._settings[MAX_PREFIXES] = compute_optional_conf(
399             MAX_PREFIXES, DEFAULT_MAX_PREFIXES, **kwargs)
400         self._settings[ADVERTISE_PEER_AS] = compute_optional_conf(
401             ADVERTISE_PEER_AS, DEFAULT_ADVERTISE_PEER_AS, **kwargs)
402         self._settings[IN_FILTER] = compute_optional_conf(
403             IN_FILTER, DEFAULT_IN_FILTER, **kwargs)
404         self._settings[OUT_FILTER] = compute_optional_conf(
405             OUT_FILTER, DEFAULT_OUT_FILTER, **kwargs)
406         self._settings[IS_ROUTE_SERVER_CLIENT] = compute_optional_conf(
407             IS_ROUTE_SERVER_CLIENT,
408             DEFAULT_IS_ROUTE_SERVER_CLIENT, **kwargs)
409         self._settings[IS_ROUTE_REFLECTOR_CLIENT] = compute_optional_conf(
410             IS_ROUTE_REFLECTOR_CLIENT,
411             DEFAULT_IS_ROUTE_REFLECTOR_CLIENT, **kwargs)
412         self._settings[CHECK_FIRST_AS] = compute_optional_conf(
413             CHECK_FIRST_AS, DEFAULT_CHECK_FIRST_AS, **kwargs)
414         self._settings[IS_NEXT_HOP_SELF] = compute_optional_conf(
415             IS_NEXT_HOP_SELF,
416             DEFAULT_IS_NEXT_HOP_SELF, **kwargs)
417         self._settings[CONNECT_MODE] = compute_optional_conf(
418             CONNECT_MODE, DEFAULT_CONNECT_MODE, **kwargs)
419         self._settings[REMOTE_PORT] = compute_optional_conf(
420             REMOTE_PORT, DEFAULT_BGP_PORT, **kwargs)
421
422         # We do not have valid default MED value.
423         # If no MED attribute is provided then we do not have to use MED.
424         # If MED attribute is provided we have to validate it and use it.
425         med = kwargs.pop(MULTI_EXIT_DISC, None)
426         if med and validate_med(med):
427             self._settings[MULTI_EXIT_DISC] = med
428
429         # We do not have valid default SOO value.
430         # If no SOO attribute is provided then we do not have to use SOO.
431         # If SOO attribute is provided we have to validate it and use it.
432         soos = kwargs.pop(SITE_OF_ORIGINS, None)
433         if soos and validate_soo_list(soos):
434             self._settings[SITE_OF_ORIGINS] = soos
435
436         # We do not have valid default LOCAL_ADDRESS and LOCAL_PORT value.
437         # If no LOCAL_ADDRESS/PORT is provided then we will bind to system
438         # default.
439         self._settings[LOCAL_ADDRESS] = compute_optional_conf(
440             LOCAL_ADDRESS, None, **kwargs)
441         self._settings[LOCAL_PORT] = compute_optional_conf(
442             LOCAL_PORT, None, **kwargs)
443
444         # We use the global defined local (router) AS as the default
445         # local AS.
446         from ryu.services.protocols.bgp.core_manager import CORE_MANAGER
447         g_local_as = CORE_MANAGER.common_conf.local_as
448         self._settings[LOCAL_AS] = compute_optional_conf(
449             LOCAL_AS, g_local_as, **kwargs)
450
451         self._settings[PEER_NEXT_HOP] = compute_optional_conf(
452             PEER_NEXT_HOP, None, **kwargs)
453
454         self._settings[PASSWORD] = compute_optional_conf(
455             PASSWORD, None, **kwargs)
456
457         # RTC configurations.
458         self._settings[CAP_RTC] = compute_optional_conf(
459             CAP_RTC, DEFAULT_CAP_RTC, **kwargs)
460         # Default RTC_AS is local (router) AS.
461         self._settings[RTC_AS] = compute_optional_conf(
462             RTC_AS, g_local_as, **kwargs)
463
464         # Since ConfWithId' default values use str(self) and repr(self), we
465         # call super method after we have initialized other settings.
466         super(NeighborConf, self)._init_opt_settings(**kwargs)
467
468     @classmethod
469     def get_opt_settings(cls):
470         self_confs = super(NeighborConf, cls).get_opt_settings()
471         self_confs.update(NeighborConf.OPTIONAL_SETTINGS)
472         return self_confs
473
474     @classmethod
475     def get_req_settings(cls):
476         self_confs = super(NeighborConf, cls).get_req_settings()
477         self_confs.update(NeighborConf.REQUIRED_SETTINGS)
478         return self_confs
479
480     @classmethod
481     def get_valid_evts(cls):
482         self_valid_evts = super(NeighborConf, cls).get_valid_evts()
483         self_valid_evts.update(NeighborConf.VALID_EVT)
484         return self_valid_evts
485
486     # =========================================================================
487     # Required attributes
488     # =========================================================================
489
490     @property
491     def remote_as(self):
492         return self._settings[REMOTE_AS]
493
494     @property
495     def ip_address(self):
496         return self._settings[IP_ADDRESS]
497
498     @property
499     def port(self):
500         return self._settings[REMOTE_PORT]
501
502     @property
503     def host_bind_ip(self):
504         return self._settings[LOCAL_ADDRESS]
505
506     @property
507     def host_bind_port(self):
508         return self._settings[LOCAL_PORT]
509
510     @property
511     def next_hop(self):
512         return self._settings[PEER_NEXT_HOP]
513
514     @property
515     def password(self):
516         return self._settings[PASSWORD]
517
518     # =========================================================================
519     # Optional attributes with valid defaults.
520     # =========================================================================
521
522     @property
523     def local_as(self):
524         return self._settings[LOCAL_AS]
525
526     @property
527     def hold_time(self):
528         return self._settings[HOLD_TIME]
529
530     @property
531     def cap_refresh(self):
532         return self._settings[CAP_REFRESH]
533
534     @property
535     def cap_enhanced_refresh(self):
536         return self._settings[CAP_ENHANCED_REFRESH]
537
538     @property
539     def cap_four_octet_as_number(self):
540         return self._settings[CAP_FOUR_OCTET_AS_NUMBER]
541
542     @cap_four_octet_as_number.setter
543     def cap_four_octet_as_number(self, cap):
544         kwargs = {CAP_FOUR_OCTET_AS_NUMBER: cap}
545         self._settings[CAP_FOUR_OCTET_AS_NUMBER] = compute_optional_conf(
546             CAP_FOUR_OCTET_AS_NUMBER,
547             DEFAULT_CAP_FOUR_OCTET_AS_NUMBER, **kwargs)
548
549     @property
550     def cap_mbgp_ipv4(self):
551         return self._settings[CAP_MBGP_IPV4]
552
553     @property
554     def cap_mbgp_ipv6(self):
555         return self._settings[CAP_MBGP_IPV6]
556
557     @property
558     def cap_mbgp_vpnv4(self):
559         return self._settings[CAP_MBGP_VPNV4]
560
561     @property
562     def cap_mbgp_vpnv6(self):
563         return self._settings[CAP_MBGP_VPNV6]
564
565     @property
566     def cap_mbgp_evpn(self):
567         return self._settings[CAP_MBGP_EVPN]
568
569     @property
570     def cap_mbgp_ipv4fs(self):
571         return self._settings[CAP_MBGP_IPV4FS]
572
573     @property
574     def cap_mbgp_ipv6fs(self):
575         return self._settings[CAP_MBGP_IPV6FS]
576
577     @property
578     def cap_mbgp_vpnv4fs(self):
579         return self._settings[CAP_MBGP_VPNV4FS]
580
581     @property
582     def cap_mbgp_vpnv6fs(self):
583         return self._settings[CAP_MBGP_VPNV6FS]
584
585     @property
586     def cap_mbgp_l2vpnfs(self):
587         return self._settings[CAP_MBGP_L2VPNFS]
588
589     @property
590     def cap_rtc(self):
591         return self._settings[CAP_RTC]
592
593     @property
594     def enabled(self):
595         return self._settings[ENABLED]
596
597     @enabled.setter
598     def enabled(self, enable):
599         # Update enabled flag and notify listeners.
600         if self._settings[ENABLED] != enable:
601             self._settings[ENABLED] = enable
602             self._notify_listeners(NeighborConf.UPDATE_ENABLED_EVT,
603                                    enable)
604
605     # =========================================================================
606     # Optional attributes with no valid defaults.
607     # =========================================================================
608
609     @property
610     def multi_exit_disc(self):
611         # This property does not have any valid default. Hence if not set we
612         # return None.
613         return self._settings.get(MULTI_EXIT_DISC)
614
615     @multi_exit_disc.setter
616     def multi_exit_disc(self, value):
617         if self._settings.get(MULTI_EXIT_DISC) != value:
618             self._settings[MULTI_EXIT_DISC] = value
619             self._notify_listeners(NeighborConf.UPDATE_MED_EVT, value)
620
621     @property
622     def soo_list(self):
623         soos = self._settings.get(SITE_OF_ORIGINS)
624         if soos:
625             soos = list(soos)
626         else:
627             soos = []
628         return soos
629
630     @property
631     def rtc_as(self):
632         return self._settings[RTC_AS]
633
634     @property
635     def in_filter(self):
636         return self._settings[IN_FILTER]
637
638     @property
639     def out_filter(self):
640         return self._settings[OUT_FILTER]
641
642     @property
643     def is_route_server_client(self):
644         return self._settings[IS_ROUTE_SERVER_CLIENT]
645
646     @property
647     def is_route_reflector_client(self):
648         return self._settings[IS_ROUTE_REFLECTOR_CLIENT]
649
650     @property
651     def check_first_as(self):
652         return self._settings[CHECK_FIRST_AS]
653
654     @property
655     def is_next_hop_self(self):
656         return self._settings[IS_NEXT_HOP_SELF]
657
658     @property
659     def connect_mode(self):
660         return self._settings[CONNECT_MODE]
661
662     @connect_mode.setter
663     def connect_mode(self, mode):
664         self._settings[CONNECT_MODE] = mode
665         self._notify_listeners(NeighborConf.UPDATE_CONNECT_MODE_EVT, mode)
666
667     def exceeds_max_prefix_allowed(self, prefix_count):
668         allowed_max = self._settings[MAX_PREFIXES]
669         does_exceed = False
670         # Check if allowed max. is unlimited.
671         if allowed_max != 0:
672             # If max. prefix is limited, check if given exceeds this limit.
673             if prefix_count > allowed_max:
674                 does_exceed = True
675
676         return does_exceed
677
678     def get_configured_capabilities(self):
679         """Returns configured capabilities."""
680
681         capabilities = OrderedDict()
682         mbgp_caps = []
683         if self.cap_mbgp_ipv4:
684             mbgp_caps.append(
685                 BGPOptParamCapabilityMultiprotocol(
686                     RF_IPv4_UC.afi, RF_IPv4_UC.safi))
687
688         if self.cap_mbgp_ipv6:
689             mbgp_caps.append(
690                 BGPOptParamCapabilityMultiprotocol(
691                     RF_IPv6_UC.afi, RF_IPv6_UC.safi))
692
693         if self.cap_mbgp_vpnv4:
694             mbgp_caps.append(
695                 BGPOptParamCapabilityMultiprotocol(
696                     RF_IPv4_VPN.afi, RF_IPv4_VPN.safi))
697
698         if self.cap_mbgp_vpnv6:
699             mbgp_caps.append(
700                 BGPOptParamCapabilityMultiprotocol(
701                     RF_IPv6_VPN.afi, RF_IPv6_VPN.safi))
702
703         if self.cap_rtc:
704             mbgp_caps.append(
705                 BGPOptParamCapabilityMultiprotocol(
706                     RF_RTC_UC.afi, RF_RTC_UC.safi))
707
708         if self.cap_mbgp_evpn:
709             mbgp_caps.append(
710                 BGPOptParamCapabilityMultiprotocol(
711                     RF_L2_EVPN.afi, RF_L2_EVPN.safi))
712
713         if self.cap_mbgp_ipv4fs:
714             mbgp_caps.append(
715                 BGPOptParamCapabilityMultiprotocol(
716                     RF_IPv4_FLOWSPEC.afi, RF_IPv4_FLOWSPEC.safi))
717
718         if self.cap_mbgp_ipv6fs:
719             mbgp_caps.append(
720                 BGPOptParamCapabilityMultiprotocol(
721                     RF_IPv6_FLOWSPEC.afi, RF_IPv6_FLOWSPEC.safi))
722
723         if self.cap_mbgp_vpnv4fs:
724             mbgp_caps.append(
725                 BGPOptParamCapabilityMultiprotocol(
726                     RF_VPNv4_FLOWSPEC.afi, RF_VPNv4_FLOWSPEC.safi))
727
728         if self.cap_mbgp_vpnv6fs:
729             mbgp_caps.append(
730                 BGPOptParamCapabilityMultiprotocol(
731                     RF_VPNv6_FLOWSPEC.afi, RF_VPNv6_FLOWSPEC.safi))
732
733         if self.cap_mbgp_l2vpnfs:
734             mbgp_caps.append(
735                 BGPOptParamCapabilityMultiprotocol(
736                     RF_L2VPN_FLOWSPEC.afi, RF_L2VPN_FLOWSPEC.safi))
737
738         if mbgp_caps:
739             capabilities[BGP_CAP_MULTIPROTOCOL] = mbgp_caps
740
741         if self.cap_refresh:
742             capabilities[BGP_CAP_ROUTE_REFRESH] = [
743                 BGPOptParamCapabilityRouteRefresh()]
744
745         if self.cap_enhanced_refresh:
746             capabilities[BGP_CAP_ENHANCED_ROUTE_REFRESH] = [
747                 BGPOptParamCapabilityEnhancedRouteRefresh()]
748
749         if self.cap_four_octet_as_number:
750             capabilities[BGP_CAP_FOUR_OCTET_AS_NUMBER] = [
751                 BGPOptParamCapabilityFourOctetAsNumber(self.local_as)]
752
753         return capabilities
754
755     def __repr__(self):
756         return '<%s(%r, %r, %r)>' % (self.__class__.__name__,
757                                      self.remote_as,
758                                      self.ip_address,
759                                      self.enabled)
760
761     def __str__(self):
762         return 'Neighbor: %s' % self.ip_address
763
764
765 class NeighborsConf(BaseConf):
766     """Container of all neighbor configurations."""
767
768     ADD_NEIGH_CONF_EVT = 'add_neigh_conf_evt'
769     REMOVE_NEIGH_CONF_EVT = 'remove_neigh_conf_evt'
770
771     VALID_EVT = frozenset([ADD_NEIGH_CONF_EVT, REMOVE_NEIGH_CONF_EVT])
772
773     def __init__(self):
774         super(NeighborsConf, self).__init__()
775         self._neighbors = {}
776
777     def _init_opt_settings(self, **kwargs):
778         pass
779
780     def update(self, **kwargs):
781         raise NotImplementedError('Use either add/remove_neighbor_conf'
782                                   ' methods instead.')
783
784     @property
785     def rtc_as_set(self):
786         """Returns current RTC AS configured for current neighbors.
787         """
788         rtc_as_set = set()
789         for neigh in self._neighbors.values():
790             rtc_as_set.add(neigh.rtc_as)
791         return rtc_as_set
792
793     @classmethod
794     def get_valid_evts(cls):
795         self_valid_evts = super(NeighborsConf, cls).get_valid_evts()
796         self_valid_evts.update(NeighborsConf.VALID_EVT)
797         return self_valid_evts
798
799     def add_neighbor_conf(self, neigh_conf):
800         # Check if we already know this neighbor
801         if neigh_conf.ip_address in self._neighbors.keys():
802             message = 'Neighbor with given ip address already exists'
803             raise RuntimeConfigError(desc=message)
804
805         # Add this neighbor to known configured neighbors and generate update
806         # event
807         self._neighbors[neigh_conf.ip_address] = neigh_conf
808         self._notify_listeners(NeighborsConf.ADD_NEIGH_CONF_EVT, neigh_conf)
809
810     def remove_neighbor_conf(self, neigh_ip_address):
811         neigh_conf = self._neighbors.pop(neigh_ip_address, None)
812         if not neigh_conf:
813             raise RuntimeConfigError(desc='Tried to remove a neighbor that '
814                                      'does not exists')
815         else:
816             self._notify_listeners(NeighborsConf.REMOVE_NEIGH_CONF_EVT,
817                                    neigh_conf)
818         return neigh_conf
819
820     def get_neighbor_conf(self, neigh_ip_address):
821         return self._neighbors.get(neigh_ip_address, None)
822
823     def __repr__(self):
824         return '<%s(%r)>' % (self.__class__.__name__, self._neighbors)
825
826     def __str__(self):
827         return '\'Neighbors\': %s' % self._neighbors
828
829     @property
830     def settings(self):
831         return [neighbor.settings for _, neighbor in
832                 self._neighbors.items()]
833
834
835 class NeighborConfListener(ConfWithIdListener, ConfWithStatsListener):
836     """Base listener for change events to a specific neighbors' configurations.
837     """
838
839     def __init__(self, neigh_conf):
840         super(NeighborConfListener, self).__init__(neigh_conf)
841         neigh_conf.add_listener(NeighborConf.UPDATE_ENABLED_EVT,
842                                 self.on_update_enabled)
843         neigh_conf.add_listener(NeighborConf.UPDATE_MED_EVT,
844                                 self.on_update_med)
845         neigh_conf.add_listener(NeighborConf.UPDATE_CONNECT_MODE_EVT,
846                                 self.on_update_connect_mode)
847
848     @abstractmethod
849     def on_update_enabled(self, evt):
850         raise NotImplementedError('This method should be overridden.')
851
852     @abstractmethod
853     def on_update_med(self, evt):
854         raise NotImplementedError('This method should be overridden.')
855
856     @abstractmethod
857     def on_update_connect_mode(self, evt):
858         raise NotImplementedError('This method should be overridden.')
859
860
861 class NeighborsConfListener(BaseConfListener):
862     """Base listener for change events to neighbor configuration container."""
863
864     def __init__(self, neighbors_conf):
865         super(NeighborsConfListener, self).__init__(neighbors_conf)
866         neighbors_conf.add_listener(NeighborsConf.ADD_NEIGH_CONF_EVT,
867                                     self.on_add_neighbor_conf)
868         neighbors_conf.add_listener(NeighborsConf.REMOVE_NEIGH_CONF_EVT,
869                                     self.on_remove_neighbor_conf)
870
871     @abstractmethod
872     def on_add_neighbor_conf(self, evt):
873         raise NotImplementedError('This method should be overridden.')
874
875     @abstractmethod
876     def on_remove_neighbor_conf(self, evt):
877         raise NotImplementedError('This method should be overridden.')