Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mup: fixes for BGP-MUP #2569

Merged
merged 2 commits into from
Sep 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 25 additions & 9 deletions api/attribute.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions api/attribute.proto
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
104 changes: 68 additions & 36 deletions cmd/gobgp/global.go
Original file line number Diff line number Diff line change
Expand Up @@ -952,24 +952,24 @@ 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:
// <ip prefix> rd <rd> [mup <segment identifier>]
// <ip prefix> rd <rd> [rt <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
}
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)
}
Expand All @@ -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{
Expand All @@ -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:
// <ip address> rd <rd> [mup <segment identifier>]
// <ip address> rd <rd> [rt <rt>...] [mup <segment identifier>]
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 {
Expand All @@ -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)
}
Expand All @@ -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{
Expand All @@ -1043,25 +1061,25 @@ func parseMUPDirectSegmentDiscoveryRouteArgs(args []string) (bgp.AddrPrefixInter

func parseMUPType1SessionTransformedRouteArgs(args []string) (bgp.AddrPrefixInterface, []string, error) {
// Format:
// <ip prefix> rd <rd> teid <teid> qfi <qfi> endpoint <endpoint> [mup <segment identifier>]
// <ip prefix> rd <rd> [rt <rt>...] teid <teid> qfi <qfi> endpoint <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
}
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)
}
Expand All @@ -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
Expand All @@ -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{
Expand All @@ -1107,23 +1127,23 @@ func parseMUPType1SessionTransformedRouteArgs(args []string) (bgp.AddrPrefixInte

func parseMUPType2SessionTransformedRouteArgs(args []string) (bgp.AddrPrefixInterface, []string, error) {
// Format:
// <endpoint address> rd <rd> teid <teid> [mup <segment identifier>]
// <endpoint address> rd <rd> [rt <rt>...] teid <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
}
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)
}
Expand All @@ -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{
Expand All @@ -1156,17 +1178,17 @@ 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))
}
subtype := args[0]
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":
Expand Down Expand Up @@ -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)
}
Expand Down Expand Up @@ -1774,10 +1796,20 @@ usage: %s rib %s { a-d <A-D> | macadv <MACADV> | multicast <MULTICAST> | esi <ES
)
helpErrMap[bgp.RF_MUP_IPv4] = fmt.Errorf(`error: %s
usage: %s rib %s { isd <ISD> | dsd <DSD> | t1st <T1ST> | t2st <T2ST> } -a mup-ipv4
<ISD> : <ip prefix> rd <rd> [mup <segment identifier>]
<DSD> : <ip address> rd <rd> [mup <segment identifier>]
<T1ST> : <ip prefix> rd <rd> teid <teid> qfi <qfi> endpoint <endpoint> [mup <segment identifier>]
<T2ST> : <endpoint address> rd <rd> teid <teid> [mup <segment identifier>]`,
<ISD> : <ip prefix> rd <rd> [rt <rt>...]
<DSD> : <ip address> rd <rd> [rt <rt>...] [mup <segment identifier>]
<T1ST> : <ip prefix> rd <rd> [rt <rt>...] teid <teid> qfi <qfi> endpoint <endpoint>
<T2ST> : <endpoint address> rd <rd> [rt <rt>...] teid <teid>`,
err,
cmdstr,
modtype,
)
helpErrMap[bgp.RF_MUP_IPv6] = fmt.Errorf(`error: %s
usage: %s rib %s { isd <ISD> | dsd <DSD> | t1st <T1ST> | t2st <T2ST> } -a mup-ipv6
<ISD> : <ip prefix> rd <rd> [rt <rt>...]
<DSD> : <ip address> rd <rd> [rt <rt>...] [mup <segment identifier>]
<T1ST> : <ip prefix> rd <rd> [rt <rt>...] teid <teid> qfi <qfi> endpoint <endpoint>
<T2ST> : <endpoint address> rd <rd> [rt <rt>...] teid <teid>`,
err,
cmdstr,
modtype,
Expand Down
11 changes: 10 additions & 1 deletion pkg/packet/bgp/mup.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
}

Expand Down
4 changes: 4 additions & 0 deletions pkg/packet/bgp/srbehavior.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
Loading