i misunderstood that RDs were in-core.
actually they are on-wire.
Signed-off-by: YAMAMOTO Takashi <[email protected]>
---
ryu/lib/packet/bgp.py | 91 ++++++++++++++++++++++++++++++---------
ryu/tests/unit/packet/test_bgp.py | 16 +++++--
2 files changed, 82 insertions(+), 25 deletions(-)
diff --git a/ryu/lib/packet/bgp.py b/ryu/lib/packet/bgp.py
index ffd332a..6c1d6ad 100644
--- a/ryu/lib/packet/bgp.py
+++ b/ryu/lib/packet/bgp.py
@@ -141,8 +141,16 @@ class _AddrPrefix(StringifyMixin):
__metaclass__ = abc.ABCMeta
_PACK_STR = '!B' # length
- def __init__(self, length, addr):
+ def __init__(self, length, addr, prefixes=None):
+ # length is on-wire bit length of prefixes+addr.
+ assert prefixes != ()
+ if isinstance(addr, tuple):
+ # for _AddrPrefix.parser
+ # also for _VPNAddrPrefix.__init__ etc
+ (addr,) = addr
self.length = length
+ if prefixes:
+ addr = prefixes + (addr,)
self.addr = addr
@staticmethod
@@ -196,19 +204,22 @@ class _BinAddrPrefix(_AddrPrefix):
class _LabelledAddrPrefix(_AddrPrefix):
_LABEL_PACK_STR = '!3B'
- def __init__(self, length, addr, labels=[]):
+ def __init__(self, length, addr, labels=[], **kwargs):
assert isinstance(labels, list)
- if isinstance(addr, tuple):
+ is_tuple = isinstance(addr, tuple)
+ if is_tuple:
+ # for _AddrPrefix.parser
assert not labels
- our_addr = addr
- our_length = length
+ labels = addr[0]
+ addr = addr[1:]
else:
- label_length = struct.calcsize(self._LABEL_PACK_STR) * 8 * \
- len(labels)
- our_length = label_length + length
- our_addr = (labels, addr)
- super(_LabelledAddrPrefix, self).__init__(length=our_length,
- addr=our_addr)
+ length += struct.calcsize(self._LABEL_PACK_STR) * 8 * len(labels)
+ assert length > struct.calcsize(self._LABEL_PACK_STR) * 8 * len(labels)
+ prefixes = (labels,)
+ super(_LabelledAddrPrefix, self).__init__(prefixes=prefixes,
+ length=length,
+ addr=addr,
+ **kwargs)
@classmethod
def _label_to_bin(cls, label):
@@ -227,33 +238,36 @@ class _LabelledAddrPrefix(_AddrPrefix):
@classmethod
def _to_bin(cls, addr):
- (labels, prefix) = addr
+ labels = addr[0]
+ rest = addr[1:]
labels = map(lambda x: x << 4, labels)
if labels:
labels[-1] |= 1 # bottom of stack
bin_labels = map(cls._label_to_bin, labels)
return bytes(reduce(lambda x, y: x + y, bin_labels,
- bytearray()) + cls._prefix_to_bin(prefix))
+ bytearray()) + cls._prefix_to_bin(rest))
@classmethod
def _from_bin(cls, addr):
+ rest = addr
labels = []
while True:
- (label, addr) = cls._label_from_bin(addr)
+ (label, rest) = cls._label_from_bin(rest)
labels.append(label >> 4)
if label & 1: # bottom of stack
break
- return (labels, cls._prefix_from_bin(addr))
+ return (labels,) + cls._prefix_from_bin(rest)
class _UnlabelledAddrPrefix(_AddrPrefix):
@classmethod
def _to_bin(cls, addr):
- return cls._prefix_to_bin(addr)
+ return cls._prefix_to_bin((addr,))
@classmethod
- def _from_bin(cls, addr):
- return cls._prefix_from_bin(addr)
+ def _from_bin(cls, binaddr):
+ (addr,) = cls._prefix_from_bin(binaddr)
+ return addr
class _IPAddrPrefix(_AddrPrefix):
@@ -265,14 +279,49 @@ class _IPAddrPrefix(_AddrPrefix):
@staticmethod
def _prefix_to_bin(addr):
+ (addr,) = addr
return addrconv.ipv4.text_to_bin(addr)
@staticmethod
def _prefix_from_bin(addr):
- return addrconv.ipv4.bin_to_text(pad(addr, 4))
+ return (addrconv.ipv4.bin_to_text(pad(addr, 4)),)
+
+
+class _VPNAddrPrefix(_AddrPrefix):
+ _RD_PACK_STR = '!Q'
+
+ def __init__(self, length, addr, prefixes=(), route_dist=0):
+ if isinstance(addr, tuple):
+ # for _AddrPrefix.parser
+ assert not route_dist
+ assert length > struct.calcsize(self._RD_PACK_STR) * 8
+ route_dist = addr[0]
+ addr = addr[1:]
+ else:
+ length += struct.calcsize(self._RD_PACK_STR) * 8
+ prefixes = prefixes + (route_dist,)
+ super(_VPNAddrPrefix, self).__init__(prefixes=prefixes,
+ length=length,
+ addr=addr)
+
+ @classmethod
+ def _prefix_to_bin(cls, addr):
+ rd = addr[0]
+ rest = addr[1:]
+ binrd = bytearray()
+ msg_pack_into(cls._RD_PACK_STR, binrd, 0, rd)
+ return binrd + super(_VPNAddrPrefix, cls)._prefix_to_bin(rest)
+
+ @classmethod
+ def _prefix_from_bin(cls, binaddr):
+ binrd = binaddr[:8]
+ binrest = binaddr[8:]
+ (rd,) = struct.unpack_from(cls._RD_PACK_STR, buffer(binrd))
+ return (rd,) + super(_VPNAddrPrefix, cls)._prefix_from_bin(binrest)
-class LabelledIPAddrPrefix(_LabelledAddrPrefix, _IPAddrPrefix):
+class LabelledVPNIPAddrPrefix(_LabelledAddrPrefix, _VPNAddrPrefix,
+ _IPAddrPrefix):
pass
@@ -282,7 +331,7 @@ class IPAddrPrefix(_UnlabelledAddrPrefix, _IPAddrPrefix):
_ADDR_CLASSES = {
(afi.IP, safi.UNICAST): IPAddrPrefix,
- (afi.IP, safi.MPLS_VPN): LabelledIPAddrPrefix,
+ (afi.IP, safi.MPLS_VPN): LabelledVPNIPAddrPrefix,
}
diff --git a/ryu/tests/unit/packet/test_bgp.py
b/ryu/tests/unit/packet/test_bgp.py
index deebb9a..6764da4 100644
--- a/ryu/tests/unit/packet/test_bgp.py
+++ b/ryu/tests/unit/packet/test_bgp.py
@@ -79,8 +79,12 @@ class Test_bgp(unittest.TestCase):
bgp.BGPWithdrawnRoute(length=32,
addr='192.0.2.13')]
mp_nlri = [
- bgp.LabelledIPAddrPrefix(24, '192.0.9.0', labels=[1, 2, 3]),
- bgp.LabelledIPAddrPrefix(26, '192.0.10.192', labels=[5, 6, 7, 8]),
+ bgp.LabelledVPNIPAddrPrefix(24, '192.0.9.0',
+ route_dist=100,
+ labels=[1, 2, 3]),
+ bgp.LabelledVPNIPAddrPrefix(26, '192.0.10.192',
+ route_dist=4000000000,
+ labels=[5, 6, 7, 8]),
]
communities = [
bgp.BGP_COMMUNITY_NO_EXPORT,
@@ -224,8 +228,12 @@ class Test_bgp(unittest.TestCase):
bgp.BGPWithdrawnRoute(length=32,
addr='192.0.2.13')]
mp_nlri = [
- bgp.LabelledIPAddrPrefix(24, '192.0.9.0', labels=[1, 2, 3]),
- bgp.LabelledIPAddrPrefix(26, '192.0.10.192', labels=[5, 6, 7, 8]),
+ bgp.LabelledVPNIPAddrPrefix(24, '192.0.9.0',
+ route_dist=100,
+ labels=[1, 2, 3]),
+ bgp.LabelledVPNIPAddrPrefix(26, '192.0.10.192',
+ route_dist=4000000000,
+ labels=[5, 6, 7, 8]),
]
communities = [
bgp.BGP_COMMUNITY_NO_EXPORT,
--
1.8.3.1
------------------------------------------------------------------------------
CenturyLink Cloud: The Leader in Enterprise Cloud Services.
Learn Why More Businesses Are Choosing CenturyLink Cloud For
Critical Workloads, Development Environments & Everything In Between.
Get a Quote or Start a Free Trial Today.
http://pubads.g.doubleclick.net/gampad/clk?id=119420431&iu=/4140/ostg.clktrk
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel