From c8bb5752f6a08eb5d1aac9fd4d58571cf9d8e2f4 Mon Sep 17 00:00:00 2001 From: Wataru Ishida Date: Sat, 20 Aug 2016 20:26:07 +0000 Subject: table: add Best/MultiPath option to SelectOption Signed-off-by: Wataru Ishida --- table/destination.go | 51 +++++++++++++++++++++++++++++++++++++++------------ table/table.go | 15 ++++++++++++--- 2 files changed, 51 insertions(+), 15 deletions(-) (limited to 'table') diff --git a/table/destination.go b/table/destination.go index 3a1c1c45..845c2ab2 100644 --- a/table/destination.go +++ b/table/destination.go @@ -852,9 +852,11 @@ func (dest *Destination) String() string { } type DestinationSelectOption struct { - ID string - VRF *Vrf - adj bool + ID string + VRF *Vrf + adj bool + Best bool + MultiPath bool } func (d *Destination) MarshalJSON() ([]byte, error) { @@ -865,6 +867,8 @@ func (old *Destination) Select(option ...DestinationSelectOption) *Destination { id := GLOBAL_RIB_NAME var vrf *Vrf adj := false + best := false + mp := false for _, o := range option { if o.ID != "" { id = o.ID @@ -873,27 +877,50 @@ func (old *Destination) Select(option ...DestinationSelectOption) *Destination { vrf = o.VRF } adj = o.adj + best = o.Best + mp = o.MultiPath } var paths []*Path if adj { paths = old.knownPathList } else { paths = old.GetKnownPathList(id) + if vrf != nil { + ps := make([]*Path, 0, len(paths)) + for _, p := range paths { + if CanImportToVrf(vrf, p) { + ps = append(ps, p) + } + } + paths = ps + } + if len(paths) == 0 { + return nil + } + if best { + if !mp { + paths = []*Path{paths[0]} + } else { + ps := make([]*Path, 0, len(paths)) + var best *Path + for _, p := range paths { + if best == nil { + best = p + ps = append(ps, p) + } else if best.Compare(p) == 0 { + ps = append(ps, p) + } + } + paths = ps + } + } } new := NewDestination(old.nlri) - list := make([]*Path, 0, len(old.knownPathList)) for _, path := range paths { - if vrf != nil && !CanImportToVrf(vrf, path) { - continue - } p := path.Clone(path.IsWithdraw) p.Filter("", path.Filtered(id)) - list = append(list, p) - } - if len(list) == 0 { - return nil + new.knownPathList = append(new.knownPathList, p) } - new.knownPathList = list return new } diff --git a/table/table.go b/table/table.go index f89e8dff..143c4c53 100644 --- a/table/table.go +++ b/table/table.go @@ -43,6 +43,8 @@ type TableSelectOption struct { LookupPrefixes []*LookupPrefix VRF *Vrf adj bool + Best bool + MultiPath bool } type Table struct { @@ -314,6 +316,8 @@ func (t *Table) Select(option ...TableSelectOption) (*Table, error) { var vrf *Vrf adj := false prefixes := make([]*LookupPrefix, 0, len(option)) + best := false + mp := false for _, o := range option { if o.ID != "" { id = o.ID @@ -323,12 +327,15 @@ func (t *Table) Select(option ...TableSelectOption) (*Table, error) { } adj = o.adj prefixes = append(prefixes, o.LookupPrefixes...) + best = o.Best + mp = o.MultiPath } + dOption := DestinationSelectOption{ID: id, VRF: vrf, adj: adj, Best: best, MultiPath: mp} dsts := make(map[string]*Destination) if (t.routeFamily == bgp.RF_IPv4_UC || t.routeFamily == bgp.RF_IPv6_UC) && len(prefixes) > 0 { f := func(id, key string) (bool, error) { if dst := t.GetDestination(key); dst != nil { - if d := dst.Select(DestinationSelectOption{ID: id, adj: adj}); d != nil { + if d := dst.Select(dOption); d != nil { dsts[key] = d return true, nil } @@ -344,7 +351,9 @@ func (t *Table) Select(option ...TableSelectOption) (*Table, error) { return nil, err } for _, dst := range ds { - dsts[dst.GetNlri().String()] = dst.Select(DestinationSelectOption{ID: id, adj: adj}) + if d := dst.Select(dOption); d != nil { + dsts[dst.GetNlri().String()] = d + } } case LOOKUP_SHORTER: _, prefix, err := net.ParseCIDR(key) @@ -374,7 +383,7 @@ func (t *Table) Select(option ...TableSelectOption) (*Table, error) { } } else { for k, dst := range t.GetDestinations() { - if d := dst.Select(DestinationSelectOption{ID: id, VRF: vrf, adj: adj}); d != nil { + if d := dst.Select(dOption); d != nil { dsts[k] = d } } -- cgit v1.2.3