diff --git a/etc/exabgp/conf-srv6-mup-v3.conf b/etc/exabgp/conf-srv6-mup-v3.conf new file mode 100644 index 000000000..7b03ffae5 --- /dev/null +++ b/etc/exabgp/conf-srv6-mup-v3.conf @@ -0,0 +1,25 @@ +neighbor 127.0.0.1 { + router-id 10.0.0.1; + local-address 127.0.0.1; + local-as 65000; + peer-as 65000; + + family { + ipv4 mup; + ipv6 mup; + } + announce { + ipv4 { + mup \ + mup-t1st 192.168.0.2/32 rd 100:100 teid 12345 qfi 9 endpoint 10.0.0.1 source 10.0.1.1 \ + next-hop 10.0.0.2 \ + extended-community [ target:10:10 ]; + } + ipv6 { + mup \ + mup-t1st 2001:db8:1:1::2/128 rd 100:100 teid 12345 qfi 9 endpoint 2001::1 source 2002::2 \ + next-hop 10.0.0.2 \ + extended-community [ target:10:10 ]; + } + } +} diff --git a/etc/exabgp/conf-srv6-mup.conf b/etc/exabgp/conf-srv6-mup.conf index c333881f2..3b7bade19 100644 --- a/etc/exabgp/conf-srv6-mup.conf +++ b/etc/exabgp/conf-srv6-mup.conf @@ -56,7 +56,7 @@ neighbor 127.0.0.1 { bgp-prefix-sid-srv6 ( l3-service 2001:db8:2:2:: 0x18 [64,24,16,0,0,0] ); mup \ - mup-t1st 2001:db8:1:1::1/128 rd 100:100 teid 12345 qfi 9 endpoint 2001::1\ + mup-t1st 2001:db8:1:1::1/128 rd 100:100 teid 12345 qfi 9 endpoint 2001::1 \ next-hop 10.0.0.2 \ extended-community [ target:10:10 ]; diff --git a/qa/encoding/conf-srv6-mup-v3.ci b/qa/encoding/conf-srv6-mup-v3.ci new file mode 100644 index 000000000..3f6ddfa38 --- /dev/null +++ b/qa/encoding/conf-srv6-mup-v3.ci @@ -0,0 +1 @@ +conf-srv6-mup-v3.conf diff --git a/qa/encoding/conf-srv6-mup-v3.msg b/qa/encoding/conf-srv6-mup-v3.msg new file mode 100644 index 000000000..da2c88ee7 --- /dev/null +++ b/qa/encoding/conf-srv6-mup-v3.msg @@ -0,0 +1,2 @@ +1:raw:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:0063:02:0000004C400101004002004003040A00000240050400000064C010080002000A0000000A800E29000155040A000002000100031C000000640000006420C0A800020000303909200A000001200A000101 +1:raw:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:008C:02:000000754001010040020040050400000064C010080002000A0000000A800E590002551000000000000000000000FFFF0A000002000100034000000064000000648020010DB8000100010000000000000002000030390980200100000000000000000000000000018020020000000000000000000000000002 diff --git a/src/exabgp/bgp/message/update/nlri/mup/t1st.py b/src/exabgp/bgp/message/update/nlri/mup/t1st.py index 5a58f6f23..d1f895592 100644 --- a/src/exabgp/bgp/message/update/nlri/mup/t1st.py +++ b/src/exabgp/bgp/message/update/nlri/mup/t1st.py @@ -25,15 +25,19 @@ # +-----------------------------------+ # 3gpp-5g Specific BGP Type 1 ST Route -# +-----------------------------------+ -# | TEID (4 octets) | -# +-----------------------------------+ -# | QFI (1 octet) | -# +-----------------------------------+ -# | Endpoint Address Length (1 octet) | -# +-----------------------------------+ -# | Endpoint Address (variable) | -# +-----------------------------------+ +# +-----------------------------------+ +# | TEID (4 octets) | +# +-----------------------------------+ +# | QFI (1 octet) | +# +-----------------------------------+ +# | Endpoint Address Length (1 octet) | +# +-----------------------------------+ +# | Endpoint Address (variable) | +# +-----------------------------------+ +# | Source Address Length (1 octet) | +# +-----------------------------------+ +# | Source Address (variable) | +# +-----------------------------------+ @MUP.register @@ -53,6 +57,8 @@ def __init__( endpoint_ip_len, endpoint_ip, afi, + source_ip_len, + source_ip, packed=None, ): MUP.__init__(self, afi) @@ -63,6 +69,8 @@ def __init__( self.qfi = qfi self.endpoint_ip_len = endpoint_ip_len self.endpoint_ip = endpoint_ip + self.source_ip_len = source_ip_len + self.source_ip = source_ip self._pack(packed) def __eq__(self, other): @@ -77,23 +85,30 @@ def __eq__(self, other): and self.qfi == other.qfi and self.endpoint_ip_len == other.endpoint_ip_len and self.endpoint_ip == other.endpoint_ip + and self.source_ip_len == other.source_ip_len + and self.source_ip == other.source_ip ) def __ne__(self, other): return not self.__eq__(other) def __str__(self): - return "%s:%s:%s%s:%s:%s:%s:%s" % ( + s = "%s:%s:%s%s:%s:%s:%s%s" % ( self._prefix(), self.rd._str(), self.ipprefix, "/%d" % self.ipprefix_len, self.teid, self.qfi, - self.endpoint_ip_len, self.endpoint_ip, + "/%d" % self.ipprefix_len, ) + if self.source_ip_len != 0 and self.source_ip != b'': + s += ":%s/%d" % (self.source_ip, self.source_ip_len) + + return s + def pack_index(self): # removed teid, qfi, endpointip packed = self.rd.pack() + pack('!B', self.ipprefix_len) + self.ipprefix.pack() @@ -112,6 +127,8 @@ def __hash__(self): self.qfi, self.endpoint_ip_len, self.endpoint_ip, + self.source_ip_len, + self.source_ip, ) ) @@ -129,6 +146,7 @@ def _pack(self, packed=None): offset += 1 ipprefix_packed = self.ipprefix.pack() + # fmt: off self._packed = ( self.rd.pack() @@ -138,11 +156,16 @@ def _pack(self, packed=None): + pack('!B',self.endpoint_ip_len) + self.endpoint_ip.pack() ) + + if self.source_ip_len != 0: + self._packed += pack('!B', self.source_ip_len) + self.source_ip.pack() + # fmt: on return self._packed @classmethod def unpack(cls, data, afi): + datasize = len(data) rd = RouteDistinguisher.unpack(data[:8]) ipprefix_len = data[8] ip_offset = ipprefix_len // 8 @@ -165,8 +188,24 @@ def unpack(cls, data, afi): size += 1 endpoint_ip_len = data[size] size += 1 - endpoint_ip = IP.unpack(data[size:]) - return cls(rd, ipprefix_len, ipprefix, teid, qfi, endpoint_ip_len, endpoint_ip, afi) + + if endpoint_ip_len in [32, 128]: + endpoint_ip = IP.unpack(data[size : size + endpoint_ip_len]) + size += endpoint_ip_len + else: + raise RuntimeError('mup t1st endpoint ip length is not 32bit or 128bit, unexpect len: %d' % endpoint_ip_len) + + source_ip_size = datasize - size + if 0 < source_ip_size: + source_ip_len = data[size] + size += 1 + if source_ip_len in [32, 128]: + source_ip = IP.unpack(data[size : size + source_ip_len]) + size += source_ip_len + else: + raise RuntimeError('mup t1st source ip length is not 32bit or 128bit, unexpect len: %d' % source_ip_len) + + return cls(rd, ipprefix_len, ipprefix, teid, qfi, endpoint_ip_len, endpoint_ip, source_ip_len, source_ip, afi) def json(self, compact=None): content = '"arch": %d, ' % self.ARCHTYPE @@ -180,4 +219,6 @@ def json(self, compact=None): content += '"qfi": "%s", ' % str(self.qfi) content += '"endpoint_ip_len": %d, ' % self.endpoint_ip_len content += '"endpoint_ip": "%s"' % str(self.endpoint_ip) + content += '"source_ip_len": %d, ' % self.source_ip_len + content += '"source_ip": "%s"' % str(self.source_ip) return '{ %s }' % content diff --git a/src/exabgp/configuration/announce/mup.py b/src/exabgp/configuration/announce/mup.py index 68a859236..8e80614ea 100644 --- a/src/exabgp/configuration/announce/mup.py +++ b/src/exabgp/configuration/announce/mup.py @@ -32,7 +32,7 @@ class AnnounceMup(ParseAnnounce): definition = [ 'mup-isd rd ', 'mup-dsd rd ', - 'mup-t1st rd teid qfi endpoint ', + 'mup-t1st rd teid qfi endpoint [source ]', 'mup-t2st rd teid ', 'next-hop ', 'extended-community [ mup:<16 bits number>: target:<16 bits number>: ]', diff --git a/src/exabgp/configuration/static/mpls.py b/src/exabgp/configuration/static/mpls.py index 87d60836a..192417872 100644 --- a/src/exabgp/configuration/static/mpls.py +++ b/src/exabgp/configuration/static/mpls.py @@ -248,7 +248,7 @@ def srv6_mup_dsd(tokeniser, afi): ) -# 'mup-t1st rd teid qfi endpoint ', +# 'mup-t1st rd teid qfi endpoint [source ]', def srv6_mup_t1st(tokeniser, afi): ip, length = parse_ip_prefix(tokeniser()) @@ -283,6 +283,19 @@ def srv6_mup_t1st(tokeniser, afi): else: raise Exception("expect endpoint, but received '%s'" % value) + source_ip = b"" + source_ip_len = 0 + if "source" == tokeniser.peek(): + tokeniser() + if afi == AFI.ipv4: + source_ip = IPv4.unpack(IPv4.pton(tokeniser())) + source_ip_len = 32 + elif afi == AFI.ipv6: + source_ip = IPv6.unpack(IPv6.pton(tokeniser())) + source_ip_len = 128 + else: + raise Exception("unexpect afi: %s" % afi) + return Type1SessionTransformedRoute( rd=rd, ipprefix_len=int(length), @@ -290,8 +303,10 @@ def srv6_mup_t1st(tokeniser, afi): teid=int(teid), qfi=int(qfi), afi=afi, - endpoint_ip=endpoint_ip, endpoint_ip_len=int(endpoint_ip_len), + endpoint_ip=endpoint_ip, + source_ip_len=int(source_ip_len), + source_ip=source_ip, )