Skip to content

Commit

Permalink
mup: handle Type 1 ST Route Prefix as Prefix instead of single address
Browse files Browse the repository at this point in the history
  • Loading branch information
higebu committed Sep 28, 2022
1 parent 086c8c9 commit ea350c5
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 67 deletions.
35 changes: 18 additions & 17 deletions cmd/gobgp/global.go
Original file line number Diff line number Diff line change
Expand Up @@ -952,7 +952,7 @@ 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, nexthop string) (bgp.AddrPrefixInterface, []string, error) {
func parseMUPInterworkSegmentDiscoveryRouteArgs(args []string, afi uint16, nexthop string) (bgp.AddrPrefixInterface, []string, error) {
// Format:
// <ip prefix> rd <rd> [rt <rt>...]
req := 5
Expand Down Expand Up @@ -1001,10 +1001,10 @@ func parseMUPInterworkSegmentDiscoveryRouteArgs(args []string, nexthop string) (
PrefixLength: uint8(prefix.Bits()),
Prefix: prefix,
}
return bgp.NewMUPNLRI(bgp.MUP_ARCH_TYPE_UNDEFINED, bgp.MUP_ROUTE_TYPE_INTERWORK_SEGMENT_DISCOVERY, r), extcomms, nil
return bgp.NewMUPNLRI(afi, bgp.MUP_ARCH_TYPE_UNDEFINED, bgp.MUP_ROUTE_TYPE_INTERWORK_SEGMENT_DISCOVERY, r), extcomms, nil
}

func parseMUPDirectSegmentDiscoveryRouteArgs(args []string, nexthop string) (bgp.AddrPrefixInterface, []string, error) {
func parseMUPDirectSegmentDiscoveryRouteArgs(args []string, afi uint16, nexthop string) (bgp.AddrPrefixInterface, []string, error) {
// Format:
// <ip address> rd <rd> [rt <rt>...] [mup <segment identifier>]
req := 5
Expand Down Expand Up @@ -1056,10 +1056,10 @@ func parseMUPDirectSegmentDiscoveryRouteArgs(args []string, nexthop string) (bgp
RD: rd,
Address: addr,
}
return bgp.NewMUPNLRI(bgp.MUP_ARCH_TYPE_UNDEFINED, bgp.MUP_ROUTE_TYPE_DIRECT_SEGMENT_DISCOVERY, r), extcomms, nil
return bgp.NewMUPNLRI(afi, bgp.MUP_ARCH_TYPE_UNDEFINED, bgp.MUP_ROUTE_TYPE_DIRECT_SEGMENT_DISCOVERY, r), extcomms, nil
}

func parseMUPType1SessionTransformedRouteArgs(args []string) (bgp.AddrPrefixInterface, []string, error) {
func parseMUPType1SessionTransformedRouteArgs(args []string, afi uint16) (bgp.AddrPrefixInterface, []string, error) {
// Format:
// <ip prefix> rd <rd> [rt <rt>...] teid <teid> qfi <qfi> endpoint <endpoint>
req := 5
Expand Down Expand Up @@ -1088,7 +1088,7 @@ func parseMUPType1SessionTransformedRouteArgs(args []string) (bgp.AddrPrefixInte
if err != nil {
return nil, nil, err
}
prefix, err := netip.ParseAddr(m[""][0])
prefix, err := netip.ParsePrefix(m[""][0])
if err != nil {
return nil, nil, err
}
Expand All @@ -1115,17 +1115,16 @@ func parseMUPType1SessionTransformedRouteArgs(args []string) (bgp.AddrPrefixInte

r := &bgp.MUPType1SessionTransformedRoute{
RD: rd,
PrefixLength: uint8(prefix.BitLen()),
Prefix: prefix,
TEID: uint32(teid),
QFI: uint8(qfi),
EndpointAddressLength: uint8(ea.BitLen()),
EndpointAddress: ea,
}
return bgp.NewMUPNLRI(bgp.MUP_ARCH_TYPE_UNDEFINED, bgp.MUP_ROUTE_TYPE_TYPE_1_SESSION_TRANSFORMED, r), extcomms, nil
return bgp.NewMUPNLRI(afi, bgp.MUP_ARCH_TYPE_UNDEFINED, bgp.MUP_ROUTE_TYPE_TYPE_1_SESSION_TRANSFORMED, r), extcomms, nil
}

func parseMUPType2SessionTransformedRouteArgs(args []string) (bgp.AddrPrefixInterface, []string, error) {
func parseMUPType2SessionTransformedRouteArgs(args []string, afi uint16) (bgp.AddrPrefixInterface, []string, error) {
// Format:
// <endpoint address> rd <rd> [rt <rt>...] teid <teid>
req := 5
Expand Down Expand Up @@ -1175,24 +1174,24 @@ func parseMUPType2SessionTransformedRouteArgs(args []string) (bgp.AddrPrefixInte
EndpointAddress: ea,
TEID: uint32(teid),
}
return bgp.NewMUPNLRI(bgp.MUP_ARCH_TYPE_UNDEFINED, bgp.MUP_ROUTE_TYPE_TYPE_2_SESSION_TRANSFORMED, r), extcomms, nil
return bgp.NewMUPNLRI(afi, bgp.MUP_ARCH_TYPE_UNDEFINED, bgp.MUP_ROUTE_TYPE_TYPE_2_SESSION_TRANSFORMED, r), extcomms, nil
}

func parseMUPArgs(args []string, nexthop string) (bgp.AddrPrefixInterface, []string, error) {
func parseMUPArgs(args []string, afi uint16, 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, nexthop)
return parseMUPInterworkSegmentDiscoveryRouteArgs(args, afi, nexthop)
case "dsd":
return parseMUPDirectSegmentDiscoveryRouteArgs(args, nexthop)
return parseMUPDirectSegmentDiscoveryRouteArgs(args, afi, nexthop)
case "t1st":
return parseMUPType1SessionTransformedRouteArgs(args)
return parseMUPType1SessionTransformedRouteArgs(args, afi)
case "t2st":
return parseMUPType2SessionTransformedRouteArgs(args)
return parseMUPType2SessionTransformedRouteArgs(args, afi)
}
return nil, nil, fmt.Errorf("invalid subtype. expect [isd|dsd|t1st|t2st] but %s", subtype)
}
Expand Down Expand Up @@ -1583,8 +1582,10 @@ func parsePath(rf bgp.RouteFamily, args []string) (*api.Path, error) {
} else {
nlri = bgp.NewOpaqueNLRI([]byte(m["key"][0]), nil)
}
case bgp.RF_MUP_IPv4, bgp.RF_MUP_IPv6:
nlri, extcomms, err = parseMUPArgs(args, nexthop)
case bgp.RF_MUP_IPv4:
nlri, extcomms, err = parseMUPArgs(args, bgp.AFI_IP, nexthop)
case bgp.RF_MUP_IPv6:
nlri, extcomms, err = parseMUPArgs(args, bgp.AFI_IP6, nexthop)
default:
return nil, fmt.Errorf("unsupported route family: %s", rf)
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/apiutil/attribute.go
Original file line number Diff line number Diff line change
Expand Up @@ -1039,7 +1039,7 @@ func MarshalNLRI(value bgp.AddrPrefixInterface) (*apb.Any, error) {
}
nlri = &api.MUPType1SessionTransformedRoute{
Rd: rd,
PrefixLength: uint32(r.PrefixLength),
PrefixLength: uint32(r.Prefix.Bits()),
Prefix: r.Prefix.String(),
Teid: r.TEID,
Qfi: uint32(r.QFI),
Expand Down Expand Up @@ -1239,7 +1239,7 @@ func UnmarshalNLRI(rf bgp.RouteFamily, an *apb.Any) (bgp.AddrPrefixInterface, er
if err != nil {
return nil, err
}
prefix, err := netip.ParseAddr(v.Prefix)
prefix, err := netip.ParsePrefix(v.Prefix)
if err != nil {
return nil, err
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/packet/bgp/bgp.go
Original file line number Diff line number Diff line change
Expand Up @@ -8447,9 +8447,9 @@ func NewPrefixFromRouteFamily(afi uint16, safi uint8, prefixStr ...string) (pref
case RF_LS:
prefix = &LsAddrPrefix{}
case RF_MUP_IPv4:
prefix = NewMUPNLRI(0, 0, nil)
prefix = NewMUPNLRI(AFI_IP, 0, 0, nil)
case RF_MUP_IPv6:
prefix = NewMUPNLRI(0, 0, nil)
prefix = NewMUPNLRI(AFI_IP6, 0, 0, nil)
default:
err = fmt.Errorf("unknown route family. AFI: %d, SAFI: %d", afi, safi)
}
Expand Down
95 changes: 63 additions & 32 deletions pkg/packet/bgp/mup.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ const (
)

type MUPRouteTypeInterface interface {
DecodeFromBytes([]byte) error
DecodeFromBytes([]byte, uint16) error
Serialize() ([]byte, error)
AFI() uint16
Len() int
Expand Down Expand Up @@ -122,6 +122,7 @@ func getMUPRouteType(at uint8, rt uint16) (MUPRouteTypeInterface, error) {

type MUPNLRI struct {
PrefixDefault
Afi uint16
ArchitectureType uint8
RouteType uint16
Length uint8
Expand All @@ -144,7 +145,7 @@ func (n *MUPNLRI) DecodeFromBytes(data []byte, options ...*MarshallingOption) er
return err
}
n.RouteTypeData = r
return n.RouteTypeData.DecodeFromBytes(data[:n.Length])
return n.RouteTypeData.DecodeFromBytes(data[:n.Length], n.Afi)
}

func (n *MUPNLRI) Serialize(options ...*MarshallingOption) ([]byte, error) {
Expand All @@ -160,7 +161,7 @@ func (n *MUPNLRI) Serialize(options ...*MarshallingOption) ([]byte, error) {
}

func (n *MUPNLRI) AFI() uint16 {
return n.RouteTypeData.AFI()
return n.Afi
}

func (n *MUPNLRI) SAFI() uint8 {
Expand Down Expand Up @@ -198,12 +199,13 @@ func (l *MUPNLRI) Flat() map[string]string {
return map[string]string{}
}

func NewMUPNLRI(at uint8, rt uint16, data MUPRouteTypeInterface) *MUPNLRI {
func NewMUPNLRI(afi uint16, at uint8, rt uint16, data MUPRouteTypeInterface) *MUPNLRI {
var l uint8
if data != nil {
l = uint8(data.Len())
}
return &MUPNLRI{
Afi: afi,
ArchitectureType: at,
RouteType: rt,
Length: l,
Expand All @@ -220,14 +222,18 @@ type MUPInterworkSegmentDiscoveryRoute struct {
}

func NewMUPInterworkSegmentDiscoveryRoute(rd RouteDistinguisherInterface, prefix netip.Prefix) *MUPNLRI {
return NewMUPNLRI(MUP_ARCH_TYPE_3GPP_5G, MUP_ROUTE_TYPE_INTERWORK_SEGMENT_DISCOVERY, &MUPInterworkSegmentDiscoveryRoute{
afi := uint16(AFI_IP)
if prefix.Addr().Is6() {
afi = AFI_IP6
}
return NewMUPNLRI(afi, MUP_ARCH_TYPE_3GPP_5G, MUP_ROUTE_TYPE_INTERWORK_SEGMENT_DISCOVERY, &MUPInterworkSegmentDiscoveryRoute{
RD: rd,
PrefixLength: uint8(prefix.Bits()),
Prefix: prefix,
})
}

func (r *MUPInterworkSegmentDiscoveryRoute) DecodeFromBytes(data []byte) error {
func (r *MUPInterworkSegmentDiscoveryRoute) DecodeFromBytes(data []byte, afi uint16) error {
r.RD = GetRouteDistinguisher(data)
p := r.RD.Len()
if len(data) < p {
Expand Down Expand Up @@ -300,13 +306,17 @@ type MUPDirectSegmentDiscoveryRoute struct {
}

func NewMUPDirectSegmentDiscoveryRoute(rd RouteDistinguisherInterface, address netip.Addr) *MUPNLRI {
return NewMUPNLRI(MUP_ARCH_TYPE_3GPP_5G, MUP_ROUTE_TYPE_DIRECT_SEGMENT_DISCOVERY, &MUPDirectSegmentDiscoveryRoute{
afi := uint16(AFI_IP)
if address.Is6() {
afi = AFI_IP6
}
return NewMUPNLRI(afi, MUP_ARCH_TYPE_3GPP_5G, MUP_ROUTE_TYPE_DIRECT_SEGMENT_DISCOVERY, &MUPDirectSegmentDiscoveryRoute{
RD: rd,
Address: address,
})
}

func (r *MUPDirectSegmentDiscoveryRoute) DecodeFromBytes(data []byte) error {
func (r *MUPDirectSegmentDiscoveryRoute) DecodeFromBytes(data []byte, afi uint16) error {
r.RD = GetRouteDistinguisher(data)
rdLen := r.RD.Len()
if len(data) != 12 && len(data) != 24 {
Expand Down Expand Up @@ -377,18 +387,20 @@ func (r *MUPDirectSegmentDiscoveryRoute) rd() RouteDistinguisherInterface {
// https://datatracker.ietf.org/doc/html/draft-mpmz-bess-mup-safi-00#section-3.1.3
type MUPType1SessionTransformedRoute struct {
RD RouteDistinguisherInterface
PrefixLength uint8
Prefix netip.Addr
Prefix netip.Prefix
TEID uint32
QFI uint8
EndpointAddressLength uint8
EndpointAddress netip.Addr
}

func NewMUPType1SessionTransformedRoute(rd RouteDistinguisherInterface, prefix netip.Addr, teid uint32, qfi uint8, ea netip.Addr) *MUPNLRI {
return NewMUPNLRI(MUP_ARCH_TYPE_3GPP_5G, MUP_ROUTE_TYPE_TYPE_1_SESSION_TRANSFORMED, &MUPType1SessionTransformedRoute{
func NewMUPType1SessionTransformedRoute(rd RouteDistinguisherInterface, prefix netip.Prefix, teid uint32, qfi uint8, ea netip.Addr) *MUPNLRI {
afi := uint16(AFI_IP)
if prefix.Addr().Is6() {
afi = uint16(AFI_IP6)
}
return NewMUPNLRI(afi, MUP_ARCH_TYPE_3GPP_5G, MUP_ROUTE_TYPE_TYPE_1_SESSION_TRANSFORMED, &MUPType1SessionTransformedRoute{
RD: rd,
PrefixLength: uint8(prefix.BitLen()),
Prefix: prefix,
TEID: teid,
QFI: qfi,
Expand All @@ -397,24 +409,38 @@ func NewMUPType1SessionTransformedRoute(rd RouteDistinguisherInterface, prefix n
})
}

func (r *MUPType1SessionTransformedRoute) DecodeFromBytes(data []byte) error {
func (r *MUPType1SessionTransformedRoute) DecodeFromBytes(data []byte, afi uint16) error {
r.RD = GetRouteDistinguisher(data)
p := r.RD.Len()
if len(data) < p {
return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "invalid 3GPP 5G specific Type 1 Session Transformed Route length")
}
r.PrefixLength = data[p]
prefixLength := int(data[p])
p += 1
if r.PrefixLength == 32 || r.PrefixLength == 128 {
prefix, ok := netip.AddrFromSlice(data[p : p+int(r.PrefixLength/8)])
switch afi {
case AFI_IP:
if prefixLength > 32 {
return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("Invalid Prefix length: %d", prefixLength))
}
addr, ok := netip.AddrFromSlice(data[p : p+4])
if !ok {
return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("Invalid Prefix: %x", data[p:p+int(r.PrefixLength/8)]))
return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("Invalid Prefix: %x", data[p:p+4]))
}
r.Prefix = prefix
} else {
return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("Invalid Prefix length: %d", r.PrefixLength))
r.Prefix = netip.PrefixFrom(addr, prefixLength)
p += 4
case AFI_IP6:
if prefixLength > 128 {
return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("Invalid Prefix length: %d", prefixLength))
}
addr, ok := netip.AddrFromSlice(data[p : p+16])
if !ok {
return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("Invalid Prefix: %x", data[p:p+16]))
}
r.Prefix = netip.PrefixFrom(addr, prefixLength)
p += 16
default:
return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("Invalid AFI: %d", afi))
}
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))
Expand Down Expand Up @@ -447,8 +473,8 @@ func (r *MUPType1SessionTransformedRoute) Serialize() ([]byte, error) {
} else {
buf = make([]byte, 8)
}
buf = append(buf, r.PrefixLength)
buf = append(buf, r.Prefix.AsSlice()...)
buf = append(buf, byte(r.Prefix.Bits()))
buf = append(buf, r.Prefix.Addr().AsSlice()...)
t := make([]byte, 4)
binary.BigEndian.PutUint32(t, r.TEID)
buf = append(buf, t...)
Expand All @@ -459,7 +485,7 @@ func (r *MUPType1SessionTransformedRoute) Serialize() ([]byte, error) {
}

func (r *MUPType1SessionTransformedRoute) AFI() uint16 {
if r.Prefix.Is6() {
if r.Prefix.Addr().Is6() {
return AFI_IP6
}
return AFI_IP
Expand All @@ -468,7 +494,7 @@ func (r *MUPType1SessionTransformedRoute) AFI() uint16 {
func (r *MUPType1SessionTransformedRoute) Len() int {
// RD(8) + PrefixLength(1) + Prefix(4 or 16)
// + TEID(4) + QFI(1) + EndpointAddressLength(1) + EndpointAddress(4 or 16)
return 15 + int(r.PrefixLength/8) + int(r.EndpointAddressLength/8)
return 15 + r.Prefix.Addr().BitLen()/8 + int(r.EndpointAddressLength/8)
}

func (r *MUPType1SessionTransformedRoute) String() string {
Expand Down Expand Up @@ -505,15 +531,19 @@ type MUPType2SessionTransformedRoute struct {
}

func NewMUPType2SessionTransformedRoute(rd RouteDistinguisherInterface, ea netip.Addr, teid uint32) *MUPNLRI {
return NewMUPNLRI(MUP_ARCH_TYPE_3GPP_5G, MUP_ROUTE_TYPE_TYPE_2_SESSION_TRANSFORMED, &MUPType2SessionTransformedRoute{
afi := uint16(AFI_IP)
if ea.Is6() {
afi = AFI_IP6
}
return NewMUPNLRI(afi, MUP_ARCH_TYPE_3GPP_5G, MUP_ROUTE_TYPE_TYPE_2_SESSION_TRANSFORMED, &MUPType2SessionTransformedRoute{
RD: rd,
EndpointAddressLength: uint8(ea.BitLen()) + 32,
EndpointAddress: ea,
TEID: teid,
})
}

func (r *MUPType2SessionTransformedRoute) DecodeFromBytes(data []byte) error {
func (r *MUPType2SessionTransformedRoute) DecodeFromBytes(data []byte, afi uint16) error {
r.RD = GetRouteDistinguisher(data)
p := r.RD.Len()
if len(data) < p {
Expand All @@ -524,22 +554,23 @@ func (r *MUPType2SessionTransformedRoute) DecodeFromBytes(data []byte) error {
var ea netip.Addr
var ok bool
teidLen := 0
if r.EndpointAddressLength >= 32 && r.EndpointAddressLength <= 64 {
switch afi {
case AFI_IP:
ea, ok = netip.AddrFromSlice(data[p : p+4])
if !ok {
return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("Invalid Endpoint Address: %x", data[p:p+int(r.EndpointAddressLength/8)]))
}
p += 4
teidLen = int(r.EndpointAddressLength)/8 - 4
} else if r.EndpointAddressLength >= 128 && r.EndpointAddressLength <= 160 {
case AFI_IP6:
ea, ok = netip.AddrFromSlice(data[p : p+16])
if !ok {
return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("Invalid Endpoint Address: %x", data[p:p+int(r.EndpointAddressLength/8)]))
}
p += 16
teidLen = int(r.EndpointAddressLength)/8 - 16
} else {
return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("Invalid Endpoint Address length: %d", r.EndpointAddressLength))
default:
return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("Invalid AFI: %d", afi))
}
r.EndpointAddress = ea
if teidLen > 0 {
Expand Down
Loading

0 comments on commit ea350c5

Please sign in to comment.