summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorISHIDA Wataru <ishida.wataru@lab.ntt.co.jp>2015-04-25 10:06:56 +0000
committerISHIDA Wataru <ishida.wataru@lab.ntt.co.jp>2015-04-25 15:16:45 +0000
commit99cccf981227a482cbd6404b664bd4f7cc9a1720 (patch)
treee8c93e477bb245122e4771cfe879db6833bcc04e
parent27d0d45b6319658bc0a43511d1909a411df40b08 (diff)
table: add support for encapsulation nlri
add encap end point route(10.0.0.1) with vni 20 $ gobgp global rib add 10.0.0.1 20 -a encap check it $ gobgp global rib -a encap Please specify one command of: add or del Network Next Hop AS_PATH Age Attrs *> 10.0.0.1 0.0.0.0 [64512] 00:00:01 [{Origin: IGP} {Encap: < VXLAN | color: 20 >}] Signed-off-by: ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp>
-rw-r--r--api/gobgp.pb.go38
-rw-r--r--api/gobgp.proto14
-rw-r--r--api/util.go1
-rw-r--r--config/default.go1
-rw-r--r--gobgp/main.go58
-rw-r--r--packet/bgp.go141
-rw-r--r--packet/bgp_test.go6
-rw-r--r--packet/routefamily_string.go56
-rw-r--r--server/grpc_server.go4
-rw-r--r--server/peer.go57
-rw-r--r--table/destination.go12
-rw-r--r--table/destination_test.go2
-rw-r--r--table/message.go2
-rw-r--r--table/path.go67
-rw-r--r--table/path_test.go4
-rw-r--r--table/table.go19
-rw-r--r--table/table_manager.go11
-rw-r--r--table/table_test.go2
18 files changed, 413 insertions, 82 deletions
diff --git a/api/gobgp.pb.go b/api/gobgp.pb.go
index 0e2874dd..4fb2413a 100644
--- a/api/gobgp.pb.go
+++ b/api/gobgp.pb.go
@@ -101,6 +101,7 @@ const (
SAFI_UNICAST SAFI = 1
SAFI_MULTICAST SAFI = 2
SAFI_MPLS_LABEL SAFI = 4
+ SAFI_ENCAP SAFI = 7
SAFI_VPLS SAFI = 65
SAFI_EVPN SAFI = 70
SAFI_MPLS_VPN SAFI = 128
@@ -113,6 +114,7 @@ var SAFI_name = map[int32]string{
1: "UNICAST",
2: "MULTICAST",
4: "MPLS_LABEL",
+ 7: "ENCAP",
65: "VPLS",
70: "EVPN",
128: "MPLS_VPN",
@@ -124,6 +126,7 @@ var SAFI_value = map[string]int32{
"UNICAST": 1,
"MULTICAST": 2,
"MPLS_LABEL": 4,
+ "ENCAP": 7,
"VPLS": 65,
"EVPN": 70,
"MPLS_VPN": 128,
@@ -228,6 +231,32 @@ func (x EVPN_TYPE) String() string {
return proto.EnumName(EVPN_TYPE_name, int32(x))
}
+type ENCAP_SUBTLV_TYPE int32
+
+const (
+ ENCAP_SUBTLV_TYPE_UNKNOWN_SUBTLV_TYPE ENCAP_SUBTLV_TYPE = 0
+ ENCAP_SUBTLV_TYPE_ENCAPSULATION ENCAP_SUBTLV_TYPE = 1
+ ENCAP_SUBTLV_TYPE_PROTOCOL ENCAP_SUBTLV_TYPE = 2
+ ENCAP_SUBTLV_TYPE_COLOR ENCAP_SUBTLV_TYPE = 4
+)
+
+var ENCAP_SUBTLV_TYPE_name = map[int32]string{
+ 0: "UNKNOWN_SUBTLV_TYPE",
+ 1: "ENCAPSULATION",
+ 2: "PROTOCOL",
+ 4: "COLOR",
+}
+var ENCAP_SUBTLV_TYPE_value = map[string]int32{
+ "UNKNOWN_SUBTLV_TYPE": 0,
+ "ENCAPSULATION": 1,
+ "PROTOCOL": 2,
+ "COLOR": 4,
+}
+
+func (x ENCAP_SUBTLV_TYPE) String() string {
+ return proto.EnumName(ENCAP_SUBTLV_TYPE_name, int32(x))
+}
+
type BGP_ATTR_TYPE int32
const (
@@ -431,8 +460,12 @@ func (m *Nlri) GetEvpnNlri() *EVPNNlri {
}
type TunnelEncapSubTLV struct {
- Type uint32 `protobuf:"varint,1,opt,name=type" json:"type,omitempty"`
- Value string `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"`
+ 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"`
+ Key uint32 `protobuf:"varint,3,opt,name=key" json:"key,omitempty"`
+ Cookie string `protobuf:"bytes,4,opt,name=cookie" json:"cookie,omitempty"`
+ Protocol uint32 `protobuf:"varint,5,opt,name=protocol" json:"protocol,omitempty"`
+ Color uint32 `protobuf:"varint,6,opt,name=color" json:"color,omitempty"`
}
func (m *TunnelEncapSubTLV) Reset() { *m = TunnelEncapSubTLV{} }
@@ -616,6 +649,7 @@ func init() {
proto.RegisterEnum("api.Origin", Origin_name, Origin_value)
proto.RegisterEnum("api.TUNNEL_TYPE", TUNNEL_TYPE_name, TUNNEL_TYPE_value)
proto.RegisterEnum("api.EVPN_TYPE", EVPN_TYPE_name, EVPN_TYPE_value)
+ proto.RegisterEnum("api.ENCAP_SUBTLV_TYPE", ENCAP_SUBTLV_TYPE_name, ENCAP_SUBTLV_TYPE_value)
proto.RegisterEnum("api.BGP_ATTR_TYPE", BGP_ATTR_TYPE_name, BGP_ATTR_TYPE_value)
proto.RegisterEnum("api.Error_ErrorCode", Error_ErrorCode_name, Error_ErrorCode_value)
}
diff --git a/api/gobgp.proto b/api/gobgp.proto
index 81b32ffb..611f1abc 100644
--- a/api/gobgp.proto
+++ b/api/gobgp.proto
@@ -73,6 +73,7 @@ enum SAFI {
UNICAST = 1;
MULTICAST = 2;
MPLS_LABEL = 4;
+ ENCAP = 7;
VPLS = 65;
EVPN = 70;
MPLS_VPN = 128;
@@ -142,9 +143,20 @@ message Nlri {
string nexthop = 4;
}
+enum ENCAP_SUBTLV_TYPE {
+ UNKNOWN_SUBTLV_TYPE = 0;
+ ENCAPSULATION = 1;
+ PROTOCOL = 2;
+ COLOR = 4;
+}
+
message TunnelEncapSubTLV {
- uint32 type = 1;
+ ENCAP_SUBTLV_TYPE type = 1;
string value = 2;
+ uint32 key = 3;
+ string cookie = 4;
+ uint32 protocol = 5;
+ uint32 color = 6;
}
message TunnelEncapTLV {
diff --git a/api/util.go b/api/util.go
index aa27e3d3..00a4366c 100644
--- a/api/util.go
+++ b/api/util.go
@@ -18,6 +18,7 @@ package api
var AF_IPV4_UC *AddressFamily = &AddressFamily{AFI_IP, SAFI_UNICAST}
var AF_IPV6_UC *AddressFamily = &AddressFamily{AFI_IP6, SAFI_UNICAST}
var AF_EVPN *AddressFamily = &AddressFamily{AFI_L2VPN, SAFI_EVPN}
+var AF_ENCAP *AddressFamily = &AddressFamily{AFI_IP, SAFI_ENCAP}
func (lhs *AddressFamily) Equal(rhs *AddressFamily) bool {
return lhs.Afi == rhs.Afi && lhs.Safi == rhs.Safi
diff --git a/config/default.go b/config/default.go
index 8b7f1fb7..2f1bedda 100644
--- a/config/default.go
+++ b/config/default.go
@@ -34,6 +34,7 @@ func SetDefaultConfigValues(md toml.MetaData, bt *Bgp) error {
AfiSafi{AfiSafiName: "ipv4-unicast"},
AfiSafi{AfiSafiName: "ipv6-unicast"},
AfiSafi{AfiSafiName: "l2vpn-evpn"},
+ AfiSafi{AfiSafiName: "encap"},
}
}
diff --git a/gobgp/main.go b/gobgp/main.go
index 4112de7a..634e95be 100644
--- a/gobgp/main.go
+++ b/gobgp/main.go
@@ -27,6 +27,7 @@ import (
"net"
"os"
"sort"
+ "strconv"
"strings"
"time"
)
@@ -234,6 +235,8 @@ func checkAddressFamily() (*api.AddressFamily, error) {
rf = api.AF_IPV6_UC
case "evpn":
rf = api.AF_EVPN
+ case "encap":
+ rf = api.AF_ENCAP
case "":
e = fmt.Errorf("address family is not specified")
default:
@@ -375,6 +378,37 @@ func modPath(modtype string, eArgs []string) error {
},
},
}
+ case api.AF_ENCAP:
+ if len(eArgs) < 3 {
+ return fmt.Errorf("usage: global rib add <end point ip address> [<vni>] -a encap")
+ }
+ prefix = eArgs[0]
+
+ path.Nlri = &api.Nlri{
+ Af: rf,
+ Prefix: prefix,
+ }
+
+ if len(eArgs) > 3 {
+ vni, err := strconv.Atoi(eArgs[1])
+ if err != nil {
+ return fmt.Errorf("invalid vni: %s", eArgs[1])
+ }
+ subTlv := &api.TunnelEncapSubTLV{
+ Type: api.ENCAP_SUBTLV_TYPE_COLOR,
+ Color: uint32(vni),
+ }
+ tlv := &api.TunnelEncapTLV{
+ Type: api.TUNNEL_TYPE_VXLAN,
+ SubTlv: []*api.TunnelEncapSubTLV{subTlv},
+ }
+ attr := &api.PathAttr{
+ Type: api.BGP_ATTR_TYPE_TUNNEL_ENCAP,
+ TunnelEncap: []*api.TunnelEncapTLV{tlv},
+ }
+
+ path.Attrs = append(path.Attrs, attr)
+ }
}
switch modtype {
case "add":
@@ -741,9 +775,29 @@ func showRoute(pathList []*api.Path, showAge bool, showBest bool) {
}
s = append(s, fmt.Sprintf("{Community: %v}", l))
case api.BGP_ATTR_TYPE_ORIGINATOR_ID:
- s = append(s, fmt.Sprintf("{Originator: %v|", a.Originator))
+ s = append(s, fmt.Sprintf("{Originator: %v}", a.Originator))
case api.BGP_ATTR_TYPE_CLUSTER_LIST:
- s = append(s, fmt.Sprintf("{Cluster: %v|", a.Cluster))
+ s = append(s, fmt.Sprintf("{Cluster: %v}", a.Cluster))
+ case api.BGP_ATTR_TYPE_TUNNEL_ENCAP:
+ s1 := bytes.NewBuffer(make([]byte, 0, 64))
+ s1.WriteString("{Encap: ")
+ var s2 []string
+ for _, tlv := range a.TunnelEncap {
+ s3 := bytes.NewBuffer(make([]byte, 0, 64))
+ s3.WriteString(fmt.Sprintf("< %s | ", tlv.Type))
+ var s4 []string
+ for _, subTlv := range tlv.SubTlv {
+ if subTlv.Type == api.ENCAP_SUBTLV_TYPE_COLOR {
+ s4 = append(s4, fmt.Sprintf("color: %d", subTlv.Color))
+ }
+ }
+ s3.WriteString(strings.Join(s4, ","))
+ s3.WriteString(" >")
+ s2 = append(s2, s3.String())
+ }
+ s1.WriteString(strings.Join(s2, "|"))
+ s1.WriteString("}")
+ s = append(s, s1.String())
case api.BGP_ATTR_TYPE_AS4_PATH, api.BGP_ATTR_TYPE_MP_REACH_NLRI, api.BGP_ATTR_TYPE_MP_UNREACH_NLRI, api.BGP_ATTR_TYPE_NEXT_HOP, api.BGP_ATTR_TYPE_AS_PATH:
default:
s = append(s, fmt.Sprintf("{%v: %v}", a.Type, a.Value))
diff --git a/packet/bgp.go b/packet/bgp.go
index c181f4b8..fa495edd 100644
--- a/packet/bgp.go
+++ b/packet/bgp.go
@@ -133,6 +133,14 @@ const (
TUNNEL_TYPE_VXLAN_GRE TunnelType = 12
)
+type EncapSubTLVType uint8
+
+const (
+ ENCAP_SUBTLV_TYPE_ENCAPSULATION EncapSubTLVType = 1
+ ENCAP_SUBTLV_TYPE_PROTOCOL EncapSubTLVType = 2
+ ENCAP_SUBTLV_TYPE_COLOR EncapSubTLVType = 4
+)
+
const (
_ = iota
BGP_MSG_OPEN
@@ -3219,26 +3227,131 @@ func NewPathAttributeAs4Aggregator(as uint32, address string) *PathAttributeAs4A
}
}
+type TunnelEncapSubTLVValue interface {
+ Serialize() ([]byte, error)
+ ToApiStruct() *api.TunnelEncapSubTLV
+}
+
+type TunnelEncapSubTLVDefault struct {
+ Value []byte
+}
+
+func (t *TunnelEncapSubTLVDefault) Serialize() ([]byte, error) {
+ return t.Value, nil
+}
+
+func (t *TunnelEncapSubTLVDefault) ToApiStruct() *api.TunnelEncapSubTLV {
+ return &api.TunnelEncapSubTLV{
+ Type: api.ENCAP_SUBTLV_TYPE_UNKNOWN_SUBTLV_TYPE,
+ Value: string(t.Value),
+ }
+}
+
+type TunnelEncapSubTLVEncapuslation struct {
+ Key uint32 // this represent both SessionID for L2TPv3 case and GRE-key for GRE case (RFC5512 4.)
+ Cookie []byte
+}
+
+func (t *TunnelEncapSubTLVEncapuslation) Serialize() ([]byte, error) {
+ buf := make([]byte, 4)
+ binary.BigEndian.PutUint32(buf, t.Key)
+ return append(buf, t.Cookie...), nil
+}
+
+func (t *TunnelEncapSubTLVEncapuslation) ToApiStruct() *api.TunnelEncapSubTLV {
+ return &api.TunnelEncapSubTLV{
+ Type: api.ENCAP_SUBTLV_TYPE_ENCAPSULATION,
+ Key: t.Key,
+ Cookie: string(t.Cookie),
+ }
+}
+
+type TunnelEncapSubTLVProtocol struct {
+ Protocol uint16
+}
+
+func (t *TunnelEncapSubTLVProtocol) Serialize() ([]byte, error) {
+ buf := make([]byte, 2)
+ binary.BigEndian.PutUint16(buf, t.Protocol)
+ return buf, nil
+}
+
+func (t *TunnelEncapSubTLVProtocol) ToApiStruct() *api.TunnelEncapSubTLV {
+ return &api.TunnelEncapSubTLV{
+ Type: api.ENCAP_SUBTLV_TYPE_PROTOCOL,
+ Protocol: uint32(t.Protocol),
+ }
+}
+
+type TunnelEncapSubTLVColor struct {
+ Color uint32
+}
+
+func (t *TunnelEncapSubTLVColor) Serialize() ([]byte, error) {
+ buf := make([]byte, 8)
+ buf[0] = byte(EC_TYPE_TRANSITIVE_OPAQUE)
+ buf[1] = byte(EC_SUBTYPE_COLOR)
+ binary.BigEndian.PutUint32(buf[4:], t.Color)
+ return buf, nil
+}
+
+func (t *TunnelEncapSubTLVColor) ToApiStruct() *api.TunnelEncapSubTLV {
+ return &api.TunnelEncapSubTLV{
+ Type: api.ENCAP_SUBTLV_TYPE_COLOR,
+ Color: t.Color,
+ }
+}
+
type TunnelEncapSubTLV struct {
- Type uint8
+ Type EncapSubTLVType
Len int
- Value []byte
+ Value TunnelEncapSubTLVValue
}
func (p *TunnelEncapSubTLV) Serialize() ([]byte, error) {
- buf := make([]byte, 2, 2+len(p.Value))
- buf = append(buf, p.Value...)
- buf[0] = p.Type
+ buf := make([]byte, 2)
+ bbuf, err := p.Value.Serialize()
+ if err != nil {
+ return nil, err
+ }
+ buf = append(buf, bbuf...)
+ buf[0] = byte(p.Type)
p.Len = len(buf) - 2
buf[1] = byte(p.Len)
return buf, nil
}
-func (p *TunnelEncapSubTLV) ToApiStruct() *api.TunnelEncapSubTLV {
- return &api.TunnelEncapSubTLV{
- Type: uint32(p.Type),
- Value: string(p.Value),
+func (p *TunnelEncapSubTLV) DecodeFromBytes(data []byte) error {
+ switch p.Type {
+ case ENCAP_SUBTLV_TYPE_ENCAPSULATION:
+ if len(data) < 4 {
+ return fmt.Errorf("Not all TunnelEncapSubTLV bytes available")
+ }
+ key := binary.BigEndian.Uint32(data[:4])
+ p.Value = &TunnelEncapSubTLVEncapuslation{
+ Key: key,
+ Cookie: data[4:],
+ }
+ case ENCAP_SUBTLV_TYPE_PROTOCOL:
+ if len(data) < 2 {
+ return fmt.Errorf("Not all TunnelEncapSubTLV bytes available")
+ }
+ protocol := binary.BigEndian.Uint16(data[:2])
+ p.Value = &TunnelEncapSubTLVProtocol{protocol}
+ case ENCAP_SUBTLV_TYPE_COLOR:
+ if len(data) < 8 {
+ return fmt.Errorf("Not all TunnelEncapSubTLV bytes available")
+ }
+ color := binary.BigEndian.Uint32(data[4:])
+ p.Value = &TunnelEncapSubTLVColor{color}
+ default:
+ p.Value = &TunnelEncapSubTLVDefault{data}
}
+ return nil
+}
+
+func (p *TunnelEncapSubTLV) ToApiStruct() *api.TunnelEncapSubTLV {
+ return p.Value.ToApiStruct()
}
type TunnelEncapTLV struct {
@@ -3253,16 +3366,18 @@ func (t *TunnelEncapTLV) DecodeFromBytes(data []byte) error {
if len(data) < curr+2 {
break
}
- subType := data[curr]
+ subType := EncapSubTLVType(data[curr])
l := int(data[curr+1])
if len(data) < curr+2+l {
return fmt.Errorf("Not all TunnelEncapSubTLV bytes available")
}
v := data[curr+2 : curr+2+l]
subTlv := &TunnelEncapSubTLV{
- Type: subType,
- Len: l,
- Value: v,
+ Type: subType,
+ }
+ err := subTlv.DecodeFromBytes(v)
+ if err != nil {
+ return err
}
t.Value = append(t.Value, subTlv)
curr += 2 + l
diff --git a/packet/bgp_test.go b/packet/bgp_test.go
index 6f078e5e..839d8f23 100644
--- a/packet/bgp_test.go
+++ b/packet/bgp_test.go
@@ -247,12 +247,12 @@ func Test_RFC5512(t *testing.T) {
assert.Equal([]byte{0x3, 0xc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8}, buf)
subTlv := &TunnelEncapSubTLV{
- Type: 1,
- Value: []byte{0, 1, 2, 3},
+ Type: ENCAP_SUBTLV_TYPE_COLOR,
+ Value: &TunnelEncapSubTLVColor{10},
}
tlv := &TunnelEncapTLV{
- Type: 1,
+ Type: TUNNEL_TYPE_VXLAN,
Value: []*TunnelEncapSubTLV{subTlv},
}
diff --git a/packet/routefamily_string.go b/packet/routefamily_string.go
index a6b9a933..9f61c5e5 100644
--- a/packet/routefamily_string.go
+++ b/packet/routefamily_string.go
@@ -1,45 +1,61 @@
-// generated by stringer -type=RouteFamily; DO NOT EDIT
+// generated by stringer -type=RouteFamily bgp.go validate.go; DO NOT EDIT
package bgp
import "fmt"
const (
- _RouteFamily_name_0 = "RF_IPv4_UC"
+ _RouteFamily_name_0 = "RF_IPv4_UCRF_IPv4_MC"
_RouteFamily_name_1 = "RF_IPv4_MPLS"
- _RouteFamily_name_2 = "RF_IPv4_VPN"
- _RouteFamily_name_3 = "RF_RTC_UC"
- _RouteFamily_name_4 = "RF_IPv6_UC"
- _RouteFamily_name_5 = "RF_IPv6_MPLS"
- _RouteFamily_name_6 = "RF_IPv6_VPN"
+ _RouteFamily_name_2 = "RF_ENCAP"
+ _RouteFamily_name_3 = "RF_IPv4_VPNRF_IPv4_VPN_MC"
+ _RouteFamily_name_4 = "RF_RTC_UC"
+ _RouteFamily_name_5 = "RF_IPv6_UCRF_IPv6_MC"
+ _RouteFamily_name_6 = "RF_IPv6_MPLS"
+ _RouteFamily_name_7 = "RF_IPv6_VPNRF_IPv6_VPN_MC"
+ _RouteFamily_name_8 = "RF_VPLS"
+ _RouteFamily_name_9 = "RF_EVPN"
)
var (
- _RouteFamily_index_0 = [...]uint8{0, 10}
+ _RouteFamily_index_0 = [...]uint8{0, 10, 20}
_RouteFamily_index_1 = [...]uint8{0, 12}
- _RouteFamily_index_2 = [...]uint8{0, 11}
- _RouteFamily_index_3 = [...]uint8{0, 9}
- _RouteFamily_index_4 = [...]uint8{0, 10}
- _RouteFamily_index_5 = [...]uint8{0, 12}
- _RouteFamily_index_6 = [...]uint8{0, 11}
+ _RouteFamily_index_2 = [...]uint8{0, 8}
+ _RouteFamily_index_3 = [...]uint8{0, 11, 25}
+ _RouteFamily_index_4 = [...]uint8{0, 9}
+ _RouteFamily_index_5 = [...]uint8{0, 10, 20}
+ _RouteFamily_index_6 = [...]uint8{0, 12}
+ _RouteFamily_index_7 = [...]uint8{0, 11, 25}
+ _RouteFamily_index_8 = [...]uint8{0, 7}
+ _RouteFamily_index_9 = [...]uint8{0, 7}
)
func (i RouteFamily) String() string {
switch {
- case i == 65537:
- return _RouteFamily_name_0
+ case 65537 <= i && i <= 65538:
+ i -= 65537
+ return _RouteFamily_name_0[_RouteFamily_index_0[i]:_RouteFamily_index_0[i+1]]
case i == 65540:
return _RouteFamily_name_1
- case i == 65664:
+ case i == 65543:
return _RouteFamily_name_2
+ case 65664 <= i && i <= 65665:
+ i -= 65664
+ return _RouteFamily_name_3[_RouteFamily_index_3[i]:_RouteFamily_index_3[i+1]]
case i == 65668:
- return _RouteFamily_name_3
- case i == 131073:
return _RouteFamily_name_4
+ case 131073 <= i && i <= 131074:
+ i -= 131073
+ return _RouteFamily_name_5[_RouteFamily_index_5[i]:_RouteFamily_index_5[i+1]]
case i == 131076:
- return _RouteFamily_name_5
- case i == 131200:
return _RouteFamily_name_6
+ case 131200 <= i && i <= 131201:
+ i -= 131200
+ return _RouteFamily_name_7[_RouteFamily_index_7[i]:_RouteFamily_index_7[i+1]]
+ case i == 1638465:
+ return _RouteFamily_name_8
+ case i == 1638470:
+ return _RouteFamily_name_9
default:
return fmt.Sprintf("RouteFamily(%d)", i)
}
diff --git a/server/grpc_server.go b/server/grpc_server.go
index 76e79943..01acaf3d 100644
--- a/server/grpc_server.go
+++ b/server/grpc_server.go
@@ -54,6 +54,8 @@ func convertAf2Rf(af *api.AddressFamily) (bgp.RouteFamily, error) {
return bgp.RF_IPv6_UC, nil
} else if af.Equal(api.AF_EVPN) {
return bgp.RF_EVPN, nil
+ } else if af.Equal(api.AF_ENCAP) {
+ return bgp.RF_ENCAP, nil
}
return bgp.RouteFamily(0), fmt.Errorf("unsupported address family: %v", af)
@@ -235,7 +237,7 @@ func (s *Server) ModPath(stream api.Grpc_ModPathServer) error {
rf, err := convertAf2Rf(arg.Path.Nlri.Af)
if err != nil {
- return nil
+ return err
}
req := NewGrpcRequest(reqType, "", rf, arg.Path)
s.bgpServerCh <- req
diff --git a/server/peer.go b/server/peer.go
index 494aea42..25411333 100644
--- a/server/peer.go
+++ b/server/peer.go
@@ -374,6 +374,55 @@ func (peer *Peer) handleGrpc(grpcReq *GrpcRequest) {
}
nlri = bgp.NewEVPNNLRI(bgp.EVPN_ROUTE_TYPE_MAC_IP_ADVERTISEMENT, 0, macIpAdv)
pattr = append(pattr, bgp.NewPathAttributeMpReachNLRI("0.0.0.0", []bgp.AddrPrefixInterface{nlri}))
+ case bgp.RF_ENCAP:
+ endpoint := net.ParseIP(path.Nlri.Prefix)
+ if endpoint == nil {
+ result.ResponseErr = fmt.Errorf("Invalid endpoint ip address: %s", path.Nlri.Prefix)
+ grpcReq.ResponseCh <- result
+ close(grpcReq.ResponseCh)
+ return
+
+ }
+ nlri = bgp.NewEncapNLRI(endpoint.String())
+ pattr = append(pattr, bgp.NewPathAttributeMpReachNLRI("0.0.0.0", []bgp.AddrPrefixInterface{nlri}))
+
+ iterSubTlvs := func(subTlvs []*api.TunnelEncapSubTLV) {
+ for _, subTlv := range subTlvs {
+ if subTlv.Type == api.ENCAP_SUBTLV_TYPE_COLOR {
+ color := subTlv.Color
+ subTlv := &bgp.TunnelEncapSubTLV{
+ Type: bgp.ENCAP_SUBTLV_TYPE_COLOR,
+ Value: &bgp.TunnelEncapSubTLVColor{color},
+ }
+ tlv := &bgp.TunnelEncapTLV{
+ Type: bgp.TUNNEL_TYPE_VXLAN,
+ Value: []*bgp.TunnelEncapSubTLV{subTlv},
+ }
+ attr := bgp.NewPathAttributeTunnelEncap([]*bgp.TunnelEncapTLV{tlv})
+ pattr = append(pattr, attr)
+ break
+ }
+ }
+ }
+
+ iterTlvs := func(tlvs []*api.TunnelEncapTLV) {
+ for _, tlv := range tlvs {
+ if tlv.Type == api.TUNNEL_TYPE_VXLAN {
+ iterSubTlvs(tlv.SubTlv)
+ break
+ }
+ }
+ }
+
+ func(attrs []*api.PathAttr) {
+ for _, attr := range attrs {
+ if attr.Type == api.BGP_ATTR_TYPE_TUNNEL_ENCAP {
+ iterTlvs(attr.TunnelEncap)
+ break
+ }
+ }
+ }(path.Attrs)
+
default:
result.ResponseErr = fmt.Errorf("Unsupported address family: %s", rf)
grpcReq.ResponseCh <- result
@@ -381,7 +430,13 @@ func (peer *Peer) handleGrpc(grpcReq *GrpcRequest) {
return
}
- p := table.CreatePath(peer.peerInfo, nlri, pattr, isWithdraw, time.Now())
+ p, err := table.CreatePath(peer.peerInfo, nlri, pattr, isWithdraw, time.Now())
+ if err != nil {
+ result.ResponseErr = err
+ grpcReq.ResponseCh <- result
+ close(grpcReq.ResponseCh)
+ return
+ }
pm := &peerMsg{
msgType: PEER_MSG_PATH,
diff --git a/table/destination.go b/table/destination.go
index cfd411ce..ead4797a 100644
--- a/table/destination.go
+++ b/table/destination.go
@@ -1041,3 +1041,15 @@ func (evpnd *EVPNDestination) MarshalJSON() ([]byte, error) {
BestPathIdx: idx,
})
}
+
+type EncapDestination struct {
+ *DestinationDefault
+}
+
+func NewEncapDestination(nlri bgp.AddrPrefixInterface) *EncapDestination {
+ d := NewDestinationDefault(nlri)
+ d.ROUTE_FAMILY = bgp.RF_ENCAP
+ return &EncapDestination{
+ DestinationDefault: d,
+ }
+}
diff --git a/table/destination_test.go b/table/destination_test.go
index 7205876a..db4e49c1 100644
--- a/table/destination_test.go
+++ b/table/destination_test.go
@@ -135,7 +135,7 @@ func DestCreatePath(msgs []*ProcessMessage) []Path {
nlriList := updateMsgD.NLRI
pathAttributes := updateMsgD.PathAttributes
nlri_info := nlriList[0]
- pathD[i] = CreatePath(msg.fromPeer, &nlri_info, pathAttributes, false, time.Now())
+ pathD[i], _ = CreatePath(msg.fromPeer, &nlri_info, pathAttributes, false, time.Now())
}
return pathD
}
diff --git a/table/message.go b/table/message.go
index 502dbd4c..70e2ffcd 100644
--- a/table/message.go
+++ b/table/message.go
@@ -155,7 +155,7 @@ func createUpdateMsgFromPath(path Path, msg *bgp.BGPMessage) *bgp.BGPMessage {
return bgp.NewBGPUpdateMessage([]bgp.WithdrawnRoute{}, pathAttrs, []bgp.NLRInfo{*nlri})
}
}
- } else if rf == bgp.RF_IPv6_UC || rf == bgp.RF_EVPN {
+ } else if rf == bgp.RF_IPv6_UC || rf == bgp.RF_EVPN || rf == bgp.RF_ENCAP {
if path.IsWithdraw() {
if msg != nil {
idx, _ := path.getPathAttr(bgp.BGP_ATTR_TYPE_MP_UNREACH_NLRI)
diff --git a/table/path.go b/table/path.go
index 9e296edb..62a98aab 100644
--- a/table/path.go
+++ b/table/path.go
@@ -209,7 +209,8 @@ func (pd *PathDefault) Clone(isWithdraw bool) Path {
newPathAttrs[i] = v
}
- return CreatePath(pd.source, nlri, newPathAttrs, isWithdraw, pd.timestamp)
+ path, _ := CreatePath(pd.source, nlri, newPathAttrs, isWithdraw, pd.timestamp)
+ return path
}
func (pd *PathDefault) GetRouteFamily() bgp.RouteFamily {
@@ -311,18 +312,11 @@ func (pi *PathDefault) String() string {
}
func (pi *PathDefault) getPrefix() string {
- switch nlri := pi.nlri.(type) {
- case *bgp.NLRInfo:
- return nlri.IPAddrPrefix.IPAddrPrefixDefault.String()
- case *bgp.WithdrawnRoute:
- return nlri.IPAddrPrefix.IPAddrPrefixDefault.String()
- }
- log.Fatal()
- return ""
+ return pi.nlri.String()
}
// create Path object based on route family
-func CreatePath(source *PeerInfo, nlri bgp.AddrPrefixInterface, attrs []bgp.PathAttributeInterface, isWithdraw bool, now time.Time) Path {
+func CreatePath(source *PeerInfo, nlri bgp.AddrPrefixInterface, attrs []bgp.PathAttributeInterface, isWithdraw bool, now time.Time) (Path, error) {
rf := bgp.RouteFamily(int(nlri.AFI())<<16 | int(nlri.SAFI()))
log.Debugf("CreatePath afi: %d, safi: %d ", int(nlri.AFI()), nlri.SAFI())
@@ -341,8 +335,13 @@ func CreatePath(source *PeerInfo, nlri bgp.AddrPrefixInterface, attrs []bgp.Path
case bgp.RF_EVPN:
log.Debugf("CreatePath RouteFamily : %s", bgp.RF_EVPN.String())
path = NewEVPNPath(source, nlri, isWithdraw, attrs, false, now)
+ case bgp.RF_ENCAP:
+ log.Debugf("CreatePath RouteFamily : %s", bgp.RF_ENCAP.String())
+ path = NewEncapPath(source, nlri, isWithdraw, attrs, false, now)
+ default:
+ return path, fmt.Errorf("Unsupported RouteFamily: %s", rf)
}
- return path
+ return path, nil
}
/*
@@ -377,7 +376,8 @@ func NewIPv6Path(source *PeerInfo, nlri bgp.AddrPrefixInterface, isWithdraw bool
func (ipv6p *IPv6Path) Clone(isWithdraw bool) Path {
nlri := ipv6p.nlri
- return CreatePath(ipv6p.source, nlri, ipv6p.pathAttrs, isWithdraw, ipv6p.PathDefault.timestamp)
+ path, _ := CreatePath(ipv6p.source, nlri, ipv6p.pathAttrs, isWithdraw, ipv6p.PathDefault.timestamp)
+ return path
}
func (ipv6p *IPv6Path) setPathDefault(pd *PathDefault) {
@@ -388,11 +388,6 @@ func (ipv6p *IPv6Path) getPathDefault() *PathDefault {
return ipv6p.PathDefault
}
-func (ipv6p *IPv6Path) getPrefix() string {
- addrPrefix := ipv6p.nlri.(*bgp.IPv6AddrPrefix)
- return addrPrefix.IPAddrPrefixDefault.String()
-}
-
// return IPv6Path's string representation
func (ipv6p *IPv6Path) String() string {
str := fmt.Sprintf("IPv6Path Source: %v, ", ipv6p.GetSource())
@@ -415,7 +410,8 @@ func NewIPv4VPNPath(source *PeerInfo, nlri bgp.AddrPrefixInterface, isWithdraw b
func (ipv4vpnp *IPv4VPNPath) Clone(isWithdraw bool) Path {
nlri := ipv4vpnp.nlri
- return CreatePath(ipv4vpnp.source, nlri, ipv4vpnp.pathAttrs, isWithdraw, ipv4vpnp.PathDefault.timestamp)
+ path, _ := CreatePath(ipv4vpnp.source, nlri, ipv4vpnp.pathAttrs, isWithdraw, ipv4vpnp.PathDefault.timestamp)
+ return path
}
func (ipv4vpnp *IPv4VPNPath) setPathDefault(pd *PathDefault) {
@@ -426,11 +422,6 @@ func (ipv4vpnp *IPv4VPNPath) getPathDefault() *PathDefault {
return ipv4vpnp.PathDefault
}
-func (ipv4vpnp *IPv4VPNPath) getPrefix() string {
- addrPrefix := ipv4vpnp.nlri.(*bgp.LabelledVPNIPAddrPrefix)
- return addrPrefix.IPAddrPrefixDefault.String()
-}
-
// return IPv4VPNPath's string representation
func (ipv4vpnp *IPv4VPNPath) String() string {
str := fmt.Sprintf("IPv4VPNPath Source: %v, ", ipv4vpnp.GetSource())
@@ -467,7 +458,8 @@ func NewEVPNPath(source *PeerInfo, nlri bgp.AddrPrefixInterface, isWithdraw bool
func (evpnp *EVPNPath) Clone(isWithdraw bool) Path {
nlri := evpnp.nlri
- return CreatePath(evpnp.source, nlri, evpnp.pathAttrs, isWithdraw, evpnp.PathDefault.timestamp)
+ path, _ := CreatePath(evpnp.source, nlri, evpnp.pathAttrs, isWithdraw, evpnp.PathDefault.timestamp)
+ return path
}
func (evpnp *EVPNPath) setPathDefault(pd *PathDefault) {
@@ -478,11 +470,6 @@ func (evpnp *EVPNPath) getPathDefault() *PathDefault {
return evpnp.PathDefault
}
-func (evpnp *EVPNPath) getPrefix() string {
- addrPrefix := evpnp.nlri.(*bgp.EVPNNLRI)
- return addrPrefix.String()
-}
-
// return EVPNPath's string representation
func (evpnp *EVPNPath) String() string {
str := fmt.Sprintf("EVPNPath Source: %v, ", evpnp.GetSource())
@@ -506,3 +493,25 @@ func (evpnp *EVPNPath) MarshalJSON() ([]byte, error) {
Age: int64(time.Now().Sub(evpnp.PathDefault.timestamp).Seconds()),
})
}
+
+type EncapPath struct {
+ *PathDefault
+}
+
+func NewEncapPath(source *PeerInfo, nlri bgp.AddrPrefixInterface, isWithdraw bool, attrs []bgp.PathAttributeInterface, medSetByTargetNeighbor bool, now time.Time) *EncapPath {
+ return &EncapPath{
+ PathDefault: NewPathDefault(bgp.RF_ENCAP, source, nlri, isWithdraw, attrs, medSetByTargetNeighbor, now),
+ }
+}
+
+func (p *EncapPath) setPathDefault(pd *PathDefault) {
+ p.PathDefault = pd
+}
+func (p *EncapPath) getPathDefault() *PathDefault {
+ return p.PathDefault
+}
+
+func (p *EncapPath) Clone(isWithdraw bool) Path {
+ path, _ := CreatePath(p.source, p.nlri, p.pathAttrs, isWithdraw, p.PathDefault.timestamp)
+ return path
+}
diff --git a/table/path_test.go b/table/path_test.go
index 3d1e47c9..378e37c7 100644
--- a/table/path_test.go
+++ b/table/path_test.go
@@ -126,7 +126,7 @@ func TestPathCreatePath(t *testing.T) {
nlriList := updateMsgP.NLRI
pathAttributes := updateMsgP.PathAttributes
nlri_info := nlriList[0]
- path := CreatePath(msgP[0].fromPeer, &nlri_info, pathAttributes, false, time.Now())
+ path, _ := CreatePath(msgP[0].fromPeer, &nlri_info, pathAttributes, false, time.Now())
assert.NotNil(t, path)
}
@@ -173,7 +173,7 @@ func PathCreatePath(msgs []*ProcessMessage) []Path {
nlriList := updateMsgP.NLRI
pathAttributes := updateMsgP.PathAttributes
nlri_info := nlriList[0]
- pathP[i] = CreatePath(msg.fromPeer, &nlri_info, pathAttributes, false, time.Now())
+ pathP[i], _ = CreatePath(msg.fromPeer, &nlri_info, pathAttributes, false, time.Now())
}
return pathP
}
diff --git a/table/table.go b/table/table.go
index 4739b292..b1434732 100644
--- a/table/table.go
+++ b/table/table.go
@@ -334,3 +334,22 @@ func (ipv4vpnt *EVPNTable) tableKey(nlri bgp.AddrPrefixInterface) string {
addrPrefix := nlri.(*bgp.EVPNNLRI)
return addrPrefix.String()
}
+
+type EncapTable struct {
+ *TableDefault
+}
+
+func NewEncapTable() *EncapTable {
+ EncapTable := &EncapTable{}
+ EncapTable.TableDefault = NewTableDefault(0)
+ EncapTable.TableDefault.ROUTE_FAMILY = bgp.RF_ENCAP
+ return EncapTable
+}
+
+func (t *EncapTable) createDest(nlri bgp.AddrPrefixInterface) Destination {
+ return Destination(NewEncapDestination(nlri))
+}
+
+func (t *EncapTable) tableKey(nlri bgp.AddrPrefixInterface) string {
+ return nlri.String()
+}
diff --git a/table/table_manager.go b/table/table_manager.go
index df89a2eb..d56c2e65 100644
--- a/table/table_manager.go
+++ b/table/table_manager.go
@@ -42,7 +42,7 @@ func (p *ProcessMessage) nlri2Path(now time.Time) []Path {
// define local variable to pass nlri's address to CreatePath
var nlri bgp.NLRInfo = nlri_info
// create Path object
- path := CreatePath(p.fromPeer, &nlri, pathAttributes, false, now)
+ path, _ := CreatePath(p.fromPeer, &nlri, pathAttributes, false, now)
pathList = append(pathList, path)
}
return pathList
@@ -56,7 +56,7 @@ func (p *ProcessMessage) withdraw2Path(now time.Time) []Path {
// define local variable to pass nlri's address to CreatePath
var w bgp.WithdrawnRoute = nlriWithdraw
// create withdrawn Path object
- path := CreatePath(p.fromPeer, &w, pathAttributes, true, now)
+ path, _ := CreatePath(p.fromPeer, &w, pathAttributes, true, now)
pathList = append(pathList, path)
}
return pathList
@@ -79,7 +79,7 @@ func (p *ProcessMessage) mpreachNlri2Path(now time.Time) []Path {
for _, mp := range attrList {
nlri_info := mp.Value
for _, nlri := range nlri_info {
- path := CreatePath(p.fromPeer, nlri, pathAttributes, false, now)
+ path, _ := CreatePath(p.fromPeer, nlri, pathAttributes, false, now)
pathList = append(pathList, path)
}
}
@@ -104,7 +104,7 @@ func (p *ProcessMessage) mpunreachNlri2Path(now time.Time) []Path {
nlri_info := mp.Value
for _, nlri := range nlri_info {
- path := CreatePath(p.fromPeer, nlri, pathAttributes, true, now)
+ path, _ := CreatePath(p.fromPeer, nlri, pathAttributes, true, now)
pathList = append(pathList, path)
}
}
@@ -141,7 +141,8 @@ func NewTableManager(owner string, rfList []bgp.RouteFamily) *TableManager {
t.Tables[bgp.RF_IPv4_VPN] = NewIPv4VPNTable(0)
case bgp.RF_EVPN:
t.Tables[bgp.RF_EVPN] = NewEVPNTable(0)
-
+ case bgp.RF_ENCAP:
+ t.Tables[bgp.RF_ENCAP] = NewEncapTable()
}
}
t.owner = owner
diff --git a/table/table_test.go b/table/table_test.go
index 407fbe0a..70e9c86b 100644
--- a/table/table_test.go
+++ b/table/table_test.go
@@ -131,7 +131,7 @@ func TableCreatePath(msgs []*ProcessMessage) []Path {
nlriList := updateMsgT.NLRI
pathAttributes := updateMsgT.PathAttributes
nlri_info := nlriList[0]
- pathT[i] = CreatePath(msg.fromPeer, &nlri_info, pathAttributes, false, time.Now())
+ pathT[i], _ = CreatePath(msg.fromPeer, &nlri_info, pathAttributes, false, time.Now())
}
return pathT
}