summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorSatoshi Fujimoto <satoshi.fujimoto7@gmail.com>2017-05-09 16:09:45 +0900
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2017-05-12 09:46:37 +0900
commitbb38fb2f3032325f5dc723fe14913fa563205f19 (patch)
tree4ea73b58cc60925ad77db9e512e4a6aedf9bdbcb
parent64b9dfcdd67875e7c0e1e32c57fd3d6301269ad4 (diff)
packet/bgp: Support IPv6 Flow Spec
Signed-off-by: Satoshi Fujimoto <satoshi.fujimoto7@gmail.com> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
-rw-r--r--ryu/lib/packet/bgp.py361
1 files changed, 324 insertions, 37 deletions
diff --git a/ryu/lib/packet/bgp.py b/ryu/lib/packet/bgp.py
index d9d70c23..29c5963f 100644
--- a/ryu/lib/packet/bgp.py
+++ b/ryu/lib/packet/bgp.py
@@ -574,7 +574,9 @@ RF_IPv4_MPLS = RouteFamily(addr_family.IP, subaddr_family.MPLS_LABEL)
RF_IPv6_MPLS = RouteFamily(addr_family.IP6, subaddr_family.MPLS_LABEL)
RF_L2_EVPN = RouteFamily(addr_family.L2VPN, subaddr_family.EVPN)
RF_IPv4_FLOWSPEC = RouteFamily(addr_family.IP, subaddr_family.IP_FLOWSPEC)
+RF_IPv6_FLOWSPEC = RouteFamily(addr_family.IP6, subaddr_family.IP_FLOWSPEC)
RF_VPNv4_FLOWSPEC = RouteFamily(addr_family.IP, subaddr_family.VPN_FLOWSPEC)
+RF_VPNv6_FLOWSPEC = RouteFamily(addr_family.IP6, subaddr_family.VPN_FLOWSPEC)
RF_RTC_UC = RouteFamily(addr_family.IP,
subaddr_family.ROUTE_TARGET_CONSTRAINTS)
@@ -587,7 +589,9 @@ _rf_map = {
(addr_family.IP6, subaddr_family.MPLS_LABEL): RF_IPv6_MPLS,
(addr_family.L2VPN, subaddr_family.EVPN): RF_L2_EVPN,
(addr_family.IP, subaddr_family.IP_FLOWSPEC): RF_IPv4_FLOWSPEC,
+ (addr_family.IP6, subaddr_family.IP_FLOWSPEC): RF_IPv6_FLOWSPEC,
(addr_family.IP, subaddr_family.VPN_FLOWSPEC): RF_VPNv4_FLOWSPEC,
+ (addr_family.IP6, subaddr_family.VPN_FLOWSPEC): RF_VPNv6_FLOWSPEC,
(addr_family.IP, subaddr_family.ROUTE_TARGET_CONSTRAINTS): RF_RTC_UC
}
@@ -2035,7 +2039,8 @@ class _FlowSpecNLRIBase(StringifyMixin, TypeDisp):
rules = []
while rest:
- subcls, rest = _FlowSpecComponentBase.parse_header(rest)
+ subcls, rest = _FlowSpecComponentBase.parse_header(
+ rest, cls.ROUTE_FAMILY.afi)
while rest:
rule, rest = subcls.parse_body(rest)
@@ -2080,7 +2085,8 @@ class _FlowSpecNLRIBase(StringifyMixin, TypeDisp):
def _from_user(cls, **kwargs):
rules = []
for k, v in kwargs.items():
- subcls = _FlowSpecComponentBase.lookup_type_name(k)
+ subcls = _FlowSpecComponentBase.lookup_type_name(
+ k, cls.ROUTE_FAMILY.afi)
rule = subcls.from_str(str(v))
rules.extend(rule)
rules.sort(key=lambda x: x.type)
@@ -2236,7 +2242,8 @@ class FlowSpecVPNv4NLRI(_FlowSpecNLRIBase):
def _from_user(cls, route_dist, **kwargs):
rules = []
for k, v in kwargs.items():
- subcls = _FlowSpecComponentBase.lookup_type_name(k)
+ subcls = _FlowSpecComponentBase.lookup_type_name(
+ k, cls.ROUTE_FAMILY.afi)
rule = subcls.from_str(str(v))
rules.extend(rule)
rules.sort(key=lambda x: x.type)
@@ -2277,6 +2284,107 @@ class FlowSpecVPNv4NLRI(_FlowSpecNLRIBase):
return '%s:%s' % (self.route_dist, self.prefix)
+class FlowSpecIPv6NLRI(_FlowSpecNLRIBase):
+ """
+ Flow Specification NLRI class for IPv6 [RFC draft-ietf-idr-flow-spec-v6-08]
+ """
+ ROUTE_FAMILY = RF_IPv6_FLOWSPEC
+ FLOWSPEC_FAMILY = 'ipv6fs'
+
+ @classmethod
+ def from_user(cls, **kwargs):
+ """
+ Utility method for creating a NLRI instance.
+
+ This function returns a NLRI instance from human readable format value.
+
+ :param kwargs: The following arguments are available.
+
+ =========== ============= ========= ==============================
+ Argument Value Operator Description
+ =========== ============= ========= ==============================
+ dst_prefix IPv6 Prefix Nothing Destination Prefix.
+ src_prefix IPv6 Prefix Nothing Source Prefix.
+ next_header Integer Numeric Next Header.
+ port Integer Numeric Port number.
+ dst_port Integer Numeric Destination port number.
+ src_port Integer Numeric Source port number.
+ icmp_type Integer Numeric ICMP type.
+ icmp_code Integer Numeric ICMP code.
+ tcp_flags Fixed string Bitmask TCP flags.
+ Supported values are
+ ``CWR``, ``ECN``, ``URGENT``,
+ ``ACK``, ``PUSH``, ``RST``,
+ ``SYN`` and ``FIN``.
+ packet_len Integer Numeric Packet length.
+ dscp Integer Numeric Differentiated Services
+ Code Point.
+ fragment Fixed string Bitmask Fragment.
+ Supported values are
+ ``ISF`` (Is a fragment),
+ ``FF`` (First fragment) and
+ ``LF`` (Last fragment)
+ flow_label Intefer Numeric Flow Label.
+ =========== ============= ========= ==============================
+
+ .. Note::
+
+ For ``dst_prefix`` and ``src_prefix``, you can give "offset" value
+ like this: ``2001::2/128/32``. At this case, ``offset`` is 32.
+ ``offset`` can be omitted, then ``offset`` is treated as 0.
+ """
+ return cls._from_user(**kwargs)
+
+
+class FlowSpecVPNv6NLRI(_FlowSpecNLRIBase):
+ """
+ Flow Specification NLRI class for VPNv6 [draft-ietf-idr-flow-spec-v6-08]
+ """
+
+ # flow-spec NLRI:
+ # +-----------------------------------+
+ # | length (0xnn or 0xfn nn) |
+ # +-----------------------------------+
+ # | RD (8 octets) |
+ # +-----------------------------------+
+ # | NLRI value (variable) |
+ # +-----------------------------------+
+ ROUTE_FAMILY = RF_VPNv6_FLOWSPEC
+ FLOWSPEC_FAMILY = 'vpnv6fs'
+
+ def __init__(self, length=0, route_dist=None, rules=None):
+ super(FlowSpecVPNv6NLRI, self).__init__(length, rules)
+ assert route_dist is not None
+ self.route_dist = route_dist
+
+ @classmethod
+ def _from_user(cls, route_dist, **kwargs):
+ rules = []
+ for k, v in kwargs.items():
+ subcls = _FlowSpecComponentBase.lookup_type_name(
+ k, cls.ROUTE_FAMILY.afi)
+ rule = subcls.from_str(str(v))
+ rules.extend(rule)
+ rules.sort(key=lambda x: x.type)
+ return cls(route_dist=route_dist, rules=rules)
+
+ @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.FlowSpecIPv6NLRI`
+ """
+ return cls._from_user(route_dist, **kwargs)
+
+ @property
+ def formatted_nlri_str(self):
+ return '%s:%s' % (self.route_dist, self.prefix)
+
+
class _FlowSpecComponentBase(StringifyMixin, TypeDisp):
"""
Base class for Flow Specification NLRI component
@@ -2286,19 +2394,6 @@ class _FlowSpecComponentBase(StringifyMixin, TypeDisp):
_BASE_STR = '!B'
_BASE_STR_SIZE = struct.calcsize(_BASE_STR)
- TYPE_DESTINATION_PREFIX = 0x01
- TYPE_SOURCE_PREFIX = 0x02
- TYPE_PROTOCOL = 0x03
- TYPE_PORT = 0x04
- TYPE_DESTINATION_PORT = 0x05
- TYPE_SOURCE_PORT = 0x06
- TYPE_ICMP = 0x07
- TYPE_ICMP_CODE = 0x08
- TYPE_TCP_FLAGS = 0x09
- TYPE_PACKET_LENGTH = 0x0a
- TYPE_DIFFSERV_CODE_POINT = 0x0b
- TYPE_FRAGMENT = 0x0c
-
# Dictionary of COMPONENT_NAME to subclass.
# e.g.)
# _NAMES = {'dst_prefix': FlowSpecDestPrefix, ...}
@@ -2306,37 +2401,81 @@ class _FlowSpecComponentBase(StringifyMixin, TypeDisp):
def __init__(self, type_=None):
if type_ is None:
- type_ = self._rev_lookup_type(self.__class__)
+ type_, _ = self._rev_lookup_type(self.__class__)
self.type = type_
@classmethod
- def register_type(cls, type_):
+ def register_type(cls, type_, afi):
cls._TYPES = cls._TYPES.copy()
cls._NAMES = cls._NAMES.copy()
def _register_type(subcls):
- cls._TYPES[type_] = subcls
- cls._NAMES[subcls.COMPONENT_NAME] = subcls
+ cls._TYPES[(type_, afi)] = subcls
+ cls._NAMES[(subcls.COMPONENT_NAME, afi)] = subcls
cls._REV_TYPES = None
return subcls
return _register_type
@classmethod
- def lookup_type_name(cls, type_name):
- return cls._NAMES[type_name]
+ def lookup_type_name(cls, type_name, afi):
+ return cls._NAMES[(type_name, afi)]
@classmethod
- def parse_header(cls, rest):
+ def _lookup_type(cls, type_, afi):
+ try:
+ return cls._TYPES[(type_, afi)]
+ except KeyError:
+ return cls._UNKNOWN_TYPE
+
+ @classmethod
+ def parse_header(cls, rest, afi):
(type_,) = struct.unpack_from(
cls._BASE_STR, six.binary_type(rest))
rest = rest[cls._BASE_STR_SIZE:]
- return cls._lookup_type(type_), rest
+ return cls._lookup_type(type_, afi), rest
def serialize_header(self):
return struct.pack(self._BASE_STR, self.type)
+class _FlowSpecIPv4Component(_FlowSpecComponentBase):
+ """
+ Base class for Flow Specification for IPv4 NLRI component
+ """
+ TYPE_DESTINATION_PREFIX = 0x01
+ TYPE_SOURCE_PREFIX = 0x02
+ TYPE_PROTOCOL = 0x03
+ TYPE_PORT = 0x04
+ TYPE_DESTINATION_PORT = 0x05
+ TYPE_SOURCE_PORT = 0x06
+ TYPE_ICMP = 0x07
+ TYPE_ICMP_CODE = 0x08
+ TYPE_TCP_FLAGS = 0x09
+ TYPE_PACKET_LENGTH = 0x0a
+ TYPE_DIFFSERV_CODE_POINT = 0x0b
+ TYPE_FRAGMENT = 0x0c
+
+
+class _FlowSpecIPv6Component(_FlowSpecComponentBase):
+ """
+ Base class for Flow Specification for IPv6 NLRI component
+ """
+ TYPE_DESTINATION_PREFIX = 0x01
+ TYPE_SOURCE_PREFIX = 0x02
+ TYPE_NEXT_HEADER = 0x03
+ TYPE_PORT = 0x04
+ TYPE_DESTINATION_PORT = 0x05
+ TYPE_SOURCE_PORT = 0x06
+ TYPE_ICMP = 0x07
+ TYPE_ICMP_CODE = 0x08
+ TYPE_TCP_FLAGS = 0x09
+ TYPE_PACKET_LENGTH = 0x0a
+ TYPE_DIFFSERV_CODE_POINT = 0x0b
+ TYPE_FRAGMENT = 0x0c
+ TYPE_FLOW_LABEL = 0x0d
+
+
@_FlowSpecComponentBase.register_unknown_type()
class FlowSpecComponentUnknown(_FlowSpecComponentBase):
"""
@@ -2355,7 +2494,7 @@ class FlowSpecComponentUnknown(_FlowSpecComponentBase):
return self.buf
-class _FlowSpecPrefixBase(_FlowSpecComponentBase, IPAddrPrefix):
+class _FlowSpecPrefixBase(_FlowSpecIPv4Component, IPAddrPrefix):
"""
Prefix base class for Flow Specification NLRI component
"""
@@ -2388,8 +2527,63 @@ class _FlowSpecPrefixBase(_FlowSpecComponentBase, IPAddrPrefix):
return self.value
+class _FlowSpecIPv6PrefixBase(_FlowSpecIPv6Component, IP6AddrPrefix):
+ """
+ Prefix base class for Flow Specification NLRI component
+ """
+ _PACK_STR = '!BB' # length, offset
+
+ def __init__(self, length, addr, offset=0, type_=None):
+ super(_FlowSpecIPv6PrefixBase, self).__init__(type_)
+ self.length = length
+ self.offset = offset
+ prefix = "%s/%s" % (addr, length)
+ self.addr = str(netaddr.ip.IPNetwork(prefix).network)
+
+ @classmethod
+ def parser(cls, buf):
+ (length, offset) = struct.unpack_from(
+ cls._PACK_STR, six.binary_type(buf))
+ rest = buf[struct.calcsize(cls._PACK_STR):]
+ byte_length = (length + 7) // 8
+ addr = cls._from_bin(rest[:byte_length])
+ rest = rest[byte_length:]
+ return cls(length=length, offset=offset, addr=addr), rest
+
+ @classmethod
+ def parse_body(cls, buf):
+ return cls.parser(buf)
+
+ def serialize(self):
+ byte_length = (self.length + 7) // 8
+ bin_addr = self._to_bin(self.addr)[:byte_length]
+ buf = bytearray()
+ msg_pack_into(self._PACK_STR, buf, 0, self.length, self.offset)
+ return buf + bin_addr
+
+ def serialize_body(self):
+ return self.serialize()
+
+ @classmethod
+ def from_str(cls, value):
+ rule = []
+ values = value.split('/')
+ if len(values) == 3:
+ rule.append(cls(int(values[1]), values[0], offset=int(values[2])))
+ else:
+ rule.append(cls(int(values[1]), values[0]))
+ return rule
+
+ @property
+ def value(self):
+ return "%s/%s/%s" % (self.addr, self.length, self.offset)
+
+ def to_str(self):
+ return self.value
+
+
@_FlowSpecComponentBase.register_type(
- _FlowSpecComponentBase.TYPE_DESTINATION_PREFIX)
+ _FlowSpecIPv4Component.TYPE_DESTINATION_PREFIX, addr_family.IP)
class FlowSpecDestPrefix(_FlowSpecPrefixBase):
"""
Destination Prefix for Flow Specification NLRI component
@@ -2398,7 +2592,7 @@ class FlowSpecDestPrefix(_FlowSpecPrefixBase):
@_FlowSpecComponentBase.register_type(
- _FlowSpecComponentBase.TYPE_SOURCE_PREFIX)
+ _FlowSpecIPv4Component.TYPE_SOURCE_PREFIX, addr_family.IP)
class FlowSpecSrcPrefix(_FlowSpecPrefixBase):
"""
Source Prefix for Flow Specification NLRI component
@@ -2406,6 +2600,24 @@ class FlowSpecSrcPrefix(_FlowSpecPrefixBase):
COMPONENT_NAME = 'src_prefix'
+@_FlowSpecComponentBase.register_type(
+ _FlowSpecIPv6Component.TYPE_DESTINATION_PREFIX, addr_family.IP6)
+class FlowSpecIPv6DestPrefix(_FlowSpecIPv6PrefixBase):
+ """
+ IPv6 destination Prefix for Flow Specification NLRI component
+ """
+ COMPONENT_NAME = 'dst_prefix'
+
+
+@_FlowSpecComponentBase.register_type(
+ _FlowSpecIPv6Component.TYPE_SOURCE_PREFIX, addr_family.IP6)
+class FlowSpecIPv6SrcPrefix(_FlowSpecIPv6PrefixBase):
+ """
+ IPv6 source Prefix for Flow Specification NLRI component
+ """
+ COMPONENT_NAME = 'src_prefix'
+
+
class _FlowSpecOperatorBase(_FlowSpecComponentBase):
"""Operator base class for Flow Specification NLRI component
@@ -2604,7 +2816,8 @@ class _FlowSpecBitmask(_FlowSpecOperatorBase):
return string
-@_FlowSpecComponentBase.register_type(_FlowSpecComponentBase.TYPE_PROTOCOL)
+@_FlowSpecComponentBase.register_type(
+ _FlowSpecIPv4Component.TYPE_PROTOCOL, addr_family.IP)
class FlowSpecIPProtocol(_FlowSpecNumeric):
"""IP Protocol for Flow Specification NLRI component
@@ -2613,7 +2826,20 @@ class FlowSpecIPProtocol(_FlowSpecNumeric):
COMPONENT_NAME = 'ip_proto'
-@_FlowSpecComponentBase.register_type(_FlowSpecComponentBase.TYPE_PORT)
+@_FlowSpecComponentBase.register_type(
+ _FlowSpecIPv6Component.TYPE_NEXT_HEADER, addr_family.IP6)
+class FlowSpecNextHeader(_FlowSpecNumeric):
+ """Next Header value in IPv6 packets
+
+ Set the IP protocol number at value
+ """
+ COMPONENT_NAME = 'next_header'
+
+
+@_FlowSpecComponentBase.register_type(
+ _FlowSpecIPv4Component.TYPE_PORT, addr_family.IP)
+@_FlowSpecComponentBase.register_type(
+ _FlowSpecIPv6Component.TYPE_PORT, addr_family.IP6)
class FlowSpecPort(_FlowSpecNumeric):
"""Port number for Flow Specification NLRI component
@@ -2623,7 +2849,9 @@ class FlowSpecPort(_FlowSpecNumeric):
@_FlowSpecComponentBase.register_type(
- _FlowSpecComponentBase.TYPE_DESTINATION_PORT)
+ _FlowSpecIPv4Component.TYPE_DESTINATION_PORT, addr_family.IP)
+@_FlowSpecComponentBase.register_type(
+ _FlowSpecIPv6Component.TYPE_DESTINATION_PORT, addr_family.IP6)
class FlowSpecDestPort(_FlowSpecNumeric):
"""Destination port number for Flow Specification NLRI component
@@ -2632,7 +2860,10 @@ class FlowSpecDestPort(_FlowSpecNumeric):
COMPONENT_NAME = 'dst_port'
-@_FlowSpecComponentBase.register_type(_FlowSpecComponentBase.TYPE_SOURCE_PORT)
+@_FlowSpecComponentBase.register_type(
+ _FlowSpecIPv4Component.TYPE_SOURCE_PORT, addr_family.IP)
+@_FlowSpecComponentBase.register_type(
+ _FlowSpecIPv6Component.TYPE_SOURCE_PORT, addr_family.IP6)
class FlowSpecSrcPort(_FlowSpecNumeric):
"""Source port number for Flow Specification NLRI component
@@ -2641,7 +2872,10 @@ class FlowSpecSrcPort(_FlowSpecNumeric):
COMPONENT_NAME = 'src_port'
-@_FlowSpecComponentBase.register_type(_FlowSpecComponentBase.TYPE_ICMP)
+@_FlowSpecComponentBase.register_type(
+ _FlowSpecIPv4Component.TYPE_ICMP, addr_family.IP)
+@_FlowSpecComponentBase.register_type(
+ _FlowSpecIPv6Component.TYPE_ICMP, addr_family.IP6)
class FlowSpecIcmpType(_FlowSpecNumeric):
"""ICMP type for Flow Specification NLRI component
@@ -2650,7 +2884,10 @@ class FlowSpecIcmpType(_FlowSpecNumeric):
COMPONENT_NAME = 'icmp_type'
-@_FlowSpecComponentBase.register_type(_FlowSpecComponentBase.TYPE_ICMP_CODE)
+@_FlowSpecComponentBase.register_type(
+ _FlowSpecIPv4Component.TYPE_ICMP_CODE, addr_family.IP)
+@_FlowSpecComponentBase.register_type(
+ _FlowSpecIPv6Component.TYPE_ICMP_CODE, addr_family.IP6)
class FlowSpecIcmpCode(_FlowSpecNumeric):
"""ICMP code Flow Specification NLRI component
@@ -2659,7 +2896,10 @@ class FlowSpecIcmpCode(_FlowSpecNumeric):
COMPONENT_NAME = 'icmp_code'
-@_FlowSpecComponentBase.register_type(_FlowSpecComponentBase.TYPE_TCP_FLAGS)
+@_FlowSpecComponentBase.register_type(
+ _FlowSpecIPv4Component.TYPE_TCP_FLAGS, addr_family.IP)
+@_FlowSpecComponentBase.register_type(
+ _FlowSpecIPv6Component.TYPE_TCP_FLAGS, addr_family.IP6)
class FlowSpecTCPFlags(_FlowSpecBitmask):
"""TCP flags for Flow Specification NLRI component
@@ -2694,7 +2934,9 @@ class FlowSpecTCPFlags(_FlowSpecBitmask):
@_FlowSpecComponentBase.register_type(
- _FlowSpecComponentBase.TYPE_PACKET_LENGTH)
+ _FlowSpecIPv4Component.TYPE_PACKET_LENGTH, addr_family.IP)
+@_FlowSpecComponentBase.register_type(
+ _FlowSpecIPv6Component.TYPE_PACKET_LENGTH, addr_family.IP6)
class FlowSpecPacketLen(_FlowSpecNumeric):
"""Packet length for Flow Specification NLRI component
@@ -2704,7 +2946,9 @@ class FlowSpecPacketLen(_FlowSpecNumeric):
@_FlowSpecComponentBase.register_type(
- _FlowSpecComponentBase.TYPE_DIFFSERV_CODE_POINT)
+ _FlowSpecIPv4Component.TYPE_DIFFSERV_CODE_POINT, addr_family.IP)
+@_FlowSpecComponentBase.register_type(
+ _FlowSpecIPv6Component.TYPE_DIFFSERV_CODE_POINT, addr_family.IP6)
class FlowSpecDSCP(_FlowSpecNumeric):
"""Diffserv Code Point for Flow Specification NLRI component
@@ -2713,7 +2957,8 @@ class FlowSpecDSCP(_FlowSpecNumeric):
COMPONENT_NAME = 'dscp'
-@_FlowSpecComponentBase.register_type(_FlowSpecComponentBase.TYPE_FRAGMENT)
+@_FlowSpecComponentBase.register_type(
+ _FlowSpecIPv4Component.TYPE_FRAGMENT, addr_family.IP)
class FlowSpecFragment(_FlowSpecBitmask):
"""Fragment for Flow Specification NLRI component
@@ -2749,6 +2994,43 @@ class FlowSpecFragment(_FlowSpecBitmask):
_bitmask_flags[DF] = 'DF'
+@_FlowSpecComponentBase.register_type(
+ _FlowSpecIPv6Component.TYPE_FRAGMENT, addr_family.IP6)
+class FlowSpecIPv6Fragment(_FlowSpecBitmask):
+ """Fragment for Flow Specification for IPv6 NLRI component
+
+ ========== ===============================================
+ Attribute Description
+ ========== ===============================================
+ LF Last fragment
+ FF First fragment
+ ISF Is a fragment
+ ========== ===============================================
+ """
+ COMPONENT_NAME = 'fragment'
+
+ # bitmask format
+ # 0 1 2 3 4 5 6 7
+ # +---+---+---+---+---+---+---+---+
+ # | Reserved |LF |FF |IsF| 0 |
+ # +---+---+---+---+---+---+---+---+
+
+ LF = 1 << 3
+ FF = 1 << 2
+ ISF = 1 << 1
+
+ _bitmask_flags = collections.OrderedDict()
+ _bitmask_flags[LF] = 'LF'
+ _bitmask_flags[FF] = 'FF'
+ _bitmask_flags[ISF] = 'ISF'
+
+
+@_FlowSpecComponentBase.register_type(
+ _FlowSpecIPv6Component.TYPE_FLOW_LABEL, addr_family.IP6)
+class FlowSpecIPv6FlowLabel(_FlowSpecNumeric):
+ COMPONENT_NAME = 'flow_label'
+
+
@functools.total_ordering
class RouteTargetMembershipNLRI(StringifyMixin):
"""Route Target Membership NLRI.
@@ -2860,7 +3142,9 @@ _ADDR_CLASSES = {
_addr_class_key(RF_IPv6_VPN): LabelledVPNIP6AddrPrefix,
_addr_class_key(RF_L2_EVPN): EvpnNLRI,
_addr_class_key(RF_IPv4_FLOWSPEC): FlowSpecIPv4NLRI,
+ _addr_class_key(RF_IPv6_FLOWSPEC): FlowSpecIPv6NLRI,
_addr_class_key(RF_VPNv4_FLOWSPEC): FlowSpecVPNv4NLRI,
+ _addr_class_key(RF_VPNv6_FLOWSPEC): FlowSpecVPNv6NLRI,
_addr_class_key(RF_RTC_UC): RouteTargetMembershipNLRI,
}
@@ -4077,6 +4361,9 @@ class BGPFlowSpecTrafficMarkingCommunity(_ExtendedCommunity):
return struct.pack(self._VALUE_PACK_STR, self.subtype, self.dscp)
+# TODO
+# Implement "Redirect-IPv6" [draft-ietf-idr-flow-spec-v6-08]
+
@_ExtendedCommunity.register_unknown_type()
class BGPUnknownExtendedCommunity(_ExtendedCommunity):
_VALUE_PACK_STR = '!7s' # opaque value