~ubuntu-branches/ubuntu/trusty/exabgp/trusty

« back to all changes in this revision

Viewing changes to build/lib.linux-x86_64-2.7/exabgp/message/open.py

  • Committer: Package Import Robot
  • Author(s): Henry-Nicolas Tourneur
  • Date: 2012-03-22 12:00:00 UTC
  • mfrom: (1.1.4)
  • Revision ID: package-import@ubuntu.com-20120322120000-v4aj8h69mhpmgbjq
Tags: 2.0.7-1

* New upstream release
* Fix bad clean target for build/ directory

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#!/usr/bin/env python
2
 
# encoding: utf-8
3
 
"""
4
 
open.py
5
 
 
6
 
Created by Thomas Mangin on 2009-11-05.
7
 
Copyright (c) 2009-2011 Exa Networks. All rights reserved.
8
 
"""
9
 
 
10
 
import os
11
 
import socket
12
 
from struct import pack
13
 
 
14
 
from exabgp.structure.address import AFI,SAFI
15
 
from exabgp.structure.asn  import ASN
16
 
from exabgp.message import Message
17
 
 
18
 
# =================================================================== Open
19
 
 
20
 
class Open (Message):
21
 
        TYPE = chr(0x01)
22
 
 
23
 
        def __init__ (self,version,asn,router_id,capabilities,hold_time):
24
 
                self.version = Version(version)
25
 
                self.asn = ASN(asn)
26
 
                self.hold_time = HoldTime(hold_time)
27
 
                self.router_id = RouterID(router_id)
28
 
                self.capabilities = capabilities
29
 
 
30
 
        def message (self):
31
 
                if self.asn.asn4():
32
 
                        return self._message("%s%s%s%s%s" % (self.version.pack(),ASN(23456).pack(False),self.hold_time.pack(),self.router_id.pack(),self.capabilities.pack()))
33
 
                return self._message("%s%s%s%s%s" % (self.version.pack(),self.asn.pack(False),self.hold_time.pack(),self.router_id.pack(),self.capabilities.pack()))
34
 
 
35
 
        def __str__ (self):
36
 
                return "OPEN version=%d asn=%d hold_time=%s router_id=%s capabilities=[%s]" % (self.version, self.asn, self.hold_time, self.router_id,self.capabilities)
37
 
 
38
 
# =================================================================== Version
39
 
 
40
 
class Version (int):
41
 
        def pack (self):
42
 
                return chr(self)
43
 
 
44
 
# =================================================================== HoldTime
45
 
 
46
 
class HoldTime (int):
47
 
        def pack (self):
48
 
                return pack('!H',self)
49
 
 
50
 
        def keepalive (self):
51
 
                return int(self/3)
52
 
 
53
 
        def __len__ (self):
54
 
                return 2
55
 
 
56
 
# =================================================================== RouterID
57
 
 
58
 
class RouterID (object):
59
 
        def __init__ (self,ip):
60
 
                self.ip = ip
61
 
                try:
62
 
                        self.raw = socket.inet_pton(socket.AF_INET,ip)
63
 
                except socket.error:
64
 
                        raise ValueError('invalid IP address %s' % str(ip))
65
 
 
66
 
        def afi (self):
67
 
                return AFI.ipv4
68
 
 
69
 
        def __len__ (self):
70
 
                return 4
71
 
 
72
 
        def pack (self):
73
 
                return self.raw
74
 
        
75
 
        def __str__ (self):
76
 
                return self.ip
77
 
 
78
 
        def __repr__ (self):
79
 
                return str(self)
80
 
 
81
 
        def __eq__ (self,other):
82
 
                return self.ip == other.ip
83
 
 
84
 
# =================================================================== Graceful (Restart)
85
 
# RFC 4727
86
 
 
87
 
class Graceful (dict):
88
 
        TIME_MASK     = 0x0FFF
89
 
        FLAG_MASK     = 0xF000
90
 
 
91
 
        # 0x8 is binary 1000
92
 
        RESTART_STATE = 0x08 
93
 
        FORWARDING_STATE = 0x80
94
 
        
95
 
        def __init__ (self,restart_flag,restart_time,protos):
96
 
                dict.__init__(self)
97
 
                self.restart_flag = restart_flag
98
 
                self.restart_time = restart_time & Graceful.TIME_MASK
99
 
                for afi,safi,family_flag in protos:
100
 
                        self[(afi,safi)] = family_flag & Graceful.FORWARDING_STATE
101
 
        
102
 
        def extract (self):
103
 
                restart  = pack('!H',((self.restart_flag << 12) | (self.restart_time & Graceful.TIME_MASK)))
104
 
                families = [(afi.pack(),safi.pack(),chr(self[(afi,safi)])) for (afi,safi) in self.keys()]
105
 
                sfamilies = ''.join(["%s%s%s" % (pafi,psafi,family) for (pafi,psafi,family) in families])
106
 
                return ["%s%s" % (restart,sfamilies)]
107
 
 
108
 
        def __str__ (self):
109
 
                families = [(str(afi),str(safi),hex(self[(afi,safi)])) for (afi,safi) in self.keys()]
110
 
                sfamilies = ' '.join(["%s/%s=%s" % (afi,safi,family) for (afi,safi,family) in families])
111
 
                return "Graceful Restart Flags %s Time %d %s" % (hex(self.restart_flag),self.restart_time,sfamilies)
112
 
 
113
 
        def families (self):
114
 
                return self.keys()
115
 
 
116
 
# =================================================================== MultiProtocol
117
 
 
118
 
class MultiProtocol (list):
119
 
        def __str__ (self):
120
 
                return 'Multiprotocol ' + ' '.join(["%s %s" % (safi,ssafi) for (safi,ssafi) in [(str(afi),str(safi)) for (afi,safi) in self]])
121
 
 
122
 
        def extract (self):
123
 
                rs = []
124
 
                for v in self:
125
 
                        rs.append(pack('!H',v[0]) + pack('!H',v[1]))
126
 
                return rs
127
 
 
128
 
# =================================================================== RouteRefresh
129
 
 
130
 
class RouteRefresh (list):
131
 
        def __str__ (self):
132
 
                return "Route Refresh (unparsed)"
133
 
 
134
 
        def extract (self):
135
 
                return []
136
 
 
137
 
class CiscoRouteRefresh (list):
138
 
        def __str__ (self):
139
 
                return "Cisco Route Refresh (unparsed)"
140
 
 
141
 
        def extract (self):
142
 
                return []
143
 
 
144
 
 
145
 
# =================================================================== Parameter
146
 
 
147
 
class ASN4 (int):
148
 
        def extract (self):
149
 
                return [pack('!L',self)]
150
 
 
151
 
# =================================================================== Unknown
152
 
 
153
 
class Unknown (object):
154
 
        def __init__ (self,value):
155
 
                self.value = value
156
 
        
157
 
        def __str__ (self):
158
 
                if self.value in Capabilities.reserved: return 'Reserved %s' % str(self.value)
159
 
                if self.value in Capabilities.unassigned: return 'Unassigned %s' % str(self.value)
160
 
                return 'unknown %s' % str(self.value)
161
 
 
162
 
        def extract (self):
163
 
                return []
164
 
 
165
 
# =================================================================== Parameter
166
 
 
167
 
class Parameter (int):
168
 
        AUTHENTIFICATION_INFORMATION = 0x01 # Depreciated
169
 
        CAPABILITIES                 = 0x02
170
 
 
171
 
        def __str__ (self):
172
 
                if self == 0x01: return "AUTHENTIFICATION INFORMATION"
173
 
                if self == 0x02: return "OPTIONAL"
174
 
                return 'UNKNOWN'
175
 
 
176
 
# =================================================================== Capabilities
177
 
# http://www.iana.org/assignments/capability-codes/
178
 
 
179
 
class Capabilities (dict):
180
 
        RESERVED                 = 0x00 # [RFC5492]
181
 
        MULTIPROTOCOL_EXTENSIONS = 0x01 # [RFC2858]
182
 
        ROUTE_REFRESH            = 0x02 # [RFC2918]
183
 
        OUTBOUND_ROUTE_FILTERING = 0x03 # [RFC5291]
184
 
        MULTIPLE_ROUTES          = 0x04 # [RFC3107]
185
 
        EXTENDED_NEXT_HOP        = 0x05 # [RFC5549]
186
 
        #6-63      Unassigned
187
 
        GRACEFUL_RESTART         = 0x40 # [RFC4724]
188
 
        FOUR_BYTES_ASN           = 0x41 # [RFC4893]
189
 
        # 66 Deprecated
190
 
        DYNAMIC_CAPABILITY       = 0x43 # [Chen]
191
 
        MULTISESSION_BGP         = 0x44 # [Appanna]
192
 
        ADD_PATH                 = 0x45 # [draft-ietf-idr-add-paths]
193
 
        # 70-127    Unassigned 
194
 
        CISCO_ROUTE_REFRESH      = 0x80 # I Can only find reference to this in the router logs
195
 
        # 128-255   Reserved for Private Use [RFC5492]
196
 
 
197
 
        unassigned = range(70,128)
198
 
        reserved = range(128,256)
199
 
 
200
 
        def announced (self,capability):
201
 
                return self.has_key(capability)
202
 
 
203
 
        def __str__ (self):
204
 
                r = []
205
 
                for key in self.keys():
206
 
                        if key == self.MULTIPROTOCOL_EXTENSIONS:
207
 
                                r += ['Multiprotocol for ' + ' '.join(["%s %s" % (str(afi),str(safi)) for (afi,safi) in self[key]])]
208
 
                        elif key == self.ROUTE_REFRESH:
209
 
                                r += ['Route Refresh']
210
 
                        elif key == self.CISCO_ROUTE_REFRESH:
211
 
                                r += ['Cisco Route Refresh']
212
 
                        elif key == self.GRACEFUL_RESTART:
213
 
                                r += ['Graceful Restart']
214
 
                        elif key == self.FOUR_BYTES_ASN:
215
 
                                r += ['4Bytes AS %d' % self[key]]
216
 
                        elif key in self.reserved:
217
 
                                r += ['private use capability %d' % key]
218
 
                        elif key in self.unassigned:
219
 
                                r += ['unassigned capability %d' % key]
220
 
                        else:
221
 
                                r += ['unhandled capability %d' % key]
222
 
                return ', '.join(r)
223
 
 
224
 
        def default (self,neighbor,restarted):
225
 
                graceful = neighbor.graceful_restart
226
 
 
227
 
                if os.environ.get('MINIMAL_MP','0') in ['','1','yes','Yes','YES']:
228
 
                        families = neighbor.families
229
 
                else:
230
 
                        families = []
231
 
                        families.append((AFI(AFI.ipv4),SAFI(SAFI.unicast)))
232
 
                        families.append((AFI(AFI.ipv6),SAFI(SAFI.unicast)))
233
 
                        families.append((AFI(AFI.ipv4),SAFI(SAFI.flow_ipv4)))
234
 
 
235
 
                mp = MultiProtocol()
236
 
                mp.extend(families)
237
 
                self[Capabilities.MULTIPROTOCOL_EXTENSIONS] = mp 
238
 
                self[Capabilities.FOUR_BYTES_ASN] = ASN4(neighbor.local_as)
239
 
 
240
 
                if graceful:
241
 
                        if restarted:
242
 
                                self[Capabilities.GRACEFUL_RESTART] = Graceful(Graceful.RESTART_STATE,graceful,[(afi,safi,Graceful.FORWARDING_STATE) for (afi,safi) in families])
243
 
                        else:
244
 
                                self[Capabilities.GRACEFUL_RESTART] = Graceful(0x0,graceful,[(afi,safi,Graceful.FORWARDING_STATE) for (afi,safi) in families])
245
 
 
246
 
 
247
 
                return self
248
 
 
249
 
        def pack (self):
250
 
                rs = []
251
 
                for k,capabilities in self.iteritems():
252
 
                        for capability in capabilities.extract():
253
 
                                rs.append("%s%s%s" % (chr(k),chr(len(capability)),capability))
254
 
                parameters = "".join(["%s%s%s" % (chr(2),chr(len(r)),r) for r in rs])
255
 
                return "%s%s" % (chr(len(parameters)),parameters)