github.com/osrg/gobgp/v3@v3.30.0/pkg/config/oc/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 oc 17 18 import ( 19 "fmt" 20 "net" 21 "path/filepath" 22 "regexp" 23 "strconv" 24 "strings" 25 "time" 26 27 tspb "google.golang.org/protobuf/types/known/timestamppb" 28 29 api "github.com/osrg/gobgp/v3/api" 30 "github.com/osrg/gobgp/v3/pkg/apiutil" 31 "github.com/osrg/gobgp/v3/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 != n.Config.LocalAs 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) || !v.MpGracefulRestart.Config.Equal(&e.MpGracefulRestart.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.AsPathOptions.Config.Equal(&new.AsPathOptions.Config) || 229 !n.GracefulRestart.Config.Equal(&new.GracefulRestart.Config) || 230 isAfiSafiChanged(n.AfiSafis, new.AfiSafis) 231 } 232 233 // TODO: these regexp are duplicated in api 234 var _regexpPrefixMaskLengthRange = regexp.MustCompile(`(\d+)\.\.(\d+)`) 235 236 func ParseMaskLength(prefix, mask string) (int, int, error) { 237 _, ipNet, err := net.ParseCIDR(prefix) 238 if err != nil { 239 return 0, 0, fmt.Errorf("invalid prefix: %s", prefix) 240 } 241 if mask == "" { 242 l, _ := ipNet.Mask.Size() 243 return l, l, nil 244 } 245 elems := _regexpPrefixMaskLengthRange.FindStringSubmatch(mask) 246 if len(elems) != 3 { 247 return 0, 0, fmt.Errorf("invalid mask length range: %s", mask) 248 } 249 // we've already checked the range is sane by regexp 250 min, _ := strconv.ParseUint(elems[1], 10, 8) 251 max, _ := strconv.ParseUint(elems[2], 10, 8) 252 if min > max { 253 return 0, 0, fmt.Errorf("invalid mask length range: %s", mask) 254 } 255 if ipv4 := ipNet.IP.To4(); ipv4 != nil { 256 f := func(i uint64) bool { 257 return i <= 32 258 } 259 if !f(min) || !f(max) { 260 return 0, 0, fmt.Errorf("ipv4 mask length range outside scope :%s", mask) 261 } 262 } else { 263 f := func(i uint64) bool { 264 return i <= 128 265 } 266 if !f(min) || !f(max) { 267 return 0, 0, fmt.Errorf("ipv6 mask length range outside scope :%s", mask) 268 } 269 } 270 return int(min), int(max), nil 271 } 272 273 func extractFamilyFromConfigAfiSafi(c *AfiSafi) uint32 { 274 if c == nil { 275 return 0 276 } 277 // If address family value is already stored in AfiSafiState structure, 278 // we prefer to use this value. 279 if c.State.Family != 0 { 280 return uint32(c.State.Family) 281 } 282 // In case that Neighbor structure came from CLI or gRPC, address family 283 // value in AfiSafiState structure can be omitted. 284 // Here extracts value from AfiSafiName field in AfiSafiConfig structure. 285 if rf, err := bgp.GetRouteFamily(string(c.Config.AfiSafiName)); err == nil { 286 return uint32(rf) 287 } 288 // Ignores invalid address family name 289 return 0 290 } 291 292 func newAfiSafiConfigFromConfigStruct(c *AfiSafi) *api.AfiSafiConfig { 293 rf := extractFamilyFromConfigAfiSafi(c) 294 afi, safi := bgp.RouteFamilyToAfiSafi(bgp.RouteFamily(rf)) 295 return &api.AfiSafiConfig{ 296 Family: &api.Family{Afi: api.Family_Afi(afi), Safi: api.Family_Safi(safi)}, 297 Enabled: c.Config.Enabled, 298 } 299 } 300 301 func newApplyPolicyFromConfigStruct(c *ApplyPolicy) *api.ApplyPolicy { 302 f := func(t DefaultPolicyType) api.RouteAction { 303 if t == DEFAULT_POLICY_TYPE_ACCEPT_ROUTE { 304 return api.RouteAction_ACCEPT 305 } else if t == DEFAULT_POLICY_TYPE_REJECT_ROUTE { 306 return api.RouteAction_REJECT 307 } 308 return api.RouteAction_NONE 309 } 310 applyPolicy := &api.ApplyPolicy{ 311 ImportPolicy: &api.PolicyAssignment{ 312 Direction: api.PolicyDirection_IMPORT, 313 DefaultAction: f(c.Config.DefaultImportPolicy), 314 }, 315 ExportPolicy: &api.PolicyAssignment{ 316 Direction: api.PolicyDirection_EXPORT, 317 DefaultAction: f(c.Config.DefaultExportPolicy), 318 }, 319 } 320 321 for _, pname := range c.Config.ImportPolicyList { 322 applyPolicy.ImportPolicy.Policies = append(applyPolicy.ImportPolicy.Policies, &api.Policy{Name: pname}) 323 } 324 for _, pname := range c.Config.ExportPolicyList { 325 applyPolicy.ExportPolicy.Policies = append(applyPolicy.ExportPolicy.Policies, &api.Policy{Name: pname}) 326 } 327 328 return applyPolicy 329 } 330 331 func newPrefixLimitFromConfigStruct(c *AfiSafi) *api.PrefixLimit { 332 if c.PrefixLimit.Config.MaxPrefixes == 0 { 333 return nil 334 } 335 afi, safi := bgp.RouteFamilyToAfiSafi(bgp.RouteFamily(c.State.Family)) 336 return &api.PrefixLimit{ 337 Family: &api.Family{Afi: api.Family_Afi(afi), Safi: api.Family_Safi(safi)}, 338 MaxPrefixes: c.PrefixLimit.Config.MaxPrefixes, 339 ShutdownThresholdPct: uint32(c.PrefixLimit.Config.ShutdownThresholdPct), 340 } 341 } 342 343 func newRouteTargetMembershipFromConfigStruct(c *RouteTargetMembership) *api.RouteTargetMembership { 344 return &api.RouteTargetMembership{ 345 Config: &api.RouteTargetMembershipConfig{ 346 DeferralTime: uint32(c.Config.DeferralTime), 347 }, 348 } 349 } 350 351 func newLongLivedGracefulRestartFromConfigStruct(c *LongLivedGracefulRestart) *api.LongLivedGracefulRestart { 352 return &api.LongLivedGracefulRestart{ 353 Config: &api.LongLivedGracefulRestartConfig{ 354 Enabled: c.Config.Enabled, 355 RestartTime: c.Config.RestartTime, 356 }, 357 } 358 } 359 360 func newAddPathsFromConfigStruct(c *AddPaths) *api.AddPaths { 361 return &api.AddPaths{ 362 Config: &api.AddPathsConfig{ 363 Receive: c.Config.Receive, 364 SendMax: uint32(c.Config.SendMax), 365 }, 366 } 367 } 368 369 func newRouteSelectionOptionsFromConfigStruct(c *RouteSelectionOptions) *api.RouteSelectionOptions { 370 return &api.RouteSelectionOptions{ 371 Config: &api.RouteSelectionOptionsConfig{ 372 AlwaysCompareMed: c.Config.AlwaysCompareMed, 373 IgnoreAsPathLength: c.Config.IgnoreAsPathLength, 374 ExternalCompareRouterId: c.Config.ExternalCompareRouterId, 375 AdvertiseInactiveRoutes: c.Config.AdvertiseInactiveRoutes, 376 EnableAigp: c.Config.EnableAigp, 377 IgnoreNextHopIgpMetric: c.Config.IgnoreNextHopIgpMetric, 378 }, 379 } 380 } 381 382 func newMpGracefulRestartFromConfigStruct(c *MpGracefulRestart) *api.MpGracefulRestart { 383 return &api.MpGracefulRestart{ 384 Config: &api.MpGracefulRestartConfig{ 385 Enabled: c.Config.Enabled, 386 }, 387 State: &api.MpGracefulRestartState{ 388 Enabled: c.State.Enabled, 389 Received: c.State.Received, 390 Advertised: c.State.Advertised, 391 EndOfRibReceived: c.State.EndOfRibReceived, 392 EndOfRibSent: c.State.EndOfRibSent, 393 }, 394 } 395 } 396 397 func newUseMultiplePathsFromConfigStruct(c *UseMultiplePaths) *api.UseMultiplePaths { 398 return &api.UseMultiplePaths{ 399 Config: &api.UseMultiplePathsConfig{ 400 Enabled: c.Config.Enabled, 401 }, 402 Ebgp: &api.Ebgp{ 403 Config: &api.EbgpConfig{ 404 AllowMultipleAsn: c.Ebgp.Config.AllowMultipleAs, 405 MaximumPaths: c.Ebgp.Config.MaximumPaths, 406 }, 407 }, 408 Ibgp: &api.Ibgp{ 409 Config: &api.IbgpConfig{ 410 MaximumPaths: c.Ibgp.Config.MaximumPaths, 411 }, 412 }, 413 } 414 } 415 416 func newAfiSafiFromConfigStruct(c *AfiSafi) *api.AfiSafi { 417 return &api.AfiSafi{ 418 MpGracefulRestart: newMpGracefulRestartFromConfigStruct(&c.MpGracefulRestart), 419 Config: newAfiSafiConfigFromConfigStruct(c), 420 ApplyPolicy: newApplyPolicyFromConfigStruct(&c.ApplyPolicy), 421 RouteSelectionOptions: newRouteSelectionOptionsFromConfigStruct(&c.RouteSelectionOptions), 422 UseMultiplePaths: newUseMultiplePathsFromConfigStruct(&c.UseMultiplePaths), 423 PrefixLimits: newPrefixLimitFromConfigStruct(c), 424 RouteTargetMembership: newRouteTargetMembershipFromConfigStruct(&c.RouteTargetMembership), 425 LongLivedGracefulRestart: newLongLivedGracefulRestartFromConfigStruct(&c.LongLivedGracefulRestart), 426 AddPaths: newAddPathsFromConfigStruct(&c.AddPaths), 427 } 428 } 429 430 func ProtoTimestamp(secs int64) *tspb.Timestamp { 431 if secs == 0 { 432 return nil 433 } 434 return tspb.New(time.Unix(secs, 0)) 435 } 436 437 func NewPeerFromConfigStruct(pconf *Neighbor) *api.Peer { 438 afiSafis := make([]*api.AfiSafi, 0, len(pconf.AfiSafis)) 439 for _, f := range pconf.AfiSafis { 440 if afiSafi := newAfiSafiFromConfigStruct(&f); afiSafi != nil { 441 afiSafis = append(afiSafis, afiSafi) 442 } 443 } 444 445 timer := pconf.Timers 446 s := pconf.State 447 localAddress := pconf.Transport.Config.LocalAddress 448 if pconf.Transport.State.LocalAddress != "" { 449 localAddress = pconf.Transport.State.LocalAddress 450 } 451 remoteCap, err := apiutil.MarshalCapabilities(pconf.State.RemoteCapabilityList) 452 if err != nil { 453 return nil 454 } 455 localCap, err := apiutil.MarshalCapabilities(pconf.State.LocalCapabilityList) 456 if err != nil { 457 return nil 458 } 459 var removePrivate api.RemovePrivate 460 switch pconf.Config.RemovePrivateAs { 461 case REMOVE_PRIVATE_AS_OPTION_ALL: 462 removePrivate = api.RemovePrivate_REMOVE_ALL 463 case REMOVE_PRIVATE_AS_OPTION_REPLACE: 464 removePrivate = api.RemovePrivate_REPLACE 465 } 466 return &api.Peer{ 467 ApplyPolicy: newApplyPolicyFromConfigStruct(&pconf.ApplyPolicy), 468 Conf: &api.PeerConf{ 469 NeighborAddress: pconf.Config.NeighborAddress, 470 PeerAsn: pconf.Config.PeerAs, 471 LocalAsn: pconf.Config.LocalAs, 472 Type: api.PeerType(pconf.Config.PeerType.ToInt()), 473 AuthPassword: pconf.Config.AuthPassword, 474 RouteFlapDamping: pconf.Config.RouteFlapDamping, 475 Description: pconf.Config.Description, 476 PeerGroup: pconf.Config.PeerGroup, 477 NeighborInterface: pconf.Config.NeighborInterface, 478 Vrf: pconf.Config.Vrf, 479 AllowOwnAsn: uint32(pconf.AsPathOptions.Config.AllowOwnAs), 480 RemovePrivate: removePrivate, 481 ReplacePeerAsn: pconf.AsPathOptions.Config.ReplacePeerAs, 482 AdminDown: pconf.Config.AdminDown, 483 SendSoftwareVersion: pconf.Config.SendSoftwareVersion, 484 }, 485 State: &api.PeerState{ 486 SessionState: api.PeerState_SessionState(api.PeerState_SessionState_value[strings.ToUpper(string(s.SessionState))]), 487 AdminState: api.PeerState_AdminState(s.AdminState.ToInt()), 488 Messages: &api.Messages{ 489 Received: &api.Message{ 490 Notification: s.Messages.Received.Notification, 491 Update: s.Messages.Received.Update, 492 Open: s.Messages.Received.Open, 493 Keepalive: s.Messages.Received.Keepalive, 494 Refresh: s.Messages.Received.Refresh, 495 Discarded: s.Messages.Received.Discarded, 496 Total: s.Messages.Received.Total, 497 WithdrawUpdate: uint64(s.Messages.Received.WithdrawUpdate), 498 WithdrawPrefix: uint64(s.Messages.Received.WithdrawPrefix), 499 }, 500 Sent: &api.Message{ 501 Notification: s.Messages.Sent.Notification, 502 Update: s.Messages.Sent.Update, 503 Open: s.Messages.Sent.Open, 504 Keepalive: s.Messages.Sent.Keepalive, 505 Refresh: s.Messages.Sent.Refresh, 506 Discarded: s.Messages.Sent.Discarded, 507 Total: s.Messages.Sent.Total, 508 }, 509 }, 510 PeerAsn: s.PeerAs, 511 LocalAsn: s.LocalAs, 512 Type: api.PeerType(s.PeerType.ToInt()), 513 NeighborAddress: pconf.State.NeighborAddress, 514 Queues: &api.Queues{}, 515 RemoteCap: remoteCap, 516 LocalCap: localCap, 517 RouterId: s.RemoteRouterId, 518 Flops: s.Flops, 519 }, 520 EbgpMultihop: &api.EbgpMultihop{ 521 Enabled: pconf.EbgpMultihop.Config.Enabled, 522 MultihopTtl: uint32(pconf.EbgpMultihop.Config.MultihopTtl), 523 }, 524 TtlSecurity: &api.TtlSecurity{ 525 Enabled: pconf.TtlSecurity.Config.Enabled, 526 TtlMin: uint32(pconf.TtlSecurity.Config.TtlMin), 527 }, 528 Timers: &api.Timers{ 529 Config: &api.TimersConfig{ 530 ConnectRetry: uint64(timer.Config.ConnectRetry), 531 HoldTime: uint64(timer.Config.HoldTime), 532 KeepaliveInterval: uint64(timer.Config.KeepaliveInterval), 533 IdleHoldTimeAfterReset: uint64(timer.Config.IdleHoldTimeAfterReset), 534 }, 535 State: &api.TimersState{ 536 KeepaliveInterval: uint64(timer.State.KeepaliveInterval), 537 NegotiatedHoldTime: uint64(timer.State.NegotiatedHoldTime), 538 Uptime: ProtoTimestamp(timer.State.Uptime), 539 Downtime: ProtoTimestamp(timer.State.Downtime), 540 }, 541 }, 542 RouteReflector: &api.RouteReflector{ 543 RouteReflectorClient: pconf.RouteReflector.Config.RouteReflectorClient, 544 RouteReflectorClusterId: string(pconf.RouteReflector.State.RouteReflectorClusterId), 545 }, 546 RouteServer: &api.RouteServer{ 547 RouteServerClient: pconf.RouteServer.Config.RouteServerClient, 548 SecondaryRoute: pconf.RouteServer.Config.SecondaryRoute, 549 }, 550 GracefulRestart: &api.GracefulRestart{ 551 Enabled: pconf.GracefulRestart.Config.Enabled, 552 RestartTime: uint32(pconf.GracefulRestart.Config.RestartTime), 553 HelperOnly: pconf.GracefulRestart.Config.HelperOnly, 554 DeferralTime: uint32(pconf.GracefulRestart.Config.DeferralTime), 555 NotificationEnabled: pconf.GracefulRestart.Config.NotificationEnabled, 556 LonglivedEnabled: pconf.GracefulRestart.Config.LongLivedEnabled, 557 LocalRestarting: pconf.GracefulRestart.State.LocalRestarting, 558 PeerRestartTime: uint32(pconf.GracefulRestart.State.PeerRestartTime), 559 PeerRestarting: pconf.GracefulRestart.State.PeerRestarting, 560 }, 561 Transport: &api.Transport{ 562 RemotePort: uint32(pconf.Transport.Config.RemotePort), 563 LocalPort: uint32(pconf.Transport.Config.LocalPort), 564 LocalAddress: localAddress, 565 PassiveMode: pconf.Transport.Config.PassiveMode, 566 BindInterface: pconf.Transport.Config.BindInterface, 567 TcpMss: uint32(pconf.Transport.Config.TcpMss), 568 }, 569 AfiSafis: afiSafis, 570 } 571 } 572 573 func NewPeerGroupFromConfigStruct(pconf *PeerGroup) *api.PeerGroup { 574 afiSafis := make([]*api.AfiSafi, 0, len(pconf.AfiSafis)) 575 for _, f := range pconf.AfiSafis { 576 if afiSafi := newAfiSafiFromConfigStruct(&f); afiSafi != nil { 577 afiSafi.AddPaths.Config.Receive = pconf.AddPaths.Config.Receive 578 afiSafi.AddPaths.Config.SendMax = uint32(pconf.AddPaths.Config.SendMax) 579 afiSafis = append(afiSafis, afiSafi) 580 } 581 } 582 583 timer := pconf.Timers 584 s := pconf.State 585 return &api.PeerGroup{ 586 ApplyPolicy: newApplyPolicyFromConfigStruct(&pconf.ApplyPolicy), 587 Conf: &api.PeerGroupConf{ 588 PeerAsn: pconf.Config.PeerAs, 589 LocalAsn: pconf.Config.LocalAs, 590 Type: api.PeerType(pconf.Config.PeerType.ToInt()), 591 AuthPassword: pconf.Config.AuthPassword, 592 RouteFlapDamping: pconf.Config.RouteFlapDamping, 593 Description: pconf.Config.Description, 594 PeerGroupName: pconf.Config.PeerGroupName, 595 SendSoftwareVersion: pconf.Config.SendSoftwareVersion, 596 }, 597 Info: &api.PeerGroupState{ 598 PeerAsn: s.PeerAs, 599 Type: api.PeerType(s.PeerType.ToInt()), 600 TotalPaths: s.TotalPaths, 601 TotalPrefixes: s.TotalPrefixes, 602 }, 603 EbgpMultihop: &api.EbgpMultihop{ 604 Enabled: pconf.EbgpMultihop.Config.Enabled, 605 MultihopTtl: uint32(pconf.EbgpMultihop.Config.MultihopTtl), 606 }, 607 TtlSecurity: &api.TtlSecurity{ 608 Enabled: pconf.TtlSecurity.Config.Enabled, 609 TtlMin: uint32(pconf.TtlSecurity.Config.TtlMin), 610 }, 611 Timers: &api.Timers{ 612 Config: &api.TimersConfig{ 613 ConnectRetry: uint64(timer.Config.ConnectRetry), 614 HoldTime: uint64(timer.Config.HoldTime), 615 KeepaliveInterval: uint64(timer.Config.KeepaliveInterval), 616 IdleHoldTimeAfterReset: uint64(timer.Config.IdleHoldTimeAfterReset), 617 }, 618 State: &api.TimersState{ 619 KeepaliveInterval: uint64(timer.State.KeepaliveInterval), 620 NegotiatedHoldTime: uint64(timer.State.NegotiatedHoldTime), 621 Uptime: ProtoTimestamp(timer.State.Uptime), 622 Downtime: ProtoTimestamp(timer.State.Downtime), 623 }, 624 }, 625 RouteReflector: &api.RouteReflector{ 626 RouteReflectorClient: pconf.RouteReflector.Config.RouteReflectorClient, 627 RouteReflectorClusterId: string(pconf.RouteReflector.Config.RouteReflectorClusterId), 628 }, 629 RouteServer: &api.RouteServer{ 630 RouteServerClient: pconf.RouteServer.Config.RouteServerClient, 631 SecondaryRoute: pconf.RouteServer.Config.SecondaryRoute, 632 }, 633 GracefulRestart: &api.GracefulRestart{ 634 Enabled: pconf.GracefulRestart.Config.Enabled, 635 RestartTime: uint32(pconf.GracefulRestart.Config.RestartTime), 636 HelperOnly: pconf.GracefulRestart.Config.HelperOnly, 637 DeferralTime: uint32(pconf.GracefulRestart.Config.DeferralTime), 638 NotificationEnabled: pconf.GracefulRestart.Config.NotificationEnabled, 639 LonglivedEnabled: pconf.GracefulRestart.Config.LongLivedEnabled, 640 LocalRestarting: pconf.GracefulRestart.State.LocalRestarting, 641 }, 642 Transport: &api.Transport{ 643 RemotePort: uint32(pconf.Transport.Config.RemotePort), 644 LocalAddress: pconf.Transport.Config.LocalAddress, 645 PassiveMode: pconf.Transport.Config.PassiveMode, 646 TcpMss: uint32(pconf.Transport.Config.TcpMss), 647 }, 648 AfiSafis: afiSafis, 649 } 650 } 651 652 func NewGlobalFromConfigStruct(c *Global) *api.Global { 653 families := make([]uint32, 0, len(c.AfiSafis)) 654 for _, f := range c.AfiSafis { 655 families = append(families, uint32(AfiSafiTypeToIntMap[f.Config.AfiSafiName])) 656 } 657 658 applyPolicy := newApplyPolicyFromConfigStruct(&c.ApplyPolicy) 659 660 return &api.Global{ 661 Asn: c.Config.As, 662 RouterId: c.Config.RouterId, 663 ListenPort: c.Config.Port, 664 ListenAddresses: c.Config.LocalAddressList, 665 Families: families, 666 UseMultiplePaths: c.UseMultiplePaths.Config.Enabled, 667 RouteSelectionOptions: &api.RouteSelectionOptionsConfig{ 668 AlwaysCompareMed: c.RouteSelectionOptions.Config.AlwaysCompareMed, 669 IgnoreAsPathLength: c.RouteSelectionOptions.Config.IgnoreAsPathLength, 670 ExternalCompareRouterId: c.RouteSelectionOptions.Config.ExternalCompareRouterId, 671 AdvertiseInactiveRoutes: c.RouteSelectionOptions.Config.AdvertiseInactiveRoutes, 672 EnableAigp: c.RouteSelectionOptions.Config.EnableAigp, 673 IgnoreNextHopIgpMetric: c.RouteSelectionOptions.Config.IgnoreNextHopIgpMetric, 674 DisableBestPathSelection: c.RouteSelectionOptions.Config.DisableBestPathSelection, 675 }, 676 DefaultRouteDistance: &api.DefaultRouteDistance{ 677 ExternalRouteDistance: uint32(c.DefaultRouteDistance.Config.ExternalRouteDistance), 678 InternalRouteDistance: uint32(c.DefaultRouteDistance.Config.InternalRouteDistance), 679 }, 680 Confederation: &api.Confederation{ 681 Enabled: c.Confederation.Config.Enabled, 682 Identifier: c.Confederation.Config.Identifier, 683 MemberAsList: c.Confederation.Config.MemberAsList, 684 }, 685 GracefulRestart: &api.GracefulRestart{ 686 Enabled: c.GracefulRestart.Config.Enabled, 687 RestartTime: uint32(c.GracefulRestart.Config.RestartTime), 688 StaleRoutesTime: uint32(c.GracefulRestart.Config.StaleRoutesTime), 689 HelperOnly: c.GracefulRestart.Config.HelperOnly, 690 DeferralTime: uint32(c.GracefulRestart.Config.DeferralTime), 691 NotificationEnabled: c.GracefulRestart.Config.NotificationEnabled, 692 LonglivedEnabled: c.GracefulRestart.Config.LongLivedEnabled, 693 }, 694 ApplyPolicy: applyPolicy, 695 } 696 } 697 698 func newAPIPrefixFromConfigStruct(c Prefix) (*api.Prefix, error) { 699 min, max, err := ParseMaskLength(c.IpPrefix, c.MasklengthRange) 700 if err != nil { 701 return nil, err 702 } 703 return &api.Prefix{ 704 IpPrefix: c.IpPrefix, 705 MaskLengthMin: uint32(min), 706 MaskLengthMax: uint32(max), 707 }, nil 708 } 709 710 func NewAPIDefinedSetsFromConfigStruct(t *DefinedSets) ([]*api.DefinedSet, error) { 711 definedSets := make([]*api.DefinedSet, 0) 712 713 for _, ps := range t.PrefixSets { 714 prefixes := make([]*api.Prefix, 0) 715 for _, p := range ps.PrefixList { 716 ap, err := newAPIPrefixFromConfigStruct(p) 717 if err != nil { 718 return nil, err 719 } 720 prefixes = append(prefixes, ap) 721 } 722 definedSets = append(definedSets, &api.DefinedSet{ 723 DefinedType: api.DefinedType_PREFIX, 724 Name: ps.PrefixSetName, 725 Prefixes: prefixes, 726 }) 727 } 728 729 for _, ns := range t.NeighborSets { 730 definedSets = append(definedSets, &api.DefinedSet{ 731 DefinedType: api.DefinedType_NEIGHBOR, 732 Name: ns.NeighborSetName, 733 List: ns.NeighborInfoList, 734 }) 735 } 736 737 bs := t.BgpDefinedSets 738 for _, cs := range bs.CommunitySets { 739 definedSets = append(definedSets, &api.DefinedSet{ 740 DefinedType: api.DefinedType_COMMUNITY, 741 Name: cs.CommunitySetName, 742 List: cs.CommunityList, 743 }) 744 } 745 746 for _, es := range bs.ExtCommunitySets { 747 definedSets = append(definedSets, &api.DefinedSet{ 748 DefinedType: api.DefinedType_EXT_COMMUNITY, 749 Name: es.ExtCommunitySetName, 750 List: es.ExtCommunityList, 751 }) 752 } 753 754 for _, ls := range bs.LargeCommunitySets { 755 definedSets = append(definedSets, &api.DefinedSet{ 756 DefinedType: api.DefinedType_LARGE_COMMUNITY, 757 Name: ls.LargeCommunitySetName, 758 List: ls.LargeCommunityList, 759 }) 760 } 761 762 for _, as := range bs.AsPathSets { 763 definedSets = append(definedSets, &api.DefinedSet{ 764 DefinedType: api.DefinedType_AS_PATH, 765 Name: as.AsPathSetName, 766 List: as.AsPathList, 767 }) 768 } 769 770 return definedSets, nil 771 }