mirror of
https://github.com/osrg/gobgp.git
synced 2024-05-11 05:55:10 +00:00
the result of memory profile (500 route-server-clients each of them advertises 100 routes) before: (pprof) top5 9330.48MB of 9367.53MB total (99.60%) Dropped 157 nodes (cum <= 46.84MB) Showing top 10 nodes out of 17 (cum >= 9334.17MB) flat flat% sum% cum cum% 6163.04MB 65.79% 65.79% 6163.04MB 65.79% github.com/osrg/gobgp/table.NewPath 1155.05MB 12.33% 78.12% 7302.59MB 77.96% github.com/osrg/gobgp/table.(*Path).Clone 986.31MB 10.53% 88.65% 1388.81MB 14.83% github.com/osrg/gobgp/table.(*AdjRib).Update 402.51MB 4.30% 92.95% 402.51MB 4.30% fmt.Sprintf 402.51MB 4.30% 97.24% 402.51MB 4.30% net.parseIPv4 after: (pprof) top 3913.02MB of 3978.69MB total (98.35%) Dropped 148 nodes (cum <= 19.89MB) Showing top 10 nodes out of 11 (cum >= 21MB) flat flat% sum% cum cum% 2970.30MB 74.66% 74.66% 2975.80MB 74.79% github.com/osrg/gobgp/server.filterpath 810.09MB 20.36% 95.02% 810.59MB 20.37% github.com/osrg/gobgp/table.(*AdjRib).Update 115.60MB 2.91% 97.92% 119.10MB 2.99% github.com/osrg/gobgp/table.createUpdateMsgFromPath 10MB 0.25% 98.17% 1878.02MB 47.20% github.com/osrg/gobgp/server.(*BgpServer).propagateUpdate 4.50MB 0.11% 98.29% 144.60MB 3.63% github.com/osrg/gobgp/table.CreateUpdateMsgFromPaths Signed-off-by: ISHIDA Wataru <[email protected]>
232 lines
5.7 KiB
Go
232 lines
5.7 KiB
Go
// Copyright (C) 2014 Nippon Telegraph and Telephone Corporation.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
// implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package table
|
|
|
|
import (
|
|
log "github.com/Sirupsen/logrus"
|
|
"github.com/osrg/gobgp/packet"
|
|
)
|
|
|
|
type Table struct {
|
|
routeFamily bgp.RouteFamily
|
|
destinations map[string]*Destination
|
|
}
|
|
|
|
func NewTable(rf bgp.RouteFamily) *Table {
|
|
return &Table{
|
|
routeFamily: rf,
|
|
destinations: make(map[string]*Destination),
|
|
}
|
|
}
|
|
|
|
func (t *Table) GetRoutefamily() bgp.RouteFamily {
|
|
return t.routeFamily
|
|
}
|
|
|
|
func (t *Table) insert(path *Path) *Destination {
|
|
t.validatePath(path)
|
|
dest := t.getOrCreateDest(path.GetNlri())
|
|
|
|
if path.IsWithdraw {
|
|
// withdraw insert
|
|
dest.addWithdraw(path)
|
|
} else {
|
|
// path insert
|
|
dest.addNewPath(path)
|
|
}
|
|
return dest
|
|
}
|
|
|
|
func (t *Table) DeleteDestByPeer(peerInfo *PeerInfo) []*Destination {
|
|
dsts := []*Destination{}
|
|
for _, dst := range t.destinations {
|
|
match := false
|
|
for _, p := range dst.knownPathList {
|
|
if p.GetSource().Equal(peerInfo) {
|
|
dst.addWithdraw(p)
|
|
match = true
|
|
}
|
|
}
|
|
if match {
|
|
dsts = append(dsts, dst)
|
|
}
|
|
}
|
|
return dsts
|
|
}
|
|
|
|
func (t *Table) deletePathsByVrf(vrf *Vrf) []*Path {
|
|
pathList := make([]*Path, 0)
|
|
for _, dest := range t.destinations {
|
|
for _, p := range dest.knownPathList {
|
|
var rd bgp.RouteDistinguisherInterface
|
|
nlri := p.GetNlri()
|
|
switch nlri.(type) {
|
|
case *bgp.LabeledVPNIPAddrPrefix:
|
|
rd = nlri.(*bgp.LabeledVPNIPAddrPrefix).RD
|
|
case *bgp.LabeledVPNIPv6AddrPrefix:
|
|
rd = nlri.(*bgp.LabeledVPNIPv6AddrPrefix).RD
|
|
case *bgp.EVPNNLRI:
|
|
rd = nlri.(*bgp.EVPNNLRI).RD()
|
|
default:
|
|
return pathList
|
|
}
|
|
if p.IsLocal() && vrf.Rd.String() == rd.String() {
|
|
p.IsWithdraw = true
|
|
pathList = append(pathList, p)
|
|
break
|
|
}
|
|
}
|
|
}
|
|
return pathList
|
|
}
|
|
|
|
func (t *Table) deleteRTCPathsByVrf(vrf *Vrf, vrfs map[string]*Vrf) []*Path {
|
|
pathList := make([]*Path, 0)
|
|
if t.routeFamily != bgp.RF_RTC_UC {
|
|
return pathList
|
|
}
|
|
for _, target := range vrf.ImportRt {
|
|
lhs := target.String()
|
|
for _, dest := range t.destinations {
|
|
nlri := dest.GetNlri().(*bgp.RouteTargetMembershipNLRI)
|
|
rhs := nlri.RouteTarget.String()
|
|
if lhs == rhs && isLastTargetUser(vrfs, target) {
|
|
for _, p := range dest.knownPathList {
|
|
if p.IsLocal() {
|
|
p.IsWithdraw = true
|
|
pathList = append(pathList, p)
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return pathList
|
|
}
|
|
|
|
func (t *Table) deleteDestByNlri(nlri bgp.AddrPrefixInterface) *Destination {
|
|
destinations := t.GetDestinations()
|
|
dest := destinations[t.tableKey(nlri)]
|
|
if dest != nil {
|
|
delete(destinations, t.tableKey(nlri))
|
|
}
|
|
return dest
|
|
}
|
|
|
|
func (t *Table) deleteDest(dest *Destination) {
|
|
destinations := t.GetDestinations()
|
|
delete(destinations, t.tableKey(dest.GetNlri()))
|
|
}
|
|
|
|
func (t *Table) validatePath(path *Path) {
|
|
if path == nil {
|
|
log.WithFields(log.Fields{
|
|
"Topic": "Table",
|
|
"Key": t.routeFamily,
|
|
}).Error("path is nil")
|
|
}
|
|
if path.GetRouteFamily() != t.routeFamily {
|
|
log.WithFields(log.Fields{
|
|
"Topic": "Table",
|
|
"Key": t.routeFamily,
|
|
"Prefix": path.GetNlri().String(),
|
|
"ReceivedRf": path.GetRouteFamily().String(),
|
|
}).Error("Invalid path. RouteFamily mismatch")
|
|
}
|
|
if attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH); attr != nil {
|
|
pathParam := attr.(*bgp.PathAttributeAsPath).Value
|
|
for _, as := range pathParam {
|
|
_, y := as.(*bgp.As4PathParam)
|
|
if !y {
|
|
log.WithFields(log.Fields{
|
|
"Topic": "Table",
|
|
"Key": t.routeFamily,
|
|
"As": as,
|
|
}).Fatal("AsPathParam must be converted to As4PathParam")
|
|
}
|
|
}
|
|
}
|
|
if attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_AS4_PATH); attr != nil {
|
|
log.WithFields(log.Fields{
|
|
"Topic": "Table",
|
|
"Key": t.routeFamily,
|
|
}).Fatal("AS4_PATH must be converted to AS_PATH")
|
|
}
|
|
if path.GetNlri() == nil {
|
|
log.WithFields(log.Fields{
|
|
"Topic": "Table",
|
|
"Key": t.routeFamily,
|
|
}).Fatal("path's nlri is nil")
|
|
}
|
|
}
|
|
|
|
func (t *Table) getOrCreateDest(nlri bgp.AddrPrefixInterface) *Destination {
|
|
tableKey := t.tableKey(nlri)
|
|
dest := t.GetDestination(tableKey)
|
|
// If destination for given prefix does not exist we create it.
|
|
if dest == nil {
|
|
log.WithFields(log.Fields{
|
|
"Topic": "Table",
|
|
"Key": tableKey,
|
|
}).Debugf("create Destination")
|
|
dest = NewDestination(nlri)
|
|
t.setDestination(tableKey, dest)
|
|
}
|
|
return dest
|
|
}
|
|
|
|
func (t *Table) GetDestinations() map[string]*Destination {
|
|
return t.destinations
|
|
}
|
|
func (t *Table) setDestinations(destinations map[string]*Destination) {
|
|
t.destinations = destinations
|
|
}
|
|
func (t *Table) GetDestination(key string) *Destination {
|
|
dest, ok := t.destinations[key]
|
|
if ok {
|
|
return dest
|
|
} else {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func (t *Table) setDestination(key string, dest *Destination) {
|
|
t.destinations[key] = dest
|
|
}
|
|
|
|
func (t *Table) tableKey(nlri bgp.AddrPrefixInterface) string {
|
|
return nlri.String()
|
|
}
|
|
|
|
func (t *Table) Bests(id string) []*Path {
|
|
paths := make([]*Path, 0, len(t.destinations))
|
|
for _, dst := range t.destinations {
|
|
path := dst.GetBestPath(id)
|
|
if path != nil {
|
|
paths = append(paths, path)
|
|
}
|
|
}
|
|
return paths
|
|
}
|
|
|
|
func (t *Table) GetKnownPathList(id string) []*Path {
|
|
paths := make([]*Path, 0, len(t.destinations))
|
|
for _, dst := range t.destinations {
|
|
paths = append(paths, dst.GetKnownPathList(id)...)
|
|
}
|
|
return paths
|
|
}
|