diff options
author | ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp> | 2015-07-02 23:39:20 +0900 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2015-07-05 23:44:22 +0900 |
commit | 2fc9b887fc63da94e173f75dd15330254e35647c (patch) | |
tree | c25548066c75ad9dc17babbf1e12286a10e60aed | |
parent | cd89516a28f4de85f844a232cb1b40b198218856 (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.go | 62 | ||||
-rw-r--r-- | api/gobgp.proto | 20 | ||||
-rw-r--r-- | api/util.go | 2 | ||||
-rw-r--r-- | config/default.go | 2 | ||||
-rw-r--r-- | gobgp/common.go | 4 | ||||
-rw-r--r-- | gobgp/global.go | 109 | ||||
-rw-r--r-- | packet/bgp.go | 71 | ||||
-rw-r--r-- | packet/bgp_test.go | 8 | ||||
-rw-r--r-- | server/grpc_server.go | 4 | ||||
-rw-r--r-- | server/server.go | 38 |
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") |