github.com/osrg/gobgp@v2.0.0+incompatible/internal/pkg/table/table.go (about) 1 // Copyright (C) 2014 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 "net" 21 "strings" 22 "unsafe" 23 24 "github.com/armon/go-radix" 25 "github.com/osrg/gobgp/pkg/packet/bgp" 26 log "github.com/sirupsen/logrus" 27 ) 28 29 type LookupOption uint8 30 31 const ( 32 LOOKUP_EXACT LookupOption = iota 33 LOOKUP_LONGER 34 LOOKUP_SHORTER 35 ) 36 37 type LookupPrefix struct { 38 Prefix string 39 LookupOption 40 } 41 42 type TableSelectOption struct { 43 ID string 44 AS uint32 45 LookupPrefixes []*LookupPrefix 46 VRF *Vrf 47 adj bool 48 Best bool 49 MultiPath bool 50 } 51 52 type Table struct { 53 routeFamily bgp.RouteFamily 54 destinations map[string]*Destination 55 } 56 57 func NewTable(rf bgp.RouteFamily, dsts ...*Destination) *Table { 58 t := &Table{ 59 routeFamily: rf, 60 destinations: make(map[string]*Destination), 61 } 62 for _, dst := range dsts { 63 t.setDestination(dst) 64 } 65 return t 66 } 67 68 func (t *Table) GetRoutefamily() bgp.RouteFamily { 69 return t.routeFamily 70 } 71 72 func (t *Table) deletePathsByVrf(vrf *Vrf) []*Path { 73 pathList := make([]*Path, 0) 74 for _, dest := range t.destinations { 75 for _, p := range dest.knownPathList { 76 var rd bgp.RouteDistinguisherInterface 77 nlri := p.GetNlri() 78 switch nlri.(type) { 79 case *bgp.LabeledVPNIPAddrPrefix: 80 rd = nlri.(*bgp.LabeledVPNIPAddrPrefix).RD 81 case *bgp.LabeledVPNIPv6AddrPrefix: 82 rd = nlri.(*bgp.LabeledVPNIPv6AddrPrefix).RD 83 case *bgp.EVPNNLRI: 84 rd = nlri.(*bgp.EVPNNLRI).RD() 85 default: 86 return pathList 87 } 88 if p.IsLocal() && vrf.Rd.String() == rd.String() { 89 pathList = append(pathList, p.Clone(true)) 90 break 91 } 92 } 93 } 94 return pathList 95 } 96 97 func (t *Table) deleteRTCPathsByVrf(vrf *Vrf, vrfs map[string]*Vrf) []*Path { 98 pathList := make([]*Path, 0) 99 if t.routeFamily != bgp.RF_RTC_UC { 100 return pathList 101 } 102 for _, target := range vrf.ImportRt { 103 lhs := target.String() 104 for _, dest := range t.destinations { 105 nlri := dest.GetNlri().(*bgp.RouteTargetMembershipNLRI) 106 rhs := nlri.RouteTarget.String() 107 if lhs == rhs && isLastTargetUser(vrfs, target) { 108 for _, p := range dest.knownPathList { 109 if p.IsLocal() { 110 pathList = append(pathList, p.Clone(true)) 111 break 112 } 113 } 114 } 115 } 116 } 117 return pathList 118 } 119 120 func (t *Table) deleteDestByNlri(nlri bgp.AddrPrefixInterface) *Destination { 121 if dst := t.GetDestination(nlri); dst != nil { 122 t.deleteDest(dst) 123 return dst 124 } 125 return nil 126 } 127 128 func (t *Table) deleteDest(dest *Destination) { 129 destinations := t.GetDestinations() 130 delete(destinations, t.tableKey(dest.GetNlri())) 131 if len(destinations) == 0 { 132 t.destinations = make(map[string]*Destination) 133 } 134 } 135 136 func (t *Table) validatePath(path *Path) { 137 if path == nil { 138 log.WithFields(log.Fields{ 139 "Topic": "Table", 140 "Key": t.routeFamily, 141 }).Error("path is nil") 142 } 143 if path.GetRouteFamily() != t.routeFamily { 144 log.WithFields(log.Fields{ 145 "Topic": "Table", 146 "Key": t.routeFamily, 147 "Prefix": path.GetNlri().String(), 148 "ReceivedRf": path.GetRouteFamily().String(), 149 }).Error("Invalid path. RouteFamily mismatch") 150 } 151 if attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH); attr != nil { 152 pathParam := attr.(*bgp.PathAttributeAsPath).Value 153 for _, as := range pathParam { 154 _, y := as.(*bgp.As4PathParam) 155 if !y { 156 log.WithFields(log.Fields{ 157 "Topic": "Table", 158 "Key": t.routeFamily, 159 "As": as, 160 }).Fatal("AsPathParam must be converted to As4PathParam") 161 } 162 } 163 } 164 if attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_AS4_PATH); attr != nil { 165 log.WithFields(log.Fields{ 166 "Topic": "Table", 167 "Key": t.routeFamily, 168 }).Fatal("AS4_PATH must be converted to AS_PATH") 169 } 170 if path.GetNlri() == nil { 171 log.WithFields(log.Fields{ 172 "Topic": "Table", 173 "Key": t.routeFamily, 174 }).Fatal("path's nlri is nil") 175 } 176 } 177 178 func (t *Table) getOrCreateDest(nlri bgp.AddrPrefixInterface) *Destination { 179 dest := t.GetDestination(nlri) 180 // If destination for given prefix does not exist we create it. 181 if dest == nil { 182 log.WithFields(log.Fields{ 183 "Topic": "Table", 184 "Nlri": nlri, 185 }).Debugf("create Destination") 186 dest = NewDestination(nlri, 64) 187 t.setDestination(dest) 188 } 189 return dest 190 } 191 192 func (t *Table) GetDestinations() map[string]*Destination { 193 return t.destinations 194 } 195 func (t *Table) setDestinations(destinations map[string]*Destination) { 196 t.destinations = destinations 197 } 198 func (t *Table) GetDestination(nlri bgp.AddrPrefixInterface) *Destination { 199 dest, ok := t.destinations[t.tableKey(nlri)] 200 if ok { 201 return dest 202 } else { 203 return nil 204 } 205 } 206 207 func (t *Table) GetLongerPrefixDestinations(key string) ([]*Destination, error) { 208 results := make([]*Destination, 0, len(t.GetDestinations())) 209 switch t.routeFamily { 210 case bgp.RF_IPv4_UC, bgp.RF_IPv6_UC, bgp.RF_IPv4_MPLS, bgp.RF_IPv6_MPLS: 211 _, prefix, err := net.ParseCIDR(key) 212 if err != nil { 213 return nil, err 214 } 215 k := CidrToRadixkey(prefix.String()) 216 r := radix.New() 217 for _, dst := range t.GetDestinations() { 218 r.Insert(AddrToRadixkey(dst.nlri), dst) 219 } 220 r.WalkPrefix(k, func(s string, v interface{}) bool { 221 results = append(results, v.(*Destination)) 222 return false 223 }) 224 default: 225 for _, dst := range t.GetDestinations() { 226 results = append(results, dst) 227 } 228 } 229 return results, nil 230 } 231 232 func (t *Table) GetEvpnDestinationsWithRouteType(typ string) ([]*Destination, error) { 233 var routeType uint8 234 switch strings.ToLower(typ) { 235 case "a-d": 236 routeType = bgp.EVPN_ROUTE_TYPE_ETHERNET_AUTO_DISCOVERY 237 case "macadv": 238 routeType = bgp.EVPN_ROUTE_TYPE_MAC_IP_ADVERTISEMENT 239 case "multicast": 240 routeType = bgp.EVPN_INCLUSIVE_MULTICAST_ETHERNET_TAG 241 case "esi": 242 routeType = bgp.EVPN_ETHERNET_SEGMENT_ROUTE 243 case "prefix": 244 routeType = bgp.EVPN_IP_PREFIX 245 default: 246 return nil, fmt.Errorf("unsupported evpn route type: %s", typ) 247 } 248 destinations := t.GetDestinations() 249 results := make([]*Destination, 0, len(destinations)) 250 switch t.routeFamily { 251 case bgp.RF_EVPN: 252 for _, dst := range destinations { 253 if nlri, ok := dst.nlri.(*bgp.EVPNNLRI); !ok { 254 return nil, fmt.Errorf("invalid evpn nlri type detected: %T", dst.nlri) 255 } else if nlri.RouteType == routeType { 256 results = append(results, dst) 257 } 258 } 259 default: 260 for _, dst := range destinations { 261 results = append(results, dst) 262 } 263 } 264 return results, nil 265 } 266 267 func (t *Table) setDestination(dst *Destination) { 268 t.destinations[t.tableKey(dst.nlri)] = dst 269 } 270 271 func (t *Table) tableKey(nlri bgp.AddrPrefixInterface) string { 272 switch T := nlri.(type) { 273 case *bgp.IPAddrPrefix: 274 b := make([]byte, 5) 275 copy(b, T.Prefix.To4()) 276 b[4] = T.Length 277 return *(*string)(unsafe.Pointer(&b)) 278 case *bgp.IPv6AddrPrefix: 279 b := make([]byte, 17) 280 copy(b, T.Prefix.To16()) 281 b[16] = T.Length 282 return *(*string)(unsafe.Pointer(&b)) 283 } 284 return nlri.String() 285 } 286 287 func (t *Table) Bests(id string, as uint32) []*Path { 288 paths := make([]*Path, 0, len(t.destinations)) 289 for _, dst := range t.destinations { 290 path := dst.GetBestPath(id, as) 291 if path != nil { 292 paths = append(paths, path) 293 } 294 } 295 return paths 296 } 297 298 func (t *Table) MultiBests(id string) [][]*Path { 299 paths := make([][]*Path, 0, len(t.destinations)) 300 for _, dst := range t.destinations { 301 path := dst.GetMultiBestPath(id) 302 if path != nil { 303 paths = append(paths, path) 304 } 305 } 306 return paths 307 } 308 309 func (t *Table) GetKnownPathList(id string, as uint32) []*Path { 310 paths := make([]*Path, 0, len(t.destinations)) 311 for _, dst := range t.destinations { 312 paths = append(paths, dst.GetKnownPathList(id, as)...) 313 } 314 return paths 315 } 316 317 func (t *Table) Select(option ...TableSelectOption) (*Table, error) { 318 id := GLOBAL_RIB_NAME 319 var vrf *Vrf 320 adj := false 321 prefixes := make([]*LookupPrefix, 0, len(option)) 322 best := false 323 mp := false 324 as := uint32(0) 325 for _, o := range option { 326 if o.ID != "" { 327 id = o.ID 328 } 329 if o.VRF != nil { 330 vrf = o.VRF 331 } 332 adj = o.adj 333 prefixes = append(prefixes, o.LookupPrefixes...) 334 best = o.Best 335 mp = o.MultiPath 336 as = o.AS 337 } 338 dOption := DestinationSelectOption{ID: id, AS: as, VRF: vrf, adj: adj, Best: best, MultiPath: mp} 339 r := &Table{ 340 routeFamily: t.routeFamily, 341 destinations: make(map[string]*Destination), 342 } 343 344 if len(prefixes) != 0 { 345 switch t.routeFamily { 346 case bgp.RF_IPv4_UC, bgp.RF_IPv6_UC: 347 f := func(prefixStr string) bool { 348 var nlri bgp.AddrPrefixInterface 349 if t.routeFamily == bgp.RF_IPv4_UC { 350 nlri, _ = bgp.NewPrefixFromRouteFamily(bgp.AFI_IP, bgp.SAFI_UNICAST, prefixStr) 351 } else { 352 nlri, _ = bgp.NewPrefixFromRouteFamily(bgp.AFI_IP6, bgp.SAFI_UNICAST, prefixStr) 353 } 354 if dst := t.GetDestination(nlri); dst != nil { 355 if d := dst.Select(dOption); d != nil { 356 r.setDestination(d) 357 return true 358 } 359 } 360 return false 361 } 362 363 for _, p := range prefixes { 364 key := p.Prefix 365 switch p.LookupOption { 366 case LOOKUP_LONGER: 367 ds, err := t.GetLongerPrefixDestinations(key) 368 if err != nil { 369 return nil, err 370 } 371 for _, dst := range ds { 372 if d := dst.Select(dOption); d != nil { 373 r.setDestination(d) 374 } 375 } 376 case LOOKUP_SHORTER: 377 addr, prefix, err := net.ParseCIDR(key) 378 if err != nil { 379 return nil, err 380 } 381 ones, _ := prefix.Mask.Size() 382 for i := ones; i >= 0; i-- { 383 _, prefix, _ := net.ParseCIDR(fmt.Sprintf("%s/%d", addr.String(), i)) 384 f(prefix.String()) 385 } 386 default: 387 if host := net.ParseIP(key); host != nil { 388 masklen := 32 389 if t.routeFamily == bgp.RF_IPv6_UC { 390 masklen = 128 391 } 392 for i := masklen; i >= 0; i-- { 393 _, prefix, err := net.ParseCIDR(fmt.Sprintf("%s/%d", key, i)) 394 if err != nil { 395 return nil, err 396 } 397 if f(prefix.String()) { 398 break 399 } 400 } 401 } else { 402 f(key) 403 } 404 } 405 } 406 case bgp.RF_EVPN: 407 for _, p := range prefixes { 408 // Uses LookupPrefix.Prefix as EVPN Route Type string 409 ds, err := t.GetEvpnDestinationsWithRouteType(p.Prefix) 410 if err != nil { 411 return nil, err 412 } 413 for _, dst := range ds { 414 if d := dst.Select(dOption); d != nil { 415 r.setDestination(d) 416 } 417 } 418 } 419 default: 420 return nil, fmt.Errorf("route filtering is not supported for this family") 421 } 422 } else { 423 for _, dst := range t.GetDestinations() { 424 if d := dst.Select(dOption); d != nil { 425 r.setDestination(d) 426 } 427 } 428 } 429 return r, nil 430 } 431 432 type TableInfo struct { 433 NumDestination int 434 NumPath int 435 NumAccepted int 436 } 437 438 func (t *Table) Info(id string, as uint32) *TableInfo { 439 var numD, numP int 440 for _, d := range t.destinations { 441 ps := d.GetKnownPathList(id, as) 442 if len(ps) > 0 { 443 numD += 1 444 numP += len(ps) 445 } 446 } 447 return &TableInfo{ 448 NumDestination: numD, 449 NumPath: numP, 450 } 451 }