diff options
-rw-r--r-- | gobgp/cmd/common.go | 4 | ||||
-rw-r--r-- | gobgp/cmd/global.go | 26 | ||||
-rw-r--r-- | gobgp/cmd/neighbor.go | 4 | ||||
-rw-r--r-- | packet/bgp.go | 25 |
4 files changed, 59 insertions, 0 deletions
diff --git a/gobgp/cmd/common.go b/gobgp/cmd/common.go index f91ee975..f41d5bcd 100644 --- a/gobgp/cmd/common.go +++ b/gobgp/cmd/common.go @@ -414,6 +414,10 @@ func checkAddressFamily(def bgp.RouteFamily) (bgp.RouteFamily, error) { rf = bgp.RF_IPv4_VPN case "vpnv6", "vpn-ipv6": rf = bgp.RF_IPv6_VPN + case "ipv4-labeled", "ipv4-labelled", "ipv4-mpls": + rf = bgp.RF_IPv4_MPLS + case "ipv6-labeled", "ipv6-labelled", "ipv6-mpls": + rf = bgp.RF_IPv6_MPLS case "evpn": rf = bgp.RF_EVPN case "encap": diff --git a/gobgp/cmd/global.go b/gobgp/cmd/global.go index 62d5ee3d..9820124a 100644 --- a/gobgp/cmd/global.go +++ b/gobgp/cmd/global.go @@ -558,6 +558,32 @@ func ParsePath(rf bgp.RouteFamily, args []string) (*api.Path, error) { } nlri = bgp.NewLabeledVPNIPv6AddrPrefix(uint8(ones), ip.String(), *mpls, rd) } + case bgp.RF_IPv4_MPLS, bgp.RF_IPv6_MPLS: + if len(args) < 2 { + return nil, fmt.Errorf("invalid format") + } + + ip, net, _ := net.ParseCIDR(args[0]) + ones, _ := net.Mask.Size() + + mpls, err := bgp.ParseMPLSLabelStack(args[1]) + if err != nil { + return nil, err + } + + extcomms = args[2:] + + if rf == bgp.RF_IPv4_MPLS { + if ip.To4() == nil { + return nil, fmt.Errorf("invalid ipv4 prefix") + } + nlri = bgp.NewLabeledIPAddrPrefix(uint8(ones), ip.String(), *mpls) + } else { + if ip.To4() != nil { + return nil, fmt.Errorf("invalid ipv6 prefix") + } + nlri = bgp.NewLabeledIPv6AddrPrefix(uint8(ones), ip.String(), *mpls) + } case bgp.RF_EVPN: nlri, extcomms, err = ParseEvpnArgs(args) case bgp.RF_FS_IPv4_UC, bgp.RF_FS_IPv6_UC: diff --git a/gobgp/cmd/neighbor.go b/gobgp/cmd/neighbor.go index 2e1cc1e5..ab89c9e7 100644 --- a/gobgp/cmd/neighbor.go +++ b/gobgp/cmd/neighbor.go @@ -441,6 +441,10 @@ func showNeighborRib(r string, name string, args []string) error { if err != nil { return err } + switch rf { + case bgp.RF_IPv4_MPLS, bgp.RF_IPv6_MPLS, bgp.RF_IPv4_VPN, bgp.RF_IPv6_VPN: + showLabel = true + } arg := &api.Table{ Type: resource, diff --git a/packet/bgp.go b/packet/bgp.go index 5e28fdc8..c71d1489 100644 --- a/packet/bgp.go +++ b/packet/bgp.go @@ -1164,6 +1164,27 @@ func NewMPLSLabelStack(labels ...uint32) *MPLSLabelStack { return &MPLSLabelStack{labels} } +func ParseMPLSLabelStack(buf string) (*MPLSLabelStack, error) { + elems := strings.Split(buf, "/") + labels := make([]uint32, 0, len(elems)) + if len(elems) == 0 { + goto ERR + } + for _, elem := range elems { + i, err := strconv.Atoi(elem) + if err != nil { + goto ERR + } + if i < 0 || i > ((1<<20)-1) { + goto ERR + } + labels = append(labels, uint32(i)) + } + return NewMPLSLabelStack(labels...), nil +ERR: + return nil, fmt.Errorf("invalid mpls label stack format") +} + // // RFC3107 Carrying Label Information in BGP-4 // @@ -1338,6 +1359,10 @@ func (l *LabeledIPAddrPrefix) Serialize() ([]byte, error) { return buf, nil } +func (l *LabeledIPAddrPrefix) String() string { + return fmt.Sprintf("%s/%d", l.Prefix.String(), int(l.Length)-l.Labels.Len()*8) +} + func NewLabeledIPAddrPrefix(length uint8, prefix string, label MPLSLabelStack) *LabeledIPAddrPrefix { return &LabeledIPAddrPrefix{ IPAddrPrefixDefault{length + uint8(label.Len()*8), net.ParseIP(prefix).To4()}, |