diff --git a/etc/exabgp/conf-srv6-mup.conf b/etc/exabgp/conf-srv6-mup.conf index c333881f2..cb35ce47d 100644 --- a/etc/exabgp/conf-srv6-mup.conf +++ b/etc/exabgp/conf-srv6-mup.conf @@ -27,6 +27,11 @@ neighbor 127.0.0.1 { next-hop 10.0.0.2 \ extended-community [ target:10:10 ]; + 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 ]; + mup \ mup-t2st 10.0.0.1 rd 100:100 teid 12345/32 \ next-hop 10.0.0.2 \ @@ -56,7 +61,12 @@ 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 ]; + + 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/qa/encoding/conf-srv6-mup.msg b/qa/encoding/conf-srv6-mup.msg index d81bf2f44..a90c4e0ad 100644 --- a/qa/encoding/conf-srv6-mup.msg +++ b/qa/encoding/conf-srv6-mup.msg @@ -1,10 +1,12 @@ 1:raw:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:0080:02:000000694001010040020040050400000064C010080002000A0000000AC028250500220001001E0020010DB800010001000000000000000000004800010006401810000000800E250001551020010000000000000000000000000001000100010C0000006400000064180A0001 1:raw:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:0088:02:000000714001010040020040050400000064C010100002000A0000000A0C00000A0000000AC028250500220001001E0020010DB800010001000000000000000000001300010006401810000000800E250001551020010000000000000000000000000002000100020C00000064000000640A000001 1:raw:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:005E:02:00000047400101004002004003040A00000240050400000064C010080002000A0000000A800E24000155040A0000020001000317000000640000006420C0A800010000303909200A000001 +1:raw:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:0063:02:0000004C400101004002004003040A00000240050400000064C010080002000A0000000A800E29000155040A000002000100031C000000640000006420C0A800020000303909200A000001200A000101 1:raw:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:0060:02:00000049400101004002004003040A00000240050400000064C010100002000A0000000A0C00000A0000000A800E1E000155040A00000200010004110000006400000064400A00000100003039 1:raw:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:005F:02:00000048400101004002004003040A00000240050400000064C010100002000A0000000A0C00000A0000000A800E1D000155040A00000200010004100000006400000064370A000001000030 1:raw:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:005C:02:00000045400101004002004003040A00000240050400000064C010100002000A0000000A0C00000A0000000A800E1A000155040A000002000100040D0000006400000064200A000001 1:raw:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:0085:02:0000006E4001010040020040050400000064C010080002000A0000000AC028250500220001001E0020010DB800010001000000000000000000004700010006401810000000800E2A000255102001000000000000000000000000000200010001110000006400000064402001000000000000 1:raw:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:0094:02:0000007D4001010040020040050400000064C010100002000A0000000A0C00000A0000000AC028250500220001001E0020010DB800020002000000000000000000001800010006401810000000800E3100025510200100000000000000000000000000020001000218000000640000006420010000000000000000000000000001 1:raw:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:007B:02:000000644001010040020040050400000064C010080002000A0000000A800E480002551000000000000000000000FFFF0A000002000100032F00000064000000648020010DB800010001000000000000000100003039098020010000000000000000000000000001 +1:raw:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:008C:02:000000754001010040020040050400000064C010080002000A0000000A800E590002551000000000000000000000FFFF0A000002000100034000000064000000648020010DB8000100010000000000000002000030390980200100000000000000000000000000018020020000000000000000000000000002 1:raw:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:0071:02:0000005A4001010040020040050400000064C010100002000A0000000A0C00000A0000000A800E360002551000000000000000000000FFFF0A000002000100041D0000006400000064A02001000000000000000000000000000100003039 diff --git a/src/exabgp/bgp/message/update/nlri/mup/t1st.py b/src/exabgp/bgp/message/update/nlri/mup/t1st.py index 5a58f6f23..e67cb52ac 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,13 +85,15 @@ 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" % ( + return "%s:%s:%s%s:%s:%s:%s:%s:%s:%s" % ( self._prefix(), self.rd._str(), self.ipprefix, @@ -92,6 +102,8 @@ def __str__(self): self.qfi, self.endpoint_ip_len, self.endpoint_ip, + self.source_ip_len, + self.source_ip, ) def pack_index(self): @@ -112,6 +124,8 @@ def __hash__(self): self.qfi, self.endpoint_ip_len, self.endpoint_ip, + self.source_ip_len, + self.source_ip, ) ) @@ -129,6 +143,7 @@ def _pack(self, packed=None): offset += 1 ipprefix_packed = self.ipprefix.pack() + # fmt: off self._packed = ( self.rd.pack() @@ -138,11 +153,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 +185,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('endpoint ip length is not 4 or 16') + + source_ip_size = datasize - size + if 0 < source_ip_size: + source_ip_len = data[size] + size += 1 + if source_ip_len in [4, 16]: + source_ip = IP.unpack(data[size : size + source_ip_len]) + size += source_ip_len + else: + raise RuntimeError('source ip length is not 4 or 16') + + 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 +216,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, )