Add app source, add vendoring and module support
This commit is contained in:
1303
vendor/github.com/osrg/gobgp/internal/pkg/apiutil/attribute.go
generated
vendored
Normal file
1303
vendor/github.com/osrg/gobgp/internal/pkg/apiutil/attribute.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
246
vendor/github.com/osrg/gobgp/internal/pkg/apiutil/capability.go
generated
vendored
Normal file
246
vendor/github.com/osrg/gobgp/internal/pkg/apiutil/capability.go
generated
vendored
Normal file
@@ -0,0 +1,246 @@
|
||||
// Copyright (C) 2018 Nippon Telegraph and Telephone Corporation.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package apiutil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
"github.com/golang/protobuf/ptypes"
|
||||
"github.com/golang/protobuf/ptypes/any"
|
||||
api "github.com/osrg/gobgp/api"
|
||||
"github.com/osrg/gobgp/pkg/packet/bgp"
|
||||
)
|
||||
|
||||
func NewMultiProtocolCapability(a *bgp.CapMultiProtocol) *api.MultiProtocolCapability {
|
||||
afi, safi := bgp.RouteFamilyToAfiSafi(a.CapValue)
|
||||
return &api.MultiProtocolCapability{
|
||||
Family: ToApiFamily(afi, safi),
|
||||
}
|
||||
}
|
||||
|
||||
func NewRouteRefreshCapability(a *bgp.CapRouteRefresh) *api.RouteRefreshCapability {
|
||||
return &api.RouteRefreshCapability{}
|
||||
}
|
||||
|
||||
func NewCarryingLabelInfoCapability(a *bgp.CapCarryingLabelInfo) *api.CarryingLabelInfoCapability {
|
||||
return &api.CarryingLabelInfoCapability{}
|
||||
}
|
||||
|
||||
func NewExtendedNexthopCapability(a *bgp.CapExtendedNexthop) *api.ExtendedNexthopCapability {
|
||||
tuples := make([]*api.ExtendedNexthopCapabilityTuple, 0, len(a.Tuples))
|
||||
for _, t := range a.Tuples {
|
||||
tuples = append(tuples, &api.ExtendedNexthopCapabilityTuple{
|
||||
NlriFamily: ToApiFamily(t.NLRIAFI, uint8(t.NLRISAFI)),
|
||||
NexthopFamily: ToApiFamily(t.NexthopAFI, bgp.SAFI_UNICAST),
|
||||
})
|
||||
}
|
||||
return &api.ExtendedNexthopCapability{
|
||||
Tuples: tuples,
|
||||
}
|
||||
}
|
||||
|
||||
func NewGracefulRestartCapability(a *bgp.CapGracefulRestart) *api.GracefulRestartCapability {
|
||||
tuples := make([]*api.GracefulRestartCapabilityTuple, 0, len(a.Tuples))
|
||||
for _, t := range a.Tuples {
|
||||
tuples = append(tuples, &api.GracefulRestartCapabilityTuple{
|
||||
Family: ToApiFamily(t.AFI, t.SAFI),
|
||||
Flags: uint32(t.Flags),
|
||||
})
|
||||
}
|
||||
return &api.GracefulRestartCapability{
|
||||
Flags: uint32(a.Flags),
|
||||
Time: uint32(a.Time),
|
||||
Tuples: tuples,
|
||||
}
|
||||
}
|
||||
|
||||
func NewFourOctetASNumberCapability(a *bgp.CapFourOctetASNumber) *api.FourOctetASNumberCapability {
|
||||
return &api.FourOctetASNumberCapability{
|
||||
As: a.CapValue,
|
||||
}
|
||||
}
|
||||
|
||||
func NewAddPathCapability(a *bgp.CapAddPath) *api.AddPathCapability {
|
||||
tuples := make([]*api.AddPathCapabilityTuple, 0, len(a.Tuples))
|
||||
for _, t := range a.Tuples {
|
||||
afi, safi := bgp.RouteFamilyToAfiSafi(t.RouteFamily)
|
||||
tuples = append(tuples, &api.AddPathCapabilityTuple{
|
||||
Family: ToApiFamily(afi, safi),
|
||||
Mode: api.AddPathMode(t.Mode),
|
||||
})
|
||||
}
|
||||
return &api.AddPathCapability{
|
||||
Tuples: tuples,
|
||||
}
|
||||
}
|
||||
|
||||
func NewEnhancedRouteRefreshCapability(a *bgp.CapEnhancedRouteRefresh) *api.EnhancedRouteRefreshCapability {
|
||||
return &api.EnhancedRouteRefreshCapability{}
|
||||
}
|
||||
|
||||
func NewLongLivedGracefulRestartCapability(a *bgp.CapLongLivedGracefulRestart) *api.LongLivedGracefulRestartCapability {
|
||||
tuples := make([]*api.LongLivedGracefulRestartCapabilityTuple, 0, len(a.Tuples))
|
||||
for _, t := range a.Tuples {
|
||||
tuples = append(tuples, &api.LongLivedGracefulRestartCapabilityTuple{
|
||||
Family: ToApiFamily(t.AFI, uint8(t.SAFI)),
|
||||
Flags: uint32(t.Flags),
|
||||
Time: t.RestartTime,
|
||||
})
|
||||
}
|
||||
return &api.LongLivedGracefulRestartCapability{
|
||||
Tuples: tuples,
|
||||
}
|
||||
}
|
||||
|
||||
func NewRouteRefreshCiscoCapability(a *bgp.CapRouteRefreshCisco) *api.RouteRefreshCiscoCapability {
|
||||
return &api.RouteRefreshCiscoCapability{}
|
||||
}
|
||||
|
||||
func NewUnknownCapability(a *bgp.CapUnknown) *api.UnknownCapability {
|
||||
return &api.UnknownCapability{
|
||||
Code: uint32(a.CapCode),
|
||||
Value: a.CapValue,
|
||||
}
|
||||
}
|
||||
|
||||
func MarshalCapability(value bgp.ParameterCapabilityInterface) (*any.Any, error) {
|
||||
var m proto.Message
|
||||
switch n := value.(type) {
|
||||
case *bgp.CapMultiProtocol:
|
||||
m = NewMultiProtocolCapability(n)
|
||||
case *bgp.CapRouteRefresh:
|
||||
m = NewRouteRefreshCapability(n)
|
||||
case *bgp.CapCarryingLabelInfo:
|
||||
m = NewCarryingLabelInfoCapability(n)
|
||||
case *bgp.CapExtendedNexthop:
|
||||
m = NewExtendedNexthopCapability(n)
|
||||
case *bgp.CapGracefulRestart:
|
||||
m = NewGracefulRestartCapability(n)
|
||||
case *bgp.CapFourOctetASNumber:
|
||||
m = NewFourOctetASNumberCapability(n)
|
||||
case *bgp.CapAddPath:
|
||||
m = NewAddPathCapability(n)
|
||||
case *bgp.CapEnhancedRouteRefresh:
|
||||
m = NewEnhancedRouteRefreshCapability(n)
|
||||
case *bgp.CapLongLivedGracefulRestart:
|
||||
m = NewLongLivedGracefulRestartCapability(n)
|
||||
case *bgp.CapRouteRefreshCisco:
|
||||
m = NewRouteRefreshCiscoCapability(n)
|
||||
case *bgp.CapUnknown:
|
||||
m = NewUnknownCapability(n)
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid capability type to marshal: %+v", value)
|
||||
}
|
||||
return ptypes.MarshalAny(m)
|
||||
}
|
||||
|
||||
func MarshalCapabilities(values []bgp.ParameterCapabilityInterface) ([]*any.Any, error) {
|
||||
caps := make([]*any.Any, 0, len(values))
|
||||
for _, value := range values {
|
||||
a, err := MarshalCapability(value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
caps = append(caps, a)
|
||||
}
|
||||
return caps, nil
|
||||
}
|
||||
|
||||
func unmarshalCapability(a *any.Any) (bgp.ParameterCapabilityInterface, error) {
|
||||
var value ptypes.DynamicAny
|
||||
if err := ptypes.UnmarshalAny(a, &value); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal capability: %s", err)
|
||||
}
|
||||
switch a := value.Message.(type) {
|
||||
case *api.MultiProtocolCapability:
|
||||
return bgp.NewCapMultiProtocol(ToRouteFamily(a.Family)), nil
|
||||
case *api.RouteRefreshCapability:
|
||||
return bgp.NewCapRouteRefresh(), nil
|
||||
case *api.CarryingLabelInfoCapability:
|
||||
return bgp.NewCapCarryingLabelInfo(), nil
|
||||
case *api.ExtendedNexthopCapability:
|
||||
tuples := make([]*bgp.CapExtendedNexthopTuple, 0, len(a.Tuples))
|
||||
for _, t := range a.Tuples {
|
||||
var nhAfi uint16
|
||||
switch t.NexthopFamily.Afi {
|
||||
case api.Family_AFI_IP:
|
||||
nhAfi = bgp.AFI_IP
|
||||
case api.Family_AFI_IP6:
|
||||
nhAfi = bgp.AFI_IP6
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid address family for nexthop afi in extended nexthop capability: %s", t.NexthopFamily)
|
||||
}
|
||||
tuples = append(tuples, bgp.NewCapExtendedNexthopTuple(ToRouteFamily(t.NlriFamily), nhAfi))
|
||||
}
|
||||
return bgp.NewCapExtendedNexthop(tuples), nil
|
||||
case *api.GracefulRestartCapability:
|
||||
tuples := make([]*bgp.CapGracefulRestartTuple, 0, len(a.Tuples))
|
||||
for _, t := range a.Tuples {
|
||||
var forward bool
|
||||
if t.Flags&0x80 > 0 {
|
||||
forward = true
|
||||
}
|
||||
tuples = append(tuples, bgp.NewCapGracefulRestartTuple(ToRouteFamily(t.Family), forward))
|
||||
}
|
||||
var restarting bool
|
||||
if a.Flags&0x08 > 0 {
|
||||
restarting = true
|
||||
}
|
||||
var notification bool
|
||||
if a.Flags&0x04 > 0 {
|
||||
notification = true
|
||||
}
|
||||
return bgp.NewCapGracefulRestart(restarting, notification, uint16(a.Time), tuples), nil
|
||||
case *api.FourOctetASNumberCapability:
|
||||
return bgp.NewCapFourOctetASNumber(a.As), nil
|
||||
case *api.AddPathCapability:
|
||||
tuples := make([]*bgp.CapAddPathTuple, 0, len(a.Tuples))
|
||||
for _, t := range a.Tuples {
|
||||
tuples = append(tuples, bgp.NewCapAddPathTuple(ToRouteFamily(t.Family), bgp.BGPAddPathMode(t.Mode)))
|
||||
}
|
||||
return bgp.NewCapAddPath(tuples), nil
|
||||
case *api.EnhancedRouteRefreshCapability:
|
||||
return bgp.NewCapEnhancedRouteRefresh(), nil
|
||||
case *api.LongLivedGracefulRestartCapability:
|
||||
tuples := make([]*bgp.CapLongLivedGracefulRestartTuple, 0, len(a.Tuples))
|
||||
for _, t := range a.Tuples {
|
||||
var forward bool
|
||||
if t.Flags&0x80 > 0 {
|
||||
forward = true
|
||||
}
|
||||
tuples = append(tuples, bgp.NewCapLongLivedGracefulRestartTuple(ToRouteFamily(t.Family), forward, t.Time))
|
||||
}
|
||||
return bgp.NewCapLongLivedGracefulRestart(tuples), nil
|
||||
case *api.RouteRefreshCiscoCapability:
|
||||
return bgp.NewCapRouteRefreshCisco(), nil
|
||||
case *api.UnknownCapability:
|
||||
return bgp.NewCapUnknown(bgp.BGPCapabilityCode(a.Code), a.Value), nil
|
||||
}
|
||||
return nil, fmt.Errorf("invalid capability type to unmarshal: %s", a.TypeUrl)
|
||||
}
|
||||
|
||||
func UnmarshalCapabilities(values []*any.Any) ([]bgp.ParameterCapabilityInterface, error) {
|
||||
caps := make([]bgp.ParameterCapabilityInterface, 0, len(values))
|
||||
for _, value := range values {
|
||||
c, err := unmarshalCapability(value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
caps = append(caps, c)
|
||||
}
|
||||
return caps, nil
|
||||
}
|
||||
125
vendor/github.com/osrg/gobgp/internal/pkg/apiutil/util.go
generated
vendored
Normal file
125
vendor/github.com/osrg/gobgp/internal/pkg/apiutil/util.go
generated
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
// Copyright (C) 2016 Nippon Telegraph and Telephone Corporation.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package apiutil
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
api "github.com/osrg/gobgp/api"
|
||||
"github.com/osrg/gobgp/pkg/packet/bgp"
|
||||
)
|
||||
|
||||
// workaround. This for the json format compatibility. Once we update senario tests, we can remove this.
|
||||
type Path struct {
|
||||
Nlri bgp.AddrPrefixInterface `json:"nlri"`
|
||||
Age int64 `json:"age"`
|
||||
Best bool `json:"best"`
|
||||
Attrs []bgp.PathAttributeInterface `json:"attrs"`
|
||||
Stale bool `json:"stale"`
|
||||
Withdrawal bool `json:"withdrawal,omitempty"`
|
||||
SourceID net.IP `json:"source-id,omitempty"`
|
||||
NeighborIP net.IP `json:"neighbor-ip,omitempty"`
|
||||
}
|
||||
|
||||
type Destination struct {
|
||||
Paths []*Path
|
||||
}
|
||||
|
||||
func (d *Destination) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(d.Paths)
|
||||
}
|
||||
|
||||
func NewDestination(dst *api.Destination) *Destination {
|
||||
l := make([]*Path, 0, len(dst.Paths))
|
||||
for _, p := range dst.Paths {
|
||||
nlri, _ := GetNativeNlri(p)
|
||||
attrs, _ := GetNativePathAttributes(p)
|
||||
l = append(l, &Path{
|
||||
Nlri: nlri,
|
||||
Age: p.Age,
|
||||
Best: p.Best,
|
||||
Attrs: attrs,
|
||||
Stale: p.Stale,
|
||||
Withdrawal: p.IsWithdraw,
|
||||
SourceID: net.ParseIP(p.SourceId),
|
||||
NeighborIP: net.ParseIP(p.NeighborIp),
|
||||
})
|
||||
}
|
||||
return &Destination{Paths: l}
|
||||
}
|
||||
|
||||
func NewPath(nlri bgp.AddrPrefixInterface, isWithdraw bool, attrs []bgp.PathAttributeInterface, age time.Time) *api.Path {
|
||||
return &api.Path{
|
||||
AnyNlri: MarshalNLRI(nlri),
|
||||
AnyPattrs: MarshalPathAttributes(attrs),
|
||||
Age: age.Unix(),
|
||||
IsWithdraw: isWithdraw,
|
||||
Family: ToApiFamily(nlri.AFI(), nlri.SAFI()),
|
||||
Identifier: nlri.PathIdentifier(),
|
||||
}
|
||||
}
|
||||
|
||||
func getNLRI(family bgp.RouteFamily, buf []byte) (bgp.AddrPrefixInterface, error) {
|
||||
afi, safi := bgp.RouteFamilyToAfiSafi(family)
|
||||
nlri, err := bgp.NewPrefixFromRouteFamily(afi, safi)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := nlri.DecodeFromBytes(buf); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nlri, nil
|
||||
}
|
||||
|
||||
func GetNativeNlri(p *api.Path) (bgp.AddrPrefixInterface, error) {
|
||||
if len(p.Nlri) > 0 {
|
||||
return getNLRI(ToRouteFamily(p.Family), p.Nlri)
|
||||
}
|
||||
return UnmarshalNLRI(ToRouteFamily(p.Family), p.AnyNlri)
|
||||
}
|
||||
|
||||
func GetNativePathAttributes(p *api.Path) ([]bgp.PathAttributeInterface, error) {
|
||||
pattrsLen := len(p.Pattrs)
|
||||
if pattrsLen > 0 {
|
||||
pattrs := make([]bgp.PathAttributeInterface, 0, pattrsLen)
|
||||
for _, attr := range p.Pattrs {
|
||||
a, err := bgp.GetPathAttribute(attr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = a.DecodeFromBytes(attr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pattrs = append(pattrs, a)
|
||||
}
|
||||
return pattrs, nil
|
||||
}
|
||||
return UnmarshalPathAttributes(p.AnyPattrs)
|
||||
}
|
||||
|
||||
func ToRouteFamily(f *api.Family) bgp.RouteFamily {
|
||||
return bgp.AfiSafiToRouteFamily(uint16(f.Afi), uint8(f.Safi))
|
||||
}
|
||||
|
||||
func ToApiFamily(afi uint16, safi uint8) *api.Family {
|
||||
return &api.Family{
|
||||
Afi: api.Family_Afi(afi),
|
||||
Safi: api.Family_Safi(safi),
|
||||
}
|
||||
}
|
||||
6335
vendor/github.com/osrg/gobgp/internal/pkg/config/bgp_configs.go
generated
vendored
Normal file
6335
vendor/github.com/osrg/gobgp/internal/pkg/config/bgp_configs.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
524
vendor/github.com/osrg/gobgp/internal/pkg/config/default.go
generated
vendored
Normal file
524
vendor/github.com/osrg/gobgp/internal/pkg/config/default.go
generated
vendored
Normal file
@@ -0,0 +1,524 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"math"
|
||||
"net"
|
||||
"reflect"
|
||||
"strconv"
|
||||
|
||||
"github.com/osrg/gobgp/pkg/packet/bgp"
|
||||
"github.com/osrg/gobgp/pkg/packet/bmp"
|
||||
"github.com/osrg/gobgp/pkg/packet/rtr"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
const (
|
||||
DEFAULT_HOLDTIME = 90
|
||||
DEFAULT_IDLE_HOLDTIME_AFTER_RESET = 30
|
||||
DEFAULT_CONNECT_RETRY = 120
|
||||
)
|
||||
|
||||
var forcedOverwrittenConfig = []string{
|
||||
"neighbor.config.peer-as",
|
||||
"neighbor.timers.config.minimum-advertisement-interval",
|
||||
}
|
||||
|
||||
var configuredFields map[string]interface{}
|
||||
|
||||
func RegisterConfiguredFields(addr string, n interface{}) {
|
||||
if configuredFields == nil {
|
||||
configuredFields = make(map[string]interface{})
|
||||
}
|
||||
configuredFields[addr] = n
|
||||
}
|
||||
|
||||
func defaultAfiSafi(typ AfiSafiType, enable bool) AfiSafi {
|
||||
return AfiSafi{
|
||||
Config: AfiSafiConfig{
|
||||
AfiSafiName: typ,
|
||||
Enabled: enable,
|
||||
},
|
||||
State: AfiSafiState{
|
||||
AfiSafiName: typ,
|
||||
Family: bgp.AddressFamilyValueMap[string(typ)],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func SetDefaultNeighborConfigValues(n *Neighbor, pg *PeerGroup, g *Global) error {
|
||||
// Determines this function is called against the same Neighbor struct,
|
||||
// and if already called, returns immediately.
|
||||
if n.State.LocalAs != 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return setDefaultNeighborConfigValuesWithViper(nil, n, g, pg)
|
||||
}
|
||||
|
||||
func setDefaultNeighborConfigValuesWithViper(v *viper.Viper, n *Neighbor, g *Global, pg *PeerGroup) error {
|
||||
if n == nil {
|
||||
return fmt.Errorf("neighbor config is nil")
|
||||
}
|
||||
if g == nil {
|
||||
return fmt.Errorf("global config is nil")
|
||||
}
|
||||
|
||||
if v == nil {
|
||||
v = viper.New()
|
||||
}
|
||||
|
||||
if pg != nil {
|
||||
if err := OverwriteNeighborConfigWithPeerGroup(n, pg); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if n.Config.LocalAs == 0 {
|
||||
n.Config.LocalAs = g.Config.As
|
||||
if !g.Confederation.Config.Enabled || n.IsConfederation(g) {
|
||||
n.Config.LocalAs = g.Config.As
|
||||
} else {
|
||||
n.Config.LocalAs = g.Confederation.Config.Identifier
|
||||
}
|
||||
}
|
||||
n.State.LocalAs = n.Config.LocalAs
|
||||
|
||||
if n.Config.PeerAs != n.Config.LocalAs {
|
||||
n.Config.PeerType = PEER_TYPE_EXTERNAL
|
||||
n.State.PeerType = PEER_TYPE_EXTERNAL
|
||||
n.State.RemovePrivateAs = n.Config.RemovePrivateAs
|
||||
n.AsPathOptions.State.ReplacePeerAs = n.AsPathOptions.Config.ReplacePeerAs
|
||||
} else {
|
||||
n.Config.PeerType = PEER_TYPE_INTERNAL
|
||||
n.State.PeerType = PEER_TYPE_INTERNAL
|
||||
if string(n.Config.RemovePrivateAs) != "" {
|
||||
return fmt.Errorf("can't set remove-private-as for iBGP peer")
|
||||
}
|
||||
if n.AsPathOptions.Config.ReplacePeerAs {
|
||||
return fmt.Errorf("can't set replace-peer-as for iBGP peer")
|
||||
}
|
||||
}
|
||||
|
||||
if n.State.NeighborAddress == "" {
|
||||
n.State.NeighborAddress = n.Config.NeighborAddress
|
||||
}
|
||||
|
||||
n.State.PeerAs = n.Config.PeerAs
|
||||
n.AsPathOptions.State.AllowOwnAs = n.AsPathOptions.Config.AllowOwnAs
|
||||
|
||||
if !v.IsSet("neighbor.error-handling.config.treat-as-withdraw") {
|
||||
n.ErrorHandling.Config.TreatAsWithdraw = true
|
||||
}
|
||||
|
||||
if !v.IsSet("neighbor.timers.config.connect-retry") && n.Timers.Config.ConnectRetry == 0 {
|
||||
n.Timers.Config.ConnectRetry = float64(DEFAULT_CONNECT_RETRY)
|
||||
}
|
||||
if !v.IsSet("neighbor.timers.config.hold-time") && n.Timers.Config.HoldTime == 0 {
|
||||
n.Timers.Config.HoldTime = float64(DEFAULT_HOLDTIME)
|
||||
}
|
||||
if !v.IsSet("neighbor.timers.config.keepalive-interval") && n.Timers.Config.KeepaliveInterval == 0 {
|
||||
n.Timers.Config.KeepaliveInterval = n.Timers.Config.HoldTime / 3
|
||||
}
|
||||
if !v.IsSet("neighbor.timers.config.idle-hold-time-after-reset") && n.Timers.Config.IdleHoldTimeAfterReset == 0 {
|
||||
n.Timers.Config.IdleHoldTimeAfterReset = float64(DEFAULT_IDLE_HOLDTIME_AFTER_RESET)
|
||||
}
|
||||
|
||||
if n.Config.NeighborInterface != "" {
|
||||
if n.RouteServer.Config.RouteServerClient {
|
||||
return fmt.Errorf("configuring route server client as unnumbered peer is not supported")
|
||||
}
|
||||
addr, err := GetIPv6LinkLocalNeighborAddress(n.Config.NeighborInterface)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
n.State.NeighborAddress = addr
|
||||
}
|
||||
|
||||
if n.Transport.Config.LocalAddress == "" {
|
||||
if n.State.NeighborAddress == "" {
|
||||
return fmt.Errorf("no neighbor address/interface specified")
|
||||
}
|
||||
ipAddr, err := net.ResolveIPAddr("ip", n.State.NeighborAddress)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
localAddress := "0.0.0.0"
|
||||
if ipAddr.IP.To4() == nil {
|
||||
localAddress = "::"
|
||||
if ipAddr.Zone != "" {
|
||||
localAddress, err = getIPv6LinkLocalAddress(ipAddr.Zone)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
n.Transport.Config.LocalAddress = localAddress
|
||||
}
|
||||
|
||||
if len(n.AfiSafis) == 0 {
|
||||
if n.Config.NeighborInterface != "" {
|
||||
n.AfiSafis = []AfiSafi{
|
||||
defaultAfiSafi(AFI_SAFI_TYPE_IPV4_UNICAST, true),
|
||||
defaultAfiSafi(AFI_SAFI_TYPE_IPV6_UNICAST, true),
|
||||
}
|
||||
} else if ipAddr, err := net.ResolveIPAddr("ip", n.State.NeighborAddress); err != nil {
|
||||
return fmt.Errorf("invalid neighbor address: %s", n.State.NeighborAddress)
|
||||
} else if ipAddr.IP.To4() != nil {
|
||||
n.AfiSafis = []AfiSafi{defaultAfiSafi(AFI_SAFI_TYPE_IPV4_UNICAST, true)}
|
||||
} else {
|
||||
n.AfiSafis = []AfiSafi{defaultAfiSafi(AFI_SAFI_TYPE_IPV6_UNICAST, true)}
|
||||
}
|
||||
for i := range n.AfiSafis {
|
||||
n.AfiSafis[i].AddPaths.Config.Receive = n.AddPaths.Config.Receive
|
||||
n.AfiSafis[i].AddPaths.State.Receive = n.AddPaths.Config.Receive
|
||||
n.AfiSafis[i].AddPaths.Config.SendMax = n.AddPaths.Config.SendMax
|
||||
n.AfiSafis[i].AddPaths.State.SendMax = n.AddPaths.Config.SendMax
|
||||
}
|
||||
} else {
|
||||
afs, err := extractArray(v.Get("neighbor.afi-safis"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for i := range n.AfiSafis {
|
||||
vv := viper.New()
|
||||
if len(afs) > i {
|
||||
vv.Set("afi-safi", afs[i])
|
||||
}
|
||||
rf, err := bgp.GetRouteFamily(string(n.AfiSafis[i].Config.AfiSafiName))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
n.AfiSafis[i].State.Family = rf
|
||||
n.AfiSafis[i].State.AfiSafiName = n.AfiSafis[i].Config.AfiSafiName
|
||||
if !vv.IsSet("afi-safi.config.enabled") {
|
||||
n.AfiSafis[i].Config.Enabled = true
|
||||
}
|
||||
n.AfiSafis[i].MpGracefulRestart.State.Enabled = n.AfiSafis[i].MpGracefulRestart.Config.Enabled
|
||||
if !vv.IsSet("afi-safi.add-paths.config.receive") {
|
||||
n.AfiSafis[i].AddPaths.Config.Receive = n.AddPaths.Config.Receive
|
||||
}
|
||||
n.AfiSafis[i].AddPaths.State.Receive = n.AfiSafis[i].AddPaths.Config.Receive
|
||||
if !vv.IsSet("afi-safi.add-paths.config.send-max") {
|
||||
n.AfiSafis[i].AddPaths.Config.SendMax = n.AddPaths.Config.SendMax
|
||||
}
|
||||
n.AfiSafis[i].AddPaths.State.SendMax = n.AfiSafis[i].AddPaths.Config.SendMax
|
||||
}
|
||||
}
|
||||
|
||||
n.State.Description = n.Config.Description
|
||||
n.State.AdminDown = n.Config.AdminDown
|
||||
|
||||
if n.GracefulRestart.Config.Enabled {
|
||||
if !v.IsSet("neighbor.graceful-restart.config.restart-time") && n.GracefulRestart.Config.RestartTime == 0 {
|
||||
// RFC 4724 4. Operation
|
||||
// A suggested default for the Restart Time is a value less than or
|
||||
// equal to the HOLDTIME carried in the OPEN.
|
||||
n.GracefulRestart.Config.RestartTime = uint16(n.Timers.Config.HoldTime)
|
||||
}
|
||||
if !v.IsSet("neighbor.graceful-restart.config.deferral-time") && n.GracefulRestart.Config.DeferralTime == 0 {
|
||||
// RFC 4724 4.1. Procedures for the Restarting Speaker
|
||||
// The value of this timer should be large
|
||||
// enough, so as to provide all the peers of the Restarting Speaker with
|
||||
// enough time to send all the routes to the Restarting Speaker
|
||||
n.GracefulRestart.Config.DeferralTime = uint16(360)
|
||||
}
|
||||
}
|
||||
|
||||
if n.EbgpMultihop.Config.Enabled {
|
||||
if n.TtlSecurity.Config.Enabled {
|
||||
return fmt.Errorf("ebgp-multihop and ttl-security are mututally exclusive")
|
||||
}
|
||||
if n.EbgpMultihop.Config.MultihopTtl == 0 {
|
||||
n.EbgpMultihop.Config.MultihopTtl = 255
|
||||
}
|
||||
} else if n.TtlSecurity.Config.Enabled {
|
||||
if n.TtlSecurity.Config.TtlMin == 0 {
|
||||
n.TtlSecurity.Config.TtlMin = 255
|
||||
}
|
||||
}
|
||||
|
||||
if n.RouteReflector.Config.RouteReflectorClient {
|
||||
if n.RouteReflector.Config.RouteReflectorClusterId == "" {
|
||||
n.RouteReflector.State.RouteReflectorClusterId = RrClusterIdType(g.Config.RouterId)
|
||||
} else {
|
||||
id := string(n.RouteReflector.Config.RouteReflectorClusterId)
|
||||
if ip := net.ParseIP(id).To4(); ip != nil {
|
||||
n.RouteReflector.State.RouteReflectorClusterId = n.RouteReflector.Config.RouteReflectorClusterId
|
||||
} else if num, err := strconv.ParseUint(id, 10, 32); err == nil {
|
||||
ip = make(net.IP, 4)
|
||||
binary.BigEndian.PutUint32(ip, uint32(num))
|
||||
n.RouteReflector.State.RouteReflectorClusterId = RrClusterIdType(ip.String())
|
||||
} else {
|
||||
return fmt.Errorf("route-reflector-cluster-id should be specified as IPv4 address or 32-bit unsigned integer")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func SetDefaultGlobalConfigValues(g *Global) error {
|
||||
if len(g.AfiSafis) == 0 {
|
||||
g.AfiSafis = []AfiSafi{}
|
||||
for k := range AfiSafiTypeToIntMap {
|
||||
g.AfiSafis = append(g.AfiSafis, defaultAfiSafi(k, true))
|
||||
}
|
||||
}
|
||||
|
||||
if g.Config.Port == 0 {
|
||||
g.Config.Port = bgp.BGP_PORT
|
||||
}
|
||||
|
||||
if len(g.Config.LocalAddressList) == 0 {
|
||||
g.Config.LocalAddressList = []string{"0.0.0.0", "::"}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func setDefaultVrfConfigValues(v *Vrf) error {
|
||||
if v == nil {
|
||||
return fmt.Errorf("cannot set default values for nil vrf config")
|
||||
}
|
||||
|
||||
if v.Config.Name == "" {
|
||||
return fmt.Errorf("specify vrf name")
|
||||
}
|
||||
|
||||
_, err := bgp.ParseRouteDistinguisher(v.Config.Rd)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid rd for vrf %s: %s", v.Config.Name, v.Config.Rd)
|
||||
}
|
||||
|
||||
if len(v.Config.ImportRtList) == 0 {
|
||||
v.Config.ImportRtList = v.Config.BothRtList
|
||||
}
|
||||
for _, rtString := range v.Config.ImportRtList {
|
||||
_, err := bgp.ParseRouteTarget(rtString)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid import rt for vrf %s: %s", v.Config.Name, rtString)
|
||||
}
|
||||
}
|
||||
|
||||
if len(v.Config.ExportRtList) == 0 {
|
||||
v.Config.ExportRtList = v.Config.BothRtList
|
||||
}
|
||||
for _, rtString := range v.Config.ExportRtList {
|
||||
_, err := bgp.ParseRouteTarget(rtString)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid export rt for vrf %s: %s", v.Config.Name, rtString)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func SetDefaultConfigValues(b *BgpConfigSet) error {
|
||||
return setDefaultConfigValuesWithViper(nil, b)
|
||||
}
|
||||
|
||||
func setDefaultPolicyConfigValuesWithViper(v *viper.Viper, p *PolicyDefinition) error {
|
||||
stmts, err := extractArray(v.Get("policy.statements"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for i := range p.Statements {
|
||||
vv := viper.New()
|
||||
if len(stmts) > i {
|
||||
vv.Set("statement", stmts[i])
|
||||
}
|
||||
if !vv.IsSet("statement.actions.route-disposition") {
|
||||
p.Statements[i].Actions.RouteDisposition = ROUTE_DISPOSITION_NONE
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func setDefaultConfigValuesWithViper(v *viper.Viper, b *BgpConfigSet) error {
|
||||
if v == nil {
|
||||
v = viper.New()
|
||||
}
|
||||
|
||||
if err := SetDefaultGlobalConfigValues(&b.Global); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for idx, server := range b.BmpServers {
|
||||
if server.Config.Port == 0 {
|
||||
server.Config.Port = bmp.BMP_DEFAULT_PORT
|
||||
}
|
||||
if server.Config.RouteMonitoringPolicy == "" {
|
||||
server.Config.RouteMonitoringPolicy = BMP_ROUTE_MONITORING_POLICY_TYPE_PRE_POLICY
|
||||
}
|
||||
// statistics-timeout is uint16 value and implicitly less than 65536
|
||||
if server.Config.StatisticsTimeout != 0 && server.Config.StatisticsTimeout < 15 {
|
||||
return fmt.Errorf("too small statistics-timeout value: %d", server.Config.StatisticsTimeout)
|
||||
}
|
||||
b.BmpServers[idx] = server
|
||||
}
|
||||
|
||||
vrfNames := make(map[string]struct{})
|
||||
vrfIDs := make(map[uint32]struct{})
|
||||
for idx, vrf := range b.Vrfs {
|
||||
if err := setDefaultVrfConfigValues(&vrf); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, ok := vrfNames[vrf.Config.Name]; ok {
|
||||
return fmt.Errorf("duplicated vrf name: %s", vrf.Config.Name)
|
||||
}
|
||||
vrfNames[vrf.Config.Name] = struct{}{}
|
||||
|
||||
if vrf.Config.Id != 0 {
|
||||
if _, ok := vrfIDs[vrf.Config.Id]; ok {
|
||||
return fmt.Errorf("duplicated vrf id: %d", vrf.Config.Id)
|
||||
}
|
||||
vrfIDs[vrf.Config.Id] = struct{}{}
|
||||
}
|
||||
|
||||
b.Vrfs[idx] = vrf
|
||||
}
|
||||
// Auto assign VRF identifier
|
||||
for idx, vrf := range b.Vrfs {
|
||||
if vrf.Config.Id == 0 {
|
||||
for id := uint32(1); id < math.MaxUint32; id++ {
|
||||
if _, ok := vrfIDs[id]; !ok {
|
||||
vrf.Config.Id = id
|
||||
vrfIDs[id] = struct{}{}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
b.Vrfs[idx] = vrf
|
||||
}
|
||||
|
||||
if b.Zebra.Config.Url == "" {
|
||||
b.Zebra.Config.Url = "unix:/var/run/quagga/zserv.api"
|
||||
}
|
||||
if b.Zebra.Config.Version < 2 {
|
||||
b.Zebra.Config.Version = 2
|
||||
} else if b.Zebra.Config.Version > 5 {
|
||||
b.Zebra.Config.Version = 5
|
||||
}
|
||||
if !v.IsSet("zebra.config.nexthop-trigger-enable") && !b.Zebra.Config.NexthopTriggerEnable && b.Zebra.Config.Version > 2 {
|
||||
b.Zebra.Config.NexthopTriggerEnable = true
|
||||
}
|
||||
if b.Zebra.Config.NexthopTriggerDelay == 0 {
|
||||
b.Zebra.Config.NexthopTriggerDelay = 5
|
||||
}
|
||||
|
||||
list, err := extractArray(v.Get("neighbors"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for idx, n := range b.Neighbors {
|
||||
vv := viper.New()
|
||||
if len(list) > idx {
|
||||
vv.Set("neighbor", list[idx])
|
||||
}
|
||||
|
||||
pg, err := b.getPeerGroup(n.Config.PeerGroup)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if pg != nil {
|
||||
identifier := vv.Get("neighbor.config.neighbor-address")
|
||||
if identifier == nil {
|
||||
identifier = vv.Get("neighbor.config.neighbor-interface")
|
||||
}
|
||||
RegisterConfiguredFields(identifier.(string), list[idx])
|
||||
}
|
||||
|
||||
if err := setDefaultNeighborConfigValuesWithViper(vv, &n, &b.Global, pg); err != nil {
|
||||
return err
|
||||
}
|
||||
b.Neighbors[idx] = n
|
||||
}
|
||||
|
||||
for _, d := range b.DynamicNeighbors {
|
||||
if err := d.validate(b); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
for idx, r := range b.RpkiServers {
|
||||
if r.Config.Port == 0 {
|
||||
b.RpkiServers[idx].Config.Port = rtr.RPKI_DEFAULT_PORT
|
||||
}
|
||||
}
|
||||
|
||||
list, err = extractArray(v.Get("policy-definitions"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for idx, p := range b.PolicyDefinitions {
|
||||
vv := viper.New()
|
||||
if len(list) > idx {
|
||||
vv.Set("policy", list[idx])
|
||||
}
|
||||
if err := setDefaultPolicyConfigValuesWithViper(vv, &p); err != nil {
|
||||
return err
|
||||
}
|
||||
b.PolicyDefinitions[idx] = p
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func OverwriteNeighborConfigWithPeerGroup(c *Neighbor, pg *PeerGroup) error {
|
||||
v := viper.New()
|
||||
|
||||
val, ok := configuredFields[c.Config.NeighborAddress]
|
||||
if ok {
|
||||
v.Set("neighbor", val)
|
||||
} else {
|
||||
v.Set("neighbor.config.peer-group", c.Config.PeerGroup)
|
||||
}
|
||||
|
||||
overwriteConfig(&c.Config, &pg.Config, "neighbor.config", v)
|
||||
overwriteConfig(&c.Timers.Config, &pg.Timers.Config, "neighbor.timers.config", v)
|
||||
overwriteConfig(&c.Transport.Config, &pg.Transport.Config, "neighbor.transport.config", v)
|
||||
overwriteConfig(&c.ErrorHandling.Config, &pg.ErrorHandling.Config, "neighbor.error-handling.config", v)
|
||||
overwriteConfig(&c.LoggingOptions.Config, &pg.LoggingOptions.Config, "neighbor.logging-options.config", v)
|
||||
overwriteConfig(&c.EbgpMultihop.Config, &pg.EbgpMultihop.Config, "neighbor.ebgp-multihop.config", v)
|
||||
overwriteConfig(&c.RouteReflector.Config, &pg.RouteReflector.Config, "neighbor.route-reflector.config", v)
|
||||
overwriteConfig(&c.AsPathOptions.Config, &pg.AsPathOptions.Config, "neighbor.as-path-options.config", v)
|
||||
overwriteConfig(&c.AddPaths.Config, &pg.AddPaths.Config, "neighbor.add-paths.config", v)
|
||||
overwriteConfig(&c.GracefulRestart.Config, &pg.GracefulRestart.Config, "neighbor.gradeful-restart.config", v)
|
||||
overwriteConfig(&c.ApplyPolicy.Config, &pg.ApplyPolicy.Config, "neighbor.apply-policy.config", v)
|
||||
overwriteConfig(&c.UseMultiplePaths.Config, &pg.UseMultiplePaths.Config, "neighbor.use-multiple-paths.config", v)
|
||||
overwriteConfig(&c.RouteServer.Config, &pg.RouteServer.Config, "neighbor.route-server.config", v)
|
||||
overwriteConfig(&c.TtlSecurity.Config, &pg.TtlSecurity.Config, "neighbor.ttl-security.config", v)
|
||||
|
||||
if !v.IsSet("neighbor.afi-safis") {
|
||||
c.AfiSafis = append(c.AfiSafis, pg.AfiSafis...)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func overwriteConfig(c, pg interface{}, tagPrefix string, v *viper.Viper) {
|
||||
nValue := reflect.Indirect(reflect.ValueOf(c))
|
||||
nType := reflect.Indirect(nValue).Type()
|
||||
pgValue := reflect.Indirect(reflect.ValueOf(pg))
|
||||
pgType := reflect.Indirect(pgValue).Type()
|
||||
|
||||
for i := 0; i < pgType.NumField(); i++ {
|
||||
field := pgType.Field(i).Name
|
||||
tag := tagPrefix + "." + nType.Field(i).Tag.Get("mapstructure")
|
||||
if func() bool {
|
||||
for _, t := range forcedOverwrittenConfig {
|
||||
if t == tag {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}() || !v.IsSet(tag) {
|
||||
nValue.FieldByName(field).Set(pgValue.FieldByName(field))
|
||||
}
|
||||
}
|
||||
}
|
||||
72
vendor/github.com/osrg/gobgp/internal/pkg/config/default_linux.go
generated
vendored
Normal file
72
vendor/github.com/osrg/gobgp/internal/pkg/config/default_linux.go
generated
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
// Copyright (C) 2016 Nippon Telegraph and Telephone Corporation.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// +build linux
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
func GetIPv6LinkLocalNeighborAddress(ifname string) (string, error) {
|
||||
ifi, err := net.InterfaceByName(ifname)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
neighs, err := netlink.NeighList(ifi.Index, netlink.FAMILY_V6)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
cnt := 0
|
||||
var addr net.IP
|
||||
for _, neigh := range neighs {
|
||||
local, err := isLocalLinkLocalAddress(ifi.Index, neigh.IP)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if neigh.State&netlink.NUD_FAILED == 0 && neigh.IP.IsLinkLocalUnicast() && !local {
|
||||
addr = neigh.IP
|
||||
cnt++
|
||||
}
|
||||
}
|
||||
|
||||
if cnt == 0 {
|
||||
return "", fmt.Errorf("no ipv6 link-local neighbor found")
|
||||
} else if cnt > 1 {
|
||||
return "", fmt.Errorf("found %d link-local neighbors. only support p2p link", cnt)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s%%%s", addr, ifname), nil
|
||||
}
|
||||
|
||||
func isLocalLinkLocalAddress(ifindex int, addr net.IP) (bool, error) {
|
||||
ifi, err := net.InterfaceByIndex(ifindex)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
addrs, err := ifi.Addrs()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
for _, a := range addrs {
|
||||
if ip, _, _ := net.ParseCIDR(a.String()); addr.Equal(ip) {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
25
vendor/github.com/osrg/gobgp/internal/pkg/config/default_nonlinux.go
generated
vendored
Normal file
25
vendor/github.com/osrg/gobgp/internal/pkg/config/default_nonlinux.go
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
// Copyright (C) 2016 Nippon Telegraph and Telephone Corporation.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// +build !linux
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func GetIPv6LinkLocalNeighborAddress(ifname string) (string, error) {
|
||||
return "", fmt.Errorf("unnumbered peering is not supported")
|
||||
}
|
||||
159
vendor/github.com/osrg/gobgp/internal/pkg/config/serve.go
generated
vendored
Normal file
159
vendor/github.com/osrg/gobgp/internal/pkg/config/serve.go
generated
vendored
Normal file
@@ -0,0 +1,159 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
type BgpConfigSet struct {
|
||||
Global Global `mapstructure:"global"`
|
||||
Neighbors []Neighbor `mapstructure:"neighbors"`
|
||||
PeerGroups []PeerGroup `mapstructure:"peer-groups"`
|
||||
RpkiServers []RpkiServer `mapstructure:"rpki-servers"`
|
||||
BmpServers []BmpServer `mapstructure:"bmp-servers"`
|
||||
Vrfs []Vrf `mapstructure:"vrfs"`
|
||||
MrtDump []Mrt `mapstructure:"mrt-dump"`
|
||||
Zebra Zebra `mapstructure:"zebra"`
|
||||
Collector Collector `mapstructure:"collector"`
|
||||
DefinedSets DefinedSets `mapstructure:"defined-sets"`
|
||||
PolicyDefinitions []PolicyDefinition `mapstructure:"policy-definitions"`
|
||||
DynamicNeighbors []DynamicNeighbor `mapstructure:"dynamic-neighbors"`
|
||||
}
|
||||
|
||||
func ReadConfigfileServe(path, format string, configCh chan *BgpConfigSet) {
|
||||
sigCh := make(chan os.Signal, 1)
|
||||
signal.Notify(sigCh, syscall.SIGHUP)
|
||||
|
||||
// Update config file type, if detectable
|
||||
format = detectConfigFileType(path, format)
|
||||
|
||||
cnt := 0
|
||||
for {
|
||||
c := &BgpConfigSet{}
|
||||
v := viper.New()
|
||||
v.SetConfigFile(path)
|
||||
v.SetConfigType(format)
|
||||
var err error
|
||||
if err = v.ReadInConfig(); err != nil {
|
||||
goto ERROR
|
||||
}
|
||||
if err = v.UnmarshalExact(c); err != nil {
|
||||
goto ERROR
|
||||
}
|
||||
if err = setDefaultConfigValuesWithViper(v, c); err != nil {
|
||||
goto ERROR
|
||||
}
|
||||
if cnt == 0 {
|
||||
log.WithFields(log.Fields{
|
||||
"Topic": "Config",
|
||||
}).Info("Finished reading the config file")
|
||||
}
|
||||
cnt++
|
||||
configCh <- c
|
||||
goto NEXT
|
||||
ERROR:
|
||||
if cnt == 0 {
|
||||
log.WithFields(log.Fields{
|
||||
"Topic": "Config",
|
||||
"Error": err,
|
||||
}).Fatalf("Can't read config file %s", path)
|
||||
} else {
|
||||
log.WithFields(log.Fields{
|
||||
"Topic": "Config",
|
||||
"Error": err,
|
||||
}).Warningf("Can't read config file %s", path)
|
||||
}
|
||||
NEXT:
|
||||
<-sigCh
|
||||
log.WithFields(log.Fields{
|
||||
"Topic": "Config",
|
||||
}).Info("Reload the config file")
|
||||
}
|
||||
}
|
||||
|
||||
func ConfigSetToRoutingPolicy(c *BgpConfigSet) *RoutingPolicy {
|
||||
return &RoutingPolicy{
|
||||
DefinedSets: c.DefinedSets,
|
||||
PolicyDefinitions: c.PolicyDefinitions,
|
||||
}
|
||||
}
|
||||
|
||||
func UpdatePeerGroupConfig(curC, newC *BgpConfigSet) ([]PeerGroup, []PeerGroup, []PeerGroup) {
|
||||
addedPg := []PeerGroup{}
|
||||
deletedPg := []PeerGroup{}
|
||||
updatedPg := []PeerGroup{}
|
||||
|
||||
for _, n := range newC.PeerGroups {
|
||||
if idx := existPeerGroup(n.Config.PeerGroupName, curC.PeerGroups); idx < 0 {
|
||||
addedPg = append(addedPg, n)
|
||||
} else if !n.Equal(&curC.PeerGroups[idx]) {
|
||||
log.WithFields(log.Fields{
|
||||
"Topic": "Config",
|
||||
}).Debugf("Current peer-group config:%v", curC.PeerGroups[idx])
|
||||
log.WithFields(log.Fields{
|
||||
"Topic": "Config",
|
||||
}).Debugf("New peer-group config:%v", n)
|
||||
updatedPg = append(updatedPg, n)
|
||||
}
|
||||
}
|
||||
|
||||
for _, n := range curC.PeerGroups {
|
||||
if existPeerGroup(n.Config.PeerGroupName, newC.PeerGroups) < 0 {
|
||||
deletedPg = append(deletedPg, n)
|
||||
}
|
||||
}
|
||||
return addedPg, deletedPg, updatedPg
|
||||
}
|
||||
|
||||
func UpdateNeighborConfig(curC, newC *BgpConfigSet) ([]Neighbor, []Neighbor, []Neighbor) {
|
||||
added := []Neighbor{}
|
||||
deleted := []Neighbor{}
|
||||
updated := []Neighbor{}
|
||||
|
||||
for _, n := range newC.Neighbors {
|
||||
if idx := inSlice(n, curC.Neighbors); idx < 0 {
|
||||
added = append(added, n)
|
||||
} else if !n.Equal(&curC.Neighbors[idx]) {
|
||||
log.WithFields(log.Fields{
|
||||
"Topic": "Config",
|
||||
}).Debugf("Current neighbor config:%v", curC.Neighbors[idx])
|
||||
log.WithFields(log.Fields{
|
||||
"Topic": "Config",
|
||||
}).Debugf("New neighbor config:%v", n)
|
||||
updated = append(updated, n)
|
||||
}
|
||||
}
|
||||
|
||||
for _, n := range curC.Neighbors {
|
||||
if inSlice(n, newC.Neighbors) < 0 {
|
||||
deleted = append(deleted, n)
|
||||
}
|
||||
}
|
||||
return added, deleted, updated
|
||||
}
|
||||
|
||||
func CheckPolicyDifference(currentPolicy *RoutingPolicy, newPolicy *RoutingPolicy) bool {
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"Topic": "Config",
|
||||
}).Debugf("Current policy:%v", currentPolicy)
|
||||
log.WithFields(log.Fields{
|
||||
"Topic": "Config",
|
||||
}).Debugf("New policy:%v", newPolicy)
|
||||
|
||||
var result bool
|
||||
if currentPolicy == nil && newPolicy == nil {
|
||||
result = false
|
||||
} else {
|
||||
if currentPolicy != nil && newPolicy != nil {
|
||||
result = !currentPolicy.Equal(newPolicy)
|
||||
} else {
|
||||
result = true
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
264
vendor/github.com/osrg/gobgp/internal/pkg/config/util.go
generated
vendored
Normal file
264
vendor/github.com/osrg/gobgp/internal/pkg/config/util.go
generated
vendored
Normal file
@@ -0,0 +1,264 @@
|
||||
// Copyright (C) 2015 Nippon Telegraph and Telephone Corporation.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
||||
"github.com/osrg/gobgp/pkg/packet/bgp"
|
||||
)
|
||||
|
||||
// Returns config file type by retrieving extension from the given path.
|
||||
// If no corresponding type found, returns the given def as the default value.
|
||||
func detectConfigFileType(path, def string) string {
|
||||
switch ext := filepath.Ext(path); ext {
|
||||
case ".toml":
|
||||
return "toml"
|
||||
case ".yaml", ".yml":
|
||||
return "yaml"
|
||||
case ".json":
|
||||
return "json"
|
||||
default:
|
||||
return def
|
||||
}
|
||||
}
|
||||
|
||||
// yaml is decoded as []interface{}
|
||||
// but toml is decoded as []map[string]interface{}.
|
||||
// currently, viper can't hide this difference.
|
||||
// handle the difference here.
|
||||
func extractArray(intf interface{}) ([]interface{}, error) {
|
||||
if intf != nil {
|
||||
list, ok := intf.([]interface{})
|
||||
if ok {
|
||||
return list, nil
|
||||
}
|
||||
l, ok := intf.([]map[string]interface{})
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid configuration: neither []interface{} nor []map[string]interface{}")
|
||||
}
|
||||
list = make([]interface{}, 0, len(l))
|
||||
for _, m := range l {
|
||||
list = append(list, m)
|
||||
}
|
||||
return list, nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func getIPv6LinkLocalAddress(ifname string) (string, error) {
|
||||
ifi, err := net.InterfaceByName(ifname)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
addrs, err := ifi.Addrs()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
for _, addr := range addrs {
|
||||
ip := addr.(*net.IPNet).IP
|
||||
if ip.To4() == nil && ip.IsLinkLocalUnicast() {
|
||||
return fmt.Sprintf("%s%%%s", ip.String(), ifname), nil
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("no ipv6 link local address for %s", ifname)
|
||||
}
|
||||
|
||||
func (b *BgpConfigSet) getPeerGroup(n string) (*PeerGroup, error) {
|
||||
if n == "" {
|
||||
return nil, nil
|
||||
}
|
||||
for _, pg := range b.PeerGroups {
|
||||
if n == pg.Config.PeerGroupName {
|
||||
return &pg, nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("no such peer-group: %s", n)
|
||||
}
|
||||
|
||||
func (d *DynamicNeighbor) validate(b *BgpConfigSet) error {
|
||||
if d.Config.PeerGroup == "" {
|
||||
return fmt.Errorf("dynamic neighbor requires the peer group config")
|
||||
}
|
||||
|
||||
if _, err := b.getPeerGroup(d.Config.PeerGroup); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, _, err := net.ParseCIDR(d.Config.Prefix); err != nil {
|
||||
return fmt.Errorf("invalid dynamic neighbor prefix %s", d.Config.Prefix)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *Neighbor) IsConfederationMember(g *Global) bool {
|
||||
for _, member := range g.Confederation.Config.MemberAsList {
|
||||
if member == n.Config.PeerAs {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (n *Neighbor) IsConfederation(g *Global) bool {
|
||||
if n.Config.PeerAs == g.Config.As {
|
||||
return true
|
||||
}
|
||||
return n.IsConfederationMember(g)
|
||||
}
|
||||
|
||||
func (n *Neighbor) IsEBGPPeer(g *Global) bool {
|
||||
return n.Config.PeerAs != g.Config.As
|
||||
}
|
||||
|
||||
func (n *Neighbor) CreateRfMap() map[bgp.RouteFamily]bgp.BGPAddPathMode {
|
||||
rfMap := make(map[bgp.RouteFamily]bgp.BGPAddPathMode)
|
||||
for _, af := range n.AfiSafis {
|
||||
mode := bgp.BGP_ADD_PATH_NONE
|
||||
if af.AddPaths.State.Receive {
|
||||
mode |= bgp.BGP_ADD_PATH_RECEIVE
|
||||
}
|
||||
if af.AddPaths.State.SendMax > 0 {
|
||||
mode |= bgp.BGP_ADD_PATH_SEND
|
||||
}
|
||||
rfMap[af.State.Family] = mode
|
||||
}
|
||||
return rfMap
|
||||
}
|
||||
|
||||
func (n *Neighbor) GetAfiSafi(family bgp.RouteFamily) *AfiSafi {
|
||||
for _, a := range n.AfiSafis {
|
||||
if string(a.Config.AfiSafiName) == family.String() {
|
||||
return &a
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *Neighbor) ExtractNeighborAddress() (string, error) {
|
||||
addr := n.State.NeighborAddress
|
||||
if addr == "" {
|
||||
addr = n.Config.NeighborAddress
|
||||
if addr == "" {
|
||||
return "", fmt.Errorf("NeighborAddress is not configured")
|
||||
}
|
||||
}
|
||||
return addr, nil
|
||||
}
|
||||
|
||||
func (n *Neighbor) IsAddPathReceiveEnabled(family bgp.RouteFamily) bool {
|
||||
for _, af := range n.AfiSafis {
|
||||
if af.State.Family == family {
|
||||
return af.AddPaths.State.Receive
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type AfiSafis []AfiSafi
|
||||
|
||||
func (c AfiSafis) ToRfList() ([]bgp.RouteFamily, error) {
|
||||
rfs := make([]bgp.RouteFamily, 0, len(c))
|
||||
for _, af := range c {
|
||||
rfs = append(rfs, af.State.Family)
|
||||
}
|
||||
return rfs, nil
|
||||
}
|
||||
|
||||
func inSlice(n Neighbor, b []Neighbor) int {
|
||||
for i, nb := range b {
|
||||
if nb.State.NeighborAddress == n.State.NeighborAddress {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
func existPeerGroup(n string, b []PeerGroup) int {
|
||||
for i, nb := range b {
|
||||
if nb.Config.PeerGroupName == n {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
func isAfiSafiChanged(x, y []AfiSafi) bool {
|
||||
if len(x) != len(y) {
|
||||
return true
|
||||
}
|
||||
m := make(map[string]bool)
|
||||
for _, e := range x {
|
||||
m[string(e.Config.AfiSafiName)] = true
|
||||
}
|
||||
for _, e := range y {
|
||||
if !m[string(e.Config.AfiSafiName)] {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (n *Neighbor) NeedsResendOpenMessage(new *Neighbor) bool {
|
||||
return !n.Config.Equal(&new.Config) ||
|
||||
!n.Transport.Config.Equal(&new.Transport.Config) ||
|
||||
!n.AddPaths.Config.Equal(&new.AddPaths.Config) ||
|
||||
!n.GracefulRestart.Config.Equal(&new.GracefulRestart.Config) ||
|
||||
isAfiSafiChanged(n.AfiSafis, new.AfiSafis)
|
||||
}
|
||||
|
||||
// TODO: these regexp are duplicated in api
|
||||
var _regexpPrefixMaskLengthRange = regexp.MustCompile(`(\d+)\.\.(\d+)`)
|
||||
|
||||
func ParseMaskLength(prefix, mask string) (int, int, error) {
|
||||
_, ipNet, err := net.ParseCIDR(prefix)
|
||||
if err != nil {
|
||||
return 0, 0, fmt.Errorf("invalid prefix: %s", prefix)
|
||||
}
|
||||
if mask == "" {
|
||||
l, _ := ipNet.Mask.Size()
|
||||
return l, l, nil
|
||||
}
|
||||
elems := _regexpPrefixMaskLengthRange.FindStringSubmatch(mask)
|
||||
if len(elems) != 3 {
|
||||
return 0, 0, fmt.Errorf("invalid mask length range: %s", mask)
|
||||
}
|
||||
// we've already checked the range is sane by regexp
|
||||
min, _ := strconv.ParseUint(elems[1], 10, 8)
|
||||
max, _ := strconv.ParseUint(elems[2], 10, 8)
|
||||
if min > max {
|
||||
return 0, 0, fmt.Errorf("invalid mask length range: %s", mask)
|
||||
}
|
||||
if ipv4 := ipNet.IP.To4(); ipv4 != nil {
|
||||
f := func(i uint64) bool {
|
||||
return i <= 32
|
||||
}
|
||||
if !f(min) || !f(max) {
|
||||
return 0, 0, fmt.Errorf("ipv4 mask length range outside scope :%s", mask)
|
||||
}
|
||||
} else {
|
||||
f := func(i uint64) bool {
|
||||
return i <= 128
|
||||
}
|
||||
if !f(min) || !f(max) {
|
||||
return 0, 0, fmt.Errorf("ipv6 mask length range outside scope :%s", mask)
|
||||
}
|
||||
}
|
||||
return int(min), int(max), nil
|
||||
}
|
||||
186
vendor/github.com/osrg/gobgp/internal/pkg/table/adj.go
generated
vendored
Normal file
186
vendor/github.com/osrg/gobgp/internal/pkg/table/adj.go
generated
vendored
Normal file
@@ -0,0 +1,186 @@
|
||||
// Copyright (C) 2015 Nippon Telegraph and Telephone Corporation.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package table
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/osrg/gobgp/pkg/packet/bgp"
|
||||
)
|
||||
|
||||
type AdjRib struct {
|
||||
accepted map[bgp.RouteFamily]int
|
||||
table map[bgp.RouteFamily]map[string]*Path
|
||||
}
|
||||
|
||||
func NewAdjRib(rfList []bgp.RouteFamily) *AdjRib {
|
||||
table := make(map[bgp.RouteFamily]map[string]*Path)
|
||||
for _, rf := range rfList {
|
||||
table[rf] = make(map[string]*Path)
|
||||
}
|
||||
return &AdjRib{
|
||||
table: table,
|
||||
accepted: make(map[bgp.RouteFamily]int),
|
||||
}
|
||||
}
|
||||
|
||||
func (adj *AdjRib) Update(pathList []*Path) {
|
||||
for _, path := range pathList {
|
||||
if path == nil || path.IsEOR() {
|
||||
continue
|
||||
}
|
||||
rf := path.GetRouteFamily()
|
||||
key := fmt.Sprintf("%d:%s", path.GetNlri().PathIdentifier(), path.getPrefix())
|
||||
|
||||
old, found := adj.table[rf][key]
|
||||
if path.IsWithdraw {
|
||||
if found {
|
||||
delete(adj.table[rf], key)
|
||||
if !old.IsAsLooped() {
|
||||
adj.accepted[rf]--
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if found {
|
||||
if old.IsAsLooped() && !path.IsAsLooped() {
|
||||
adj.accepted[rf]++
|
||||
} else if !old.IsAsLooped() && path.IsAsLooped() {
|
||||
adj.accepted[rf]--
|
||||
}
|
||||
} else {
|
||||
if !path.IsAsLooped() {
|
||||
adj.accepted[rf]++
|
||||
}
|
||||
}
|
||||
if found && old.Equal(path) {
|
||||
path.setTimestamp(old.GetTimestamp())
|
||||
}
|
||||
adj.table[rf][key] = path
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (adj *AdjRib) PathList(rfList []bgp.RouteFamily, accepted bool) []*Path {
|
||||
pathList := make([]*Path, 0, adj.Count(rfList))
|
||||
for _, rf := range rfList {
|
||||
for _, rr := range adj.table[rf] {
|
||||
if accepted && rr.IsAsLooped() {
|
||||
continue
|
||||
}
|
||||
pathList = append(pathList, rr)
|
||||
}
|
||||
}
|
||||
return pathList
|
||||
}
|
||||
|
||||
func (adj *AdjRib) Count(rfList []bgp.RouteFamily) int {
|
||||
count := 0
|
||||
for _, rf := range rfList {
|
||||
if table, ok := adj.table[rf]; ok {
|
||||
count += len(table)
|
||||
}
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
func (adj *AdjRib) Accepted(rfList []bgp.RouteFamily) int {
|
||||
count := 0
|
||||
for _, rf := range rfList {
|
||||
if n, ok := adj.accepted[rf]; ok {
|
||||
count += n
|
||||
}
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
func (adj *AdjRib) Drop(rfList []bgp.RouteFamily) {
|
||||
for _, rf := range rfList {
|
||||
if _, ok := adj.table[rf]; ok {
|
||||
adj.table[rf] = make(map[string]*Path)
|
||||
adj.accepted[rf] = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (adj *AdjRib) DropStale(rfList []bgp.RouteFamily) []*Path {
|
||||
pathList := make([]*Path, 0, adj.Count(rfList))
|
||||
for _, rf := range rfList {
|
||||
if table, ok := adj.table[rf]; ok {
|
||||
for k, p := range table {
|
||||
if p.IsStale() {
|
||||
delete(table, k)
|
||||
if !p.IsAsLooped() {
|
||||
adj.accepted[rf]--
|
||||
}
|
||||
pathList = append(pathList, p.Clone(true))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return pathList
|
||||
}
|
||||
|
||||
func (adj *AdjRib) StaleAll(rfList []bgp.RouteFamily) []*Path {
|
||||
pathList := make([]*Path, 0)
|
||||
for _, rf := range rfList {
|
||||
if table, ok := adj.table[rf]; ok {
|
||||
l := make([]*Path, 0, len(table))
|
||||
for k, p := range table {
|
||||
n := p.Clone(false)
|
||||
n.MarkStale(true)
|
||||
table[k] = n
|
||||
l = append(l, n)
|
||||
}
|
||||
if len(l) > 0 {
|
||||
pathList = append(pathList, l...)
|
||||
}
|
||||
}
|
||||
}
|
||||
return pathList
|
||||
}
|
||||
|
||||
func (adj *AdjRib) Select(family bgp.RouteFamily, accepted bool, option ...TableSelectOption) (*Table, error) {
|
||||
m := make(map[string][]*Path)
|
||||
pl := adj.PathList([]bgp.RouteFamily{family}, accepted)
|
||||
for _, path := range pl {
|
||||
key := path.GetNlri().String()
|
||||
if _, y := m[key]; y {
|
||||
m[key] = append(m[key], path)
|
||||
} else {
|
||||
m[key] = []*Path{path}
|
||||
}
|
||||
}
|
||||
d := make([]*Destination, 0, len(pl))
|
||||
for _, l := range m {
|
||||
d = append(d, NewDestination(l[0].GetNlri(), 0, l...))
|
||||
}
|
||||
tbl := NewTable(family, d...)
|
||||
option = append(option, TableSelectOption{adj: true})
|
||||
return tbl.Select(option...)
|
||||
}
|
||||
|
||||
func (adj *AdjRib) TableInfo(family bgp.RouteFamily) (*TableInfo, error) {
|
||||
if _, ok := adj.table[family]; !ok {
|
||||
return nil, fmt.Errorf("%s unsupported", family)
|
||||
}
|
||||
c := adj.Count([]bgp.RouteFamily{family})
|
||||
a := adj.Accepted([]bgp.RouteFamily{family})
|
||||
return &TableInfo{
|
||||
NumDestination: c,
|
||||
NumPath: c,
|
||||
NumAccepted: a,
|
||||
}, nil
|
||||
}
|
||||
1041
vendor/github.com/osrg/gobgp/internal/pkg/table/destination.go
generated
vendored
Normal file
1041
vendor/github.com/osrg/gobgp/internal/pkg/table/destination.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
502
vendor/github.com/osrg/gobgp/internal/pkg/table/message.go
generated
vendored
Normal file
502
vendor/github.com/osrg/gobgp/internal/pkg/table/message.go
generated
vendored
Normal file
@@ -0,0 +1,502 @@
|
||||
// Copyright (C) 2014 Nippon Telegraph and Telephone Corporation.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package table
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"reflect"
|
||||
|
||||
"github.com/osrg/gobgp/pkg/packet/bgp"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func UpdatePathAttrs2ByteAs(msg *bgp.BGPUpdate) error {
|
||||
ps := msg.PathAttributes
|
||||
msg.PathAttributes = make([]bgp.PathAttributeInterface, len(ps))
|
||||
copy(msg.PathAttributes, ps)
|
||||
var asAttr *bgp.PathAttributeAsPath
|
||||
idx := 0
|
||||
for i, attr := range msg.PathAttributes {
|
||||
if a, ok := attr.(*bgp.PathAttributeAsPath); ok {
|
||||
asAttr = a
|
||||
idx = i
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if asAttr == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
as4Params := make([]*bgp.As4PathParam, 0, len(asAttr.Value))
|
||||
as2Params := make([]bgp.AsPathParamInterface, 0, len(asAttr.Value))
|
||||
mkAs4 := false
|
||||
for _, param := range asAttr.Value {
|
||||
segType := param.GetType()
|
||||
asList := param.GetAS()
|
||||
as2Path := make([]uint16, 0, len(asList))
|
||||
for _, as := range asList {
|
||||
if as > (1<<16)-1 {
|
||||
mkAs4 = true
|
||||
as2Path = append(as2Path, bgp.AS_TRANS)
|
||||
} else {
|
||||
as2Path = append(as2Path, uint16(as))
|
||||
}
|
||||
}
|
||||
as2Params = append(as2Params, bgp.NewAsPathParam(segType, as2Path))
|
||||
|
||||
// RFC 6793 4.2.2 Generating Updates
|
||||
//
|
||||
// Whenever the AS path information contains the AS_CONFED_SEQUENCE or
|
||||
// AS_CONFED_SET path segment, the NEW BGP speaker MUST exclude such
|
||||
// path segments from the AS4_PATH attribute being constructed.
|
||||
switch segType {
|
||||
case bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SEQ, bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SET:
|
||||
// pass
|
||||
default:
|
||||
if as4param, ok := param.(*bgp.As4PathParam); ok {
|
||||
as4Params = append(as4Params, as4param)
|
||||
}
|
||||
}
|
||||
}
|
||||
msg.PathAttributes[idx] = bgp.NewPathAttributeAsPath(as2Params)
|
||||
if mkAs4 {
|
||||
msg.PathAttributes = append(msg.PathAttributes, bgp.NewPathAttributeAs4Path(as4Params))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func UpdatePathAttrs4ByteAs(msg *bgp.BGPUpdate) error {
|
||||
var asAttr *bgp.PathAttributeAsPath
|
||||
var as4Attr *bgp.PathAttributeAs4Path
|
||||
asAttrPos := 0
|
||||
as4AttrPos := 0
|
||||
for i, attr := range msg.PathAttributes {
|
||||
switch attr.(type) {
|
||||
case *bgp.PathAttributeAsPath:
|
||||
asAttr = attr.(*bgp.PathAttributeAsPath)
|
||||
for j, param := range asAttr.Value {
|
||||
as2Param, ok := param.(*bgp.AsPathParam)
|
||||
if ok {
|
||||
asPath := make([]uint32, 0, len(as2Param.AS))
|
||||
for _, as := range as2Param.AS {
|
||||
asPath = append(asPath, uint32(as))
|
||||
}
|
||||
as4Param := bgp.NewAs4PathParam(as2Param.Type, asPath)
|
||||
asAttr.Value[j] = as4Param
|
||||
}
|
||||
}
|
||||
asAttrPos = i
|
||||
msg.PathAttributes[i] = asAttr
|
||||
case *bgp.PathAttributeAs4Path:
|
||||
as4AttrPos = i
|
||||
as4Attr = attr.(*bgp.PathAttributeAs4Path)
|
||||
}
|
||||
}
|
||||
|
||||
if as4Attr != nil {
|
||||
msg.PathAttributes = append(msg.PathAttributes[:as4AttrPos], msg.PathAttributes[as4AttrPos+1:]...)
|
||||
}
|
||||
|
||||
if asAttr == nil || as4Attr == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
asLen := 0
|
||||
asConfedLen := 0
|
||||
asParams := make([]bgp.AsPathParamInterface, 0, len(asAttr.Value))
|
||||
for _, param := range asAttr.Value {
|
||||
asLen += param.ASLen()
|
||||
switch param.GetType() {
|
||||
case bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SET:
|
||||
asConfedLen++
|
||||
case bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SEQ:
|
||||
asConfedLen += len(param.GetAS())
|
||||
}
|
||||
asParams = append(asParams, param)
|
||||
}
|
||||
|
||||
as4Len := 0
|
||||
as4Params := make([]bgp.AsPathParamInterface, 0, len(as4Attr.Value))
|
||||
if as4Attr != nil {
|
||||
for _, p := range as4Attr.Value {
|
||||
// RFC 6793 6. Error Handling
|
||||
//
|
||||
// the path segment types AS_CONFED_SEQUENCE and AS_CONFED_SET [RFC5065]
|
||||
// MUST NOT be carried in the AS4_PATH attribute of an UPDATE message.
|
||||
// A NEW BGP speaker that receives these path segment types in the AS4_PATH
|
||||
// attribute of an UPDATE message from an OLD BGP speaker MUST discard
|
||||
// these path segments, adjust the relevant attribute fields accordingly,
|
||||
// and continue processing the UPDATE message.
|
||||
// This case SHOULD be logged locally for analysis.
|
||||
switch p.Type {
|
||||
case bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SEQ, bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SET:
|
||||
typ := "CONFED_SEQ"
|
||||
if p.Type == bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SET {
|
||||
typ = "CONFED_SET"
|
||||
}
|
||||
log.WithFields(log.Fields{
|
||||
"Topic": "Table",
|
||||
}).Warnf("AS4_PATH contains %s segment %s. ignore", typ, p.String())
|
||||
continue
|
||||
}
|
||||
as4Len += p.ASLen()
|
||||
as4Params = append(as4Params, p)
|
||||
}
|
||||
}
|
||||
|
||||
if asLen+asConfedLen < as4Len {
|
||||
log.WithFields(log.Fields{
|
||||
"Topic": "Table",
|
||||
}).Warn("AS4_PATH is longer than AS_PATH. ignore AS4_PATH")
|
||||
return nil
|
||||
}
|
||||
|
||||
keepNum := asLen + asConfedLen - as4Len
|
||||
|
||||
newParams := make([]bgp.AsPathParamInterface, 0, len(asAttr.Value))
|
||||
for _, param := range asParams {
|
||||
if keepNum-param.ASLen() >= 0 {
|
||||
newParams = append(newParams, param)
|
||||
keepNum -= param.ASLen()
|
||||
} else {
|
||||
// only SEQ param reaches here
|
||||
newParams = append(newParams, bgp.NewAs4PathParam(param.GetType(), param.GetAS()[:keepNum]))
|
||||
keepNum = 0
|
||||
}
|
||||
|
||||
if keepNum <= 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
for _, param := range as4Params {
|
||||
lastParam := newParams[len(newParams)-1]
|
||||
lastParamAS := lastParam.GetAS()
|
||||
paramType := param.GetType()
|
||||
paramAS := param.GetAS()
|
||||
if paramType == lastParam.GetType() && paramType == bgp.BGP_ASPATH_ATTR_TYPE_SEQ {
|
||||
if len(lastParamAS)+len(paramAS) > 255 {
|
||||
newParams[len(newParams)-1] = bgp.NewAs4PathParam(paramType, append(lastParamAS, paramAS[:255-len(lastParamAS)]...))
|
||||
newParams = append(newParams, bgp.NewAs4PathParam(paramType, paramAS[255-len(lastParamAS):]))
|
||||
} else {
|
||||
newParams[len(newParams)-1] = bgp.NewAs4PathParam(paramType, append(lastParamAS, paramAS...))
|
||||
}
|
||||
} else {
|
||||
newParams = append(newParams, param)
|
||||
}
|
||||
}
|
||||
|
||||
newIntfParams := make([]bgp.AsPathParamInterface, 0, len(asAttr.Value))
|
||||
newIntfParams = append(newIntfParams, newParams...)
|
||||
|
||||
msg.PathAttributes[asAttrPos] = bgp.NewPathAttributeAsPath(newIntfParams)
|
||||
return nil
|
||||
}
|
||||
|
||||
func UpdatePathAggregator2ByteAs(msg *bgp.BGPUpdate) {
|
||||
as := uint32(0)
|
||||
var addr string
|
||||
for i, attr := range msg.PathAttributes {
|
||||
switch attr.(type) {
|
||||
case *bgp.PathAttributeAggregator:
|
||||
agg := attr.(*bgp.PathAttributeAggregator)
|
||||
addr = agg.Value.Address.String()
|
||||
if agg.Value.AS > (1<<16)-1 {
|
||||
as = agg.Value.AS
|
||||
msg.PathAttributes[i] = bgp.NewPathAttributeAggregator(uint16(bgp.AS_TRANS), addr)
|
||||
} else {
|
||||
msg.PathAttributes[i] = bgp.NewPathAttributeAggregator(uint16(agg.Value.AS), addr)
|
||||
}
|
||||
}
|
||||
}
|
||||
if as != 0 {
|
||||
msg.PathAttributes = append(msg.PathAttributes, bgp.NewPathAttributeAs4Aggregator(as, addr))
|
||||
}
|
||||
}
|
||||
|
||||
func UpdatePathAggregator4ByteAs(msg *bgp.BGPUpdate) error {
|
||||
var aggAttr *bgp.PathAttributeAggregator
|
||||
var agg4Attr *bgp.PathAttributeAs4Aggregator
|
||||
agg4AttrPos := 0
|
||||
for i, attr := range msg.PathAttributes {
|
||||
switch attr.(type) {
|
||||
case *bgp.PathAttributeAggregator:
|
||||
attr := attr.(*bgp.PathAttributeAggregator)
|
||||
if attr.Value.Askind == reflect.Uint16 {
|
||||
aggAttr = attr
|
||||
aggAttr.Value.Askind = reflect.Uint32
|
||||
}
|
||||
case *bgp.PathAttributeAs4Aggregator:
|
||||
agg4Attr = attr.(*bgp.PathAttributeAs4Aggregator)
|
||||
agg4AttrPos = i
|
||||
}
|
||||
}
|
||||
if aggAttr == nil && agg4Attr == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if aggAttr == nil && agg4Attr != nil {
|
||||
return bgp.NewMessageError(bgp.BGP_ERROR_UPDATE_MESSAGE_ERROR, bgp.BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "AS4 AGGREGATOR attribute exists, but AGGREGATOR doesn't")
|
||||
}
|
||||
|
||||
if agg4Attr != nil {
|
||||
msg.PathAttributes = append(msg.PathAttributes[:agg4AttrPos], msg.PathAttributes[agg4AttrPos+1:]...)
|
||||
aggAttr.Value.AS = agg4Attr.Value.AS
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type cage struct {
|
||||
attrsBytes []byte
|
||||
paths []*Path
|
||||
}
|
||||
|
||||
func newCage(b []byte, path *Path) *cage {
|
||||
return &cage{
|
||||
attrsBytes: b,
|
||||
paths: []*Path{path},
|
||||
}
|
||||
}
|
||||
|
||||
type packerInterface interface {
|
||||
add(*Path)
|
||||
pack(options ...*bgp.MarshallingOption) []*bgp.BGPMessage
|
||||
}
|
||||
|
||||
type packer struct {
|
||||
eof bool
|
||||
family bgp.RouteFamily
|
||||
total uint32
|
||||
}
|
||||
|
||||
type packerMP struct {
|
||||
packer
|
||||
paths []*Path
|
||||
withdrawals []*Path
|
||||
}
|
||||
|
||||
func (p *packerMP) add(path *Path) {
|
||||
p.packer.total++
|
||||
|
||||
if path.IsEOR() {
|
||||
p.packer.eof = true
|
||||
return
|
||||
}
|
||||
|
||||
if path.IsWithdraw {
|
||||
p.withdrawals = append(p.withdrawals, path)
|
||||
return
|
||||
}
|
||||
|
||||
p.paths = append(p.paths, path)
|
||||
}
|
||||
|
||||
func createMPReachMessage(path *Path) *bgp.BGPMessage {
|
||||
oattrs := path.GetPathAttrs()
|
||||
attrs := make([]bgp.PathAttributeInterface, 0, len(oattrs))
|
||||
for _, a := range oattrs {
|
||||
if a.GetType() == bgp.BGP_ATTR_TYPE_MP_REACH_NLRI {
|
||||
attrs = append(attrs, bgp.NewPathAttributeMpReachNLRI(path.GetNexthop().String(), []bgp.AddrPrefixInterface{path.GetNlri()}))
|
||||
} else {
|
||||
attrs = append(attrs, a)
|
||||
}
|
||||
}
|
||||
return bgp.NewBGPUpdateMessage(nil, attrs, nil)
|
||||
}
|
||||
|
||||
func (p *packerMP) pack(options ...*bgp.MarshallingOption) []*bgp.BGPMessage {
|
||||
msgs := make([]*bgp.BGPMessage, 0, p.packer.total)
|
||||
|
||||
for _, path := range p.withdrawals {
|
||||
nlris := []bgp.AddrPrefixInterface{path.GetNlri()}
|
||||
msgs = append(msgs, bgp.NewBGPUpdateMessage(nil, []bgp.PathAttributeInterface{bgp.NewPathAttributeMpUnreachNLRI(nlris)}, nil))
|
||||
}
|
||||
|
||||
for _, path := range p.paths {
|
||||
msgs = append(msgs, createMPReachMessage(path))
|
||||
}
|
||||
|
||||
if p.eof {
|
||||
msgs = append(msgs, bgp.NewEndOfRib(p.family))
|
||||
}
|
||||
return msgs
|
||||
}
|
||||
|
||||
func newPackerMP(f bgp.RouteFamily) *packerMP {
|
||||
return &packerMP{
|
||||
packer: packer{
|
||||
family: f,
|
||||
},
|
||||
withdrawals: make([]*Path, 0),
|
||||
paths: make([]*Path, 0),
|
||||
}
|
||||
}
|
||||
|
||||
type packerV4 struct {
|
||||
packer
|
||||
hashmap map[uint32][]*cage
|
||||
mpPaths []*Path
|
||||
withdrawals []*Path
|
||||
}
|
||||
|
||||
func (p *packerV4) add(path *Path) {
|
||||
p.packer.total++
|
||||
|
||||
if path.IsEOR() {
|
||||
p.packer.eof = true
|
||||
return
|
||||
}
|
||||
|
||||
if path.IsWithdraw {
|
||||
p.withdrawals = append(p.withdrawals, path)
|
||||
return
|
||||
}
|
||||
|
||||
if path.GetNexthop().To4() == nil {
|
||||
// RFC 5549
|
||||
p.mpPaths = append(p.mpPaths, path)
|
||||
return
|
||||
}
|
||||
|
||||
key := path.GetHash()
|
||||
attrsB := bytes.NewBuffer(make([]byte, 0))
|
||||
for _, v := range path.GetPathAttrs() {
|
||||
b, _ := v.Serialize()
|
||||
attrsB.Write(b)
|
||||
}
|
||||
|
||||
if cages, y := p.hashmap[key]; y {
|
||||
added := false
|
||||
for _, c := range cages {
|
||||
if bytes.Equal(c.attrsBytes, attrsB.Bytes()) {
|
||||
c.paths = append(c.paths, path)
|
||||
added = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !added {
|
||||
p.hashmap[key] = append(p.hashmap[key], newCage(attrsB.Bytes(), path))
|
||||
}
|
||||
} else {
|
||||
p.hashmap[key] = []*cage{newCage(attrsB.Bytes(), path)}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *packerV4) pack(options ...*bgp.MarshallingOption) []*bgp.BGPMessage {
|
||||
split := func(max int, paths []*Path) ([]*bgp.IPAddrPrefix, []*Path) {
|
||||
nlris := make([]*bgp.IPAddrPrefix, 0, max)
|
||||
i := 0
|
||||
if max > len(paths) {
|
||||
max = len(paths)
|
||||
}
|
||||
for ; i < max; i++ {
|
||||
nlris = append(nlris, paths[i].GetNlri().(*bgp.IPAddrPrefix))
|
||||
}
|
||||
return nlris, paths[i:]
|
||||
}
|
||||
addpathNLRILen := 0
|
||||
if bgp.IsAddPathEnabled(false, p.packer.family, options) {
|
||||
addpathNLRILen = 4
|
||||
}
|
||||
// Header + Update (WithdrawnRoutesLen +
|
||||
// TotalPathAttributeLen + attributes + maxlen of NLRI).
|
||||
// the max size of NLRI is 5bytes (plus 4bytes with addpath enabled)
|
||||
maxNLRIs := func(attrsLen int) int {
|
||||
return (bgp.BGP_MAX_MESSAGE_LENGTH - (19 + 2 + 2 + attrsLen)) / (5 + addpathNLRILen)
|
||||
}
|
||||
|
||||
loop := func(attrsLen int, paths []*Path, cb func([]*bgp.IPAddrPrefix)) {
|
||||
max := maxNLRIs(attrsLen)
|
||||
var nlris []*bgp.IPAddrPrefix
|
||||
for {
|
||||
nlris, paths = split(max, paths)
|
||||
if len(nlris) == 0 {
|
||||
break
|
||||
}
|
||||
cb(nlris)
|
||||
}
|
||||
}
|
||||
|
||||
msgs := make([]*bgp.BGPMessage, 0, p.packer.total)
|
||||
|
||||
loop(0, p.withdrawals, func(nlris []*bgp.IPAddrPrefix) {
|
||||
msgs = append(msgs, bgp.NewBGPUpdateMessage(nlris, nil, nil))
|
||||
})
|
||||
|
||||
for _, cages := range p.hashmap {
|
||||
for _, c := range cages {
|
||||
paths := c.paths
|
||||
|
||||
attrs := paths[0].GetPathAttrs()
|
||||
attrsLen := 0
|
||||
for _, a := range attrs {
|
||||
attrsLen += a.Len()
|
||||
}
|
||||
|
||||
loop(attrsLen, paths, func(nlris []*bgp.IPAddrPrefix) {
|
||||
msgs = append(msgs, bgp.NewBGPUpdateMessage(nil, attrs, nlris))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
for _, path := range p.mpPaths {
|
||||
msgs = append(msgs, createMPReachMessage(path))
|
||||
}
|
||||
|
||||
if p.eof {
|
||||
msgs = append(msgs, bgp.NewEndOfRib(p.family))
|
||||
}
|
||||
return msgs
|
||||
}
|
||||
|
||||
func newPackerV4(f bgp.RouteFamily) *packerV4 {
|
||||
return &packerV4{
|
||||
packer: packer{
|
||||
family: f,
|
||||
},
|
||||
hashmap: make(map[uint32][]*cage),
|
||||
withdrawals: make([]*Path, 0),
|
||||
mpPaths: make([]*Path, 0),
|
||||
}
|
||||
}
|
||||
|
||||
func newPacker(f bgp.RouteFamily) packerInterface {
|
||||
switch f {
|
||||
case bgp.RF_IPv4_UC:
|
||||
return newPackerV4(bgp.RF_IPv4_UC)
|
||||
default:
|
||||
return newPackerMP(f)
|
||||
}
|
||||
}
|
||||
|
||||
func CreateUpdateMsgFromPaths(pathList []*Path, options ...*bgp.MarshallingOption) []*bgp.BGPMessage {
|
||||
msgs := make([]*bgp.BGPMessage, 0, len(pathList))
|
||||
|
||||
m := make(map[bgp.RouteFamily]packerInterface)
|
||||
for _, path := range pathList {
|
||||
f := path.GetRouteFamily()
|
||||
if _, y := m[f]; !y {
|
||||
m[f] = newPacker(f)
|
||||
}
|
||||
m[f].add(path)
|
||||
}
|
||||
|
||||
for _, p := range m {
|
||||
msgs = append(msgs, p.pack(options...)...)
|
||||
}
|
||||
return msgs
|
||||
}
|
||||
1179
vendor/github.com/osrg/gobgp/internal/pkg/table/path.go
generated
vendored
Normal file
1179
vendor/github.com/osrg/gobgp/internal/pkg/table/path.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
3895
vendor/github.com/osrg/gobgp/internal/pkg/table/policy.go
generated
vendored
Normal file
3895
vendor/github.com/osrg/gobgp/internal/pkg/table/policy.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
60
vendor/github.com/osrg/gobgp/internal/pkg/table/roa.go
generated
vendored
Normal file
60
vendor/github.com/osrg/gobgp/internal/pkg/table/roa.go
generated
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
// Copyright (C) 2016 Nippon Telegraph and Telephone Corporation.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package table
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
)
|
||||
|
||||
type IPPrefix struct {
|
||||
Prefix net.IP
|
||||
Length uint8
|
||||
}
|
||||
|
||||
func (p *IPPrefix) String() string {
|
||||
return fmt.Sprintf("%s/%d", p.Prefix, p.Length)
|
||||
}
|
||||
|
||||
type ROA struct {
|
||||
Family int
|
||||
Prefix *IPPrefix
|
||||
MaxLen uint8
|
||||
AS uint32
|
||||
Src string
|
||||
}
|
||||
|
||||
func NewROA(family int, prefixByte []byte, prefixLen uint8, maxLen uint8, as uint32, src string) *ROA {
|
||||
p := make([]byte, len(prefixByte))
|
||||
copy(p, prefixByte)
|
||||
return &ROA{
|
||||
Family: family,
|
||||
Prefix: &IPPrefix{
|
||||
Prefix: p,
|
||||
Length: prefixLen,
|
||||
},
|
||||
MaxLen: maxLen,
|
||||
AS: as,
|
||||
Src: src,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *ROA) Equal(roa *ROA) bool {
|
||||
if r.MaxLen == roa.MaxLen && r.Src == roa.Src && r.AS == roa.AS {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
451
vendor/github.com/osrg/gobgp/internal/pkg/table/table.go
generated
vendored
Normal file
451
vendor/github.com/osrg/gobgp/internal/pkg/table/table.go
generated
vendored
Normal file
@@ -0,0 +1,451 @@
|
||||
// Copyright (C) 2014 Nippon Telegraph and Telephone Corporation.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package table
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
"unsafe"
|
||||
|
||||
"github.com/armon/go-radix"
|
||||
"github.com/osrg/gobgp/pkg/packet/bgp"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type LookupOption uint8
|
||||
|
||||
const (
|
||||
LOOKUP_EXACT LookupOption = iota
|
||||
LOOKUP_LONGER
|
||||
LOOKUP_SHORTER
|
||||
)
|
||||
|
||||
type LookupPrefix struct {
|
||||
Prefix string
|
||||
LookupOption
|
||||
}
|
||||
|
||||
type TableSelectOption struct {
|
||||
ID string
|
||||
AS uint32
|
||||
LookupPrefixes []*LookupPrefix
|
||||
VRF *Vrf
|
||||
adj bool
|
||||
Best bool
|
||||
MultiPath bool
|
||||
}
|
||||
|
||||
type Table struct {
|
||||
routeFamily bgp.RouteFamily
|
||||
destinations map[string]*Destination
|
||||
}
|
||||
|
||||
func NewTable(rf bgp.RouteFamily, dsts ...*Destination) *Table {
|
||||
t := &Table{
|
||||
routeFamily: rf,
|
||||
destinations: make(map[string]*Destination),
|
||||
}
|
||||
for _, dst := range dsts {
|
||||
t.setDestination(dst)
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
func (t *Table) GetRoutefamily() bgp.RouteFamily {
|
||||
return t.routeFamily
|
||||
}
|
||||
|
||||
func (t *Table) deletePathsByVrf(vrf *Vrf) []*Path {
|
||||
pathList := make([]*Path, 0)
|
||||
for _, dest := range t.destinations {
|
||||
for _, p := range dest.knownPathList {
|
||||
var rd bgp.RouteDistinguisherInterface
|
||||
nlri := p.GetNlri()
|
||||
switch nlri.(type) {
|
||||
case *bgp.LabeledVPNIPAddrPrefix:
|
||||
rd = nlri.(*bgp.LabeledVPNIPAddrPrefix).RD
|
||||
case *bgp.LabeledVPNIPv6AddrPrefix:
|
||||
rd = nlri.(*bgp.LabeledVPNIPv6AddrPrefix).RD
|
||||
case *bgp.EVPNNLRI:
|
||||
rd = nlri.(*bgp.EVPNNLRI).RD()
|
||||
default:
|
||||
return pathList
|
||||
}
|
||||
if p.IsLocal() && vrf.Rd.String() == rd.String() {
|
||||
pathList = append(pathList, p.Clone(true))
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return pathList
|
||||
}
|
||||
|
||||
func (t *Table) deleteRTCPathsByVrf(vrf *Vrf, vrfs map[string]*Vrf) []*Path {
|
||||
pathList := make([]*Path, 0)
|
||||
if t.routeFamily != bgp.RF_RTC_UC {
|
||||
return pathList
|
||||
}
|
||||
for _, target := range vrf.ImportRt {
|
||||
lhs := target.String()
|
||||
for _, dest := range t.destinations {
|
||||
nlri := dest.GetNlri().(*bgp.RouteTargetMembershipNLRI)
|
||||
rhs := nlri.RouteTarget.String()
|
||||
if lhs == rhs && isLastTargetUser(vrfs, target) {
|
||||
for _, p := range dest.knownPathList {
|
||||
if p.IsLocal() {
|
||||
pathList = append(pathList, p.Clone(true))
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return pathList
|
||||
}
|
||||
|
||||
func (t *Table) deleteDestByNlri(nlri bgp.AddrPrefixInterface) *Destination {
|
||||
if dst := t.GetDestination(nlri); dst != nil {
|
||||
t.deleteDest(dst)
|
||||
return dst
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *Table) deleteDest(dest *Destination) {
|
||||
destinations := t.GetDestinations()
|
||||
delete(destinations, t.tableKey(dest.GetNlri()))
|
||||
if len(destinations) == 0 {
|
||||
t.destinations = make(map[string]*Destination)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Table) validatePath(path *Path) {
|
||||
if path == nil {
|
||||
log.WithFields(log.Fields{
|
||||
"Topic": "Table",
|
||||
"Key": t.routeFamily,
|
||||
}).Error("path is nil")
|
||||
}
|
||||
if path.GetRouteFamily() != t.routeFamily {
|
||||
log.WithFields(log.Fields{
|
||||
"Topic": "Table",
|
||||
"Key": t.routeFamily,
|
||||
"Prefix": path.GetNlri().String(),
|
||||
"ReceivedRf": path.GetRouteFamily().String(),
|
||||
}).Error("Invalid path. RouteFamily mismatch")
|
||||
}
|
||||
if attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH); attr != nil {
|
||||
pathParam := attr.(*bgp.PathAttributeAsPath).Value
|
||||
for _, as := range pathParam {
|
||||
_, y := as.(*bgp.As4PathParam)
|
||||
if !y {
|
||||
log.WithFields(log.Fields{
|
||||
"Topic": "Table",
|
||||
"Key": t.routeFamily,
|
||||
"As": as,
|
||||
}).Fatal("AsPathParam must be converted to As4PathParam")
|
||||
}
|
||||
}
|
||||
}
|
||||
if attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_AS4_PATH); attr != nil {
|
||||
log.WithFields(log.Fields{
|
||||
"Topic": "Table",
|
||||
"Key": t.routeFamily,
|
||||
}).Fatal("AS4_PATH must be converted to AS_PATH")
|
||||
}
|
||||
if path.GetNlri() == nil {
|
||||
log.WithFields(log.Fields{
|
||||
"Topic": "Table",
|
||||
"Key": t.routeFamily,
|
||||
}).Fatal("path's nlri is nil")
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Table) getOrCreateDest(nlri bgp.AddrPrefixInterface) *Destination {
|
||||
dest := t.GetDestination(nlri)
|
||||
// If destination for given prefix does not exist we create it.
|
||||
if dest == nil {
|
||||
log.WithFields(log.Fields{
|
||||
"Topic": "Table",
|
||||
"Nlri": nlri,
|
||||
}).Debugf("create Destination")
|
||||
dest = NewDestination(nlri, 64)
|
||||
t.setDestination(dest)
|
||||
}
|
||||
return dest
|
||||
}
|
||||
|
||||
func (t *Table) GetDestinations() map[string]*Destination {
|
||||
return t.destinations
|
||||
}
|
||||
func (t *Table) setDestinations(destinations map[string]*Destination) {
|
||||
t.destinations = destinations
|
||||
}
|
||||
func (t *Table) GetDestination(nlri bgp.AddrPrefixInterface) *Destination {
|
||||
dest, ok := t.destinations[t.tableKey(nlri)]
|
||||
if ok {
|
||||
return dest
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Table) GetLongerPrefixDestinations(key string) ([]*Destination, error) {
|
||||
results := make([]*Destination, 0, len(t.GetDestinations()))
|
||||
switch t.routeFamily {
|
||||
case bgp.RF_IPv4_UC, bgp.RF_IPv6_UC, bgp.RF_IPv4_MPLS, bgp.RF_IPv6_MPLS:
|
||||
_, prefix, err := net.ParseCIDR(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
k := CidrToRadixkey(prefix.String())
|
||||
r := radix.New()
|
||||
for _, dst := range t.GetDestinations() {
|
||||
r.Insert(AddrToRadixkey(dst.nlri), dst)
|
||||
}
|
||||
r.WalkPrefix(k, func(s string, v interface{}) bool {
|
||||
results = append(results, v.(*Destination))
|
||||
return false
|
||||
})
|
||||
default:
|
||||
for _, dst := range t.GetDestinations() {
|
||||
results = append(results, dst)
|
||||
}
|
||||
}
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (t *Table) GetEvpnDestinationsWithRouteType(typ string) ([]*Destination, error) {
|
||||
var routeType uint8
|
||||
switch strings.ToLower(typ) {
|
||||
case "a-d":
|
||||
routeType = bgp.EVPN_ROUTE_TYPE_ETHERNET_AUTO_DISCOVERY
|
||||
case "macadv":
|
||||
routeType = bgp.EVPN_ROUTE_TYPE_MAC_IP_ADVERTISEMENT
|
||||
case "multicast":
|
||||
routeType = bgp.EVPN_INCLUSIVE_MULTICAST_ETHERNET_TAG
|
||||
case "esi":
|
||||
routeType = bgp.EVPN_ETHERNET_SEGMENT_ROUTE
|
||||
case "prefix":
|
||||
routeType = bgp.EVPN_IP_PREFIX
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported evpn route type: %s", typ)
|
||||
}
|
||||
destinations := t.GetDestinations()
|
||||
results := make([]*Destination, 0, len(destinations))
|
||||
switch t.routeFamily {
|
||||
case bgp.RF_EVPN:
|
||||
for _, dst := range destinations {
|
||||
if nlri, ok := dst.nlri.(*bgp.EVPNNLRI); !ok {
|
||||
return nil, fmt.Errorf("invalid evpn nlri type detected: %T", dst.nlri)
|
||||
} else if nlri.RouteType == routeType {
|
||||
results = append(results, dst)
|
||||
}
|
||||
}
|
||||
default:
|
||||
for _, dst := range destinations {
|
||||
results = append(results, dst)
|
||||
}
|
||||
}
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (t *Table) setDestination(dst *Destination) {
|
||||
t.destinations[t.tableKey(dst.nlri)] = dst
|
||||
}
|
||||
|
||||
func (t *Table) tableKey(nlri bgp.AddrPrefixInterface) string {
|
||||
switch T := nlri.(type) {
|
||||
case *bgp.IPAddrPrefix:
|
||||
b := make([]byte, 5)
|
||||
copy(b, T.Prefix.To4())
|
||||
b[4] = T.Length
|
||||
return *(*string)(unsafe.Pointer(&b))
|
||||
case *bgp.IPv6AddrPrefix:
|
||||
b := make([]byte, 17)
|
||||
copy(b, T.Prefix.To16())
|
||||
b[16] = T.Length
|
||||
return *(*string)(unsafe.Pointer(&b))
|
||||
}
|
||||
return nlri.String()
|
||||
}
|
||||
|
||||
func (t *Table) Bests(id string, as uint32) []*Path {
|
||||
paths := make([]*Path, 0, len(t.destinations))
|
||||
for _, dst := range t.destinations {
|
||||
path := dst.GetBestPath(id, as)
|
||||
if path != nil {
|
||||
paths = append(paths, path)
|
||||
}
|
||||
}
|
||||
return paths
|
||||
}
|
||||
|
||||
func (t *Table) MultiBests(id string) [][]*Path {
|
||||
paths := make([][]*Path, 0, len(t.destinations))
|
||||
for _, dst := range t.destinations {
|
||||
path := dst.GetMultiBestPath(id)
|
||||
if path != nil {
|
||||
paths = append(paths, path)
|
||||
}
|
||||
}
|
||||
return paths
|
||||
}
|
||||
|
||||
func (t *Table) GetKnownPathList(id string, as uint32) []*Path {
|
||||
paths := make([]*Path, 0, len(t.destinations))
|
||||
for _, dst := range t.destinations {
|
||||
paths = append(paths, dst.GetKnownPathList(id, as)...)
|
||||
}
|
||||
return paths
|
||||
}
|
||||
|
||||
func (t *Table) Select(option ...TableSelectOption) (*Table, error) {
|
||||
id := GLOBAL_RIB_NAME
|
||||
var vrf *Vrf
|
||||
adj := false
|
||||
prefixes := make([]*LookupPrefix, 0, len(option))
|
||||
best := false
|
||||
mp := false
|
||||
as := uint32(0)
|
||||
for _, o := range option {
|
||||
if o.ID != "" {
|
||||
id = o.ID
|
||||
}
|
||||
if o.VRF != nil {
|
||||
vrf = o.VRF
|
||||
}
|
||||
adj = o.adj
|
||||
prefixes = append(prefixes, o.LookupPrefixes...)
|
||||
best = o.Best
|
||||
mp = o.MultiPath
|
||||
as = o.AS
|
||||
}
|
||||
dOption := DestinationSelectOption{ID: id, AS: as, VRF: vrf, adj: adj, Best: best, MultiPath: mp}
|
||||
r := &Table{
|
||||
routeFamily: t.routeFamily,
|
||||
destinations: make(map[string]*Destination),
|
||||
}
|
||||
|
||||
if len(prefixes) != 0 {
|
||||
switch t.routeFamily {
|
||||
case bgp.RF_IPv4_UC, bgp.RF_IPv6_UC:
|
||||
f := func(prefixStr string) bool {
|
||||
var nlri bgp.AddrPrefixInterface
|
||||
if t.routeFamily == bgp.RF_IPv4_UC {
|
||||
nlri, _ = bgp.NewPrefixFromRouteFamily(bgp.AFI_IP, bgp.SAFI_UNICAST, prefixStr)
|
||||
} else {
|
||||
nlri, _ = bgp.NewPrefixFromRouteFamily(bgp.AFI_IP6, bgp.SAFI_UNICAST, prefixStr)
|
||||
}
|
||||
if dst := t.GetDestination(nlri); dst != nil {
|
||||
if d := dst.Select(dOption); d != nil {
|
||||
r.setDestination(d)
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
for _, p := range prefixes {
|
||||
key := p.Prefix
|
||||
switch p.LookupOption {
|
||||
case LOOKUP_LONGER:
|
||||
ds, err := t.GetLongerPrefixDestinations(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, dst := range ds {
|
||||
if d := dst.Select(dOption); d != nil {
|
||||
r.setDestination(d)
|
||||
}
|
||||
}
|
||||
case LOOKUP_SHORTER:
|
||||
addr, prefix, err := net.ParseCIDR(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ones, _ := prefix.Mask.Size()
|
||||
for i := ones; i >= 0; i-- {
|
||||
_, prefix, _ := net.ParseCIDR(fmt.Sprintf("%s/%d", addr.String(), i))
|
||||
f(prefix.String())
|
||||
}
|
||||
default:
|
||||
if host := net.ParseIP(key); host != nil {
|
||||
masklen := 32
|
||||
if t.routeFamily == bgp.RF_IPv6_UC {
|
||||
masklen = 128
|
||||
}
|
||||
for i := masklen; i >= 0; i-- {
|
||||
_, prefix, err := net.ParseCIDR(fmt.Sprintf("%s/%d", key, i))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if f(prefix.String()) {
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
f(key)
|
||||
}
|
||||
}
|
||||
}
|
||||
case bgp.RF_EVPN:
|
||||
for _, p := range prefixes {
|
||||
// Uses LookupPrefix.Prefix as EVPN Route Type string
|
||||
ds, err := t.GetEvpnDestinationsWithRouteType(p.Prefix)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, dst := range ds {
|
||||
if d := dst.Select(dOption); d != nil {
|
||||
r.setDestination(d)
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
return nil, fmt.Errorf("route filtering is not supported for this family")
|
||||
}
|
||||
} else {
|
||||
for _, dst := range t.GetDestinations() {
|
||||
if d := dst.Select(dOption); d != nil {
|
||||
r.setDestination(d)
|
||||
}
|
||||
}
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
|
||||
type TableInfo struct {
|
||||
NumDestination int
|
||||
NumPath int
|
||||
NumAccepted int
|
||||
}
|
||||
|
||||
func (t *Table) Info(id string, as uint32) *TableInfo {
|
||||
var numD, numP int
|
||||
for _, d := range t.destinations {
|
||||
ps := d.GetKnownPathList(id, as)
|
||||
if len(ps) > 0 {
|
||||
numD += 1
|
||||
numP += len(ps)
|
||||
}
|
||||
}
|
||||
return &TableInfo{
|
||||
NumDestination: numD,
|
||||
NumPath: numP,
|
||||
}
|
||||
}
|
||||
370
vendor/github.com/osrg/gobgp/internal/pkg/table/table_manager.go
generated
vendored
Normal file
370
vendor/github.com/osrg/gobgp/internal/pkg/table/table_manager.go
generated
vendored
Normal file
@@ -0,0 +1,370 @@
|
||||
// Copyright (C) 2014 Nippon Telegraph and Telephone Corporation.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package table
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
farm "github.com/dgryski/go-farm"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/osrg/gobgp/pkg/packet/bgp"
|
||||
)
|
||||
|
||||
const (
|
||||
GLOBAL_RIB_NAME = "global"
|
||||
)
|
||||
|
||||
func ProcessMessage(m *bgp.BGPMessage, peerInfo *PeerInfo, timestamp time.Time) []*Path {
|
||||
update := m.Body.(*bgp.BGPUpdate)
|
||||
|
||||
if y, f := update.IsEndOfRib(); y {
|
||||
// this message has no normal updates or withdrawals.
|
||||
return []*Path{NewEOR(f)}
|
||||
}
|
||||
|
||||
adds := make([]bgp.AddrPrefixInterface, 0, len(update.NLRI))
|
||||
for _, nlri := range update.NLRI {
|
||||
adds = append(adds, nlri)
|
||||
}
|
||||
|
||||
dels := make([]bgp.AddrPrefixInterface, 0, len(update.WithdrawnRoutes))
|
||||
for _, nlri := range update.WithdrawnRoutes {
|
||||
dels = append(dels, nlri)
|
||||
}
|
||||
|
||||
attrs := make([]bgp.PathAttributeInterface, 0, len(update.PathAttributes))
|
||||
var reach *bgp.PathAttributeMpReachNLRI
|
||||
for _, attr := range update.PathAttributes {
|
||||
switch a := attr.(type) {
|
||||
case *bgp.PathAttributeMpReachNLRI:
|
||||
reach = a
|
||||
case *bgp.PathAttributeMpUnreachNLRI:
|
||||
l := make([]bgp.AddrPrefixInterface, 0, len(a.Value))
|
||||
l = append(l, a.Value...)
|
||||
dels = append(dels, l...)
|
||||
default:
|
||||
attrs = append(attrs, attr)
|
||||
}
|
||||
}
|
||||
|
||||
listLen := len(adds) + len(dels)
|
||||
if reach != nil {
|
||||
listLen += len(reach.Value)
|
||||
}
|
||||
|
||||
var hash uint32
|
||||
if len(adds) > 0 || reach != nil {
|
||||
total := bytes.NewBuffer(make([]byte, 0))
|
||||
for _, a := range attrs {
|
||||
b, _ := a.Serialize()
|
||||
total.Write(b)
|
||||
}
|
||||
hash = farm.Hash32(total.Bytes())
|
||||
}
|
||||
|
||||
pathList := make([]*Path, 0, listLen)
|
||||
for _, nlri := range adds {
|
||||
p := NewPath(peerInfo, nlri, false, attrs, timestamp, false)
|
||||
p.SetHash(hash)
|
||||
pathList = append(pathList, p)
|
||||
}
|
||||
if reach != nil {
|
||||
reachAttrs := make([]bgp.PathAttributeInterface, len(attrs)+1)
|
||||
copy(reachAttrs, attrs)
|
||||
// we sort attributes when creating a bgp message from paths
|
||||
reachAttrs[len(reachAttrs)-1] = reach
|
||||
|
||||
for _, nlri := range reach.Value {
|
||||
p := NewPath(peerInfo, nlri, false, reachAttrs, timestamp, false)
|
||||
p.SetHash(hash)
|
||||
pathList = append(pathList, p)
|
||||
}
|
||||
}
|
||||
for _, nlri := range dels {
|
||||
p := NewPath(peerInfo, nlri, true, []bgp.PathAttributeInterface{}, timestamp, false)
|
||||
pathList = append(pathList, p)
|
||||
}
|
||||
return pathList
|
||||
}
|
||||
|
||||
type TableManager struct {
|
||||
Tables map[bgp.RouteFamily]*Table
|
||||
Vrfs map[string]*Vrf
|
||||
rfList []bgp.RouteFamily
|
||||
}
|
||||
|
||||
func NewTableManager(rfList []bgp.RouteFamily) *TableManager {
|
||||
t := &TableManager{
|
||||
Tables: make(map[bgp.RouteFamily]*Table),
|
||||
Vrfs: make(map[string]*Vrf),
|
||||
rfList: rfList,
|
||||
}
|
||||
for _, rf := range rfList {
|
||||
t.Tables[rf] = NewTable(rf)
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
func (manager *TableManager) GetRFlist() []bgp.RouteFamily {
|
||||
return manager.rfList
|
||||
}
|
||||
|
||||
func (manager *TableManager) AddVrf(name string, id uint32, rd bgp.RouteDistinguisherInterface, importRt, exportRt []bgp.ExtendedCommunityInterface, info *PeerInfo) ([]*Path, error) {
|
||||
if _, ok := manager.Vrfs[name]; ok {
|
||||
return nil, fmt.Errorf("vrf %s already exists", name)
|
||||
}
|
||||
log.WithFields(log.Fields{
|
||||
"Topic": "Vrf",
|
||||
"Key": name,
|
||||
"Rd": rd,
|
||||
"ImportRt": importRt,
|
||||
"ExportRt": exportRt,
|
||||
}).Debugf("add vrf")
|
||||
manager.Vrfs[name] = &Vrf{
|
||||
Name: name,
|
||||
Id: id,
|
||||
Rd: rd,
|
||||
ImportRt: importRt,
|
||||
ExportRt: exportRt,
|
||||
}
|
||||
msgs := make([]*Path, 0, len(importRt))
|
||||
nexthop := "0.0.0.0"
|
||||
for _, target := range importRt {
|
||||
nlri := bgp.NewRouteTargetMembershipNLRI(info.AS, target)
|
||||
pattr := make([]bgp.PathAttributeInterface, 0, 2)
|
||||
pattr = append(pattr, bgp.NewPathAttributeOrigin(bgp.BGP_ORIGIN_ATTR_TYPE_IGP))
|
||||
pattr = append(pattr, bgp.NewPathAttributeMpReachNLRI(nexthop, []bgp.AddrPrefixInterface{nlri}))
|
||||
msgs = append(msgs, NewPath(info, nlri, false, pattr, time.Now(), false))
|
||||
}
|
||||
return msgs, nil
|
||||
}
|
||||
|
||||
func (manager *TableManager) DeleteVrf(name string) ([]*Path, error) {
|
||||
if _, ok := manager.Vrfs[name]; !ok {
|
||||
return nil, fmt.Errorf("vrf %s not found", name)
|
||||
}
|
||||
msgs := make([]*Path, 0)
|
||||
vrf := manager.Vrfs[name]
|
||||
for _, t := range manager.Tables {
|
||||
msgs = append(msgs, t.deletePathsByVrf(vrf)...)
|
||||
}
|
||||
log.WithFields(log.Fields{
|
||||
"Topic": "Vrf",
|
||||
"Key": vrf.Name,
|
||||
"Rd": vrf.Rd,
|
||||
"ImportRt": vrf.ImportRt,
|
||||
"ExportRt": vrf.ExportRt,
|
||||
}).Debugf("delete vrf")
|
||||
delete(manager.Vrfs, name)
|
||||
rtcTable := manager.Tables[bgp.RF_RTC_UC]
|
||||
msgs = append(msgs, rtcTable.deleteRTCPathsByVrf(vrf, manager.Vrfs)...)
|
||||
return msgs, nil
|
||||
}
|
||||
|
||||
func (tm *TableManager) update(newPath *Path) *Update {
|
||||
t := tm.Tables[newPath.GetRouteFamily()]
|
||||
t.validatePath(newPath)
|
||||
dst := t.getOrCreateDest(newPath.GetNlri())
|
||||
u := dst.Calculate(newPath)
|
||||
if len(dst.knownPathList) == 0 {
|
||||
t.deleteDest(dst)
|
||||
}
|
||||
return u
|
||||
}
|
||||
|
||||
func (manager *TableManager) GetPathListByPeer(info *PeerInfo, rf bgp.RouteFamily) []*Path {
|
||||
if t, ok := manager.Tables[rf]; ok {
|
||||
pathList := make([]*Path, 0, len(t.destinations))
|
||||
for _, dst := range t.destinations {
|
||||
for _, p := range dst.knownPathList {
|
||||
if p.GetSource().Equal(info) {
|
||||
pathList = append(pathList, p)
|
||||
}
|
||||
}
|
||||
}
|
||||
return pathList
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (manager *TableManager) Update(newPath *Path) []*Update {
|
||||
if newPath == nil || newPath.IsEOR() {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Except for a special case with EVPN, we'll have one destination.
|
||||
updates := make([]*Update, 0, 1)
|
||||
family := newPath.GetRouteFamily()
|
||||
if _, ok := manager.Tables[family]; ok {
|
||||
updates = append(updates, manager.update(newPath))
|
||||
|
||||
if family == bgp.RF_EVPN {
|
||||
for _, p := range manager.handleMacMobility(newPath) {
|
||||
updates = append(updates, manager.update(p))
|
||||
}
|
||||
}
|
||||
}
|
||||
return updates
|
||||
}
|
||||
|
||||
// EVPN MAC MOBILITY HANDLING
|
||||
//
|
||||
// RFC7432 15. MAC Mobility
|
||||
//
|
||||
// A PE receiving a MAC/IP Advertisement route for a MAC address with a
|
||||
// different Ethernet segment identifier and a higher sequence number
|
||||
// than that which it had previously advertised withdraws its MAC/IP
|
||||
// Advertisement route.
|
||||
func (manager *TableManager) handleMacMobility(path *Path) []*Path {
|
||||
pathList := make([]*Path, 0)
|
||||
nlri := path.GetNlri().(*bgp.EVPNNLRI)
|
||||
if path.IsWithdraw || path.IsLocal() || nlri.RouteType != bgp.EVPN_ROUTE_TYPE_MAC_IP_ADVERTISEMENT {
|
||||
return nil
|
||||
}
|
||||
for _, path2 := range manager.GetPathList(GLOBAL_RIB_NAME, 0, []bgp.RouteFamily{bgp.RF_EVPN}) {
|
||||
if !path2.IsLocal() || path2.GetNlri().(*bgp.EVPNNLRI).RouteType != bgp.EVPN_ROUTE_TYPE_MAC_IP_ADVERTISEMENT {
|
||||
continue
|
||||
}
|
||||
f := func(p *Path) (bgp.EthernetSegmentIdentifier, net.HardwareAddr, int) {
|
||||
nlri := p.GetNlri().(*bgp.EVPNNLRI)
|
||||
d := nlri.RouteTypeData.(*bgp.EVPNMacIPAdvertisementRoute)
|
||||
ecs := p.GetExtCommunities()
|
||||
seq := -1
|
||||
for _, ec := range ecs {
|
||||
if t, st := ec.GetTypes(); t == bgp.EC_TYPE_EVPN && st == bgp.EC_SUBTYPE_MAC_MOBILITY {
|
||||
seq = int(ec.(*bgp.MacMobilityExtended).Sequence)
|
||||
break
|
||||
}
|
||||
}
|
||||
return d.ESI, d.MacAddress, seq
|
||||
}
|
||||
e1, m1, s1 := f(path)
|
||||
e2, m2, s2 := f(path2)
|
||||
if bytes.Equal(m1, m2) && !bytes.Equal(e1.Value, e2.Value) && s1 > s2 {
|
||||
pathList = append(pathList, path2.Clone(true))
|
||||
}
|
||||
}
|
||||
return pathList
|
||||
}
|
||||
|
||||
func (manager *TableManager) tables(list ...bgp.RouteFamily) []*Table {
|
||||
l := make([]*Table, 0, len(manager.Tables))
|
||||
if len(list) == 0 {
|
||||
for _, v := range manager.Tables {
|
||||
l = append(l, v)
|
||||
}
|
||||
return l
|
||||
}
|
||||
for _, f := range list {
|
||||
if t, ok := manager.Tables[f]; ok {
|
||||
l = append(l, t)
|
||||
}
|
||||
}
|
||||
return l
|
||||
}
|
||||
|
||||
func (manager *TableManager) getDestinationCount(rfList []bgp.RouteFamily) int {
|
||||
count := 0
|
||||
for _, t := range manager.tables(rfList...) {
|
||||
count += len(t.GetDestinations())
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
func (manager *TableManager) GetBestPathList(id string, as uint32, rfList []bgp.RouteFamily) []*Path {
|
||||
if SelectionOptions.DisableBestPathSelection {
|
||||
// Note: If best path selection disabled, there is no best path.
|
||||
return nil
|
||||
}
|
||||
paths := make([]*Path, 0, manager.getDestinationCount(rfList))
|
||||
for _, t := range manager.tables(rfList...) {
|
||||
paths = append(paths, t.Bests(id, as)...)
|
||||
}
|
||||
return paths
|
||||
}
|
||||
|
||||
func (manager *TableManager) GetBestMultiPathList(id string, rfList []bgp.RouteFamily) [][]*Path {
|
||||
if !UseMultiplePaths.Enabled || SelectionOptions.DisableBestPathSelection {
|
||||
// Note: If multi path not enabled or best path selection disabled,
|
||||
// there is no best multi path.
|
||||
return nil
|
||||
}
|
||||
paths := make([][]*Path, 0, manager.getDestinationCount(rfList))
|
||||
for _, t := range manager.tables(rfList...) {
|
||||
paths = append(paths, t.MultiBests(id)...)
|
||||
}
|
||||
return paths
|
||||
}
|
||||
|
||||
func (manager *TableManager) GetPathList(id string, as uint32, rfList []bgp.RouteFamily) []*Path {
|
||||
paths := make([]*Path, 0, manager.getDestinationCount(rfList))
|
||||
for _, t := range manager.tables(rfList...) {
|
||||
paths = append(paths, t.GetKnownPathList(id, as)...)
|
||||
}
|
||||
return paths
|
||||
}
|
||||
|
||||
func (manager *TableManager) GetPathListWithNexthop(id string, rfList []bgp.RouteFamily, nexthop net.IP) []*Path {
|
||||
paths := make([]*Path, 0, manager.getDestinationCount(rfList))
|
||||
for _, rf := range rfList {
|
||||
if t, ok := manager.Tables[rf]; ok {
|
||||
for _, path := range t.GetKnownPathList(id, 0) {
|
||||
if path.GetNexthop().Equal(nexthop) {
|
||||
paths = append(paths, path)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return paths
|
||||
}
|
||||
|
||||
func (manager *TableManager) GetPathListWithSource(id string, rfList []bgp.RouteFamily, source *PeerInfo) []*Path {
|
||||
paths := make([]*Path, 0, manager.getDestinationCount(rfList))
|
||||
for _, rf := range rfList {
|
||||
if t, ok := manager.Tables[rf]; ok {
|
||||
for _, path := range t.GetKnownPathList(id, 0) {
|
||||
if path.GetSource().Equal(source) {
|
||||
paths = append(paths, path)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return paths
|
||||
}
|
||||
|
||||
func (manager *TableManager) GetDestination(path *Path) *Destination {
|
||||
if path == nil {
|
||||
return nil
|
||||
}
|
||||
family := path.GetRouteFamily()
|
||||
t, ok := manager.Tables[family]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return t.GetDestination(path.GetNlri())
|
||||
}
|
||||
|
||||
func (manager *TableManager) TableInfo(id string, as uint32, family bgp.RouteFamily) (*TableInfo, error) {
|
||||
t, ok := manager.Tables[family]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("address family %s is not configured", family)
|
||||
}
|
||||
return t.Info(id, as), nil
|
||||
}
|
||||
53
vendor/github.com/osrg/gobgp/internal/pkg/table/vrf.go
generated
vendored
Normal file
53
vendor/github.com/osrg/gobgp/internal/pkg/table/vrf.go
generated
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
// Copyright (C) 2014-2016 Nippon Telegraph and Telephone Corporation.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package table
|
||||
|
||||
import (
|
||||
"github.com/osrg/gobgp/pkg/packet/bgp"
|
||||
)
|
||||
|
||||
type Vrf struct {
|
||||
Name string
|
||||
Id uint32
|
||||
Rd bgp.RouteDistinguisherInterface
|
||||
ImportRt []bgp.ExtendedCommunityInterface
|
||||
ExportRt []bgp.ExtendedCommunityInterface
|
||||
}
|
||||
|
||||
func (v *Vrf) Clone() *Vrf {
|
||||
f := func(rt []bgp.ExtendedCommunityInterface) []bgp.ExtendedCommunityInterface {
|
||||
l := make([]bgp.ExtendedCommunityInterface, 0, len(rt))
|
||||
return append(l, rt...)
|
||||
}
|
||||
return &Vrf{
|
||||
Name: v.Name,
|
||||
Id: v.Id,
|
||||
Rd: v.Rd,
|
||||
ImportRt: f(v.ImportRt),
|
||||
ExportRt: f(v.ExportRt),
|
||||
}
|
||||
}
|
||||
|
||||
func isLastTargetUser(vrfs map[string]*Vrf, target bgp.ExtendedCommunityInterface) bool {
|
||||
for _, vrf := range vrfs {
|
||||
for _, rt := range vrf.ImportRt {
|
||||
if target.String() == rt.String() {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
17
vendor/github.com/osrg/gobgp/internal/pkg/zebra/afi_string.go
generated
vendored
Normal file
17
vendor/github.com/osrg/gobgp/internal/pkg/zebra/afi_string.go
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
// Code generated by "stringer -type=AFI"; DO NOT EDIT.
|
||||
|
||||
package zebra
|
||||
|
||||
import "strconv"
|
||||
|
||||
const _AFI_name = "AFI_IPAFI_IP6AFI_ETHERAFI_MAX"
|
||||
|
||||
var _AFI_index = [...]uint8{0, 6, 13, 22, 29}
|
||||
|
||||
func (i AFI) String() string {
|
||||
i -= 1
|
||||
if i >= AFI(len(_AFI_index)-1) {
|
||||
return "AFI(" + strconv.FormatInt(int64(i+1), 10) + ")"
|
||||
}
|
||||
return _AFI_name[_AFI_index[i]:_AFI_index[i+1]]
|
||||
}
|
||||
16
vendor/github.com/osrg/gobgp/internal/pkg/zebra/api_type_string.go
generated
vendored
Normal file
16
vendor/github.com/osrg/gobgp/internal/pkg/zebra/api_type_string.go
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
// Code generated by "stringer -type=API_TYPE"; DO NOT EDIT.
|
||||
|
||||
package zebra
|
||||
|
||||
import "strconv"
|
||||
|
||||
const _API_TYPE_name = "FRR_ZAPI5_INTERFACE_ADDFRR_ZAPI5_INTERFACE_DELETEFRR_ZAPI5_INTERFACE_ADDRESS_ADDFRR_ZAPI5_INTERFACE_ADDRESS_DELETEFRR_ZAPI5_INTERFACE_UPFRR_ZAPI5_INTERFACE_DOWNFRR_ZAPI5_INTERFACE_SET_MASTERFRR_ZAPI5_ROUTE_ADDFRR_ZAPI5_ROUTE_DELETEFRR_ZAPI5_ROUTE_NOTIFY_OWNERFRR_ZAPI5_IPV4_ROUTE_ADDFRR_ZAPI5_IPV4_ROUTE_DELETEFRR_ZAPI5_IPV6_ROUTE_ADDFRR_ZAPI5_IPV6_ROUTE_DELETEFRR_ZAPI5_REDISTRIBUTE_ADDFRR_ZAPI5_REDISTRIBUTE_DELETEFRR_ZAPI5_REDISTRIBUTE_DEFAULT_ADDFRR_ZAPI5_REDISTRIBUTE_DEFAULT_DELETEFRR_ZAPI5_ROUTER_ID_ADDFRR_ZAPI5_ROUTER_ID_DELETEFRR_ZAPI5_ROUTER_ID_UPDATEFRR_ZAPI5_HELLOFRR_ZAPI5_CAPABILITIESFRR_ZAPI5_NEXTHOP_REGISTERFRR_ZAPI5_NEXTHOP_UNREGISTERFRR_ZAPI5_NEXTHOP_UPDATEFRR_ZAPI5_INTERFACE_NBR_ADDRESS_ADDFRR_ZAPI5_INTERFACE_NBR_ADDRESS_DELETEFRR_ZAPI5_INTERFACE_BFD_DEST_UPDATEFRR_ZAPI5_IMPORT_ROUTE_REGISTERFRR_ZAPI5_IMPORT_ROUTE_UNREGISTERFRR_ZAPI5_IMPORT_CHECK_UPDATEFRR_ZAPI5_IPV4_ROUTE_IPV6_NEXTHOP_ADDFRR_ZAPI5_BFD_DEST_REGISTERFRR_ZAPI5_BFD_DEST_DEREGISTERFRR_ZAPI5_BFD_DEST_UPDATEFRR_ZAPI5_BFD_DEST_REPLAYFRR_ZAPI5_REDISTRIBUTE_ROUTE_ADDFRR_ZAPI5_REDISTRIBUTE_ROUTE_DELFRR_ZAPI5_VRF_UNREGISTERFRR_ZAPI5_VRF_ADDFRR_ZAPI5_VRF_DELETEFRR_ZAPI5_VRF_LABELFRR_ZAPI5_INTERFACE_VRF_UPDATEFRR_ZAPI5_BFD_CLIENT_REGISTERFRR_ZAPI5_INTERFACE_ENABLE_RADVFRR_ZAPI5_INTERFACE_DISABLE_RADVFRR_ZAPI5_IPV4_NEXTHOP_LOOKUP_MRIBFRR_ZAPI5_INTERFACE_LINK_PARAMSFRR_ZAPI5_MPLS_LABELS_ADDFRR_ZAPI5_MPLS_LABELS_DELETEFRR_ZAPI5_IPMR_ROUTE_STATSFRR_ZAPI5_LABEL_MANAGER_CONNECTFRR_ZAPI5_GET_LABEL_CHUNKFRR_ZAPI5_RELEASE_LABEL_CHUNKFRR_ZAPI5_FEC_REGISTERFRR_ZAPI5_FEC_UNREGISTERFRR_ZAPI5_FEC_UPDATEFRR_ZAPI5_ADVERTISE_DEFAULT_GWFRR_ZAPI5_ADVERTISE_SUBNETFRR_ZAPI5_ADVERTISE_ALL_VNIFRR_ZAPI5_VNI_ADDFRR_ZAPI5_VNI_DELFRR_ZAPI5_L3VNI_ADDFRR_ZAPI5_L3VNI_DELFRR_ZAPI5_REMOTE_VTEP_ADDFRR_ZAPI5_REMOTE_VTEP_DELFRR_ZAPI5_MACIP_ADDFRR_ZAPI5_MACIP_DELFRR_ZAPI5_IP_PREFIX_ROUTE_ADDFRR_ZAPI5_IP_PREFIX_ROUTE_DELFRR_ZAPI5_REMOTE_MACIP_ADDFRR_ZAPI5_REMOTE_MACIP_DELFRR_ZAPI5_PW_ADDFRR_ZAPI5_PW_DELETEFRR_ZAPI5_PW_SETFRR_ZAPI5_PW_UNSETFRR_ZAPI5_PW_STATUS_UPDATEFRR_ZAPI5_RULE_ADDFRR_ZAPI5_RULE_DELETEFRR_ZAPI5_RULE_NOTIFY_OWNERFRR_ZAPI5_TABLE_MANAGER_CONNECTFRR_ZAPI5_GET_TABLE_CHUNKFRR_ZAPI5_RELEASE_TABLE_CHUNKFRR_ZAPI5_IPSET_CREATEFRR_ZAPI5_IPSET_DESTROYFRR_ZAPI5_IPSET_ENTRY_ADDFRR_ZAPI5_IPSET_ENTRY_DELETEFRR_ZAPI5_IPSET_NOTIFY_OWNERFRR_ZAPI5_IPSET_ENTRY_NOTIFY_OWNERFRR_ZAPI5_IPTABLE_ADDFRR_ZAPI5_IPTABLE_DELETEFRR_ZAPI5_IPTABLE_NOTIFY_OWNER"
|
||||
|
||||
var _API_TYPE_index = [...]uint16{0, 23, 49, 80, 114, 136, 160, 190, 209, 231, 259, 283, 310, 334, 361, 387, 416, 450, 487, 510, 536, 562, 577, 599, 625, 653, 677, 712, 750, 785, 816, 849, 878, 915, 942, 971, 996, 1021, 1053, 1085, 1109, 1126, 1146, 1165, 1195, 1224, 1255, 1287, 1321, 1352, 1377, 1405, 1431, 1462, 1487, 1516, 1538, 1562, 1582, 1612, 1638, 1665, 1682, 1699, 1718, 1737, 1762, 1787, 1806, 1825, 1854, 1883, 1909, 1935, 1951, 1970, 1986, 2004, 2030, 2048, 2069, 2096, 2127, 2152, 2181, 2203, 2226, 2251, 2279, 2307, 2341, 2362, 2386, 2416}
|
||||
|
||||
func (i API_TYPE) String() string {
|
||||
if i >= API_TYPE(len(_API_TYPE_index)-1) {
|
||||
return "API_TYPE(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
||||
return _API_TYPE_name[_API_TYPE_index[i]:_API_TYPE_index[i+1]]
|
||||
}
|
||||
16
vendor/github.com/osrg/gobgp/internal/pkg/zebra/link_type_string.go
generated
vendored
Normal file
16
vendor/github.com/osrg/gobgp/internal/pkg/zebra/link_type_string.go
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
// Code generated by "stringer -type=LINK_TYPE"; DO NOT EDIT.
|
||||
|
||||
package zebra
|
||||
|
||||
import "strconv"
|
||||
|
||||
const _LINK_TYPE_name = "LINK_TYPE_UNKNOWNLINK_TYPE_ETHERLINK_TYPE_EETHERLINK_TYPE_AX25LINK_TYPE_PRONETLINK_TYPE_IEEE802LINK_TYPE_ARCNETLINK_TYPE_APPLETLKLINK_TYPE_DLCILINK_TYPE_ATMLINK_TYPE_METRICOMLINK_TYPE_IEEE1394LINK_TYPE_EUI64LINK_TYPE_INFINIBANDLINK_TYPE_SLIPLINK_TYPE_CSLIPLINK_TYPE_SLIP6LINK_TYPE_CSLIP6LINK_TYPE_RSRVDLINK_TYPE_ADAPTLINK_TYPE_ROSELINK_TYPE_X25LINK_TYPE_PPPLINK_TYPE_CHDLCLINK_TYPE_LAPBLINK_TYPE_RAWHDLCLINK_TYPE_IPIPLINK_TYPE_IPIP6LINK_TYPE_FRADLINK_TYPE_SKIPLINK_TYPE_LOOPBACKLINK_TYPE_LOCALTLKLINK_TYPE_FDDILINK_TYPE_SITLINK_TYPE_IPDDPLINK_TYPE_IPGRELINK_TYPE_IP6GRELINK_TYPE_PIMREGLINK_TYPE_HIPPILINK_TYPE_ECONETLINK_TYPE_IRDALINK_TYPE_FCPPLINK_TYPE_FCALLINK_TYPE_FCPLLINK_TYPE_FCFABRICLINK_TYPE_IEEE802_TRLINK_TYPE_IEEE80211LINK_TYPE_IEEE80211_RADIOTAPLINK_TYPE_IEEE802154LINK_TYPE_IEEE802154_PHY"
|
||||
|
||||
var _LINK_TYPE_index = [...]uint16{0, 17, 32, 48, 62, 78, 95, 111, 129, 143, 156, 174, 192, 207, 227, 241, 256, 271, 287, 302, 317, 331, 344, 357, 372, 386, 403, 417, 432, 446, 460, 478, 496, 510, 523, 538, 553, 569, 585, 600, 616, 630, 644, 658, 672, 690, 710, 729, 757, 777, 801}
|
||||
|
||||
func (i LINK_TYPE) String() string {
|
||||
if i >= LINK_TYPE(len(_LINK_TYPE_index)-1) {
|
||||
return "LINK_TYPE(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
||||
return _LINK_TYPE_name[_LINK_TYPE_index[i]:_LINK_TYPE_index[i+1]]
|
||||
}
|
||||
41
vendor/github.com/osrg/gobgp/internal/pkg/zebra/nexthop_flag_string.go
generated
vendored
Normal file
41
vendor/github.com/osrg/gobgp/internal/pkg/zebra/nexthop_flag_string.go
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
// Code generated by "stringer -type=NEXTHOP_FLAG"; DO NOT EDIT.
|
||||
|
||||
package zebra
|
||||
|
||||
import "strconv"
|
||||
|
||||
const (
|
||||
_NEXTHOP_FLAG_name_0 = "NEXTHOP_FLAG_ACTIVENEXTHOP_FLAG_FIB"
|
||||
_NEXTHOP_FLAG_name_1 = "NEXTHOP_FLAG_RECURSIVE"
|
||||
_NEXTHOP_FLAG_name_2 = "NEXTHOP_FLAG_ONLINK"
|
||||
_NEXTHOP_FLAG_name_3 = "NEXTHOP_FLAG_MATCHED"
|
||||
_NEXTHOP_FLAG_name_4 = "NEXTHOP_FLAG_FILTERED"
|
||||
_NEXTHOP_FLAG_name_5 = "NEXTHOP_FLAG_DUPLICATE"
|
||||
_NEXTHOP_FLAG_name_6 = "NEXTHOP_FLAG_EVPN_RVTEP"
|
||||
)
|
||||
|
||||
var (
|
||||
_NEXTHOP_FLAG_index_0 = [...]uint8{0, 19, 35}
|
||||
)
|
||||
|
||||
func (i NEXTHOP_FLAG) String() string {
|
||||
switch {
|
||||
case 1 <= i && i <= 2:
|
||||
i -= 1
|
||||
return _NEXTHOP_FLAG_name_0[_NEXTHOP_FLAG_index_0[i]:_NEXTHOP_FLAG_index_0[i+1]]
|
||||
case i == 4:
|
||||
return _NEXTHOP_FLAG_name_1
|
||||
case i == 8:
|
||||
return _NEXTHOP_FLAG_name_2
|
||||
case i == 16:
|
||||
return _NEXTHOP_FLAG_name_3
|
||||
case i == 32:
|
||||
return _NEXTHOP_FLAG_name_4
|
||||
case i == 64:
|
||||
return _NEXTHOP_FLAG_name_5
|
||||
case i == 128:
|
||||
return _NEXTHOP_FLAG_name_6
|
||||
default:
|
||||
return "NEXTHOP_FLAG(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
||||
}
|
||||
17
vendor/github.com/osrg/gobgp/internal/pkg/zebra/nexthop_type_string.go
generated
vendored
Normal file
17
vendor/github.com/osrg/gobgp/internal/pkg/zebra/nexthop_type_string.go
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
// Code generated by "stringer -type=NEXTHOP_TYPE"; DO NOT EDIT.
|
||||
|
||||
package zebra
|
||||
|
||||
import "strconv"
|
||||
|
||||
const _NEXTHOP_TYPE_name = "FRR_NEXTHOP_TYPE_IFINDEXFRR_NEXTHOP_TYPE_IPV4FRR_NEXTHOP_TYPE_IPV4_IFINDEXFRR_NEXTHOP_TYPE_IPV6FRR_NEXTHOP_TYPE_IPV6_IFINDEXFRR_NEXTHOP_TYPE_BLACKHOLENEXTHOP_TYPE_IPV6_IFINDEXNEXTHOP_TYPE_IPV6_IFNAMENEXTHOP_TYPE_BLACKHOLE"
|
||||
|
||||
var _NEXTHOP_TYPE_index = [...]uint8{0, 24, 45, 74, 95, 124, 150, 175, 199, 221}
|
||||
|
||||
func (i NEXTHOP_TYPE) String() string {
|
||||
i -= 1
|
||||
if i >= NEXTHOP_TYPE(len(_NEXTHOP_TYPE_index)-1) {
|
||||
return "NEXTHOP_TYPE(" + strconv.FormatInt(int64(i+1), 10) + ")"
|
||||
}
|
||||
return _NEXTHOP_TYPE_name[_NEXTHOP_TYPE_index[i]:_NEXTHOP_TYPE_index[i+1]]
|
||||
}
|
||||
16
vendor/github.com/osrg/gobgp/internal/pkg/zebra/ptm_enable_string.go
generated
vendored
Normal file
16
vendor/github.com/osrg/gobgp/internal/pkg/zebra/ptm_enable_string.go
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
// Code generated by "stringer -type=PTM_ENABLE"; DO NOT EDIT.
|
||||
|
||||
package zebra
|
||||
|
||||
import "strconv"
|
||||
|
||||
const _PTM_ENABLE_name = "PTM_ENABLE_OFFPTM_ENABLE_ONPTM_ENABLE_UNSPEC"
|
||||
|
||||
var _PTM_ENABLE_index = [...]uint8{0, 14, 27, 44}
|
||||
|
||||
func (i PTM_ENABLE) String() string {
|
||||
if i >= PTM_ENABLE(len(_PTM_ENABLE_index)-1) {
|
||||
return "PTM_ENABLE(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
||||
return _PTM_ENABLE_name[_PTM_ENABLE_index[i]:_PTM_ENABLE_index[i+1]]
|
||||
}
|
||||
16
vendor/github.com/osrg/gobgp/internal/pkg/zebra/ptm_status_string.go
generated
vendored
Normal file
16
vendor/github.com/osrg/gobgp/internal/pkg/zebra/ptm_status_string.go
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
// Code generated by "stringer -type=PTM_STATUS"; DO NOT EDIT.
|
||||
|
||||
package zebra
|
||||
|
||||
import "strconv"
|
||||
|
||||
const _PTM_STATUS_name = "PTM_STATUS_DOWNPTM_STATUS_UPPTM_STATUS_UNKNOWN"
|
||||
|
||||
var _PTM_STATUS_index = [...]uint8{0, 15, 28, 46}
|
||||
|
||||
func (i PTM_STATUS) String() string {
|
||||
if i >= PTM_STATUS(len(_PTM_STATUS_index)-1) {
|
||||
return "PTM_STATUS(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
||||
return _PTM_STATUS_name[_PTM_STATUS_index[i]:_PTM_STATUS_index[i+1]]
|
||||
}
|
||||
16
vendor/github.com/osrg/gobgp/internal/pkg/zebra/route_type_string.go
generated
vendored
Normal file
16
vendor/github.com/osrg/gobgp/internal/pkg/zebra/route_type_string.go
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
// Code generated by "stringer -type=ROUTE_TYPE"; DO NOT EDIT.
|
||||
|
||||
package zebra
|
||||
|
||||
import "strconv"
|
||||
|
||||
const _ROUTE_TYPE_name = "FRR_ZAPI5_ROUTE_SYSTEMFRR_ZAPI5_ROUTE_KERNELFRR_ZAPI5_ROUTE_CONNECTFRR_ZAPI5_ROUTE_STATICFRR_ZAPI5_ROUTE_RIPFRR_ZAPI5_ROUTE_RIPNGFRR_ZAPI5_ROUTE_OSPFFRR_ZAPI5_ROUTE_OSPF6FRR_ZAPI5_ROUTE_ISISFRR_ZAPI5_ROUTE_BGPFRR_ZAPI5_ROUTE_PIMFRR_ZAPI5_ROUTE_EIGRPFRR_ZAPI5_ROUTE_NHRPFRR_ZAPI5_ROUTE_HSLSFRR_ZAPI5_ROUTE_OLSRFRR_ZAPI5_ROUTE_TABLEFRR_ZAPI5_ROUTE_LDPFRR_ZAPI5_ROUTE_VNCFRR_ZAPI5_ROUTE_VNC_DIRECTFRR_ZAPI5_ROUTE_VNC_DIRECT_RHFRR_ZAPI5_ROUTE_BGP_DIRECTFRR_ZAPI5_ROUTE_BGP_DIRECT_EXTFRR_ZAPI5_ROUTE_BABELFRR_ZAPI5_ROUTE_SHARPFRR_ZAPI5_ROUTE_PBRFRR_ZAPI5_ROUTE_ALLFRR_ZAPI5_ROUTE_MAX"
|
||||
|
||||
var _ROUTE_TYPE_index = [...]uint16{0, 22, 44, 67, 89, 108, 129, 149, 170, 190, 209, 228, 249, 269, 289, 309, 330, 349, 368, 394, 423, 449, 479, 500, 521, 540, 559, 578}
|
||||
|
||||
func (i ROUTE_TYPE) String() string {
|
||||
if i >= ROUTE_TYPE(len(_ROUTE_TYPE_index)-1) {
|
||||
return "ROUTE_TYPE(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
||||
return _ROUTE_TYPE_name[_ROUTE_TYPE_index[i]:_ROUTE_TYPE_index[i+1]]
|
||||
}
|
||||
17
vendor/github.com/osrg/gobgp/internal/pkg/zebra/safi_string.go
generated
vendored
Normal file
17
vendor/github.com/osrg/gobgp/internal/pkg/zebra/safi_string.go
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
// Code generated by "stringer -type=SAFI"; DO NOT EDIT.
|
||||
|
||||
package zebra
|
||||
|
||||
import "strconv"
|
||||
|
||||
const _SAFI_name = "SAFI_UNICASTSAFI_MULTICASTSAFI_RESERVED_3SAFI_MPLS_VPNSAFI_MAX"
|
||||
|
||||
var _SAFI_index = [...]uint8{0, 12, 26, 41, 54, 62}
|
||||
|
||||
func (i SAFI) String() string {
|
||||
i -= 1
|
||||
if i >= SAFI(len(_SAFI_index)-1) {
|
||||
return "SAFI(" + strconv.FormatInt(int64(i+1), 10) + ")"
|
||||
}
|
||||
return _SAFI_name[_SAFI_index[i]:_SAFI_index[i+1]]
|
||||
}
|
||||
2534
vendor/github.com/osrg/gobgp/internal/pkg/zebra/zapi.go
generated
vendored
Normal file
2534
vendor/github.com/osrg/gobgp/internal/pkg/zebra/zapi.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
58
vendor/github.com/osrg/gobgp/internal/pkg/zebra/zapi_bsd.go
generated
vendored
Normal file
58
vendor/github.com/osrg/gobgp/internal/pkg/zebra/zapi_bsd.go
generated
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
// Copyright (C) 2014, 2015 Nippon Telegraph and Telephone Corporation.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// +build freebsd netbsd openbsd
|
||||
|
||||
package zebra
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func intfflag2string(flag uint64) string {
|
||||
ss := make([]string, 0, 10)
|
||||
if flag&syscall.IFF_UP > 0 {
|
||||
ss = append(ss, "UP")
|
||||
}
|
||||
if flag&syscall.IFF_BROADCAST > 0 {
|
||||
ss = append(ss, "BROADCAST")
|
||||
}
|
||||
if flag&syscall.IFF_DEBUG > 0 {
|
||||
ss = append(ss, "DEBUG")
|
||||
}
|
||||
if flag&syscall.IFF_LOOPBACK > 0 {
|
||||
ss = append(ss, "LOOPBACK")
|
||||
}
|
||||
if flag&syscall.IFF_POINTOPOINT > 0 {
|
||||
ss = append(ss, "POINTOPOINT")
|
||||
}
|
||||
if flag&syscall.IFF_RUNNING > 0 {
|
||||
ss = append(ss, "RUNNING")
|
||||
}
|
||||
if flag&syscall.IFF_NOARP > 0 {
|
||||
ss = append(ss, "NOARP")
|
||||
}
|
||||
if flag&syscall.IFF_PROMISC > 0 {
|
||||
ss = append(ss, "PROMISC")
|
||||
}
|
||||
if flag&syscall.IFF_ALLMULTI > 0 {
|
||||
ss = append(ss, "ALLMULTI")
|
||||
}
|
||||
if flag&syscall.IFF_MULTICAST > 0 {
|
||||
ss = append(ss, "MULTICAST")
|
||||
}
|
||||
return strings.Join(ss, " | ")
|
||||
}
|
||||
59
vendor/github.com/osrg/gobgp/internal/pkg/zebra/zapi_darwin.go
generated
vendored
Normal file
59
vendor/github.com/osrg/gobgp/internal/pkg/zebra/zapi_darwin.go
generated
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
// Copyright (C) 2014, 2015 Nippon Telegraph and Telephone Corporation.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package zebra
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func intfflag2string(flag uint64) string {
|
||||
ss := make([]string, 0, 10)
|
||||
if flag&syscall.IFF_UP > 0 {
|
||||
ss = append(ss, "UP")
|
||||
}
|
||||
if flag&syscall.IFF_BROADCAST > 0 {
|
||||
ss = append(ss, "BROADCAST")
|
||||
}
|
||||
if flag&syscall.IFF_DEBUG > 0 {
|
||||
ss = append(ss, "DEBUG")
|
||||
}
|
||||
if flag&syscall.IFF_LOOPBACK > 0 {
|
||||
ss = append(ss, "LOOPBACK")
|
||||
}
|
||||
if flag&syscall.IFF_POINTOPOINT > 0 {
|
||||
ss = append(ss, "POINTOPOINT")
|
||||
}
|
||||
if flag&syscall.IFF_NOTRAILERS > 0 {
|
||||
ss = append(ss, "NOTRAILERS")
|
||||
}
|
||||
if flag&syscall.IFF_RUNNING > 0 {
|
||||
ss = append(ss, "RUNNING")
|
||||
}
|
||||
if flag&syscall.IFF_NOARP > 0 {
|
||||
ss = append(ss, "NOARP")
|
||||
}
|
||||
if flag&syscall.IFF_PROMISC > 0 {
|
||||
ss = append(ss, "PROMISC")
|
||||
}
|
||||
if flag&syscall.IFF_ALLMULTI > 0 {
|
||||
ss = append(ss, "ALLMULTI")
|
||||
}
|
||||
if flag&syscall.IFF_MULTICAST > 0 {
|
||||
ss = append(ss, "MULTICAST")
|
||||
}
|
||||
return strings.Join(ss, " | ")
|
||||
}
|
||||
83
vendor/github.com/osrg/gobgp/internal/pkg/zebra/zapi_linux.go
generated
vendored
Normal file
83
vendor/github.com/osrg/gobgp/internal/pkg/zebra/zapi_linux.go
generated
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
// Copyright (C) 2014, 2015 Nippon Telegraph and Telephone Corporation.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package zebra
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func intfflag2string(flag uint64) string {
|
||||
ss := make([]string, 0, 10)
|
||||
if flag&syscall.IFF_UP > 0 {
|
||||
ss = append(ss, "UP")
|
||||
}
|
||||
if flag&syscall.IFF_BROADCAST > 0 {
|
||||
ss = append(ss, "BROADCAST")
|
||||
}
|
||||
if flag&syscall.IFF_DEBUG > 0 {
|
||||
ss = append(ss, "DEBUG")
|
||||
}
|
||||
if flag&syscall.IFF_LOOPBACK > 0 {
|
||||
ss = append(ss, "LOOPBACK")
|
||||
}
|
||||
if flag&syscall.IFF_POINTOPOINT > 0 {
|
||||
ss = append(ss, "POINTOPOINT")
|
||||
}
|
||||
if flag&syscall.IFF_NOTRAILERS > 0 {
|
||||
ss = append(ss, "NOTRAILERS")
|
||||
}
|
||||
if flag&syscall.IFF_RUNNING > 0 {
|
||||
ss = append(ss, "RUNNING")
|
||||
}
|
||||
if flag&syscall.IFF_NOARP > 0 {
|
||||
ss = append(ss, "NOARP")
|
||||
}
|
||||
if flag&syscall.IFF_PROMISC > 0 {
|
||||
ss = append(ss, "PROMISC")
|
||||
}
|
||||
if flag&syscall.IFF_ALLMULTI > 0 {
|
||||
ss = append(ss, "ALLMULTI")
|
||||
}
|
||||
if flag&syscall.IFF_MASTER > 0 {
|
||||
ss = append(ss, "MASTER")
|
||||
}
|
||||
if flag&syscall.IFF_SLAVE > 0 {
|
||||
ss = append(ss, "SLAVE")
|
||||
}
|
||||
if flag&syscall.IFF_MULTICAST > 0 {
|
||||
ss = append(ss, "MULTICAST")
|
||||
}
|
||||
if flag&syscall.IFF_PORTSEL > 0 {
|
||||
ss = append(ss, "PORTSEL")
|
||||
}
|
||||
if flag&syscall.IFF_AUTOMEDIA > 0 {
|
||||
ss = append(ss, "AUTOMEDIA")
|
||||
}
|
||||
if flag&syscall.IFF_DYNAMIC > 0 {
|
||||
ss = append(ss, "DYNAMIC")
|
||||
}
|
||||
// if flag&syscall.IFF_LOWER_UP > 0 {
|
||||
// ss = append(ss, "LOWER_UP")
|
||||
// }
|
||||
// if flag&syscall.IFF_DORMANT > 0 {
|
||||
// ss = append(ss, "DORMANT")
|
||||
// }
|
||||
// if flag&syscall.IFF_ECHO > 0 {
|
||||
// ss = append(ss, "ECHO")
|
||||
// }
|
||||
return strings.Join(ss, " | ")
|
||||
}
|
||||
38
vendor/github.com/osrg/gobgp/internal/pkg/zebra/zapi_windows.go
generated
vendored
Normal file
38
vendor/github.com/osrg/gobgp/internal/pkg/zebra/zapi_windows.go
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
// Copyright (C) 2014, 2015 Nippon Telegraph and Telephone Corporation.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package zebra
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func intfflag2string(flag uint64) string {
|
||||
ss := make([]string, 0, 10)
|
||||
if flag&syscall.IFF_UP > 0 {
|
||||
ss = append(ss, "UP")
|
||||
}
|
||||
if flag&syscall.IFF_BROADCAST > 0 {
|
||||
ss = append(ss, "BROADCAST")
|
||||
}
|
||||
if flag&syscall.IFF_LOOPBACK > 0 {
|
||||
ss = append(ss, "LOOPBACK")
|
||||
}
|
||||
if flag&syscall.IFF_MULTICAST > 0 {
|
||||
ss = append(ss, "MULTICAST")
|
||||
}
|
||||
return strings.Join(ss, " | ")
|
||||
}
|
||||
Reference in New Issue
Block a user