github.com/osrg/gobgp@v2.0.0+incompatible/internal/pkg/table/adj.go (about) 1 // Copyright (C) 2015 Nippon Telegraph and Telephone Corporation. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 12 // implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 16 package table 17 18 import ( 19 "fmt" 20 21 "github.com/osrg/gobgp/pkg/packet/bgp" 22 ) 23 24 type AdjRib struct { 25 accepted map[bgp.RouteFamily]int 26 table map[bgp.RouteFamily]map[string]*Path 27 } 28 29 func NewAdjRib(rfList []bgp.RouteFamily) *AdjRib { 30 table := make(map[bgp.RouteFamily]map[string]*Path) 31 for _, rf := range rfList { 32 table[rf] = make(map[string]*Path) 33 } 34 return &AdjRib{ 35 table: table, 36 accepted: make(map[bgp.RouteFamily]int), 37 } 38 } 39 40 func (adj *AdjRib) Update(pathList []*Path) { 41 for _, path := range pathList { 42 if path == nil || path.IsEOR() { 43 continue 44 } 45 rf := path.GetRouteFamily() 46 key := fmt.Sprintf("%d:%s", path.GetNlri().PathIdentifier(), path.getPrefix()) 47 48 old, found := adj.table[rf][key] 49 if path.IsWithdraw { 50 if found { 51 delete(adj.table[rf], key) 52 if !old.IsAsLooped() { 53 adj.accepted[rf]-- 54 } 55 } 56 } else { 57 if found { 58 if old.IsAsLooped() && !path.IsAsLooped() { 59 adj.accepted[rf]++ 60 } else if !old.IsAsLooped() && path.IsAsLooped() { 61 adj.accepted[rf]-- 62 } 63 } else { 64 if !path.IsAsLooped() { 65 adj.accepted[rf]++ 66 } 67 } 68 if found && old.Equal(path) { 69 path.setTimestamp(old.GetTimestamp()) 70 } 71 adj.table[rf][key] = path 72 } 73 } 74 } 75 76 func (adj *AdjRib) PathList(rfList []bgp.RouteFamily, accepted bool) []*Path { 77 pathList := make([]*Path, 0, adj.Count(rfList)) 78 for _, rf := range rfList { 79 for _, rr := range adj.table[rf] { 80 if accepted && rr.IsAsLooped() { 81 continue 82 } 83 pathList = append(pathList, rr) 84 } 85 } 86 return pathList 87 } 88 89 func (adj *AdjRib) Count(rfList []bgp.RouteFamily) int { 90 count := 0 91 for _, rf := range rfList { 92 if table, ok := adj.table[rf]; ok { 93 count += len(table) 94 } 95 } 96 return count 97 } 98 99 func (adj *AdjRib) Accepted(rfList []bgp.RouteFamily) int { 100 count := 0 101 for _, rf := range rfList { 102 if n, ok := adj.accepted[rf]; ok { 103 count += n 104 } 105 } 106 return count 107 } 108 109 func (adj *AdjRib) Drop(rfList []bgp.RouteFamily) { 110 for _, rf := range rfList { 111 if _, ok := adj.table[rf]; ok { 112 adj.table[rf] = make(map[string]*Path) 113 adj.accepted[rf] = 0 114 } 115 } 116 } 117 118 func (adj *AdjRib) DropStale(rfList []bgp.RouteFamily) []*Path { 119 pathList := make([]*Path, 0, adj.Count(rfList)) 120 for _, rf := range rfList { 121 if table, ok := adj.table[rf]; ok { 122 for k, p := range table { 123 if p.IsStale() { 124 delete(table, k) 125 if !p.IsAsLooped() { 126 adj.accepted[rf]-- 127 } 128 pathList = append(pathList, p.Clone(true)) 129 } 130 } 131 } 132 } 133 return pathList 134 } 135 136 func (adj *AdjRib) StaleAll(rfList []bgp.RouteFamily) []*Path { 137 pathList := make([]*Path, 0) 138 for _, rf := range rfList { 139 if table, ok := adj.table[rf]; ok { 140 l := make([]*Path, 0, len(table)) 141 for k, p := range table { 142 n := p.Clone(false) 143 n.MarkStale(true) 144 table[k] = n 145 l = append(l, n) 146 } 147 if len(l) > 0 { 148 pathList = append(pathList, l...) 149 } 150 } 151 } 152 return pathList 153 } 154 155 func (adj *AdjRib) Select(family bgp.RouteFamily, accepted bool, option ...TableSelectOption) (*Table, error) { 156 m := make(map[string][]*Path) 157 pl := adj.PathList([]bgp.RouteFamily{family}, accepted) 158 for _, path := range pl { 159 key := path.GetNlri().String() 160 if _, y := m[key]; y { 161 m[key] = append(m[key], path) 162 } else { 163 m[key] = []*Path{path} 164 } 165 } 166 d := make([]*Destination, 0, len(pl)) 167 for _, l := range m { 168 d = append(d, NewDestination(l[0].GetNlri(), 0, l...)) 169 } 170 tbl := NewTable(family, d...) 171 option = append(option, TableSelectOption{adj: true}) 172 return tbl.Select(option...) 173 } 174 175 func (adj *AdjRib) TableInfo(family bgp.RouteFamily) (*TableInfo, error) { 176 if _, ok := adj.table[family]; !ok { 177 return nil, fmt.Errorf("%s unsupported", family) 178 } 179 c := adj.Count([]bgp.RouteFamily{family}) 180 a := adj.Accepted([]bgp.RouteFamily{family}) 181 return &TableInfo{ 182 NumDestination: c, 183 NumPath: c, 184 NumAccepted: a, 185 }, nil 186 }