github.com/osrg/gobgp@v2.0.0+incompatible/internal/pkg/config/util.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 config 17 18 import ( 19 "fmt" 20 "net" 21 "path/filepath" 22 "regexp" 23 "strconv" 24 "strings" 25 "time" 26 27 "github.com/golang/protobuf/ptypes" 28 "github.com/golang/protobuf/ptypes/timestamp" 29 api "github.com/osrg/gobgp/api" 30 "github.com/osrg/gobgp/internal/pkg/apiutil" 31 "github.com/osrg/gobgp/pkg/packet/bgp" 32 ) 33 34 // Returns config file type by retrieving extension from the given path. 35 // If no corresponding type found, returns the given def as the default value. 36 func detectConfigFileType(path, def string) string { 37 switch ext := filepath.Ext(path); ext { 38 case ".toml": 39 return "toml" 40 case ".yaml", ".yml": 41 return "yaml" 42 case ".json": 43 return "json" 44 default: 45 return def 46 } 47 } 48 49 // yaml is decoded as []interface{} 50 // but toml is decoded as []map[string]interface{}. 51 // currently, viper can't hide this difference. 52 // handle the difference here. 53 func extractArray(intf interface{}) ([]interface{}, error) { 54 if intf != nil { 55 list, ok := intf.([]interface{}) 56 if ok { 57 return list, nil 58 } 59 l, ok := intf.([]map[string]interface{}) 60 if !ok { 61 return nil, fmt.Errorf("invalid configuration: neither []interface{} nor []map[string]interface{}") 62 } 63 list = make([]interface{}, 0, len(l)) 64 for _, m := range l { 65 list = append(list, m) 66 } 67 return list, nil 68 } 69 return nil, nil 70 } 71 72 func getIPv6LinkLocalAddress(ifname string) (string, error) { 73 ifi, err := net.InterfaceByName(ifname) 74 if err != nil { 75 return "", err 76 } 77 addrs, err := ifi.Addrs() 78 if err != nil { 79 return "", err 80 } 81 for _, addr := range addrs { 82 ip := addr.(*net.IPNet).IP 83 if ip.To4() == nil && ip.IsLinkLocalUnicast() { 84 return fmt.Sprintf("%s%%%s", ip.String(), ifname), nil 85 } 86 } 87 return "", fmt.Errorf("no ipv6 link local address for %s", ifname) 88 } 89 90 func (b *BgpConfigSet) getPeerGroup(n string) (*PeerGroup, error) { 91 if n == "" { 92 return nil, nil 93 } 94 for _, pg := range b.PeerGroups { 95 if n == pg.Config.PeerGroupName { 96 return &pg, nil 97 } 98 } 99 return nil, fmt.Errorf("no such peer-group: %s", n) 100 } 101 102 func (d *DynamicNeighbor) validate(b *BgpConfigSet) error { 103 if d.Config.PeerGroup == "" { 104 return fmt.Errorf("dynamic neighbor requires the peer group config") 105 } 106 107 if _, err := b.getPeerGroup(d.Config.PeerGroup); err != nil { 108 return err 109 } 110 if _, _, err := net.ParseCIDR(d.Config.Prefix); err != nil { 111 return fmt.Errorf("invalid dynamic neighbor prefix %s", d.Config.Prefix) 112 } 113 return nil 114 } 115 116 func (n *Neighbor) IsConfederationMember(g *Global) bool { 117 for _, member := range g.Confederation.Config.MemberAsList { 118 if member == n.Config.PeerAs { 119 return true 120 } 121 } 122 return false 123 } 124 125 func (n *Neighbor) IsConfederation(g *Global) bool { 126 if n.Config.PeerAs == g.Config.As { 127 return true 128 } 129 return n.IsConfederationMember(g) 130 } 131 132 func (n *Neighbor) IsEBGPPeer(g *Global) bool { 133 return n.Config.PeerAs != g.Config.As 134 } 135 136 func (n *Neighbor) CreateRfMap() map[bgp.RouteFamily]bgp.BGPAddPathMode { 137 rfMap := make(map[bgp.RouteFamily]bgp.BGPAddPathMode) 138 for _, af := range n.AfiSafis { 139 mode := bgp.BGP_ADD_PATH_NONE 140 if af.AddPaths.State.Receive { 141 mode |= bgp.BGP_ADD_PATH_RECEIVE 142 } 143 if af.AddPaths.State.SendMax > 0 { 144 mode |= bgp.BGP_ADD_PATH_SEND 145 } 146 rfMap[af.State.Family] = mode 147 } 148 return rfMap 149 } 150 151 func (n *Neighbor) GetAfiSafi(family bgp.RouteFamily) *AfiSafi { 152 for _, a := range n.AfiSafis { 153 if string(a.Config.AfiSafiName) == family.String() { 154 return &a 155 } 156 } 157 return nil 158 } 159 160 func (n *Neighbor) ExtractNeighborAddress() (string, error) { 161 addr := n.State.NeighborAddress 162 if addr == "" { 163 addr = n.Config.NeighborAddress 164 if addr == "" { 165 return "", fmt.Errorf("NeighborAddress is not configured") 166 } 167 } 168 return addr, nil 169 } 170 171 func (n *Neighbor) IsAddPathReceiveEnabled(family bgp.RouteFamily) bool { 172 for _, af := range n.AfiSafis { 173 if af.State.Family == family { 174 return af.AddPaths.State.Receive 175 } 176 } 177 return false 178 } 179 180 type AfiSafis []AfiSafi 181 182 func (c AfiSafis) ToRfList() ([]bgp.RouteFamily, error) { 183 rfs := make([]bgp.RouteFamily, 0, len(c)) 184 for _, af := range c { 185 rfs = append(rfs, af.State.Family) 186 } 187 return rfs, nil 188 } 189 190 func inSlice(n Neighbor, b []Neighbor) int { 191 for i, nb := range b { 192 if nb.State.NeighborAddress == n.State.NeighborAddress { 193 return i 194 } 195 } 196 return -1 197 } 198 199 func existPeerGroup(n string, b []PeerGroup) int { 200 for i, nb := range b { 201 if nb.Config.PeerGroupName == n { 202 return i 203 } 204 } 205 return -1 206 } 207 208 func isAfiSafiChanged(x, y []AfiSafi) bool { 209 if len(x) != len(y) { 210 return true 211 } 212 m := make(map[string]AfiSafi) 213 for i, e := range x { 214 m[string(e.Config.AfiSafiName)] = x[i] 215 } 216 for _, e := range y { 217 if v, ok := m[string(e.Config.AfiSafiName)]; !ok || !v.Config.Equal(&e.Config) || !v.AddPaths.Config.Equal(&e.AddPaths.Config) { 218 return true 219 } 220 } 221 return false 222 } 223 224 func (n *Neighbor) NeedsResendOpenMessage(new *Neighbor) bool { 225 return !n.Config.Equal(&new.Config) || 226 !n.Transport.Config.Equal(&new.Transport.Config) || 227 !n.AddPaths.Config.Equal(&new.AddPaths.Config) || 228 !n.GracefulRestart.Config.Equal(&new.GracefulRestart.Config) || 229 isAfiSafiChanged(n.AfiSafis, new.AfiSafis) 230 } 231 232 // TODO: these regexp are duplicated in api 233 var _regexpPrefixMaskLengthRange = regexp.MustCompile(`(\d+)\.\.(\d+)`) 234 235 func ParseMaskLength(prefix, mask string) (int, int, error) { 236 _, ipNet, err := net.ParseCIDR(prefix) 237 if err != nil { 238 return 0, 0, fmt.Errorf("invalid prefix: %s", prefix) 239 } 240 if mask == "" { 241 l, _ := ipNet.Mask.Size() 242 return l, l, nil 243 } 244 elems := _regexpPrefixMaskLengthRange.FindStringSubmatch(mask) 245 if len(elems) != 3 { 246 return 0, 0, fmt.Errorf("invalid mask length range: %s", mask) 247 } 248 // we've already checked the range is sane by regexp 249 min, _ := strconv.ParseUint(elems[1], 10, 8) 250 max, _ := strconv.ParseUint(elems[2], 10, 8) 251 if min > max { 252 return 0, 0, fmt.Errorf("invalid mask length range: %s", mask) 253 } 254 if ipv4 := ipNet.IP.To4(); ipv4 != nil { 255 f := func(i uint64) bool { 256 return i <= 32 257 } 258 if !f(min) || !f(max) { 259 return 0, 0, fmt.Errorf("ipv4 mask length range outside scope :%s", mask) 260 } 261 } else { 262 f := func(i uint64) bool { 263 return i <= 128 264 } 265 if !f(min) || !f(max) { 266 return 0, 0, fmt.Errorf("ipv6 mask length range outside scope :%s", mask) 267 } 268 } 269 return int(min), int(max), nil 270 } 271 272 func extractFamilyFromConfigAfiSafi(c *AfiSafi) uint32 { 273 if c == nil { 274 return 0 275 } 276 // If address family value is already stored in AfiSafiState structure, 277 // we prefer to use this value. 278 if c.State.Family != 0 { 279 return uint32(c.State.Family) 280 } 281 // In case that Neighbor structure came from CLI or gRPC, address family 282 // value in AfiSafiState structure can be omitted. 283 // Here extracts value from AfiSafiName field in AfiSafiConfig structure. 284 if rf, err := bgp.GetRouteFamily(string(c.Config.AfiSafiName)); err == nil { 285 return uint32(rf) 286 } 287 // Ignores invalid address family name 288 return 0 289 } 290 291 func newAfiSafiConfigFromConfigStruct(c *AfiSafi) *api.AfiSafiConfig { 292 rf := extractFamilyFromConfigAfiSafi(c) 293 afi, safi := bgp.RouteFamilyToAfiSafi(bgp.RouteFamily(rf)) 294 return &api.AfiSafiConfig{ 295 Family: &api.Family{Afi: api.Family_Afi(afi), Safi: api.Family_Safi(safi)}, 296 Enabled: c.Config.Enabled, 297 } 298 } 299 300 func newApplyPolicyFromConfigStruct(c *ApplyPolicy) *api.ApplyPolicy { 301 applyPolicy := &api.ApplyPolicy{ 302 ImportPolicy: &api.PolicyAssignment{ 303 Direction: api.PolicyDirection_IMPORT, 304 DefaultAction: api.RouteAction(c.Config.DefaultImportPolicy.ToInt()), 305 }, 306 ExportPolicy: &api.PolicyAssignment{ 307 Direction: api.PolicyDirection_EXPORT, 308 DefaultAction: api.RouteAction(c.Config.DefaultExportPolicy.ToInt()), 309 }, 310 } 311 312 for _, pname := range c.Config.ImportPolicyList { 313 applyPolicy.ImportPolicy.Policies = append(applyPolicy.ImportPolicy.Policies, &api.Policy{Name: pname}) 314 } 315 for _, pname := range c.Config.ExportPolicyList { 316 applyPolicy.ExportPolicy.Policies = append(applyPolicy.ExportPolicy.Policies, &api.Policy{Name: pname}) 317 } 318 319 return applyPolicy 320 } 321 322 func newPrefixLimitFromConfigStruct(c *AfiSafi) *api.PrefixLimit { 323 if c.PrefixLimit.Config.MaxPrefixes == 0 { 324 return nil 325 } 326 afi, safi := bgp.RouteFamilyToAfiSafi(bgp.RouteFamily(c.State.Family)) 327 return &api.PrefixLimit{ 328 Family: &api.Family{Afi: api.Family_Afi(afi), Safi: api.Family_Safi(safi)}, 329 MaxPrefixes: c.PrefixLimit.Config.MaxPrefixes, 330 ShutdownThresholdPct: uint32(c.PrefixLimit.Config.ShutdownThresholdPct), 331 } 332 } 333 334 func newRouteTargetMembershipFromConfigStruct(c *RouteTargetMembership) *api.RouteTargetMembership { 335 return &api.RouteTargetMembership{ 336 Config: &api.RouteTargetMembershipConfig{ 337 DeferralTime: uint32(c.Config.DeferralTime), 338 }, 339 } 340 } 341 342 func newLongLivedGracefulRestartFromConfigStruct(c *LongLivedGracefulRestart) *api.LongLivedGracefulRestart { 343 return &api.LongLivedGracefulRestart{ 344 Config: &api.LongLivedGracefulRestartConfig{ 345 Enabled: c.Config.Enabled, 346 RestartTime: c.Config.RestartTime, 347 }, 348 } 349 } 350 351 func newAddPathsFromConfigStruct(c *AddPaths) *api.AddPaths { 352 return &api.AddPaths{ 353 Config: &api.AddPathsConfig{ 354 Receive: c.Config.Receive, 355 SendMax: uint32(c.Config.SendMax), 356 }, 357 } 358 } 359 360 func newRouteSelectionOptionsFromConfigStruct(c *RouteSelectionOptions) *api.RouteSelectionOptions { 361 return &api.RouteSelectionOptions{ 362 Config: &api.RouteSelectionOptionsConfig{ 363 AlwaysCompareMed: c.Config.AlwaysCompareMed, 364 IgnoreAsPathLength: c.Config.IgnoreAsPathLength, 365 ExternalCompareRouterId: c.Config.ExternalCompareRouterId, 366 AdvertiseInactiveRoutes: c.Config.AdvertiseInactiveRoutes, 367 EnableAigp: c.Config.EnableAigp, 368 IgnoreNextHopIgpMetric: c.Config.IgnoreNextHopIgpMetric, 369 }, 370 } 371 } 372 373 func newMpGracefulRestartFromConfigStruct(c *MpGracefulRestart) *api.MpGracefulRestart { 374 return &api.MpGracefulRestart{ 375 Config: &api.MpGracefulRestartConfig{ 376 Enabled: c.Config.Enabled, 377 }, 378 } 379 } 380 381 func newUseMultiplePathsFromConfigStruct(c *UseMultiplePaths) *api.UseMultiplePaths { 382 return &api.UseMultiplePaths{ 383 Config: &api.UseMultiplePathsConfig{ 384 Enabled: c.Config.Enabled, 385 }, 386 Ebgp: &api.Ebgp{ 387 Config: &api.EbgpConfig{ 388 AllowMultipleAs: c.Ebgp.Config.AllowMultipleAs, 389 MaximumPaths: c.Ebgp.Config.MaximumPaths, 390 }, 391 }, 392 Ibgp: &api.Ibgp{ 393 Config: &api.IbgpConfig{ 394 MaximumPaths: c.Ibgp.Config.MaximumPaths, 395 }, 396 }, 397 } 398 } 399 400 func newAfiSafiFromConfigStruct(c *AfiSafi) *api.AfiSafi { 401 return &api.AfiSafi{ 402 MpGracefulRestart: newMpGracefulRestartFromConfigStruct(&c.MpGracefulRestart), 403 Config: newAfiSafiConfigFromConfigStruct(c), 404 ApplyPolicy: newApplyPolicyFromConfigStruct(&c.ApplyPolicy), 405 RouteSelectionOptions: newRouteSelectionOptionsFromConfigStruct(&c.RouteSelectionOptions), 406 UseMultiplePaths: newUseMultiplePathsFromConfigStruct(&c.UseMultiplePaths), 407 PrefixLimits: newPrefixLimitFromConfigStruct(c), 408 RouteTargetMembership: newRouteTargetMembershipFromConfigStruct(&c.RouteTargetMembership), 409 LongLivedGracefulRestart: newLongLivedGracefulRestartFromConfigStruct(&c.LongLivedGracefulRestart), 410 AddPaths: newAddPathsFromConfigStruct(&c.AddPaths), 411 } 412 } 413 414 func ProtoTimestamp(secs int64) *timestamp.Timestamp { 415 if secs == 0 { 416 return nil 417 } 418 t, _ := ptypes.TimestampProto(time.Unix(secs, 0)) 419 return t 420 } 421 422 func NewPeerFromConfigStruct(pconf *Neighbor) *api.Peer { 423 afiSafis := make([]*api.AfiSafi, 0, len(pconf.AfiSafis)) 424 for _, f := range pconf.AfiSafis { 425 if afiSafi := newAfiSafiFromConfigStruct(&f); afiSafi != nil { 426 afiSafis = append(afiSafis, afiSafi) 427 } 428 } 429 430 timer := pconf.Timers 431 s := pconf.State 432 localAddress := pconf.Transport.Config.LocalAddress 433 if pconf.Transport.State.LocalAddress != "" { 434 localAddress = pconf.Transport.State.LocalAddress 435 } 436 remoteCap, err := apiutil.MarshalCapabilities(pconf.State.RemoteCapabilityList) 437 if err != nil { 438 return nil 439 } 440 localCap, err := apiutil.MarshalCapabilities(pconf.State.LocalCapabilityList) 441 if err != nil { 442 return nil 443 } 444 var removePrivateAs api.PeerConf_RemovePrivateAs 445 switch pconf.Config.RemovePrivateAs { 446 case REMOVE_PRIVATE_AS_OPTION_ALL: 447 removePrivateAs = api.PeerConf_ALL 448 case REMOVE_PRIVATE_AS_OPTION_REPLACE: 449 removePrivateAs = api.PeerConf_REPLACE 450 } 451 return &api.Peer{ 452 ApplyPolicy: newApplyPolicyFromConfigStruct(&pconf.ApplyPolicy), 453 Conf: &api.PeerConf{ 454 NeighborAddress: pconf.Config.NeighborAddress, 455 PeerAs: pconf.Config.PeerAs, 456 LocalAs: pconf.Config.LocalAs, 457 PeerType: uint32(pconf.Config.PeerType.ToInt()), 458 AuthPassword: pconf.Config.AuthPassword, 459 RouteFlapDamping: pconf.Config.RouteFlapDamping, 460 Description: pconf.Config.Description, 461 PeerGroup: pconf.Config.PeerGroup, 462 NeighborInterface: pconf.Config.NeighborInterface, 463 Vrf: pconf.Config.Vrf, 464 AllowOwnAs: uint32(pconf.AsPathOptions.Config.AllowOwnAs), 465 RemovePrivateAs: removePrivateAs, 466 ReplacePeerAs: pconf.AsPathOptions.Config.ReplacePeerAs, 467 AdminDown: pconf.Config.AdminDown, 468 }, 469 State: &api.PeerState{ 470 SessionState: api.PeerState_SessionState(api.PeerState_SessionState_value[strings.ToUpper(string(s.SessionState))]), 471 AdminState: api.PeerState_AdminState(s.AdminState.ToInt()), 472 Messages: &api.Messages{ 473 Received: &api.Message{ 474 Notification: s.Messages.Received.Notification, 475 Update: s.Messages.Received.Update, 476 Open: s.Messages.Received.Open, 477 Keepalive: s.Messages.Received.Keepalive, 478 Refresh: s.Messages.Received.Refresh, 479 Discarded: s.Messages.Received.Discarded, 480 Total: s.Messages.Received.Total, 481 WithdrawUpdate: uint64(s.Messages.Received.WithdrawUpdate), 482 WithdrawPrefix: uint64(s.Messages.Received.WithdrawPrefix), 483 }, 484 Sent: &api.Message{ 485 Notification: s.Messages.Sent.Notification, 486 Update: s.Messages.Sent.Update, 487 Open: s.Messages.Sent.Open, 488 Keepalive: s.Messages.Sent.Keepalive, 489 Refresh: s.Messages.Sent.Refresh, 490 Discarded: s.Messages.Sent.Discarded, 491 Total: s.Messages.Sent.Total, 492 }, 493 }, 494 PeerAs: s.PeerAs, 495 PeerType: uint32(s.PeerType.ToInt()), 496 NeighborAddress: pconf.State.NeighborAddress, 497 Queues: &api.Queues{}, 498 RemoteCap: remoteCap, 499 LocalCap: localCap, 500 RouterId: s.RemoteRouterId, 501 }, 502 EbgpMultihop: &api.EbgpMultihop{ 503 Enabled: pconf.EbgpMultihop.Config.Enabled, 504 MultihopTtl: uint32(pconf.EbgpMultihop.Config.MultihopTtl), 505 }, 506 Timers: &api.Timers{ 507 Config: &api.TimersConfig{ 508 ConnectRetry: uint64(timer.Config.ConnectRetry), 509 HoldTime: uint64(timer.Config.HoldTime), 510 KeepaliveInterval: uint64(timer.Config.KeepaliveInterval), 511 }, 512 State: &api.TimersState{ 513 KeepaliveInterval: uint64(timer.State.KeepaliveInterval), 514 NegotiatedHoldTime: uint64(timer.State.NegotiatedHoldTime), 515 Uptime: ProtoTimestamp(timer.State.Uptime), 516 Downtime: ProtoTimestamp(timer.State.Downtime), 517 }, 518 }, 519 RouteReflector: &api.RouteReflector{ 520 RouteReflectorClient: pconf.RouteReflector.Config.RouteReflectorClient, 521 RouteReflectorClusterId: string(pconf.RouteReflector.State.RouteReflectorClusterId), 522 }, 523 RouteServer: &api.RouteServer{ 524 RouteServerClient: pconf.RouteServer.Config.RouteServerClient, 525 }, 526 GracefulRestart: &api.GracefulRestart{ 527 Enabled: pconf.GracefulRestart.Config.Enabled, 528 RestartTime: uint32(pconf.GracefulRestart.Config.RestartTime), 529 HelperOnly: pconf.GracefulRestart.Config.HelperOnly, 530 DeferralTime: uint32(pconf.GracefulRestart.Config.DeferralTime), 531 NotificationEnabled: pconf.GracefulRestart.Config.NotificationEnabled, 532 LonglivedEnabled: pconf.GracefulRestart.Config.LongLivedEnabled, 533 LocalRestarting: pconf.GracefulRestart.State.LocalRestarting, 534 }, 535 Transport: &api.Transport{ 536 RemotePort: uint32(pconf.Transport.Config.RemotePort), 537 LocalAddress: localAddress, 538 PassiveMode: pconf.Transport.Config.PassiveMode, 539 }, 540 AfiSafis: afiSafis, 541 } 542 } 543 544 func NewPeerGroupFromConfigStruct(pconf *PeerGroup) *api.PeerGroup { 545 afiSafis := make([]*api.AfiSafi, 0, len(pconf.AfiSafis)) 546 for _, f := range pconf.AfiSafis { 547 if afiSafi := newAfiSafiFromConfigStruct(&f); afiSafi != nil { 548 afiSafis = append(afiSafis, afiSafi) 549 } 550 } 551 552 timer := pconf.Timers 553 s := pconf.State 554 return &api.PeerGroup{ 555 ApplyPolicy: newApplyPolicyFromConfigStruct(&pconf.ApplyPolicy), 556 Conf: &api.PeerGroupConf{ 557 PeerAs: pconf.Config.PeerAs, 558 LocalAs: pconf.Config.LocalAs, 559 PeerType: uint32(pconf.Config.PeerType.ToInt()), 560 AuthPassword: pconf.Config.AuthPassword, 561 RouteFlapDamping: pconf.Config.RouteFlapDamping, 562 Description: pconf.Config.Description, 563 PeerGroupName: pconf.Config.PeerGroupName, 564 }, 565 Info: &api.PeerGroupState{ 566 PeerAs: s.PeerAs, 567 PeerType: uint32(s.PeerType.ToInt()), 568 TotalPaths: s.TotalPaths, 569 TotalPrefixes: s.TotalPrefixes, 570 }, 571 Timers: &api.Timers{ 572 Config: &api.TimersConfig{ 573 ConnectRetry: uint64(timer.Config.ConnectRetry), 574 HoldTime: uint64(timer.Config.HoldTime), 575 KeepaliveInterval: uint64(timer.Config.KeepaliveInterval), 576 }, 577 State: &api.TimersState{ 578 KeepaliveInterval: uint64(timer.State.KeepaliveInterval), 579 NegotiatedHoldTime: uint64(timer.State.NegotiatedHoldTime), 580 Uptime: ProtoTimestamp(timer.State.Uptime), 581 Downtime: ProtoTimestamp(timer.State.Downtime), 582 }, 583 }, 584 RouteReflector: &api.RouteReflector{ 585 RouteReflectorClient: pconf.RouteReflector.Config.RouteReflectorClient, 586 RouteReflectorClusterId: string(pconf.RouteReflector.Config.RouteReflectorClusterId), 587 }, 588 RouteServer: &api.RouteServer{ 589 RouteServerClient: pconf.RouteServer.Config.RouteServerClient, 590 }, 591 GracefulRestart: &api.GracefulRestart{ 592 Enabled: pconf.GracefulRestart.Config.Enabled, 593 RestartTime: uint32(pconf.GracefulRestart.Config.RestartTime), 594 HelperOnly: pconf.GracefulRestart.Config.HelperOnly, 595 DeferralTime: uint32(pconf.GracefulRestart.Config.DeferralTime), 596 NotificationEnabled: pconf.GracefulRestart.Config.NotificationEnabled, 597 LonglivedEnabled: pconf.GracefulRestart.Config.LongLivedEnabled, 598 LocalRestarting: pconf.GracefulRestart.State.LocalRestarting, 599 }, 600 Transport: &api.Transport{ 601 RemotePort: uint32(pconf.Transport.Config.RemotePort), 602 LocalAddress: pconf.Transport.Config.LocalAddress, 603 PassiveMode: pconf.Transport.Config.PassiveMode, 604 }, 605 AfiSafis: afiSafis, 606 } 607 } 608 609 func NewGlobalFromConfigStruct(c *Global) *api.Global { 610 families := make([]uint32, 0, len(c.AfiSafis)) 611 for _, f := range c.AfiSafis { 612 families = append(families, uint32(AfiSafiTypeToIntMap[f.Config.AfiSafiName])) 613 } 614 615 applyPolicy := newApplyPolicyFromConfigStruct(&c.ApplyPolicy) 616 617 return &api.Global{ 618 As: c.Config.As, 619 RouterId: c.Config.RouterId, 620 ListenPort: c.Config.Port, 621 ListenAddresses: c.Config.LocalAddressList, 622 Families: families, 623 UseMultiplePaths: c.UseMultiplePaths.Config.Enabled, 624 RouteSelectionOptions: &api.RouteSelectionOptionsConfig{ 625 AlwaysCompareMed: c.RouteSelectionOptions.Config.AlwaysCompareMed, 626 IgnoreAsPathLength: c.RouteSelectionOptions.Config.IgnoreAsPathLength, 627 ExternalCompareRouterId: c.RouteSelectionOptions.Config.ExternalCompareRouterId, 628 AdvertiseInactiveRoutes: c.RouteSelectionOptions.Config.AdvertiseInactiveRoutes, 629 EnableAigp: c.RouteSelectionOptions.Config.EnableAigp, 630 IgnoreNextHopIgpMetric: c.RouteSelectionOptions.Config.IgnoreNextHopIgpMetric, 631 DisableBestPathSelection: c.RouteSelectionOptions.Config.DisableBestPathSelection, 632 }, 633 DefaultRouteDistance: &api.DefaultRouteDistance{ 634 ExternalRouteDistance: uint32(c.DefaultRouteDistance.Config.ExternalRouteDistance), 635 InternalRouteDistance: uint32(c.DefaultRouteDistance.Config.InternalRouteDistance), 636 }, 637 Confederation: &api.Confederation{ 638 Enabled: c.Confederation.Config.Enabled, 639 Identifier: c.Confederation.Config.Identifier, 640 MemberAsList: c.Confederation.Config.MemberAsList, 641 }, 642 GracefulRestart: &api.GracefulRestart{ 643 Enabled: c.GracefulRestart.Config.Enabled, 644 RestartTime: uint32(c.GracefulRestart.Config.RestartTime), 645 StaleRoutesTime: uint32(c.GracefulRestart.Config.StaleRoutesTime), 646 HelperOnly: c.GracefulRestart.Config.HelperOnly, 647 DeferralTime: uint32(c.GracefulRestart.Config.DeferralTime), 648 NotificationEnabled: c.GracefulRestart.Config.NotificationEnabled, 649 LonglivedEnabled: c.GracefulRestart.Config.LongLivedEnabled, 650 }, 651 ApplyPolicy: applyPolicy, 652 } 653 } 654 655 func newAPIPrefixFromConfigStruct(c Prefix) (*api.Prefix, error) { 656 min, max, err := ParseMaskLength(c.IpPrefix, c.MasklengthRange) 657 if err != nil { 658 return nil, err 659 } 660 return &api.Prefix{ 661 IpPrefix: c.IpPrefix, 662 MaskLengthMin: uint32(min), 663 MaskLengthMax: uint32(max), 664 }, nil 665 } 666 667 func NewAPIDefinedSetsFromConfigStruct(t *DefinedSets) ([]*api.DefinedSet, error) { 668 definedSets := make([]*api.DefinedSet, 0) 669 670 for _, ps := range t.PrefixSets { 671 prefixes := make([]*api.Prefix, 0) 672 for _, p := range ps.PrefixList { 673 ap, err := newAPIPrefixFromConfigStruct(p) 674 if err != nil { 675 return nil, err 676 } 677 prefixes = append(prefixes, ap) 678 } 679 definedSets = append(definedSets, &api.DefinedSet{ 680 DefinedType: api.DefinedType_PREFIX, 681 Name: ps.PrefixSetName, 682 Prefixes: prefixes, 683 }) 684 } 685 686 for _, ns := range t.NeighborSets { 687 definedSets = append(definedSets, &api.DefinedSet{ 688 DefinedType: api.DefinedType_NEIGHBOR, 689 Name: ns.NeighborSetName, 690 List: ns.NeighborInfoList, 691 }) 692 } 693 694 bs := t.BgpDefinedSets 695 for _, cs := range bs.CommunitySets { 696 definedSets = append(definedSets, &api.DefinedSet{ 697 DefinedType: api.DefinedType_COMMUNITY, 698 Name: cs.CommunitySetName, 699 List: cs.CommunityList, 700 }) 701 } 702 703 for _, es := range bs.ExtCommunitySets { 704 definedSets = append(definedSets, &api.DefinedSet{ 705 DefinedType: api.DefinedType_EXT_COMMUNITY, 706 Name: es.ExtCommunitySetName, 707 List: es.ExtCommunityList, 708 }) 709 } 710 711 for _, ls := range bs.LargeCommunitySets { 712 definedSets = append(definedSets, &api.DefinedSet{ 713 DefinedType: api.DefinedType_LARGE_COMMUNITY, 714 Name: ls.LargeCommunitySetName, 715 List: ls.LargeCommunityList, 716 }) 717 } 718 719 for _, as := range bs.AsPathSets { 720 definedSets = append(definedSets, &api.DefinedSet{ 721 DefinedType: api.DefinedType_AS_PATH, 722 Name: as.AsPathSetName, 723 List: as.AsPathList, 724 }) 725 } 726 727 return definedSets, nil 728 }