diff options
author | ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp> | 2015-04-25 10:06:56 +0000 |
---|---|---|
committer | ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp> | 2015-04-25 15:16:45 +0000 |
commit | 99cccf981227a482cbd6404b664bd4f7cc9a1720 (patch) | |
tree | e8c93e477bb245122e4771cfe879db6833bcc04e | |
parent | 27d0d45b6319658bc0a43511d1909a411df40b08 (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.go | 38 | ||||
-rw-r--r-- | api/gobgp.proto | 14 | ||||
-rw-r--r-- | api/util.go | 1 | ||||
-rw-r--r-- | config/default.go | 1 | ||||
-rw-r--r-- | gobgp/main.go | 58 | ||||
-rw-r--r-- | packet/bgp.go | 141 | ||||
-rw-r--r-- | packet/bgp_test.go | 6 | ||||
-rw-r--r-- | packet/routefamily_string.go | 56 | ||||
-rw-r--r-- | server/grpc_server.go | 4 | ||||
-rw-r--r-- | server/peer.go | 57 | ||||
-rw-r--r-- | table/destination.go | 12 | ||||
-rw-r--r-- | table/destination_test.go | 2 | ||||
-rw-r--r-- | table/message.go | 2 | ||||
-rw-r--r-- | table/path.go | 67 | ||||
-rw-r--r-- | table/path_test.go | 4 | ||||
-rw-r--r-- | table/table.go | 19 | ||||
-rw-r--r-- | table/table_manager.go | 11 | ||||
-rw-r--r-- | table/table_test.go | 2 |
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 } |