5
Created by Thomas Mangin on 2012-07-08.
6
Copyright (c) 2009-2013 Exa Networks. All rights reserved.
9
from struct import pack,unpack
10
from exabgp.protocol.family import AFI,SAFI
12
from exabgp.bgp.message.update.nlri.prefix import mask_to_bytes,Prefix
14
class PathInfo (object):
15
def __init__ (self,integer=None,ip=None,packed=None):
17
self.path_info = packed
19
self.path_info = ''.join([chr(int(_)) for _ in ip.split('.')])
21
self.path_info = ''.join([chr((integer>>offset) & 0xff) for offset in [24,16,8,0]])
24
#sum(int(a)<<offset for (a,offset) in zip(ip.split('.'), range(24, -8, -8)))
27
return len(self.path_info)
30
return '"path-information": "%s"' % '.'.join([str(ord(_)) for _ in self.path_info])
34
return ' path-information %s' % '.'.join([str(ord(_)) for _ in self.path_info])
40
return '\x00\x00\x00\x00'
42
_NoPathInfo = PathInfo()
45
class Labels (object):
48
def __init__ (self,labels):
52
# shift to 20 bits of the label to be at the top of three bytes and then truncate.
53
packed.append(pack('!L',label << 4)[1:])
54
# Mark the bottom of stack with the bit
57
packed.append(pack('!L',(label << 4)|1)[1:])
58
self.packed = ''.join(packed)
59
self._len = len(self.packed)
69
return '"label": [ %s ]' % ', '.join([str(_) for _ in self.labels])
75
return ' label [ %s ]' % ' '.join([str(_) for _ in self.labels])
77
return ' label %s' % self.labels[0]
81
_NoLabels = Labels([])
83
class RouteDistinguisher (object):
84
def __init__ (self,rd):
86
self._len = len(self.rd)
95
t,c1,c2,c3 = unpack('!HHHH',self.rd)
97
rd = '%d:%d' % (c1,(c2<<16)+c3)
99
rd = '%d.%d.%d.%d:%d' % (c1>>8,c1&0xFF,c2>>8,c2&0xFF,c3)
101
rd = '%d:%d' % ((c1<<16)+c2,c3)
109
return '"route-distinguisher": "%s"' % self._str()
114
return ' route-distinguisher %s' % self._str()
116
_NoRD = RouteDistinguisher('')
120
def __init__(self,afi,safi,packed,mask,nexthop,action):
121
self.path_info = _NoPathInfo
122
self.labels = _NoLabels
124
self.nexthop = nexthop
127
Prefix.__init__(self,afi,safi,packed,mask)
129
def has_label (self):
130
if self.afi == AFI.ipv4 and self.safi in (SAFI.nlri_mpls,SAFI.mpls_vpn):
132
if self.afi == AFI.ipv6 and self.safi == SAFI.mpls_vpn:
137
return "%s%s%s%s" % (self.prefix(),str(self.labels),str(self.path_info),str(self.rd))
140
prefix_len = len(self.path_info) + len(self.labels) + len(self.rd)
141
return 1 + prefix_len + mask_to_bytes[self.mask]
144
nexthop = ' next-hop %s' % self.nexthop.inet() if self.nexthop else ''
145
return "%s%s" % (self.nlri(),nexthop)
147
def __eq__ (self,other):
148
return str(self) == str(other)
150
def __ne__ (self,other):
151
return not self.__eq__(other)
153
def json (self,announced=True):
154
label = self.labels.json()
155
pinfo = self.path_info.json()
156
rdist = self.rd.json()
160
if self.labels: r.append(label)
161
if self.rd: r.append(rdist)
162
if self.path_info: r.append(pinfo)
163
return '"%s": { %s }' % (self.prefix(),", ".join(r))
165
def pack (self,addpath):
167
path_info = self.path_info.pack()
172
length = len(self.labels)*8 + len(self.rd)*8 + self.mask
173
return path_info + chr(length) + self.labels.pack() + self.rd.pack() + self.packed[:mask_to_bytes[self.mask]]
175
return path_info + Prefix.pack(self)
178
return self.pack(True)+self.rd.rd+self.path_info.path_info