|
1
|
|
|
# encoding: utf-8 |
|
2
|
|
|
""" |
|
3
|
|
|
nlri.py |
|
4
|
|
|
|
|
5
|
|
|
Created by Thomas Mangin on 2012-07-08. |
|
6
|
|
|
Copyright (c) 2009-2017 Exa Networks. All rights reserved. |
|
7
|
|
|
License: 3-clause BSD. (See the COPYRIGHT file) |
|
8
|
|
|
""" |
|
9
|
|
|
|
|
10
|
|
|
from exabgp.protocol.family import AFI |
|
11
|
|
|
from exabgp.protocol.family import SAFI |
|
12
|
|
|
from exabgp.protocol.family import Family |
|
13
|
|
|
from exabgp.bgp.message import OUT |
|
14
|
|
|
from exabgp.bgp.message.notification import Notify |
|
15
|
|
|
|
|
16
|
|
|
from exabgp.logger import Logger |
|
17
|
|
|
from exabgp.logger import LazyNLRI |
|
18
|
|
|
|
|
19
|
|
|
|
|
20
|
|
|
class NLRI(Family): |
|
21
|
|
|
__slots__ = ['action'] |
|
22
|
|
|
|
|
23
|
|
|
EOR = False |
|
24
|
|
|
|
|
25
|
|
|
registered_nlri = dict() |
|
26
|
|
|
registered_families = [(AFI.ipv4, SAFI.multicast)] |
|
27
|
|
|
logger = None |
|
28
|
|
|
|
|
29
|
|
|
def __init__(self, afi, safi, action=OUT.UNSET): |
|
30
|
|
|
Family.__init__(self, afi, safi) |
|
31
|
|
|
self.action = action |
|
32
|
|
|
|
|
33
|
|
|
def __hash__(self): |
|
34
|
|
|
return hash("%s:%s:%s" % (self.afi, self.safi, self.pack_nlri())) |
|
35
|
|
|
|
|
36
|
|
|
def __eq__(self, other): |
|
37
|
|
|
return self.index() == other.index() |
|
38
|
|
|
|
|
39
|
|
|
def __ne__(self, other): |
|
40
|
|
|
return self.index() != other.index() |
|
41
|
|
|
|
|
42
|
|
|
# does not really make sense but allows to get the NLRI in a |
|
43
|
|
|
# deterministic order when generating update (Good for testing) |
|
44
|
|
|
|
|
45
|
|
|
def __lt__(self, other): |
|
46
|
|
|
return self.index() < other.index() |
|
47
|
|
|
|
|
48
|
|
|
def __le__(self, other): |
|
49
|
|
|
return self == other or self.index() < other.index() |
|
50
|
|
|
|
|
51
|
|
|
def __gt__(self, other): |
|
52
|
|
|
return self.index() > other.index() |
|
53
|
|
|
|
|
54
|
|
|
def __ge__(self, other): |
|
55
|
|
|
return self == other or self.index() > other.index() |
|
56
|
|
|
|
|
57
|
|
|
def feedback(self, action): |
|
58
|
|
|
raise RuntimeError('feedback is not implemented') |
|
59
|
|
|
|
|
60
|
|
|
def assign(self, name, value): |
|
61
|
|
|
setattr(self, name, value) |
|
62
|
|
|
|
|
63
|
|
|
def index(self): |
|
64
|
|
|
return Family.index(self) + self.pack_nlri() |
|
65
|
|
|
|
|
66
|
|
|
# remove this when code restructure is finished |
|
67
|
|
|
def pack(self, negotiated=None): |
|
68
|
|
|
return self.pack_nlri(negotiated) |
|
69
|
|
|
|
|
70
|
|
|
def pack_nlri(self, negotiated=None): |
|
71
|
|
|
raise Exception('unimplemented in NLRI children class') |
|
72
|
|
|
|
|
73
|
|
|
@classmethod |
|
74
|
|
|
def register(cls, afi, safi, force=False): |
|
75
|
|
|
def register_nlri(klass): |
|
76
|
|
|
new = (AFI.create(afi), SAFI.create(safi)) |
|
77
|
|
|
if new in cls.registered_nlri: |
|
78
|
|
|
if force: |
|
79
|
|
|
# python has a bug and does not allow %ld/%ld (pypy does) |
|
80
|
|
|
cls.registered_nlri['%s/%s' % new] = klass |
|
81
|
|
|
else: |
|
82
|
|
|
raise RuntimeError('Tried to register %s/%s twice' % new) |
|
83
|
|
|
else: |
|
84
|
|
|
# python has a bug and does not allow %ld/%ld (pypy does) |
|
85
|
|
|
cls.registered_nlri['%s/%s' % new] = klass |
|
86
|
|
|
cls.registered_families.append(new) |
|
87
|
|
|
return klass |
|
88
|
|
|
|
|
89
|
|
|
return register_nlri |
|
90
|
|
|
|
|
91
|
|
|
@staticmethod |
|
92
|
|
|
def known_families(): |
|
93
|
|
|
# we do not want to take the risk of the caller modifying the list by accident |
|
94
|
|
|
# it can not be a generator |
|
95
|
|
|
return list(NLRI.registered_families) |
|
96
|
|
|
|
|
97
|
|
|
@classmethod |
|
98
|
|
|
def unpack_nlri(cls, afi, safi, data, action, addpath): |
|
99
|
|
|
if not cls.logger: |
|
100
|
|
|
cls.logger = Logger() |
|
101
|
|
|
|
|
102
|
|
|
a, s = AFI.create(afi), SAFI.create(safi) |
|
103
|
|
|
cls.logger.debug(LazyNLRI(a, s, addpath, data), 'parser') |
|
104
|
|
|
|
|
105
|
|
|
key = '%s/%s' % (a, s) |
|
106
|
|
|
if key in cls.registered_nlri: |
|
107
|
|
|
return cls.registered_nlri[key].unpack_nlri(a, s, data, action, addpath) |
|
108
|
|
|
raise Notify(3, 0, 'trying to decode unknown family %s/%s' % (a, s)) |
|
109
|
|
|
|