summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorISHIDA Wataru <ishida.wataru@lab.ntt.co.jp>2015-07-02 23:39:20 +0900
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2015-07-05 23:44:22 +0900
commit2fc9b887fc63da94e173f75dd15330254e35647c (patch)
treec25548066c75ad9dc17babbf1e12286a10e60aed
parentcd89516a28f4de85f844a232cb1b40b198218856 (diff)
server/cli: support add/delete vpnv4/vpnv6 routes
$ gobgp global rib add 1:10.0.0.1:1000:10.0.0.0/24 -a vpnv4 Signed-off-by: ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp>
-rw-r--r--api/gobgp.pb.go62
-rw-r--r--api/gobgp.proto20
-rw-r--r--api/util.go2
-rw-r--r--config/default.go2
-rw-r--r--gobgp/common.go4
-rw-r--r--gobgp/global.go109
-rw-r--r--packet/bgp.go71
-rw-r--r--packet/bgp_test.go8
-rw-r--r--server/grpc_server.go4
-rw-r--r--server/server.go38
10 files changed, 253 insertions, 67 deletions
diff --git a/api/gobgp.pb.go b/api/gobgp.pb.go
index e4214a66..b0897927 100644
--- a/api/gobgp.pb.go
+++ b/api/gobgp.pb.go
@@ -14,6 +14,7 @@ It has these top-level messages:
ModPathArguments
PolicyArguments
AddressFamily
+ RouteDistinguisher
GracefulRestartTuple
GracefulRestart
Capability
@@ -23,6 +24,7 @@ It has these top-level messages:
EvpnMacIpAdvertisement
EvpnInclusiveMulticastEthernetTag
RTNlri
+ VPNNlri
Nlri
TunnelEncapSubTLV
TunnelEncapTLV
@@ -198,6 +200,29 @@ func (x SAFI) String() string {
return proto.EnumName(SAFI_name, int32(x))
}
+type ROUTE_DISTINGUISHER_TYPE int32
+
+const (
+ ROUTE_DISTINGUISHER_TYPE_TWO_OCTET_AS ROUTE_DISTINGUISHER_TYPE = 0
+ ROUTE_DISTINGUISHER_TYPE_IP4 ROUTE_DISTINGUISHER_TYPE = 1
+ ROUTE_DISTINGUISHER_TYPE_FOUR_OCTET_AS ROUTE_DISTINGUISHER_TYPE = 2
+)
+
+var ROUTE_DISTINGUISHER_TYPE_name = map[int32]string{
+ 0: "TWO_OCTET_AS",
+ 1: "IP4",
+ 2: "FOUR_OCTET_AS",
+}
+var ROUTE_DISTINGUISHER_TYPE_value = map[string]int32{
+ "TWO_OCTET_AS": 0,
+ "IP4": 1,
+ "FOUR_OCTET_AS": 2,
+}
+
+func (x ROUTE_DISTINGUISHER_TYPE) String() string {
+ return proto.EnumName(ROUTE_DISTINGUISHER_TYPE_name, int32(x))
+}
+
type BGP_CAPABILITY int32
const (
@@ -608,6 +633,16 @@ func (m *AddressFamily) Reset() { *m = AddressFamily{} }
func (m *AddressFamily) String() string { return proto.CompactTextString(m) }
func (*AddressFamily) ProtoMessage() {}
+type RouteDistinguisher struct {
+ Type ROUTE_DISTINGUISHER_TYPE `protobuf:"varint,1,opt,name=type,enum=api.ROUTE_DISTINGUISHER_TYPE" json:"type,omitempty"`
+ Admin string `protobuf:"bytes,2,opt,name=admin" json:"admin,omitempty"`
+ Assigned uint32 `protobuf:"varint,3,opt,name=assigned" json:"assigned,omitempty"`
+}
+
+func (m *RouteDistinguisher) Reset() { *m = RouteDistinguisher{} }
+func (m *RouteDistinguisher) String() string { return proto.CompactTextString(m) }
+func (*RouteDistinguisher) ProtoMessage() {}
+
type GracefulRestartTuple struct {
Af *AddressFamily `protobuf:"bytes,1,opt,name=af" json:"af,omitempty"`
Flags uint32 `protobuf:"varint,2,opt,name=flags" json:"flags,omitempty"`
@@ -756,12 +791,31 @@ func (m *RTNlri) GetTarget() *ExtendedCommunity {
return nil
}
+type VPNNlri struct {
+ Rd *RouteDistinguisher `protobuf:"bytes,1,opt,name=rd" json:"rd,omitempty"`
+ Labels []uint32 `protobuf:"varint,2,rep,name=labels" json:"labels,omitempty"`
+ IpAddr string `protobuf:"bytes,3,opt,name=ip_addr" json:"ip_addr,omitempty"`
+ IpAddrLen uint32 `protobuf:"varint,4,opt,name=ip_addr_len" json:"ip_addr_len,omitempty"`
+}
+
+func (m *VPNNlri) Reset() { *m = VPNNlri{} }
+func (m *VPNNlri) String() string { return proto.CompactTextString(m) }
+func (*VPNNlri) ProtoMessage() {}
+
+func (m *VPNNlri) GetRd() *RouteDistinguisher {
+ if m != nil {
+ return m.Rd
+ }
+ return nil
+}
+
type Nlri struct {
Af *AddressFamily `protobuf:"bytes,1,opt,name=af" json:"af,omitempty"`
Prefix string `protobuf:"bytes,2,opt,name=prefix" json:"prefix,omitempty"`
Nexthop string `protobuf:"bytes,3,opt,name=nexthop" json:"nexthop,omitempty"`
EvpnNlri *EVPNNlri `protobuf:"bytes,4,opt,name=evpn_nlri" json:"evpn_nlri,omitempty"`
RtNlri *RTNlri `protobuf:"bytes,5,opt,name=rt_nlri" json:"rt_nlri,omitempty"`
+ VpnNlri *VPNNlri `protobuf:"bytes,6,opt,name=vpn_nlri" json:"vpn_nlri,omitempty"`
}
func (m *Nlri) Reset() { *m = Nlri{} }
@@ -789,6 +843,13 @@ func (m *Nlri) GetRtNlri() *RTNlri {
return nil
}
+func (m *Nlri) GetVpnNlri() *VPNNlri {
+ if m != nil {
+ return m.VpnNlri
+ }
+ return nil
+}
+
type TunnelEncapSubTLV struct {
Type ENCAP_SUBTLV_TYPE `protobuf:"varint,1,opt,name=type,enum=api.ENCAP_SUBTLV_TYPE" json:"type,omitempty"`
Value string `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"`
@@ -1255,6 +1316,7 @@ func init() {
proto.RegisterEnum("api.Operation", Operation_name, Operation_value)
proto.RegisterEnum("api.AFI", AFI_name, AFI_value)
proto.RegisterEnum("api.SAFI", SAFI_name, SAFI_value)
+ proto.RegisterEnum("api.ROUTE_DISTINGUISHER_TYPE", ROUTE_DISTINGUISHER_TYPE_name, ROUTE_DISTINGUISHER_TYPE_value)
proto.RegisterEnum("api.BGP_CAPABILITY", BGP_CAPABILITY_name, BGP_CAPABILITY_value)
proto.RegisterEnum("api.Origin", Origin_name, Origin_value)
proto.RegisterEnum("api.EXTENDED_COMMUNITIE_TYPE", EXTENDED_COMMUNITIE_TYPE_name, EXTENDED_COMMUNITIE_TYPE_value)
diff --git a/api/gobgp.proto b/api/gobgp.proto
index d52f96dc..677ee963 100644
--- a/api/gobgp.proto
+++ b/api/gobgp.proto
@@ -113,6 +113,18 @@ message AddressFamily {
SAFI Safi = 2;
}
+enum ROUTE_DISTINGUISHER_TYPE {
+ TWO_OCTET_AS = 0;
+ IP4 = 1;
+ FOUR_OCTET_AS = 2;
+}
+
+message RouteDistinguisher {
+ ROUTE_DISTINGUISHER_TYPE type = 1;
+ string admin = 2;
+ uint32 assigned = 3;
+}
+
enum BGP_CAPABILITY {
UNKNOWN_CAP = 0;
MULTIPROTOCOL = 1;
@@ -238,12 +250,20 @@ message RTNlri {
uint32 length = 3;
}
+message VPNNlri {
+ RouteDistinguisher rd = 1;
+ repeated uint32 labels = 2;
+ string ip_addr = 3;
+ uint32 ip_addr_len = 4;
+}
+
message Nlri {
AddressFamily af = 1;
string prefix = 2;
string nexthop = 3;
EVPNNlri evpn_nlri = 4;
RTNlri rt_nlri = 5;
+ VPNNlri vpn_nlri = 6;
}
enum ENCAP_SUBTLV_TYPE {
diff --git a/api/util.go b/api/util.go
index 591c1c59..677d4f6a 100644
--- a/api/util.go
+++ b/api/util.go
@@ -17,6 +17,8 @@ package api
var AF_IPV4_UC *AddressFamily = &AddressFamily{AFI_IP, SAFI_UNICAST}
var AF_IPV6_UC *AddressFamily = &AddressFamily{AFI_IP6, SAFI_UNICAST}
+var AF_IPV4_VPN *AddressFamily = &AddressFamily{AFI_IP, SAFI_MPLS_VPN}
+var AF_IPV6_VPN *AddressFamily = &AddressFamily{AFI_IP6, SAFI_MPLS_VPN}
var AF_EVPN *AddressFamily = &AddressFamily{AFI_L2VPN, SAFI_EVPN}
var AF_ENCAP *AddressFamily = &AddressFamily{AFI_IP, SAFI_ENCAP}
var AF_RTC *AddressFamily = &AddressFamily{AFI_IP, SAFI_ROUTE_TARGET_CONSTRAINTS}
diff --git a/config/default.go b/config/default.go
index 6e08a70e..f0c37f66 100644
--- a/config/default.go
+++ b/config/default.go
@@ -33,6 +33,8 @@ func SetDefaultConfigValues(md toml.MetaData, bt *Bgp) error {
bt.Global.AfiSafiList = []AfiSafi{
AfiSafi{AfiSafiName: "ipv4-unicast"},
AfiSafi{AfiSafiName: "ipv6-unicast"},
+ AfiSafi{AfiSafiName: "l3vpn-ipv4-unicast"},
+ AfiSafi{AfiSafiName: "l3vpn-ipv6-unicast"},
AfiSafi{AfiSafiName: "l2vpn-evpn"},
AfiSafi{AfiSafiName: "encap"},
AfiSafi{AfiSafiName: "rtc"},
diff --git a/gobgp/common.go b/gobgp/common.go
index b58eb4aa..f2533c37 100644
--- a/gobgp/common.go
+++ b/gobgp/common.go
@@ -273,6 +273,10 @@ func checkAddressFamily(ip net.IP) (*api.AddressFamily, error) {
rf = api.AF_IPV4_UC
case "ipv6", "v6", "6":
rf = api.AF_IPV6_UC
+ case "vpnv4", "vpn-ipv4":
+ rf = api.AF_IPV4_VPN
+ case "vpnv6", "vpn-ipv6":
+ rf = api.AF_IPV6_VPN
case "evpn":
rf = api.AF_EVPN
case "encap":
diff --git a/gobgp/global.go b/gobgp/global.go
index 8744449f..79d91a65 100644
--- a/gobgp/global.go
+++ b/gobgp/global.go
@@ -23,6 +23,7 @@ import (
"net"
"os"
"strconv"
+ "strings"
)
func showGlobalRib(args []string) error {
@@ -30,47 +31,95 @@ func showGlobalRib(args []string) error {
return showNeighborRib(CMD_GLOBAL, bogusIp, args)
}
-func modPath(modtype string, eArgs []string) error {
+func parseRD(args []string) (*api.RouteDistinguisher, error) {
+ t, err := strconv.Atoi(args[0])
+ if err != nil {
+ return nil, err
+ }
+ typ := api.ROUTE_DISTINGUISHER_TYPE(t)
+ admin := args[1]
+ assigned, err := strconv.Atoi(args[2])
+ if err != nil {
+ return nil, err
+ }
+ return &api.RouteDistinguisher{
+ Type: typ,
+ Admin: admin,
+ Assigned: uint32(assigned),
+ }, nil
+}
+
+func modPath(modtype string, args []string) error {
rf, err := checkAddressFamily(net.IP{})
if err != nil {
return err
}
path := &api.Path{}
- var prefix string
switch rf {
case api.AF_IPV4_UC, api.AF_IPV6_UC:
- if len(eArgs) == 1 || len(eArgs) == 3 {
- prefix = eArgs[0]
- } else {
+ if len(args) != 1 {
return fmt.Errorf("usage: global rib %s <prefix> -a { ipv4 | ipv6 }", modtype)
}
+ prefix := args[0]
path.Nlri = &api.Nlri{
Af: rf,
Prefix: prefix,
}
+ case api.AF_IPV4_VPN, api.AF_IPV6_VPN:
+ if len(args) < 1 {
+ return fmt.Errorf("usage: global rib %s <rd>:<prefix> [<rt>...] -a { vpn-ipv4 | vpn-ipv6 }", modtype)
+ }
+ elems := strings.SplitN(args[0], ":", 4)
+ if len(elems) != 4 {
+ return fmt.Errorf("invalid <rd>:<prefix>: %s. hint. <rd> := <type>:<admin>:<assigned>", args[0])
+ }
+ rd, err := parseRD(elems[:3])
+ if err != nil {
+ return err
+ }
+ prefix := elems[3]
+ elems = strings.Split(prefix, "/")
+ if len(elems) != 2 {
+ return fmt.Errorf("invalid prefix: %s", prefix)
+ }
+
+ masklen, err := strconv.Atoi(elems[1])
+ if err != nil {
+ return fmt.Errorf("invalid prefix: %s", prefix)
+ }
+
+ nlri := &api.VPNNlri{
+ Rd: rd,
+ IpAddr: elems[0],
+ IpAddrLen: uint32(masklen),
+ }
+ path.Nlri = &api.Nlri{
+ Af: rf,
+ VpnNlri: nlri,
+ }
case api.AF_EVPN:
var nlri *api.EVPNNlri
- if len(eArgs) < 1 {
+ if len(args) < 1 {
return fmt.Errorf("usage: global rib %s { macadv | multicast } ... -a evpn", modtype)
}
- subtype := eArgs[0]
+ subtype := args[0]
switch subtype {
case "macadv":
- if len(eArgs) < 5 {
+ if len(args) < 5 {
return fmt.Errorf("usage: global rib %s macadv <mac address> <ip address> <etag> <label> -a evpn", modtype)
}
- macAddr := eArgs[1]
- ipAddr := eArgs[2]
- eTag, err := strconv.Atoi(eArgs[3])
+ macAddr := args[1]
+ ipAddr := args[2]
+ eTag, err := strconv.Atoi(args[3])
if err != nil {
- return fmt.Errorf("invalid eTag: %s. err: %s", eArgs[3], err)
+ return fmt.Errorf("invalid eTag: %s. err: %s", args[3], err)
}
- label, err := strconv.Atoi(eArgs[4])
+ label, err := strconv.Atoi(args[4])
if err != nil {
- return fmt.Errorf("invalid label: %s. err: %s", eArgs[4], err)
+ return fmt.Errorf("invalid label: %s. err: %s", args[4], err)
}
nlri = &api.EVPNNlri{
Type: api.EVPN_TYPE_ROUTE_TYPE_MAC_IP_ADVERTISEMENT,
@@ -82,16 +131,16 @@ func modPath(modtype string, eArgs []string) error {
},
}
case "multicast":
- if len(eArgs) < 3 {
+ if len(args) < 3 {
return fmt.Errorf("usage : global rib %s multicast <etag> <label> -a evpn", modtype)
}
- eTag, err := strconv.Atoi(eArgs[1])
+ eTag, err := strconv.Atoi(args[1])
if err != nil {
- return fmt.Errorf("invalid eTag: %s. err: %s", eArgs[1], err)
+ return fmt.Errorf("invalid eTag: %s. err: %s", args[1], err)
}
- label, err := strconv.Atoi(eArgs[2])
+ label, err := strconv.Atoi(args[2])
if err != nil {
- return fmt.Errorf("invalid label: %s. err: %s", eArgs[2], err)
+ return fmt.Errorf("invalid label: %s. err: %s", args[2], err)
}
nlri = &api.EVPNNlri{
Type: api.EVPN_TYPE_INCLUSIVE_MULTICAST_ETHERNET_TAG,
@@ -117,20 +166,20 @@ func modPath(modtype string, eArgs []string) error {
EvpnNlri: nlri,
}
case api.AF_ENCAP:
- if len(eArgs) < 3 {
+ if len(args) < 1 {
return fmt.Errorf("usage: global rib %s <end point ip address> [<vni>] -a encap", modtype)
}
- prefix = eArgs[0]
+ prefix := args[0]
path.Nlri = &api.Nlri{
Af: rf,
Prefix: prefix,
}
- if len(eArgs) > 3 {
- vni, err := strconv.Atoi(eArgs[1])
+ if len(args) > 1 {
+ vni, err := strconv.Atoi(args[1])
if err != nil {
- return fmt.Errorf("invalid vni: %s", eArgs[1])
+ return fmt.Errorf("invalid vni: %s", args[1])
}
subTlv := &api.TunnelEncapSubTLV{
Type: api.ENCAP_SUBTLV_TYPE_COLOR,
@@ -148,19 +197,19 @@ func modPath(modtype string, eArgs []string) error {
path.Attrs = append(path.Attrs, attr)
}
case api.AF_RTC:
- if !(len(eArgs) == 3 && eArgs[0] == "default") && len(eArgs) < 4 {
+ if !(len(args) == 3 && args[0] == "default") && len(args) < 4 {
return fmt.Errorf("usage: global rib add <asn> <local admin> -a rtc")
}
var asn, admin int
- if eArgs[0] != "default" {
- asn, err = strconv.Atoi(eArgs[0])
+ if args[0] != "default" {
+ asn, err = strconv.Atoi(args[0])
if err != nil {
- return fmt.Errorf("invalid asn: %s", eArgs[0])
+ return fmt.Errorf("invalid asn: %s", args[0])
}
- admin, err = strconv.Atoi(eArgs[1])
+ admin, err = strconv.Atoi(args[1])
if err != nil {
- return fmt.Errorf("invalid local admin: %s", eArgs[1])
+ return fmt.Errorf("invalid local admin: %s", args[1])
}
}
path.Nlri = &api.Nlri{
diff --git a/packet/bgp.go b/packet/bgp.go
index bdd07911..6cc9145d 100644
--- a/packet/bgp.go
+++ b/packet/bgp.go
@@ -938,14 +938,14 @@ func NewMPLSLabelStack(labels ...uint32) *MPLSLabelStack {
// followed by an IPv4 prefix.
//
-type LabelledVPNIPAddrPrefix struct {
+type LabeledVPNIPAddrPrefix struct {
IPAddrPrefixDefault
Labels MPLSLabelStack
RD RouteDistinguisherInterface
addrlen uint8
}
-func (l *LabelledVPNIPAddrPrefix) DecodeFromBytes(data []byte) error {
+func (l *LabeledVPNIPAddrPrefix) DecodeFromBytes(data []byte) error {
l.Length = uint8(data[0])
data = data[1:]
l.Labels.DecodeFromBytes(data)
@@ -960,7 +960,7 @@ func (l *LabelledVPNIPAddrPrefix) DecodeFromBytes(data []byte) error {
return nil
}
-func (l *LabelledVPNIPAddrPrefix) Serialize() ([]byte, error) {
+func (l *LabeledVPNIPAddrPrefix) Serialize() ([]byte, error) {
buf := make([]byte, 1)
buf[0] = l.Length
lbuf, err := l.Labels.Serialize()
@@ -982,27 +982,32 @@ func (l *LabelledVPNIPAddrPrefix) Serialize() ([]byte, error) {
return buf, nil
}
-func (l *LabelledVPNIPAddrPrefix) AFI() uint16 {
+func (l *LabeledVPNIPAddrPrefix) AFI() uint16 {
return AFI_IP
}
-func (l *LabelledVPNIPAddrPrefix) SAFI() uint8 {
+func (l *LabeledVPNIPAddrPrefix) SAFI() uint8 {
return SAFI_MPLS_VPN
}
-func (l *LabelledVPNIPAddrPrefix) ToApiStruct() *api.Nlri {
+func (l *LabeledVPNIPAddrPrefix) ToApiStruct() *api.Nlri {
return &api.Nlri{
Af: &api.AddressFamily{api.AFI(l.AFI()), api.SAFI(l.SAFI())},
Prefix: l.String(),
}
}
-func NewLabelledVPNIPAddrPrefix(length uint8, prefix string, label MPLSLabelStack, rd RouteDistinguisherInterface) *LabelledVPNIPAddrPrefix {
+func (l *LabeledVPNIPAddrPrefix) String() string {
+ masklen := l.IPAddrPrefixDefault.Length - uint8(8*(l.Labels.Len()+l.RD.Len()))
+ return fmt.Sprintf("%s:%s/%d", l.RD, l.IPAddrPrefixDefault.Prefix, masklen)
+}
+
+func NewLabeledVPNIPAddrPrefix(length uint8, prefix string, label MPLSLabelStack, rd RouteDistinguisherInterface) *LabeledVPNIPAddrPrefix {
rdlen := 0
if rd != nil {
rdlen = rd.Len()
}
- return &LabelledVPNIPAddrPrefix{
+ return &LabeledVPNIPAddrPrefix{
IPAddrPrefixDefault{length + uint8(8*(label.Len()+rdlen)), net.ParseIP(prefix)},
label,
rd,
@@ -1010,21 +1015,21 @@ func NewLabelledVPNIPAddrPrefix(length uint8, prefix string, label MPLSLabelStac
}
}
-type LabelledVPNIPv6AddrPrefix struct {
- LabelledVPNIPAddrPrefix
+type LabeledVPNIPv6AddrPrefix struct {
+ LabeledVPNIPAddrPrefix
}
-func (l *LabelledVPNIPv6AddrPrefix) AFI() uint16 {
+func (l *LabeledVPNIPv6AddrPrefix) AFI() uint16 {
return AFI_IP6
}
-func NewLabelledVPNIPv6AddrPrefix(length uint8, prefix string, label MPLSLabelStack, rd RouteDistinguisherInterface) *LabelledVPNIPv6AddrPrefix {
+func NewLabeledVPNIPv6AddrPrefix(length uint8, prefix string, label MPLSLabelStack, rd RouteDistinguisherInterface) *LabeledVPNIPv6AddrPrefix {
rdlen := 0
if rd != nil {
rdlen = rd.Len()
}
- return &LabelledVPNIPv6AddrPrefix{
- LabelledVPNIPAddrPrefix{
+ return &LabeledVPNIPv6AddrPrefix{
+ LabeledVPNIPAddrPrefix{
IPAddrPrefixDefault{length + uint8(8*(label.Len()+rdlen)), net.ParseIP(prefix)},
label,
rd,
@@ -1033,21 +1038,21 @@ func NewLabelledVPNIPv6AddrPrefix(length uint8, prefix string, label MPLSLabelSt
}
}
-type LabelledIPAddrPrefix struct {
+type LabeledIPAddrPrefix struct {
IPAddrPrefixDefault
Labels MPLSLabelStack
addrlen uint8
}
-func (r *LabelledIPAddrPrefix) AFI() uint16 {
+func (r *LabeledIPAddrPrefix) AFI() uint16 {
return AFI_IP
}
-func (r *LabelledIPAddrPrefix) SAFI() uint8 {
+func (r *LabeledIPAddrPrefix) SAFI() uint8 {
return SAFI_MPLS_LABEL
}
-func (r *LabelledIPAddrPrefix) ToApiStruct() *api.Nlri {
+func (r *LabeledIPAddrPrefix) ToApiStruct() *api.Nlri {
return &api.Nlri{
Af: &api.AddressFamily{api.AFI(r.AFI()), api.SAFI(r.SAFI())},
Prefix: r.String(),
@@ -1062,18 +1067,18 @@ func (r *IPAddrPrefix) decodeNextHop(data []byte) net.IP {
return next
}
-func (r *LabelledVPNIPAddrPrefix) decodeNextHop(data []byte) net.IP {
+func (r *LabeledVPNIPAddrPrefix) decodeNextHop(data []byte) net.IP {
// skip rd
var next net.IP = data[8 : 8+r.addrlen]
return next
}
-func (r *LabelledIPAddrPrefix) decodeNextHop(data []byte) net.IP {
+func (r *LabeledIPAddrPrefix) decodeNextHop(data []byte) net.IP {
var next net.IP = data[0:r.addrlen]
return next
}
-func (l *LabelledIPAddrPrefix) DecodeFromBytes(data []byte) error {
+func (l *LabeledIPAddrPrefix) DecodeFromBytes(data []byte) error {
l.Length = uint8(data[0])
data = data[1:]
l.Labels.DecodeFromBytes(data)
@@ -1086,7 +1091,7 @@ func (l *LabelledIPAddrPrefix) DecodeFromBytes(data []byte) error {
return nil
}
-func (l *LabelledIPAddrPrefix) Serialize() ([]byte, error) {
+func (l *LabeledIPAddrPrefix) Serialize() ([]byte, error) {
buf := make([]byte, 1)
buf[0] = l.Length
restbits := int(l.Length) - 8*(l.Labels.Len())
@@ -1103,21 +1108,21 @@ func (l *LabelledIPAddrPrefix) Serialize() ([]byte, error) {
return buf, nil
}
-func NewLabelledIPAddrPrefix(length uint8, prefix string, label MPLSLabelStack) *LabelledIPAddrPrefix {
- return &LabelledIPAddrPrefix{
+func NewLabeledIPAddrPrefix(length uint8, prefix string, label MPLSLabelStack) *LabeledIPAddrPrefix {
+ return &LabeledIPAddrPrefix{
IPAddrPrefixDefault{length + uint8(label.Len()*8), net.ParseIP(prefix)},
label,
4,
}
}
-type LabelledIPv6AddrPrefix struct {
- LabelledIPAddrPrefix
+type LabeledIPv6AddrPrefix struct {
+ LabeledIPAddrPrefix
}
-func NewLabelledIPv6AddrPrefix(length uint8, prefix string, label MPLSLabelStack) *LabelledIPv6AddrPrefix {
- return &LabelledIPv6AddrPrefix{
- LabelledIPAddrPrefix{
+func NewLabeledIPv6AddrPrefix(length uint8, prefix string, label MPLSLabelStack) *LabeledIPv6AddrPrefix {
+ return &LabeledIPv6AddrPrefix{
+ LabeledIPAddrPrefix{
IPAddrPrefixDefault{length + uint8(label.Len()*8), net.ParseIP(prefix)},
label,
16,
@@ -1800,13 +1805,13 @@ func NewPrefixFromRouteFamily(afi uint16, safi uint8) (prefix AddrPrefixInterfac
case RF_IPv6_UC, RF_IPv6_MC:
prefix = NewIPv6AddrPrefix(0, "")
case RF_IPv4_VPN:
- prefix = NewLabelledVPNIPAddrPrefix(0, "", *NewMPLSLabelStack(), nil)
+ prefix = NewLabeledVPNIPAddrPrefix(0, "", *NewMPLSLabelStack(), nil)
case RF_IPv6_VPN:
- prefix = NewLabelledVPNIPv6AddrPrefix(0, "", *NewMPLSLabelStack(), nil)
+ prefix = NewLabeledVPNIPv6AddrPrefix(0, "", *NewMPLSLabelStack(), nil)
case RF_IPv4_MPLS:
- prefix = NewLabelledIPAddrPrefix(0, "", *NewMPLSLabelStack())
+ prefix = NewLabeledIPAddrPrefix(0, "", *NewMPLSLabelStack())
case RF_IPv6_MPLS:
- prefix = NewLabelledIPv6AddrPrefix(0, "", *NewMPLSLabelStack())
+ prefix = NewLabeledIPv6AddrPrefix(0, "", *NewMPLSLabelStack())
case RF_EVPN:
prefix = NewEVPNNLRI(0, 0, nil)
case RF_RTC_UC:
diff --git a/packet/bgp_test.go b/packet/bgp_test.go
index 16055819..84aaed75 100644
--- a/packet/bgp_test.go
+++ b/packet/bgp_test.go
@@ -69,20 +69,20 @@ func update() *BGPMessage {
}
mp_nlri := []AddrPrefixInterface{
- NewLabelledVPNIPAddrPrefix(20, "192.0.9.0", *NewMPLSLabelStack(1, 2, 3),
+ NewLabeledVPNIPAddrPrefix(20, "192.0.9.0", *NewMPLSLabelStack(1, 2, 3),
NewRouteDistinguisherTwoOctetAS(256, 10000)),
- NewLabelledVPNIPAddrPrefix(26, "192.10.8.192", *NewMPLSLabelStack(5, 6, 7, 8),
+ NewLabeledVPNIPAddrPrefix(26, "192.10.8.192", *NewMPLSLabelStack(5, 6, 7, 8),
NewRouteDistinguisherIPAddressAS("10.0.1.1", 10001)),
}
mp_nlri2 := []AddrPrefixInterface{NewIPv6AddrPrefix(100,
"fe80:1234:1234:5667:8967:af12:8912:1023")}
- mp_nlri3 := []AddrPrefixInterface{NewLabelledVPNIPv6AddrPrefix(100,
+ mp_nlri3 := []AddrPrefixInterface{NewLabeledVPNIPv6AddrPrefix(100,
"fe80:1234:1234:5667:8967:af12:1203:33a1", *NewMPLSLabelStack(5, 6),
NewRouteDistinguisherFourOctetAS(5, 6))}
- mp_nlri4 := []AddrPrefixInterface{NewLabelledIPAddrPrefix(25, "192.168.0.0",
+ mp_nlri4 := []AddrPrefixInterface{NewLabeledIPAddrPrefix(25, "192.168.0.0",
*NewMPLSLabelStack(5, 6, 7))}
mac, _ := net.ParseMAC("01:23:45:67:89:ab")
diff --git a/server/grpc_server.go b/server/grpc_server.go
index 25af6dc7..1e81e3ce 100644
--- a/server/grpc_server.go
+++ b/server/grpc_server.go
@@ -89,6 +89,10 @@ func convertAf2Rf(af *api.AddressFamily) (bgp.RouteFamily, error) {
return bgp.RF_IPv4_UC, nil
} else if af.Equal(api.AF_IPV6_UC) {
return bgp.RF_IPv6_UC, nil
+ } else if af.Equal(api.AF_IPV4_VPN) {
+ return bgp.RF_IPv4_VPN, nil
+ } else if af.Equal(api.AF_IPV6_VPN) {
+ return bgp.RF_IPv6_VPN, nil
} else if af.Equal(api.AF_EVPN) {
return bgp.RF_EVPN, nil
} else if af.Equal(api.AF_ENCAP) {
diff --git a/server/server.go b/server/server.go
index 57f7c7ee..a3d512a9 100644
--- a/server/server.go
+++ b/server/server.go
@@ -712,6 +712,44 @@ func handleGlobalRibRequest(grpcReq *GrpcRequest, peerInfo *table.PeerInfo) []*t
pattr = append(pattr, bgp.NewPathAttributeMpReachNLRI("::", []bgp.AddrPrefixInterface{nlri}))
+ case bgp.RF_IPv4_VPN, bgp.RF_IPv6_VPN:
+ var rd bgp.RouteDistinguisherInterface
+ switch path.Nlri.VpnNlri.Rd.Type {
+ case api.ROUTE_DISTINGUISHER_TYPE_TWO_OCTET_AS:
+ a, err := strconv.Atoi(path.Nlri.VpnNlri.Rd.Admin)
+ if err != nil {
+ result.ResponseErr = fmt.Errorf("Invalid admin value: %s", path.Nlri.VpnNlri.Rd.Admin)
+ goto ERR
+ }
+ rd = bgp.NewRouteDistinguisherTwoOctetAS(uint16(a), path.Nlri.VpnNlri.Rd.Assigned)
+ case api.ROUTE_DISTINGUISHER_TYPE_IP4:
+ ip := net.ParseIP(path.Nlri.VpnNlri.Rd.Admin)
+ if ip.To4() == nil {
+ result.ResponseErr = fmt.Errorf("Invalid ipv4 prefix: %s", path.Nlri.VpnNlri.Rd.Admin)
+ goto ERR
+ }
+ assigned := uint16(path.Nlri.VpnNlri.Rd.Assigned)
+ rd = bgp.NewRouteDistinguisherIPAddressAS(path.Nlri.VpnNlri.Rd.Admin, assigned)
+ case api.ROUTE_DISTINGUISHER_TYPE_FOUR_OCTET_AS:
+ a, err := strconv.Atoi(path.Nlri.VpnNlri.Rd.Admin)
+ if err != nil {
+ result.ResponseErr = fmt.Errorf("Invalid admin value: %s", path.Nlri.VpnNlri.Rd.Admin)
+ goto ERR
+ }
+ admin := uint32(a)
+ assigned := uint16(path.Nlri.VpnNlri.Rd.Assigned)
+ rd = bgp.NewRouteDistinguisherFourOctetAS(admin, assigned)
+ }
+
+ mpls := bgp.NewMPLSLabelStack(0)
+ if rf == bgp.RF_IPv4_VPN {
+ nlri = bgp.NewLabeledVPNIPAddrPrefix(uint8(path.Nlri.VpnNlri.IpAddrLen), path.Nlri.VpnNlri.IpAddr, *mpls, rd)
+ pattr = append(pattr, bgp.NewPathAttributeMpReachNLRI("0.0.0.0", []bgp.AddrPrefixInterface{nlri}))
+ } else {
+ nlri = bgp.NewLabeledVPNIPv6AddrPrefix(uint8(path.Nlri.VpnNlri.IpAddrLen), path.Nlri.VpnNlri.IpAddr, *mpls, rd)
+ pattr = append(pattr, bgp.NewPathAttributeMpReachNLRI("::", []bgp.AddrPrefixInterface{nlri}))
+ }
+
case bgp.RF_EVPN:
if peerInfo.AS > (1<<16 - 1) {
result.ResponseErr = fmt.Errorf("evpn path can't be created in 4byte-AS env")