summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gobgp/cmd/common.go4
-rw-r--r--gobgp/cmd/global.go26
-rw-r--r--gobgp/cmd/neighbor.go4
-rw-r--r--packet/bgp.go25
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()},