github.com/osrg/gobgp@v2.0.0+incompatible/internal/pkg/table/table_manager.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 "bytes" 20 "fmt" 21 "net" 22 "time" 23 24 farm "github.com/dgryski/go-farm" 25 log "github.com/sirupsen/logrus" 26 27 "github.com/osrg/gobgp/pkg/packet/bgp" 28 ) 29 30 const ( 31 GLOBAL_RIB_NAME = "global" 32 ) 33 34 func ProcessMessage(m *bgp.BGPMessage, peerInfo *PeerInfo, timestamp time.Time) []*Path { 35 update := m.Body.(*bgp.BGPUpdate) 36 37 if y, f := update.IsEndOfRib(); y { 38 // this message has no normal updates or withdrawals. 39 return []*Path{NewEOR(f)} 40 } 41 42 adds := make([]bgp.AddrPrefixInterface, 0, len(update.NLRI)) 43 for _, nlri := range update.NLRI { 44 adds = append(adds, nlri) 45 } 46 47 dels := make([]bgp.AddrPrefixInterface, 0, len(update.WithdrawnRoutes)) 48 for _, nlri := range update.WithdrawnRoutes { 49 dels = append(dels, nlri) 50 } 51 52 attrs := make([]bgp.PathAttributeInterface, 0, len(update.PathAttributes)) 53 var reach *bgp.PathAttributeMpReachNLRI 54 for _, attr := range update.PathAttributes { 55 switch a := attr.(type) { 56 case *bgp.PathAttributeMpReachNLRI: 57 reach = a 58 case *bgp.PathAttributeMpUnreachNLRI: 59 l := make([]bgp.AddrPrefixInterface, 0, len(a.Value)) 60 l = append(l, a.Value...) 61 dels = append(dels, l...) 62 default: 63 attrs = append(attrs, attr) 64 } 65 } 66 67 listLen := len(adds) + len(dels) 68 if reach != nil { 69 listLen += len(reach.Value) 70 } 71 72 var hash uint32 73 if len(adds) > 0 || reach != nil { 74 total := bytes.NewBuffer(make([]byte, 0)) 75 for _, a := range attrs { 76 b, _ := a.Serialize() 77 total.Write(b) 78 } 79 hash = farm.Hash32(total.Bytes()) 80 } 81 82 pathList := make([]*Path, 0, listLen) 83 for _, nlri := range adds { 84 p := NewPath(peerInfo, nlri, false, attrs, timestamp, false) 85 p.SetHash(hash) 86 pathList = append(pathList, p) 87 } 88 if reach != nil { 89 reachAttrs := make([]bgp.PathAttributeInterface, len(attrs)+1) 90 copy(reachAttrs, attrs) 91 // we sort attributes when creating a bgp message from paths 92 reachAttrs[len(reachAttrs)-1] = reach 93 94 for _, nlri := range reach.Value { 95 p := NewPath(peerInfo, nlri, false, reachAttrs, timestamp, false) 96 p.SetHash(hash) 97 pathList = append(pathList, p) 98 } 99 } 100 for _, nlri := range dels { 101 p := NewPath(peerInfo, nlri, true, []bgp.PathAttributeInterface{}, timestamp, false) 102 pathList = append(pathList, p) 103 } 104 return pathList 105 } 106 107 type TableManager struct { 108 Tables map[bgp.RouteFamily]*Table 109 Vrfs map[string]*Vrf 110 rfList []bgp.RouteFamily 111 } 112 113 func NewTableManager(rfList []bgp.RouteFamily) *TableManager { 114 t := &TableManager{ 115 Tables: make(map[bgp.RouteFamily]*Table), 116 Vrfs: make(map[string]*Vrf), 117 rfList: rfList, 118 } 119 for _, rf := range rfList { 120 t.Tables[rf] = NewTable(rf) 121 } 122 return t 123 } 124 125 func (manager *TableManager) GetRFlist() []bgp.RouteFamily { 126 return manager.rfList 127 } 128 129 func (manager *TableManager) AddVrf(name string, id uint32, rd bgp.RouteDistinguisherInterface, importRt, exportRt []bgp.ExtendedCommunityInterface, info *PeerInfo) ([]*Path, error) { 130 if _, ok := manager.Vrfs[name]; ok { 131 return nil, fmt.Errorf("vrf %s already exists", name) 132 } 133 log.WithFields(log.Fields{ 134 "Topic": "Vrf", 135 "Key": name, 136 "Rd": rd, 137 "ImportRt": importRt, 138 "ExportRt": exportRt, 139 }).Debugf("add vrf") 140 manager.Vrfs[name] = &Vrf{ 141 Name: name, 142 Id: id, 143 Rd: rd, 144 ImportRt: importRt, 145 ExportRt: exportRt, 146 } 147 msgs := make([]*Path, 0, len(importRt)) 148 nexthop := "0.0.0.0" 149 for _, target := range importRt { 150 nlri := bgp.NewRouteTargetMembershipNLRI(info.AS, target) 151 pattr := make([]bgp.PathAttributeInterface, 0, 2) 152 pattr = append(pattr, bgp.NewPathAttributeOrigin(bgp.BGP_ORIGIN_ATTR_TYPE_IGP)) 153 pattr = append(pattr, bgp.NewPathAttributeMpReachNLRI(nexthop, []bgp.AddrPrefixInterface{nlri})) 154 msgs = append(msgs, NewPath(info, nlri, false, pattr, time.Now(), false)) 155 } 156 return msgs, nil 157 } 158 159 func (manager *TableManager) DeleteVrf(name string) ([]*Path, error) { 160 if _, ok := manager.Vrfs[name]; !ok { 161 return nil, fmt.Errorf("vrf %s not found", name) 162 } 163 msgs := make([]*Path, 0) 164 vrf := manager.Vrfs[name] 165 for _, t := range manager.Tables { 166 msgs = append(msgs, t.deletePathsByVrf(vrf)...) 167 } 168 log.WithFields(log.Fields{ 169 "Topic": "Vrf", 170 "Key": vrf.Name, 171 "Rd": vrf.Rd, 172 "ImportRt": vrf.ImportRt, 173 "ExportRt": vrf.ExportRt, 174 }).Debugf("delete vrf") 175 delete(manager.Vrfs, name) 176 rtcTable := manager.Tables[bgp.RF_RTC_UC] 177 msgs = append(msgs, rtcTable.deleteRTCPathsByVrf(vrf, manager.Vrfs)...) 178 return msgs, nil 179 } 180 181 func (tm *TableManager) update(newPath *Path) *Update { 182 t := tm.Tables[newPath.GetRouteFamily()] 183 t.validatePath(newPath) 184 dst := t.getOrCreateDest(newPath.GetNlri()) 185 u := dst.Calculate(newPath) 186 if len(dst.knownPathList) == 0 { 187 t.deleteDest(dst) 188 } 189 return u 190 } 191 192 func (manager *TableManager) GetPathListByPeer(info *PeerInfo, rf bgp.RouteFamily) []*Path { 193 if t, ok := manager.Tables[rf]; ok { 194 pathList := make([]*Path, 0, len(t.destinations)) 195 for _, dst := range t.destinations { 196 for _, p := range dst.knownPathList { 197 if p.GetSource().Equal(info) { 198 pathList = append(pathList, p) 199 } 200 } 201 } 202 return pathList 203 } 204 return nil 205 } 206 207 func (manager *TableManager) Update(newPath *Path) []*Update { 208 if newPath == nil || newPath.IsEOR() { 209 return nil 210 } 211 212 // Except for a special case with EVPN, we'll have one destination. 213 updates := make([]*Update, 0, 1) 214 family := newPath.GetRouteFamily() 215 if _, ok := manager.Tables[family]; ok { 216 updates = append(updates, manager.update(newPath)) 217 218 if family == bgp.RF_EVPN { 219 for _, p := range manager.handleMacMobility(newPath) { 220 updates = append(updates, manager.update(p)) 221 } 222 } 223 } 224 return updates 225 } 226 227 // EVPN MAC MOBILITY HANDLING 228 // 229 // RFC7432 15. MAC Mobility 230 // 231 // A PE receiving a MAC/IP Advertisement route for a MAC address with a 232 // different Ethernet segment identifier and a higher sequence number 233 // than that which it had previously advertised withdraws its MAC/IP 234 // Advertisement route. 235 // ...... 236 // If the PE is the originator of the MAC route and it receives the same 237 // MAC address with the same sequence number that it generated, it will 238 // compare its own IP address with the IP address of the remote PE and 239 // will select the lowest IP. If its own route is not the best one, it 240 // will withdraw the route. 241 func (manager *TableManager) handleMacMobility(path *Path) []*Path { 242 pathList := make([]*Path, 0) 243 nlri := path.GetNlri().(*bgp.EVPNNLRI) 244 if path.IsWithdraw || path.IsLocal() || nlri.RouteType != bgp.EVPN_ROUTE_TYPE_MAC_IP_ADVERTISEMENT { 245 return nil 246 } 247 for _, path2 := range manager.GetPathList(GLOBAL_RIB_NAME, 0, []bgp.RouteFamily{bgp.RF_EVPN}) { 248 if !path2.IsLocal() || path2.GetNlri().(*bgp.EVPNNLRI).RouteType != bgp.EVPN_ROUTE_TYPE_MAC_IP_ADVERTISEMENT { 249 continue 250 } 251 f := func(p *Path) (bgp.EthernetSegmentIdentifier, uint32, net.HardwareAddr, int, net.IP) { 252 nlri := p.GetNlri().(*bgp.EVPNNLRI) 253 d := nlri.RouteTypeData.(*bgp.EVPNMacIPAdvertisementRoute) 254 ecs := p.GetExtCommunities() 255 seq := -1 256 for _, ec := range ecs { 257 if t, st := ec.GetTypes(); t == bgp.EC_TYPE_EVPN && st == bgp.EC_SUBTYPE_MAC_MOBILITY { 258 seq = int(ec.(*bgp.MacMobilityExtended).Sequence) 259 break 260 } 261 } 262 return d.ESI, d.ETag, d.MacAddress, seq, p.info.source.Address 263 } 264 e1, et1, m1, s1, i1 := f(path) 265 e2, et2, m2, s2, i2 := f(path2) 266 if et1 == et2 && bytes.Equal(m1, m2) && !bytes.Equal(e1.Value, e2.Value) { 267 if s1 > s2 || s1 == s2 && bytes.Compare(i1, i2) < 0 { 268 pathList = append(pathList, path2.Clone(true)) 269 } 270 } 271 } 272 return pathList 273 } 274 275 func (manager *TableManager) tables(list ...bgp.RouteFamily) []*Table { 276 l := make([]*Table, 0, len(manager.Tables)) 277 if len(list) == 0 { 278 for _, v := range manager.Tables { 279 l = append(l, v) 280 } 281 return l 282 } 283 for _, f := range list { 284 if t, ok := manager.Tables[f]; ok { 285 l = append(l, t) 286 } 287 } 288 return l 289 } 290 291 func (manager *TableManager) getDestinationCount(rfList []bgp.RouteFamily) int { 292 count := 0 293 for _, t := range manager.tables(rfList...) { 294 count += len(t.GetDestinations()) 295 } 296 return count 297 } 298 299 func (manager *TableManager) GetBestPathList(id string, as uint32, rfList []bgp.RouteFamily) []*Path { 300 if SelectionOptions.DisableBestPathSelection { 301 // Note: If best path selection disabled, there is no best path. 302 return nil 303 } 304 paths := make([]*Path, 0, manager.getDestinationCount(rfList)) 305 for _, t := range manager.tables(rfList...) { 306 paths = append(paths, t.Bests(id, as)...) 307 } 308 return paths 309 } 310 311 func (manager *TableManager) GetBestMultiPathList(id string, rfList []bgp.RouteFamily) [][]*Path { 312 if !UseMultiplePaths.Enabled || SelectionOptions.DisableBestPathSelection { 313 // Note: If multi path not enabled or best path selection disabled, 314 // there is no best multi path. 315 return nil 316 } 317 paths := make([][]*Path, 0, manager.getDestinationCount(rfList)) 318 for _, t := range manager.tables(rfList...) { 319 paths = append(paths, t.MultiBests(id)...) 320 } 321 return paths 322 } 323 324 func (manager *TableManager) GetPathList(id string, as uint32, rfList []bgp.RouteFamily) []*Path { 325 paths := make([]*Path, 0, manager.getDestinationCount(rfList)) 326 for _, t := range manager.tables(rfList...) { 327 paths = append(paths, t.GetKnownPathList(id, as)...) 328 } 329 return paths 330 } 331 332 func (manager *TableManager) GetPathListWithNexthop(id string, rfList []bgp.RouteFamily, nexthop net.IP) []*Path { 333 paths := make([]*Path, 0, manager.getDestinationCount(rfList)) 334 for _, rf := range rfList { 335 if t, ok := manager.Tables[rf]; ok { 336 for _, path := range t.GetKnownPathList(id, 0) { 337 if path.GetNexthop().Equal(nexthop) { 338 paths = append(paths, path) 339 } 340 } 341 } 342 } 343 return paths 344 } 345 346 func (manager *TableManager) GetPathListWithSource(id string, rfList []bgp.RouteFamily, source *PeerInfo) []*Path { 347 paths := make([]*Path, 0, manager.getDestinationCount(rfList)) 348 for _, rf := range rfList { 349 if t, ok := manager.Tables[rf]; ok { 350 for _, path := range t.GetKnownPathList(id, 0) { 351 if path.GetSource().Equal(source) { 352 paths = append(paths, path) 353 } 354 } 355 } 356 } 357 return paths 358 } 359 360 func (manager *TableManager) GetDestination(path *Path) *Destination { 361 if path == nil { 362 return nil 363 } 364 family := path.GetRouteFamily() 365 t, ok := manager.Tables[family] 366 if !ok { 367 return nil 368 } 369 return t.GetDestination(path.GetNlri()) 370 } 371 372 func (manager *TableManager) TableInfo(id string, as uint32, family bgp.RouteFamily) (*TableInfo, error) { 373 t, ok := manager.Tables[family] 374 if !ok { 375 return nil, fmt.Errorf("address family %s is not configured", family) 376 } 377 return t.Info(id, as), nil 378 }