diff --git a/doc/man/exabgp.1 b/doc/man/exabgp.1 index 2213158f1..7d6a85c5c 100644 --- a/doc/man/exabgp.1 +++ b/doc/man/exabgp.1 @@ -348,6 +348,8 @@ The Accumulated IGP Metric Attribute for BGP Rules for IPv6 .It draft-simpson-idr-flowspec-redirect-00 (-02) BGP Flow-Spec Redirect to IP Action +.It draft-ietf-idr-flowspec-redirect-00 (-02) +BGP Flow-Spec Redirect to IP Action .It draft-ietf-idr-add-paths-08 (-10) Advertisement of Multiple Paths in BGP .It draft-ietf-idr-bgp-multisession-07 (??) diff --git a/doc/man/exabgp.conf.5 b/doc/man/exabgp.conf.5 index 0fa65cfa5..7e5fc32bf 100644 --- a/doc/man/exabgp.conf.5 +++ b/doc/man/exabgp.conf.5 @@ -127,6 +127,7 @@ group { rate-limit ; redirect ( | ); redirect-to-nexthop; // Ref. next-hop above + redirect-to-nexthop-ietf ; copy ; mark ; action ( sample | terminal | sample-terminal ); diff --git a/lib/exabgp/bgp/message/update/attribute/community/extended/__init__.py b/lib/exabgp/bgp/message/update/attribute/community/extended/__init__.py index 3b7a18bad..373c9aad2 100644 --- a/lib/exabgp/bgp/message/update/attribute/community/extended/__init__.py +++ b/lib/exabgp/bgp/message/update/attribute/community/extended/__init__.py @@ -27,6 +27,7 @@ from exabgp.bgp.message.update.attribute.community.extended.traffic import TrafficRedirect from exabgp.bgp.message.update.attribute.community.extended.traffic import TrafficRedirectASN4 from exabgp.bgp.message.update.attribute.community.extended.traffic import TrafficMark +from exabgp.bgp.message.update.attribute.community.extended.traffic import TrafficNextHopIPv4IETF from exabgp.bgp.message.update.attribute.community.extended.traffic import TrafficNextHopSimpson from exabgp.bgp.message.update.attribute.community.extended.encapsulation import Encapsulation from exabgp.bgp.message.update.attribute.community.extended.chso import ConsistentHashSortOrder diff --git a/lib/exabgp/bgp/message/update/attribute/community/extended/traffic.py b/lib/exabgp/bgp/message/update/attribute/community/extended/traffic.py index d424c62b2..7f1ecd520 100644 --- a/lib/exabgp/bgp/message/update/attribute/community/extended/traffic.py +++ b/lib/exabgp/bgp/message/update/attribute/community/extended/traffic.py @@ -10,6 +10,7 @@ from struct import pack from struct import unpack +from exabgp.protocol.ip import IPv4 from exabgp.bgp.message.open.asn import ASN from exabgp.bgp.message.open.capability.asn4 import ASN4 from exabgp.bgp.message.update.attribute.community.extended import ExtendedCommunity @@ -96,7 +97,7 @@ def unpack (data): # ============================================================== TrafficRedirect -# RFC 5575 +# RFC 5575 and 7674 @ExtendedCommunity.register class TrafficRedirect (ExtendedCommunity): @@ -182,6 +183,38 @@ def unpack (data): dscp, = unpack('!B',data[7:8]) return TrafficMark(dscp,data[:8]) +# =============================================================== TrafficNextHopIPv4IETF +# draft-ietf-idr-flowspec-redirect-02 +# see RFC 4360 for ipv4 address specific extended community format + +@ExtendedCommunity.register +class TrafficNextHopIPv4IETF (ExtendedCommunity): + COMMUNITY_TYPE = 0x01 + COMMUNITY_SUBTYPE = 0x0C + + __slots__ = ['ip', 'copy'] + + def __init__ (self, ip, copy, community=None): + self.ip = ip + self.copy = copy + ExtendedCommunity.__init__( + self, + community if community is not None else pack( + "!2s4sH", + self._subtype(), + ip.pack(), + 1 if copy else 0 + ) + ) + + def __repr__ (self): + return "copy-to-nexthop-ietf" if self.copy else "redirect-to-nexthop-ietf" + + @staticmethod + def unpack (data): + ip, bit = unpack('!4sH', data[2:8]) + return TrafficNextHopIPv4IETF(IPv4.ntop(ip), bool(bit & 0x01), data[:8]) + # =============================================================== TrafficNextHopSimpson # draft-simpson-idr-flowspec-redirect-02 diff --git a/lib/exabgp/configuration/announce/flow.py b/lib/exabgp/configuration/announce/flow.py index b1d703af4..2e119b7bb 100644 --- a/lib/exabgp/configuration/announce/flow.py +++ b/lib/exabgp/configuration/announce/flow.py @@ -38,6 +38,7 @@ from exabgp.configuration.flow.parser import rate_limit from exabgp.configuration.flow.parser import redirect from exabgp.configuration.flow.parser import redirect_next_hop +from exabgp.configuration.flow.parser import redirect_next_hop_ietf from exabgp.configuration.flow.parser import copy from exabgp.configuration.flow.parser import mark from exabgp.configuration.flow.parser import action @@ -106,17 +107,18 @@ class AnnounceFlow (ParseAnnounce): 'fragment': fragment, 'flow-label': flow_label, - 'accept': accept, - 'discard': discard, - 'rate-limit': rate_limit, - 'redirect': redirect, - 'redirect-to-nexthop': redirect_next_hop, - 'copy': copy, - 'mark': mark, - 'action': action, - 'community': community, - 'large-community': large_community, - 'extended-community': extended_community, + 'accept': accept, + 'discard': discard, + 'rate-limit': rate_limit, + 'redirect': redirect, + 'redirect-to-nexthop': redirect_next_hop, + 'redirect-to-nexthop-ietf': redirect_next_hop_ietf, + 'copy': copy, + 'mark': mark, + 'action': action, + 'community': community, + 'large-community': large_community, + 'extended-community': extended_community, 'interface-set': interface_set, } @@ -145,19 +147,19 @@ class AnnounceFlow (ParseAnnounce): 'traffic-class': 'nlri-add', 'flow-label': 'nlri-add', - 'accept': 'nop', - 'discard': 'attribute-add', - 'rate-limit': 'attribute-add', - 'redirect': 'nexthop-and-attribute', - 'redirect-to-nexthop': 'attribute-add', - 'copy': 'nexthop-and-attribute', - 'mark': 'attribute-add', - 'action': 'attribute-add', - 'community': 'attribute-add', - 'large-community': 'attribute-add', - 'extended-community': 'attribute-add', - - 'interface-set': 'attribute-add', + 'accept': 'nop', + 'discard': 'attribute-add', + 'rate-limit': 'attribute-add', + 'redirect': 'nexthop-and-attribute', + 'redirect-to-nexthop': 'attribute-add', + 'redirect-to-nexthop-ietf': 'attribute-add', + 'copy': 'nexthop-and-attribute', + 'mark': 'attribute-add', + 'action': 'attribute-add', + 'community': 'attribute-add', + 'large-community': 'attribute-add', + 'extended-community': 'attribute-add', + 'interface-set': 'attribute-add', } assign = dict() diff --git a/lib/exabgp/configuration/flow/parser.py b/lib/exabgp/configuration/flow/parser.py index ba524d613..d8c852ff5 100644 --- a/lib/exabgp/configuration/flow/parser.py +++ b/lib/exabgp/configuration/flow/parser.py @@ -37,6 +37,7 @@ from exabgp.bgp.message.update.attribute.community.extended import TrafficRedirect from exabgp.bgp.message.update.attribute.community.extended import TrafficRedirectASN4 from exabgp.bgp.message.update.attribute.community.extended import TrafficMark +from exabgp.bgp.message.update.attribute.community.extended import TrafficNextHopIPv4IETF from exabgp.bgp.message.update.attribute.community.extended import TrafficNextHopSimpson from exabgp.bgp.message.update.attribute.community.extended import InterfaceSet @@ -296,6 +297,12 @@ def redirect (tokeniser): def redirect_next_hop (tokeniser): return ExtendedCommunities().add(TrafficNextHopSimpson(False)) +def redirect_next_hop_ietf (tokeniser): + ip = IP.create(tokeniser()) + if ip.ipv4(): + return ExtendedCommunities().add(TrafficNextHopIPv4IETF(ip, False)) + else: + raise ValueError('ipv6 address not supported %s' % ip) def copy (tokeniser): return IP.create(tokeniser()),ExtendedCommunities().add(TrafficNextHopSimpson(True)) diff --git a/lib/exabgp/configuration/flow/then.py b/lib/exabgp/configuration/flow/then.py index 12ed77ab8..c7ad0845c 100644 --- a/lib/exabgp/configuration/flow/then.py +++ b/lib/exabgp/configuration/flow/then.py @@ -14,6 +14,7 @@ from exabgp.configuration.flow.parser import rate_limit from exabgp.configuration.flow.parser import redirect from exabgp.configuration.flow.parser import redirect_next_hop +from exabgp.configuration.flow.parser import redirect_next_hop_ietf from exabgp.configuration.flow.parser import copy from exabgp.configuration.flow.parser import mark from exabgp.configuration.flow.parser import action @@ -43,33 +44,35 @@ class ParseFlowThen (Section): '}' % ';\n '.join(definition) known = { - 'accept': accept, - 'discard': discard, - 'rate-limit': rate_limit, - 'redirect': redirect, - 'redirect-to-nexthop': redirect_next_hop, - 'copy': copy, - 'mark': mark, - 'action': action, - 'community': community, - 'large-community': large_community, - 'extended-community': extended_community, + 'accept': accept, + 'discard': discard, + 'rate-limit': rate_limit, + 'redirect': redirect, + 'redirect-to-nexthop': redirect_next_hop, + 'redirect-to-nexthop-ietf': redirect_next_hop_ietf, + 'copy': copy, + 'mark': mark, + 'action': action, + 'community': community, + 'large-community': large_community, + 'extended-community': extended_community, } # 'community','extended-community' action = { - 'accept': 'nop', - 'discard': 'attribute-add', - 'rate-limit': 'attribute-add', - 'redirect': 'nexthop-and-attribute', - 'redirect-to-nexthop': 'attribute-add', - 'copy': 'nexthop-and-attribute', - 'mark': 'attribute-add', - 'action': 'attribute-add', - 'community': 'attribute-add', - 'large-community': 'attribute-add', - 'extended-community': 'attribute-add', + 'accept': 'nop', + 'discard': 'attribute-add', + 'rate-limit': 'attribute-add', + 'redirect': 'nexthop-and-attribute', + 'redirect-to-nexthop': 'attribute-add', + 'redirect-to-nexthop-ietf': 'attribute-add', + 'copy': 'nexthop-and-attribute', + 'mark': 'attribute-add', + 'action': 'attribute-add', + 'community': 'attribute-add', + 'large-community': 'attribute-add', + 'extended-community': 'attribute-add', } name = 'flow/then'