summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorShinpei Muraoka <shinpei.muraoka@gmail.com>2017-03-21 09:50:45 +0900
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2017-03-28 09:55:48 +0900
commit66a5bddaf0fe036cca298a6ffbe4fae540083916 (patch)
treef92da22bf5d340ff24e0059660c808219eab57da
parent16c3640673e5a8059532592001a67cc40043277f (diff)
packet/bgp: Fix data structure for VPNv4 Flow Specification
The Route Distinguisher did not include in data structure for VPNv4 Flow Specification. This patch adds the Route Distinguisher to data structure for VPNv4 Flow Specification. For details, refer to Chapter 8 of RFC 5575. Signed-off-by: Shinpei Muraoka <shinpei.muraoka@gmail.com> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
-rw-r--r--ryu/lib/packet/bgp.py90
-rw-r--r--ryu/tests/packet_data/bgp4/flowspec_nlri_ipv4.pcapbin217 -> 273 bytes
-rw-r--r--ryu/tests/packet_data/bgp4/flowspec_nlri_vpn4.pcapbin217 -> 289 bytes
-rw-r--r--ryu/tests/unit/packet/test_bgp.py3
4 files changed, 78 insertions, 15 deletions
diff --git a/ryu/lib/packet/bgp.py b/ryu/lib/packet/bgp.py
index 47feeb39..d22bb0ed 100644
--- a/ryu/lib/packet/bgp.py
+++ b/ryu/lib/packet/bgp.py
@@ -1997,7 +1997,7 @@ class _FlowSpecNLRIBase(StringifyMixin, TypeDisp):
# +-----------------------------------+
# | NLRI value (variable) |
# +-----------------------------------+
-
+ ROUTE_FAMILY = None
_LENGTH_SHORT_FMT = '!B'
LENGTH_SHORT_SIZE = struct.calcsize(_LENGTH_SHORT_FMT)
_LENGTH_LONG_FMT = '!H'
@@ -2013,7 +2013,7 @@ class _FlowSpecNLRIBase(StringifyMixin, TypeDisp):
@classmethod
def parser(cls, buf):
- (length, ) = struct.unpack_from(
+ (length,) = struct.unpack_from(
cls._LENGTH_LONG_FMT, six.binary_type(buf))
if length < cls._LENGTH_THRESHOLD:
@@ -2022,7 +2022,14 @@ class _FlowSpecNLRIBase(StringifyMixin, TypeDisp):
else:
offset = cls.LENGTH_LONG_SIZE
+ kwargs = {'length': length}
rest = buf[offset:offset + length]
+
+ if cls.ROUTE_FAMILY.safi == subaddr_family.VPN_FLOW_SPEC:
+ route_dist = _RouteDistinguisher.parser(rest[:8])
+ kwargs['route_dist'] = route_dist.formatted_str
+ rest = rest[8:]
+
rules = []
while rest:
@@ -2036,10 +2043,17 @@ class _FlowSpecNLRIBase(StringifyMixin, TypeDisp):
rule.operator & rule.END_OF_LIST):
break
- return cls(length, rules), rest
+ kwargs['rules'] = rules
+
+ return cls(**kwargs), rest
def serialize(self):
- rules_bin = bytearray()
+ rules_bin = b''
+
+ if self.ROUTE_FAMILY.safi == subaddr_family.VPN_FLOW_SPEC:
+ route_dist = _RouteDistinguisher.from_str(self.route_dist)
+ rules_bin += route_dist.serialize()
+
self.rules.sort(key=lambda x: x.type)
for _, rules in itertools.groupby(self.rules, key=lambda x: x.type):
rules = list(rules)
@@ -2114,18 +2128,19 @@ class FlowSpecIPv4NLRI(_FlowSpecNLRIBase):
=========== ============= ========= ==============================
Example::
+
>>> msg = bgp.FlowSpecIPv4NLRI.from_user(
... dst_prefix='10.0.0.0/24',
... src_prefix='20.0.0.1/24',
- ... ip_proto='==6',
- ... port='==80 | ==8000',
+ ... ip_proto=6,
+ ... port='80 | 8000',
... dst_port='>9000 & <9050',
... src_port='>=8500 & <=9000',
- ... icmp_type='==0',
- ... icmp_code='==6',
+ ... icmp_type=0,
+ ... icmp_code=6,
... tcp_flags='SYN+ACK & !=URGENT',
- ... packet_len='==1000',
- ... dscp='==22 | ==24',
+ ... packet_len=1000,
+ ... dscp='22 | 24',
... fragment='LF | ==FF')
>>>
@@ -2173,15 +2188,62 @@ class FlowSpecIPv4NLRI(_FlowSpecNLRIBase):
class FlowSpecVPNv4NLRI(_FlowSpecNLRIBase):
"""
Flow Specification NLRI class for VPNv4 [RFC 5575]
-
- See :py:mod:`ryu.lib.packet.bgp.FlowSpecIPv4NLRI`
"""
+
+ # flow-spec NLRI:
+ # +-----------------------------------+
+ # | length (0xnn or 0xfn nn) |
+ # +-----------------------------------+
+ # | RD (8 octets) |
+ # +-----------------------------------+
+ # | NLRI value (variable) |
+ # +-----------------------------------+
ROUTE_FAMILY = RF_VPNv4_FLOW_SPEC
+ def __init__(self, length=0, route_dist=None, rules=None):
+ super(FlowSpecVPNv4NLRI, self).__init__(length, rules)
+ assert route_dist is not None
+ self.route_dist = route_dist
+
@classmethod
- def from_user(cls, **kwargs):
+ def _from_user(cls, route_dist, **kwargs):
+ rules = []
+ for k, v in kwargs.items():
+ subcls = _FlowSpecComponentBase.lookup_type_name(k)
+ rule = subcls.from_str(str(v))
+ rules.extend(rule)
+ rules.sort(key=lambda x: x.type)
+ return cls(route_dist=route_dist, rules=rules)
- return cls._from_user(**kwargs)
+ @classmethod
+ def from_user(cls, route_dist, **kwargs):
+ """
+ Utility method for creating a NLRI instance.
+
+ This function returns a NLRI instance from human readable format value.
+
+ :param route_dist: Route Distinguisher.
+ :param kwargs: See :py:mod:`ryu.lib.packet.bgp.FlowSpecIPv4NLRI`
+
+ Example::
+
+ >>> msg = bgp.FlowSpecIPv4NLRI.from_user(
+ ... route_dist='65000:1000',
+ ... dst_prefix='10.0.0.0/24',
+ ... src_prefix='20.0.0.1/24',
+ ... ip_proto=6,
+ ... port='80 | 8000',
+ ... dst_port='>9000 & <9050',
+ ... src_port='>=8500 & <=9000',
+ ... icmp_type=0,
+ ... icmp_code=6,
+ ... tcp_flags='SYN+ACK & !=URGENT',
+ ... packet_len=1000,
+ ... dscp='22 | 24',
+ ... fragment='LF | ==FF')
+ >>>
+ """
+ return cls._from_user(route_dist, **kwargs)
class _FlowSpecComponentBase(StringifyMixin, TypeDisp):
diff --git a/ryu/tests/packet_data/bgp4/flowspec_nlri_ipv4.pcap b/ryu/tests/packet_data/bgp4/flowspec_nlri_ipv4.pcap
index c7953484..885a106a 100644
--- a/ryu/tests/packet_data/bgp4/flowspec_nlri_ipv4.pcap
+++ b/ryu/tests/packet_data/bgp4/flowspec_nlri_ipv4.pcap
Binary files differ
diff --git a/ryu/tests/packet_data/bgp4/flowspec_nlri_vpn4.pcap b/ryu/tests/packet_data/bgp4/flowspec_nlri_vpn4.pcap
index 74a7d174..236110db 100644
--- a/ryu/tests/packet_data/bgp4/flowspec_nlri_vpn4.pcap
+++ b/ryu/tests/packet_data/bgp4/flowspec_nlri_vpn4.pcap
Binary files differ
diff --git a/ryu/tests/unit/packet/test_bgp.py b/ryu/tests/unit/packet/test_bgp.py
index dec1dae6..a3b7a68f 100644
--- a/ryu/tests/unit/packet/test_bgp.py
+++ b/ryu/tests/unit/packet/test_bgp.py
@@ -561,6 +561,7 @@ class Test_bgp(unittest.TestCase):
eq_(rest, b'')
msg = bgp.FlowSpecVPNv4NLRI.from_user(
+ route_dist='65001:250',
dst_prefix='10.0.0.0/24',
src_prefix='20.0.0.0/24',
ip_proto='6',
@@ -573,7 +574,7 @@ class Test_bgp(unittest.TestCase):
packet_len='1000 & 1100',
dscp='22 24',
fragment='LF ==FF&==ISF | !=DF')
- msg2 = bgp.FlowSpecVPNv4NLRI(rules=rules)
+ msg2 = bgp.FlowSpecVPNv4NLRI(route_dist='65001:250', rules=rules)
binmsg = msg.serialize()
binmsg2 = msg2.serialize()
eq_(str(msg), str(msg2))