From 06af56ebb42c090a6d90646c5e5155b2d9211ef4 Mon Sep 17 00:00:00 2001 From: Yuya Kusakabe Date: Thu, 1 Sep 2022 10:34:52 +0900 Subject: [PATCH 1/2] pkg/packet/bgp,api: add SRv6 behavior for SRv6 MUP - End.M.GTP6.D: 45 - End.M.GTP6.Di: 46 - End.M.GTP6.E: 47 - End.M.GTP4.E: 48 https://www.iana.org/assignments/segment-routing/segment-routing.xhtml --- api/attribute.pb.go | 34 +++++++++++++++++++++++++--------- api/attribute.proto | 4 ++++ pkg/packet/bgp/srbehavior.go | 4 ++++ 3 files changed, 33 insertions(+), 9 deletions(-) diff --git a/api/attribute.pb.go b/api/attribute.pb.go index 3725bb878..c066f3ed6 100644 --- a/api/attribute.pb.go +++ b/api/attribute.pb.go @@ -260,6 +260,10 @@ const ( SRv6Behavior_ENDT_WITH_PSP_USD SRv6Behavior = 37 SRv6Behavior_ENDT_WITH_USP_USD SRv6Behavior = 38 SRv6Behavior_ENDT_WITH_PSP_USP_USD SRv6Behavior = 39 + SRv6Behavior_ENDM_GTP6D SRv6Behavior = 45 + SRv6Behavior_ENDM_GTP6DI SRv6Behavior = 46 + SRv6Behavior_ENDM_GTP6E SRv6Behavior = 47 + SRv6Behavior_ENDM_GTP4E SRv6Behavior = 48 ) // Enum value maps for SRv6Behavior. @@ -302,6 +306,10 @@ var ( 37: "ENDT_WITH_PSP_USD", 38: "ENDT_WITH_USP_USD", 39: "ENDT_WITH_PSP_USP_USD", + 45: "ENDM_GTP6D", + 46: "ENDM_GTP6DI", + 47: "ENDM_GTP6E", + 48: "ENDM_GTP4E", } SRv6Behavior_value = map[string]int32{ "RESERVED": 0, @@ -341,6 +349,10 @@ var ( "ENDT_WITH_PSP_USD": 37, "ENDT_WITH_USP_USD": 38, "ENDT_WITH_PSP_USP_USD": 39, + "ENDM_GTP6D": 45, + "ENDM_GTP6DI": 46, + "ENDM_GTP6E": 47, + "ENDM_GTP4E": 48, } ) @@ -8466,7 +8478,7 @@ var file_attribute_proto_rawDesc = []byte{ 0x45, 0x43, 0x54, 0x10, 0x04, 0x12, 0x16, 0x0a, 0x12, 0x4c, 0x53, 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x49, 0x43, 0x10, 0x05, 0x12, 0x17, 0x0a, 0x13, 0x4c, 0x53, 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x4f, 0x53, 0x50, - 0x46, 0x5f, 0x56, 0x33, 0x10, 0x06, 0x2a, 0xac, 0x05, 0x0a, 0x0c, 0x53, 0x52, 0x76, 0x36, 0x42, + 0x46, 0x5f, 0x56, 0x33, 0x10, 0x06, 0x2a, 0xed, 0x05, 0x0a, 0x0c, 0x53, 0x52, 0x76, 0x36, 0x42, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x45, 0x53, 0x45, 0x52, 0x56, 0x45, 0x44, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x45, 0x4e, 0x44, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x45, 0x4e, 0x44, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x50, 0x53, 0x50, 0x10, 0x02, @@ -8509,14 +8521,18 @@ var file_attribute_proto_rawDesc = []byte{ 0x44, 0x10, 0x25, 0x12, 0x15, 0x0a, 0x11, 0x45, 0x4e, 0x44, 0x54, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x55, 0x53, 0x50, 0x5f, 0x55, 0x53, 0x44, 0x10, 0x26, 0x12, 0x19, 0x0a, 0x15, 0x45, 0x4e, 0x44, 0x54, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x5f, 0x50, 0x53, 0x50, 0x5f, 0x55, 0x53, 0x50, 0x5f, - 0x55, 0x53, 0x44, 0x10, 0x27, 0x2a, 0x44, 0x0a, 0x08, 0x45, 0x4e, 0x4c, 0x50, 0x54, 0x79, 0x70, - 0x65, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x10, 0x00, 0x12, - 0x09, 0x0a, 0x05, 0x54, 0x79, 0x70, 0x65, 0x31, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x54, 0x79, - 0x70, 0x65, 0x32, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x54, 0x79, 0x70, 0x65, 0x33, 0x10, 0x03, - 0x12, 0x09, 0x0a, 0x05, 0x54, 0x79, 0x70, 0x65, 0x34, 0x10, 0x04, 0x42, 0x24, 0x5a, 0x22, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x73, 0x72, 0x67, 0x2f, 0x67, - 0x6f, 0x62, 0x67, 0x70, 0x2f, 0x76, 0x33, 0x2f, 0x61, 0x70, 0x69, 0x3b, 0x61, 0x70, 0x69, 0x70, - 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x55, 0x53, 0x44, 0x10, 0x27, 0x12, 0x0e, 0x0a, 0x0a, 0x45, 0x4e, 0x44, 0x4d, 0x5f, 0x47, 0x54, + 0x50, 0x36, 0x44, 0x10, 0x2d, 0x12, 0x0f, 0x0a, 0x0b, 0x45, 0x4e, 0x44, 0x4d, 0x5f, 0x47, 0x54, + 0x50, 0x36, 0x44, 0x49, 0x10, 0x2e, 0x12, 0x0e, 0x0a, 0x0a, 0x45, 0x4e, 0x44, 0x4d, 0x5f, 0x47, + 0x54, 0x50, 0x36, 0x45, 0x10, 0x2f, 0x12, 0x0e, 0x0a, 0x0a, 0x45, 0x4e, 0x44, 0x4d, 0x5f, 0x47, + 0x54, 0x50, 0x34, 0x45, 0x10, 0x30, 0x2a, 0x44, 0x0a, 0x08, 0x45, 0x4e, 0x4c, 0x50, 0x54, 0x79, + 0x70, 0x65, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x10, 0x00, + 0x12, 0x09, 0x0a, 0x05, 0x54, 0x79, 0x70, 0x65, 0x31, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x54, + 0x79, 0x70, 0x65, 0x32, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x54, 0x79, 0x70, 0x65, 0x33, 0x10, + 0x03, 0x12, 0x09, 0x0a, 0x05, 0x54, 0x79, 0x70, 0x65, 0x34, 0x10, 0x04, 0x42, 0x24, 0x5a, 0x22, + 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x73, 0x72, 0x67, 0x2f, + 0x67, 0x6f, 0x62, 0x67, 0x70, 0x2f, 0x76, 0x33, 0x2f, 0x61, 0x70, 0x69, 0x3b, 0x61, 0x70, 0x69, + 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/api/attribute.proto b/api/attribute.proto index 8ac378e58..ae6711efd 100644 --- a/api/attribute.proto +++ b/api/attribute.proto @@ -634,6 +634,10 @@ enum SRv6Behavior { ENDT_WITH_PSP_USD = 37; ENDT_WITH_USP_USD = 38; ENDT_WITH_PSP_USP_USD = 39; + ENDM_GTP6D = 45; + ENDM_GTP6DI = 46; + ENDM_GTP6E = 47; + ENDM_GTP4E = 48; } message SRv6EndPointBehavior { diff --git a/pkg/packet/bgp/srbehavior.go b/pkg/packet/bgp/srbehavior.go index 322510e68..deb94a60d 100644 --- a/pkg/packet/bgp/srbehavior.go +++ b/pkg/packet/bgp/srbehavior.go @@ -40,4 +40,8 @@ const ( ENDT_WITH_PSP_USD SRBehavior = 37 ENDT_WITH_USP_USD SRBehavior = 38 ENDT_WITH_PSP_USP_USD SRBehavior = 39 + ENDM_GTP6D SRBehavior = 45 + ENDM_GTP6DI SRBehavior = 46 + ENDM_GTP6E SRBehavior = 47 + ENDM_GTP4E SRBehavior = 48 ) From 6966da918c3533c282b331d6000b86dfeb52f437 Mon Sep 17 00:00:00 2001 From: Yuya Kusakabe Date: Thu, 1 Sep 2022 12:05:55 +0900 Subject: [PATCH 2/2] mup: fixes for BGP-MUP - Route Target support for MUP routes - Only Direct Segment Discovery route needs MUP Extended Community - TEID value of 0 is invalid --- cmd/gobgp/global.go | 104 +++++++++++++++++++++------------ pkg/packet/bgp/mup.go | 11 +++- test/scenario_test/mup_test.py | 21 ++++--- 3 files changed, 90 insertions(+), 46 deletions(-) diff --git a/cmd/gobgp/global.go b/cmd/gobgp/global.go index 68d510c3c..b9c11c6c4 100644 --- a/cmd/gobgp/global.go +++ b/cmd/gobgp/global.go @@ -952,16 +952,16 @@ func parseEvpnArgs(args []string) (bgp.AddrPrefixInterface, []string, error) { return nil, nil, fmt.Errorf("invalid subtype. expect [macadv|multicast|prefix] but %s", subtype) } -func parseMUPInterworkSegmentDiscoveryRouteArgs(args []string) (bgp.AddrPrefixInterface, []string, error) { +func parseMUPInterworkSegmentDiscoveryRouteArgs(args []string, nexthop string) (bgp.AddrPrefixInterface, []string, error) { // Format: - // rd [mup ] + // rd [rt ...] req := 5 if len(args) < req { return nil, nil, fmt.Errorf("%d args required at least, but got %d", req, len(args)) } m, err := extractReserved(args, map[string]int{ - "rd": paramSingle, - "mup": paramSingle, + "rd": paramSingle, + "rt": paramSingle, }) if err != nil { return nil, nil, err @@ -969,7 +969,7 @@ func parseMUPInterworkSegmentDiscoveryRouteArgs(args []string) (bgp.AddrPrefixIn if len(m[""]) < 1 { return nil, nil, fmt.Errorf("specify prefix") } - for _, f := range []string{"rd"} { + for _, f := range []string{"rd", "rt"} { for len(m[f]) == 0 { return nil, nil, fmt.Errorf("specify %s", f) } @@ -982,11 +982,18 @@ func parseMUPInterworkSegmentDiscoveryRouteArgs(args []string) (bgp.AddrPrefixIn if err != nil { return nil, nil, err } + nh, err := netip.ParseAddr(nexthop) + if err != nil { + return nil, nil, err + } + if nh.Is4() { + return nil, nil, fmt.Errorf("nexthop should be IPv6 address: %s", nexthop) + } + extcomms := make([]string, 0) - if len(m["mup"]) > 0 { - extcomms = append(extcomms, "mup", m["mup"][0]) - } else { - extcomms = append(extcomms, "mup", "0:0") + if len(m["rt"]) > 0 { + extcomms = append(extcomms, "rt") + extcomms = append(extcomms, m["rt"]...) } r := &bgp.MUPInterworkSegmentDiscoveryRoute{ @@ -997,15 +1004,16 @@ func parseMUPInterworkSegmentDiscoveryRouteArgs(args []string) (bgp.AddrPrefixIn return bgp.NewMUPNLRI(bgp.MUP_ARCH_TYPE_UNDEFINED, bgp.MUP_ROUTE_TYPE_INTERWORK_SEGMENT_DISCOVERY, r), extcomms, nil } -func parseMUPDirectSegmentDiscoveryRouteArgs(args []string) (bgp.AddrPrefixInterface, []string, error) { +func parseMUPDirectSegmentDiscoveryRouteArgs(args []string, nexthop string) (bgp.AddrPrefixInterface, []string, error) { // Format: - // rd [mup ] + // rd [rt ...] [mup ] req := 5 if len(args) < req { return nil, nil, fmt.Errorf("%d args required at least, but got %d", req, len(args)) } m, err := extractReserved(args, map[string]int{ "rd": paramSingle, + "rt": paramSingle, "mup": paramSingle, }) if err != nil { @@ -1014,7 +1022,7 @@ func parseMUPDirectSegmentDiscoveryRouteArgs(args []string) (bgp.AddrPrefixInter if len(m[""]) < 1 { return nil, nil, fmt.Errorf("specify address") } - for _, f := range []string{"rd"} { + for _, f := range []string{"rd", "rt", "mup"} { for len(m[f]) == 0 { return nil, nil, fmt.Errorf("specify %s", f) } @@ -1027,11 +1035,21 @@ func parseMUPDirectSegmentDiscoveryRouteArgs(args []string) (bgp.AddrPrefixInter if err != nil { return nil, nil, err } + nh, err := netip.ParseAddr(nexthop) + if err != nil { + return nil, nil, err + } + if nh.Is4() { + return nil, nil, fmt.Errorf("nexthop should be IPv6 address: %s", nexthop) + } + extcomms := make([]string, 0) + if len(m["rt"]) > 0 { + extcomms = append(extcomms, "rt") + extcomms = append(extcomms, m["rt"]...) + } if len(m["mup"]) > 0 { extcomms = append(extcomms, "mup", m["mup"][0]) - } else { - extcomms = append(extcomms, "mup", "0:0") } r := &bgp.MUPDirectSegmentDiscoveryRoute{ @@ -1043,17 +1061,17 @@ func parseMUPDirectSegmentDiscoveryRouteArgs(args []string) (bgp.AddrPrefixInter func parseMUPType1SessionTransformedRouteArgs(args []string) (bgp.AddrPrefixInterface, []string, error) { // Format: - // rd teid qfi endpoint [mup ] + // rd [rt ...] teid qfi endpoint req := 5 if len(args) < req { return nil, nil, fmt.Errorf("%d args required at least, but got %d", req, len(args)) } m, err := extractReserved(args, map[string]int{ "rd": paramSingle, + "rt": paramSingle, "teid": paramSingle, "qfi": paramSingle, "endpoint": paramSingle, - "mup": paramSingle, }) if err != nil { return nil, nil, err @@ -1061,7 +1079,7 @@ func parseMUPType1SessionTransformedRouteArgs(args []string) (bgp.AddrPrefixInte if len(m[""]) < 1 { return nil, nil, fmt.Errorf("specify prefix") } - for _, f := range []string{"rd", "teid", "qfi", "endpoint"} { + for _, f := range []string{"rd", "rt", "teid", "qfi", "endpoint"} { for len(m[f]) == 0 { return nil, nil, fmt.Errorf("specify %s", f) } @@ -1078,6 +1096,9 @@ func parseMUPType1SessionTransformedRouteArgs(args []string) (bgp.AddrPrefixInte if err != nil { return nil, nil, err } + if teid == 0 { + return nil, nil, fmt.Errorf("teid should not be 0") + } qfi, err := strconv.ParseUint(m["qfi"][0], 10, 8) if err != nil { return nil, nil, err @@ -1087,10 +1108,9 @@ func parseMUPType1SessionTransformedRouteArgs(args []string) (bgp.AddrPrefixInte return nil, nil, err } extcomms := make([]string, 0) - if len(m["mup"]) > 0 { - extcomms = append(extcomms, "mup", m["mup"][0]) - } else { - extcomms = append(extcomms, "mup", "0:0") + if len(m["rt"]) > 0 { + extcomms = append(extcomms, "rt") + extcomms = append(extcomms, m["rt"]...) } r := &bgp.MUPType1SessionTransformedRoute{ @@ -1107,15 +1127,15 @@ func parseMUPType1SessionTransformedRouteArgs(args []string) (bgp.AddrPrefixInte func parseMUPType2SessionTransformedRouteArgs(args []string) (bgp.AddrPrefixInterface, []string, error) { // Format: - // rd teid [mup ] + // rd [rt ...] teid req := 5 if len(args) < req { return nil, nil, fmt.Errorf("%d args required at least, but got %d", req, len(args)) } m, err := extractReserved(args, map[string]int{ "rd": paramSingle, + "rt": paramSingle, "teid": paramSingle, - "mup": paramSingle, }) if err != nil { return nil, nil, err @@ -1123,7 +1143,7 @@ func parseMUPType2SessionTransformedRouteArgs(args []string) (bgp.AddrPrefixInte if len(m[""]) < 1 { return nil, nil, fmt.Errorf("specify endpoint") } - for _, f := range []string{"rd", "teid"} { + for _, f := range []string{"rd", "rt", "teid"} { for len(m[f]) == 0 { return nil, nil, fmt.Errorf("specify %s", f) } @@ -1140,11 +1160,13 @@ func parseMUPType2SessionTransformedRouteArgs(args []string) (bgp.AddrPrefixInte if err != nil { return nil, nil, err } + if teid == 0 { + return nil, nil, fmt.Errorf("teid should not be 0") + } extcomms := make([]string, 0) - if len(m["mup"]) > 0 { - extcomms = append(extcomms, "mup", m["mup"][0]) - } else { - extcomms = append(extcomms, "mup", "0:0") + if len(m["rt"]) > 0 { + extcomms = append(extcomms, "rt") + extcomms = append(extcomms, m["rt"]...) } r := &bgp.MUPType2SessionTransformedRoute{ @@ -1156,7 +1178,7 @@ func parseMUPType2SessionTransformedRouteArgs(args []string) (bgp.AddrPrefixInte return bgp.NewMUPNLRI(bgp.MUP_ARCH_TYPE_UNDEFINED, bgp.MUP_ROUTE_TYPE_TYPE_2_SESSION_TRANSFORMED, r), extcomms, nil } -func parseMUPArgs(args []string) (bgp.AddrPrefixInterface, []string, error) { +func parseMUPArgs(args []string, nexthop string) (bgp.AddrPrefixInterface, []string, error) { if len(args) < 1 { return nil, nil, fmt.Errorf("lack of args. need 1 but %d", len(args)) } @@ -1164,9 +1186,9 @@ func parseMUPArgs(args []string) (bgp.AddrPrefixInterface, []string, error) { args = args[1:] switch subtype { case "isd": - return parseMUPInterworkSegmentDiscoveryRouteArgs(args) + return parseMUPInterworkSegmentDiscoveryRouteArgs(args, nexthop) case "dsd": - return parseMUPDirectSegmentDiscoveryRouteArgs(args) + return parseMUPDirectSegmentDiscoveryRouteArgs(args, nexthop) case "t1st": return parseMUPType1SessionTransformedRouteArgs(args) case "t2st": @@ -1562,7 +1584,7 @@ func parsePath(rf bgp.RouteFamily, args []string) (*api.Path, error) { nlri = bgp.NewOpaqueNLRI([]byte(m["key"][0]), nil) } case bgp.RF_MUP_IPv4, bgp.RF_MUP_IPv6: - nlri, extcomms, err = parseMUPArgs(args) + nlri, extcomms, err = parseMUPArgs(args, nexthop) default: return nil, fmt.Errorf("unsupported route family: %s", rf) } @@ -1774,10 +1796,20 @@ usage: %s rib %s { a-d | macadv | multicast | esi | dsd | t1st | t2st } -a mup-ipv4 - : rd [mup ] - : rd [mup ] - : rd teid qfi endpoint [mup ] - : rd teid [mup ]`, + : rd [rt ...] + : rd [rt ...] [mup ] + : rd [rt ...] teid qfi endpoint + : rd [rt ...] teid `, + err, + cmdstr, + modtype, + ) + helpErrMap[bgp.RF_MUP_IPv6] = fmt.Errorf(`error: %s +usage: %s rib %s { isd | dsd | t1st | t2st } -a mup-ipv6 + : rd [rt ...] + : rd [rt ...] [mup ] + : rd [rt ...] teid qfi endpoint + : rd [rt ...] teid `, err, cmdstr, modtype, diff --git a/pkg/packet/bgp/mup.go b/pkg/packet/bgp/mup.go index 410f8e156..d1424046f 100644 --- a/pkg/packet/bgp/mup.go +++ b/pkg/packet/bgp/mup.go @@ -416,6 +416,9 @@ func (r *MUPType1SessionTransformedRoute) DecodeFromBytes(data []byte) error { } p += int(r.PrefixLength / 8) r.TEID = binary.BigEndian.Uint32(data[p : p+4]) + if r.TEID == 0 { + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("Invalid TEID: %d", r.TEID)) + } p += 4 r.QFI = data[p] p += 1 @@ -539,7 +542,13 @@ func (r *MUPType2SessionTransformedRoute) DecodeFromBytes(data []byte) error { return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("Invalid Endpoint Address length: %d", r.EndpointAddressLength)) } r.EndpointAddress = ea - r.TEID = binary.BigEndian.Uint32(data[p : p+teidLen]) + if teidLen > 0 { + teidData := append(make([]byte, 4-teidLen), data[p:p+teidLen]...) + r.TEID = binary.BigEndian.Uint32(teidData) + if r.TEID == 0 { + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("Invalid TEID: %d", r.TEID)) + } + } return nil } diff --git a/test/scenario_test/mup_test.py b/test/scenario_test/mup_test.py index e1ee8ace1..258462782 100644 --- a/test/scenario_test/mup_test.py +++ b/test/scenario_test/mup_test.py @@ -18,6 +18,8 @@ import sys import time import unittest +import logging +log = logging.getLogger(__name__) import nose @@ -66,20 +68,21 @@ def test_01_neighbor_established(self): def test_02_add_del_mup_route(self): tests = [ - ('mup_isd_route_ipv4', 'ipv4-mup', 'isd 10.0.0.0/24 rd 100:100 mup 10:10', '0.0.0.0'), - ('mup_dsd_route_ipv4', 'ipv4-mup', 'dsd 10.0.0.1 rd 100:100 mup 10:10', '0.0.0.0'), - ('mup_t1st_route_ipv4', 'ipv4-mup', 't1st 192.168.0.1 rd 100:100 teid 12345 qfi 9 endpoint 10.0.0.1 mup 10:10', '0.0.0.0'), - ('mup_t2st_route_ipv4', 'ipv4-mup', 't2st 10.0.0.1 rd 100:100 teid 12345 mup 10:10', '0.0.0.0'), - ('mup_isd_route_ipv6', 'ipv6-mup', 'isd 2001::/64 rd 100:100 mup 10:10', '::'), - ('mup_dsd_route_ipv6', 'ipv6-mup', 'dsd 2001::1 rd 100:100 mup 10:10', '::'), - ('mup_t1st_route_ipv6', 'ipv6-mup', 't1st 2001:db8:1:1::1 rd 100:100 teid 12345 qfi 9 endpoint 2001::1 mup 10:10', '::'), - ('mup_t2st_route_ipv6', 'ipv6-mup', 't2st 2001::1 rd 100:100 teid 12345 mup 10:10', '::'), + ('mup_isd_route_ipv4', 'ipv4-mup', 'isd 10.0.0.0/24 rd 100:100 rt 10:10 nexthop 2001::2', '2001::2'), + ('mup_dsd_route_ipv4', 'ipv4-mup', 'dsd 10.0.0.1 rd 100:100 rt 10:10 mup 10:10 nexthop 2001::2', '2001::2'), + ('mup_t1st_route_ipv4', 'ipv4-mup', 't1st 192.168.0.1 rd 100:100 rt 10:10 teid 12345 qfi 9 endpoint 10.0.0.1 nexthop 10.0.0.2', '10.0.0.2'), + ('mup_t2st_route_ipv4', 'ipv4-mup', 't2st 10.0.0.1 rd 100:100 rt 10:10 teid 12345 nexthop 10.0.0.2', '10.0.0.2'), + ('mup_isd_route_ipv6', 'ipv6-mup', 'isd 2001::/64 rd 100:100 rt 10:10 nexthop 2001::2', '2001::2'), + ('mup_dsd_route_ipv6', 'ipv6-mup', 'dsd 2001::1 rd 100:100 rt 10:10 mup 10:10 nexthop 2001::2', '2001::2'), + ('mup_t1st_route_ipv6', 'ipv6-mup', 't1st 2001:db8:1:1::1 rd 100:100 rt 10:10 teid 12345 qfi 9 endpoint 2001::1 nexthop 10.0.0.2', '10.0.0.2'), + ('mup_t2st_route_ipv6', 'ipv6-mup', 't2st 2001::1 rd 100:100 rt 10:10 teid 12345 nexthop 10.0.0.2', '10.0.0.2'), ] for msg, rf, route, nh in tests: with self.subTest(msg): self.g1.local('gobgp global rib add ' '-a {} {}'.format(rf, route)) grib = self.g1.get_global_rib(rf=rf) + log.debug('grib: {}'.format(grib)) self.assertEqual(len(grib), 1) dst = grib[0] self.assertEqual(len(dst['paths']), 1) @@ -103,7 +106,7 @@ def test_02_add_del_mup_route(self): self.assertEqual(len(dst['paths']), 1) path = dst['paths'][0] n_addrs = [i[1].split('/')[0] for i in self.g1.ip_addrs] - self.assertTrue(path['nexthop'] in n_addrs) + self.assertEqual(path['nexthop'], nh) done = True self.g1.local('gobgp global rib del '