client: add golang client library

Signed-off-by: Wataru Ishida <[email protected]>
This commit is contained in:
Wataru Ishida
2016-11-14 02:15:45 +00:00
parent 480eb32783
commit 3f2dd34d37
6 changed files with 1620 additions and 242 deletions
+395 -202
View File
@@ -17,13 +17,6 @@ package gobgpapi
import (
"fmt"
log "github.com/Sirupsen/logrus"
"github.com/osrg/gobgp/config"
"github.com/osrg/gobgp/packet/bgp"
"github.com/osrg/gobgp/server"
"github.com/osrg/gobgp/table"
"golang.org/x/net/context"
"google.golang.org/grpc"
"io"
"net"
"reflect"
@@ -32,6 +25,14 @@ import (
"strings"
"sync"
"time"
log "github.com/Sirupsen/logrus"
"github.com/osrg/gobgp/config"
"github.com/osrg/gobgp/packet/bgp"
"github.com/osrg/gobgp/server"
"github.com/osrg/gobgp/table"
"golang.org/x/net/context"
"google.golang.org/grpc"
)
type Server struct {
@@ -87,108 +88,108 @@ func (s *Server) Serve() error {
return nil
}
func (s *Server) GetNeighbor(ctx context.Context, arg *GetNeighborRequest) (*GetNeighborResponse, error) {
toApi := func(pconf *config.Neighbor) *Peer {
prefixLimits := make([]*PrefixLimit, 0, len(pconf.AfiSafis))
for _, family := range pconf.AfiSafis {
if c := family.PrefixLimit.Config; c.MaxPrefixes > 0 {
k, _ := bgp.GetRouteFamily(string(family.Config.AfiSafiName))
prefixLimits = append(prefixLimits, &PrefixLimit{
Family: uint32(k),
MaxPrefixes: c.MaxPrefixes,
ShutdownThresholdPct: uint32(c.ShutdownThresholdPct),
})
}
}
timer := pconf.Timers
s := pconf.State
localAddress := pconf.Transport.Config.LocalAddress
if pconf.Transport.State.LocalAddress != "" {
localAddress = pconf.Transport.State.LocalAddress
}
var remoteCap, localCap [][]byte
for _, cap := range pconf.State.RemoteCapabilityList {
c, _ := cap.Serialize()
remoteCap = append(remoteCap, c)
}
for _, cap := range pconf.State.LocalCapabilityList {
c, _ := cap.Serialize()
localCap = append(localCap, c)
}
return &Peer{
Conf: &PeerConf{
NeighborAddress: pconf.Config.NeighborAddress,
Id: s.RemoteRouterId,
PeerAs: pconf.Config.PeerAs,
LocalAs: pconf.Config.LocalAs,
PeerType: uint32(pconf.Config.PeerType.ToInt()),
AuthPassword: pconf.Config.AuthPassword,
RemovePrivateAs: uint32(pconf.Config.RemovePrivateAs.ToInt()),
RouteFlapDamping: pconf.Config.RouteFlapDamping,
SendCommunity: uint32(pconf.Config.SendCommunity.ToInt()),
Description: pconf.Config.Description,
PeerGroup: pconf.Config.PeerGroup,
RemoteCap: remoteCap,
LocalCap: localCap,
PrefixLimits: prefixLimits,
LocalAddress: localAddress,
NeighborInterface: pconf.Config.NeighborInterface,
Vrf: pconf.Config.Vrf,
},
Info: &PeerState{
BgpState: bgp.FSMState(s.SessionState.ToInt()).String(),
AdminState: s.AdminState,
Messages: &Messages{
Received: &Message{
NOTIFICATION: s.Messages.Received.Notification,
UPDATE: s.Messages.Received.Update,
OPEN: s.Messages.Received.Open,
KEEPALIVE: s.Messages.Received.Keepalive,
REFRESH: s.Messages.Received.Refresh,
DISCARDED: s.Messages.Received.Discarded,
TOTAL: s.Messages.Received.Total,
},
Sent: &Message{
NOTIFICATION: s.Messages.Sent.Notification,
UPDATE: s.Messages.Sent.Update,
OPEN: s.Messages.Sent.Open,
KEEPALIVE: s.Messages.Sent.Keepalive,
REFRESH: s.Messages.Sent.Refresh,
DISCARDED: s.Messages.Sent.Discarded,
TOTAL: s.Messages.Sent.Total,
},
},
Received: s.AdjTable.Received,
Accepted: s.AdjTable.Accepted,
Advertised: s.AdjTable.Advertised,
},
Timers: &Timers{
Config: &TimersConfig{
ConnectRetry: uint64(timer.Config.ConnectRetry),
HoldTime: uint64(timer.Config.HoldTime),
KeepaliveInterval: uint64(timer.Config.KeepaliveInterval),
},
State: &TimersState{
KeepaliveInterval: uint64(timer.State.KeepaliveInterval),
NegotiatedHoldTime: uint64(timer.State.NegotiatedHoldTime),
Uptime: uint64(timer.State.Uptime),
Downtime: uint64(timer.State.Downtime),
},
},
RouteReflector: &RouteReflector{
RouteReflectorClient: pconf.RouteReflector.Config.RouteReflectorClient,
RouteReflectorClusterId: string(pconf.RouteReflector.Config.RouteReflectorClusterId),
},
RouteServer: &RouteServer{
RouteServerClient: pconf.RouteServer.Config.RouteServerClient,
},
func NewPeerFromConfigStruct(pconf *config.Neighbor) *Peer {
prefixLimits := make([]*PrefixLimit, 0, len(pconf.AfiSafis))
for _, family := range pconf.AfiSafis {
if c := family.PrefixLimit.Config; c.MaxPrefixes > 0 {
k, _ := bgp.GetRouteFamily(string(family.Config.AfiSafiName))
prefixLimits = append(prefixLimits, &PrefixLimit{
Family: uint32(k),
MaxPrefixes: c.MaxPrefixes,
ShutdownThresholdPct: uint32(c.ShutdownThresholdPct),
})
}
}
timer := pconf.Timers
s := pconf.State
localAddress := pconf.Transport.Config.LocalAddress
if pconf.Transport.State.LocalAddress != "" {
localAddress = pconf.Transport.State.LocalAddress
}
var remoteCap, localCap [][]byte
for _, cap := range pconf.State.RemoteCapabilityList {
c, _ := cap.Serialize()
remoteCap = append(remoteCap, c)
}
for _, cap := range pconf.State.LocalCapabilityList {
c, _ := cap.Serialize()
localCap = append(localCap, c)
}
return &Peer{
Conf: &PeerConf{
NeighborAddress: pconf.Config.NeighborAddress,
Id: s.RemoteRouterId,
PeerAs: pconf.Config.PeerAs,
LocalAs: pconf.Config.LocalAs,
PeerType: uint32(pconf.Config.PeerType.ToInt()),
AuthPassword: pconf.Config.AuthPassword,
RemovePrivateAs: uint32(pconf.Config.RemovePrivateAs.ToInt()),
RouteFlapDamping: pconf.Config.RouteFlapDamping,
SendCommunity: uint32(pconf.Config.SendCommunity.ToInt()),
Description: pconf.Config.Description,
PeerGroup: pconf.Config.PeerGroup,
RemoteCap: remoteCap,
LocalCap: localCap,
PrefixLimits: prefixLimits,
LocalAddress: localAddress,
NeighborInterface: pconf.Config.NeighborInterface,
Vrf: pconf.Config.Vrf,
},
Info: &PeerState{
BgpState: string(s.SessionState),
AdminState: s.AdminState,
Messages: &Messages{
Received: &Message{
NOTIFICATION: s.Messages.Received.Notification,
UPDATE: s.Messages.Received.Update,
OPEN: s.Messages.Received.Open,
KEEPALIVE: s.Messages.Received.Keepalive,
REFRESH: s.Messages.Received.Refresh,
DISCARDED: s.Messages.Received.Discarded,
TOTAL: s.Messages.Received.Total,
},
Sent: &Message{
NOTIFICATION: s.Messages.Sent.Notification,
UPDATE: s.Messages.Sent.Update,
OPEN: s.Messages.Sent.Open,
KEEPALIVE: s.Messages.Sent.Keepalive,
REFRESH: s.Messages.Sent.Refresh,
DISCARDED: s.Messages.Sent.Discarded,
TOTAL: s.Messages.Sent.Total,
},
},
Received: s.AdjTable.Received,
Accepted: s.AdjTable.Accepted,
Advertised: s.AdjTable.Advertised,
},
Timers: &Timers{
Config: &TimersConfig{
ConnectRetry: uint64(timer.Config.ConnectRetry),
HoldTime: uint64(timer.Config.HoldTime),
KeepaliveInterval: uint64(timer.Config.KeepaliveInterval),
},
State: &TimersState{
KeepaliveInterval: uint64(timer.State.KeepaliveInterval),
NegotiatedHoldTime: uint64(timer.State.NegotiatedHoldTime),
Uptime: uint64(timer.State.Uptime),
Downtime: uint64(timer.State.Downtime),
},
},
RouteReflector: &RouteReflector{
RouteReflectorClient: pconf.RouteReflector.Config.RouteReflectorClient,
RouteReflectorClusterId: string(pconf.RouteReflector.Config.RouteReflectorClusterId),
},
RouteServer: &RouteServer{
RouteServerClient: pconf.RouteServer.Config.RouteServerClient,
},
}
}
func (s *Server) GetNeighbor(ctx context.Context, arg *GetNeighborRequest) (*GetNeighborResponse, error) {
p := []*Peer{}
for _, e := range s.bgpServer.GetNeighbor() {
p = append(p, toApi(e))
p = append(p, NewPeerFromConfigStruct(e))
}
return &GetNeighborResponse{Peers: p}, nil
}
@@ -205,20 +206,24 @@ func ToPathApi(path *table.Path) *Path {
}
return ret
}(path.GetPathAttrs())
return &Path{
Nlri: n,
Pattrs: pattrs,
Age: path.GetTimestamp().Unix(),
IsWithdraw: path.IsWithdraw,
Validation: int32(path.Validation().ToInt()),
Filtered: path.Filtered("") == table.POLICY_DIRECTION_IN,
Family: family,
SourceAsn: path.GetSource().AS,
SourceId: path.GetSource().ID.String(),
NeighborIp: path.GetSource().Address.String(),
Stale: path.IsStale(),
IsFromExternal: path.IsFromExternal(),
p := &Path{
Nlri: n,
Pattrs: pattrs,
Age: path.GetTimestamp().Unix(),
IsWithdraw: path.IsWithdraw,
Validation: int32(path.Validation().ToInt()),
Filtered: path.Filtered("") == table.POLICY_DIRECTION_IN,
Family: family,
Stale: path.IsStale(),
IsFromExternal: path.IsFromExternal(),
NoImplicitWithdraw: path.NoImplicitWithdraw(),
}
if s := path.GetSource(); s != nil {
p.SourceAsn = s.AS
p.SourceId = s.ID.String()
p.NeighborIp = s.Address.String()
}
return p
}
func (s *Server) GetRib(ctx context.Context, arg *GetRibRequest) (*GetRibResponse, error) {
@@ -776,80 +781,163 @@ func (s *Server) DeleteVrf(ctx context.Context, arg *DeleteVrfRequest) (*DeleteV
return &DeleteVrfResponse{}, s.bgpServer.DeleteVrf(arg.Vrf.Name)
}
func (s *Server) AddNeighbor(ctx context.Context, arg *AddNeighborRequest) (*AddNeighborResponse, error) {
c, err := func(a *Peer) (*config.Neighbor, error) {
pconf := &config.Neighbor{}
if a.Conf != nil {
pconf.Config.NeighborAddress = a.Conf.NeighborAddress
pconf.Config.PeerAs = a.Conf.PeerAs
pconf.Config.LocalAs = a.Conf.LocalAs
pconf.Config.AuthPassword = a.Conf.AuthPassword
pconf.Config.RemovePrivateAs = config.RemovePrivateAsOption(a.Conf.RemovePrivateAs)
pconf.Config.RouteFlapDamping = a.Conf.RouteFlapDamping
pconf.Config.SendCommunity = config.CommunityType(a.Conf.SendCommunity)
pconf.Config.Description = a.Conf.Description
pconf.Config.PeerGroup = a.Conf.PeerGroup
pconf.Config.NeighborAddress = a.Conf.NeighborAddress
pconf.Config.NeighborInterface = a.Conf.NeighborInterface
pconf.Config.Vrf = a.Conf.Vrf
func NewNeighborFromAPIStruct(a *Peer) (*config.Neighbor, error) {
pconf := &config.Neighbor{}
if a.Conf != nil {
pconf.Config.NeighborAddress = a.Conf.NeighborAddress
pconf.Config.PeerAs = a.Conf.PeerAs
pconf.Config.LocalAs = a.Conf.LocalAs
pconf.Config.AuthPassword = a.Conf.AuthPassword
pconf.Config.RemovePrivateAs = config.RemovePrivateAsOption(a.Conf.RemovePrivateAs)
pconf.Config.RouteFlapDamping = a.Conf.RouteFlapDamping
pconf.Config.SendCommunity = config.CommunityType(a.Conf.SendCommunity)
pconf.Config.Description = a.Conf.Description
pconf.Config.PeerGroup = a.Conf.PeerGroup
pconf.Config.NeighborAddress = a.Conf.NeighborAddress
pconf.Config.NeighborInterface = a.Conf.NeighborInterface
pconf.Config.Vrf = a.Conf.Vrf
f := func(bufs [][]byte) ([]bgp.ParameterCapabilityInterface, error) {
var caps []bgp.ParameterCapabilityInterface
for _, buf := range bufs {
cap, err := bgp.DecodeCapability(buf)
if err != nil {
return nil, err
}
caps = append(caps, cap)
}
return caps, nil
}
if a.Timers != nil && a.Timers.Config != nil {
localCaps, err := f(a.Conf.LocalCap)
if err != nil {
return nil, err
}
remoteCaps, err := f(a.Conf.RemoteCap)
if err != nil {
return nil, err
}
pconf.State.LocalCapabilityList = localCaps
pconf.State.RemoteCapabilityList = remoteCaps
pconf.State.RemoteRouterId = a.Conf.Id
for _, f := range a.Families {
family := bgp.RouteFamily(f)
pconf.AfiSafis = append(pconf.AfiSafis, config.AfiSafi{
Config: config.AfiSafiConfig{
AfiSafiName: config.AfiSafiType(family.String()),
Enabled: true,
},
})
}
for _, pl := range a.Conf.PrefixLimits {
for _, f := range pconf.AfiSafis {
if f.Config.AfiSafiName == config.AfiSafiType(bgp.RouteFamily(pl.Family).String()) {
f.PrefixLimit.Config.MaxPrefixes = pl.MaxPrefixes
f.PrefixLimit.Config.ShutdownThresholdPct = config.Percentage(pl.ShutdownThresholdPct)
}
}
}
}
if a.Timers != nil {
if a.Timers.Config != nil {
pconf.Timers.Config.ConnectRetry = float64(a.Timers.Config.ConnectRetry)
pconf.Timers.Config.HoldTime = float64(a.Timers.Config.HoldTime)
pconf.Timers.Config.KeepaliveInterval = float64(a.Timers.Config.KeepaliveInterval)
pconf.Timers.Config.MinimumAdvertisementInterval = float64(a.Timers.Config.MinimumAdvertisementInterval)
}
if a.RouteReflector != nil {
pconf.RouteReflector.Config.RouteReflectorClusterId = config.RrClusterIdType(a.RouteReflector.RouteReflectorClusterId)
pconf.RouteReflector.Config.RouteReflectorClient = a.RouteReflector.RouteReflectorClient
if a.Timers.State != nil {
pconf.Timers.State.KeepaliveInterval = float64(a.Timers.State.KeepaliveInterval)
pconf.Timers.State.NegotiatedHoldTime = float64(a.Timers.State.NegotiatedHoldTime)
pconf.Timers.State.Uptime = int64(a.Timers.State.Uptime)
pconf.Timers.State.Downtime = int64(a.Timers.State.Downtime)
}
if a.RouteServer != nil {
pconf.RouteServer.Config.RouteServerClient = a.RouteServer.RouteServerClient
}
if a.ApplyPolicy != nil {
if a.ApplyPolicy.ImportPolicy != nil {
pconf.ApplyPolicy.Config.DefaultImportPolicy = config.DefaultPolicyType(a.ApplyPolicy.ImportPolicy.Default)
for _, p := range a.ApplyPolicy.ImportPolicy.Policies {
pconf.ApplyPolicy.Config.ImportPolicyList = append(pconf.ApplyPolicy.Config.ImportPolicyList, p.Name)
}
}
if a.ApplyPolicy.ExportPolicy != nil {
pconf.ApplyPolicy.Config.DefaultExportPolicy = config.DefaultPolicyType(a.ApplyPolicy.ExportPolicy.Default)
for _, p := range a.ApplyPolicy.ExportPolicy.Policies {
pconf.ApplyPolicy.Config.ExportPolicyList = append(pconf.ApplyPolicy.Config.ExportPolicyList, p.Name)
}
}
if a.ApplyPolicy.InPolicy != nil {
pconf.ApplyPolicy.Config.DefaultInPolicy = config.DefaultPolicyType(a.ApplyPolicy.InPolicy.Default)
for _, p := range a.ApplyPolicy.InPolicy.Policies {
pconf.ApplyPolicy.Config.InPolicyList = append(pconf.ApplyPolicy.Config.InPolicyList, p.Name)
}
}
if a.RouteReflector != nil {
pconf.RouteReflector.Config.RouteReflectorClusterId = config.RrClusterIdType(a.RouteReflector.RouteReflectorClusterId)
pconf.RouteReflector.Config.RouteReflectorClient = a.RouteReflector.RouteReflectorClient
}
if a.RouteServer != nil {
pconf.RouteServer.Config.RouteServerClient = a.RouteServer.RouteServerClient
}
if a.ApplyPolicy != nil {
if a.ApplyPolicy.ImportPolicy != nil {
pconf.ApplyPolicy.Config.DefaultImportPolicy = config.DefaultPolicyType(a.ApplyPolicy.ImportPolicy.Default)
for _, p := range a.ApplyPolicy.ImportPolicy.Policies {
pconf.ApplyPolicy.Config.ImportPolicyList = append(pconf.ApplyPolicy.Config.ImportPolicyList, p.Name)
}
}
if a.Families != nil {
for _, family := range a.Families {
name, ok := bgp.AddressFamilyNameMap[bgp.RouteFamily(family)]
if !ok {
return pconf, fmt.Errorf("invalid address family: %d", family)
}
cAfiSafi := config.AfiSafi{
Config: config.AfiSafiConfig{
AfiSafiName: config.AfiSafiType(name),
},
}
pconf.AfiSafis = append(pconf.AfiSafis, cAfiSafi)
if a.ApplyPolicy.ExportPolicy != nil {
pconf.ApplyPolicy.Config.DefaultExportPolicy = config.DefaultPolicyType(a.ApplyPolicy.ExportPolicy.Default)
for _, p := range a.ApplyPolicy.ExportPolicy.Policies {
pconf.ApplyPolicy.Config.ExportPolicyList = append(pconf.ApplyPolicy.Config.ExportPolicyList, p.Name)
}
}
if a.Transport != nil {
pconf.Transport.Config.LocalAddress = a.Transport.LocalAddress
pconf.Transport.Config.PassiveMode = a.Transport.PassiveMode
if a.ApplyPolicy.InPolicy != nil {
pconf.ApplyPolicy.Config.DefaultInPolicy = config.DefaultPolicyType(a.ApplyPolicy.InPolicy.Default)
for _, p := range a.ApplyPolicy.InPolicy.Policies {
pconf.ApplyPolicy.Config.InPolicyList = append(pconf.ApplyPolicy.Config.InPolicyList, p.Name)
}
}
if a.EbgpMultihop != nil {
pconf.EbgpMultihop.Config.Enabled = a.EbgpMultihop.Enabled
pconf.EbgpMultihop.Config.MultihopTtl = uint8(a.EbgpMultihop.MultihopTtl)
}
if a.Families != nil {
for _, family := range a.Families {
name, ok := bgp.AddressFamilyNameMap[bgp.RouteFamily(family)]
if !ok {
return pconf, fmt.Errorf("invalid address family: %d", family)
}
cAfiSafi := config.AfiSafi{
Config: config.AfiSafiConfig{
AfiSafiName: config.AfiSafiType(name),
},
}
pconf.AfiSafis = append(pconf.AfiSafis, cAfiSafi)
}
return pconf, nil
}(arg.Peer)
}
if a.Transport != nil {
pconf.Transport.Config.LocalAddress = a.Transport.LocalAddress
pconf.Transport.Config.PassiveMode = a.Transport.PassiveMode
}
if a.EbgpMultihop != nil {
pconf.EbgpMultihop.Config.Enabled = a.EbgpMultihop.Enabled
pconf.EbgpMultihop.Config.MultihopTtl = uint8(a.EbgpMultihop.MultihopTtl)
}
if a.Info != nil {
pconf.State.SessionState = config.SessionState(a.Info.BgpState)
pconf.State.AdminState = a.Info.AdminState
pconf.State.AdjTable.Received = a.Info.Received
pconf.State.AdjTable.Accepted = a.Info.Accepted
pconf.State.AdjTable.Advertised = a.Info.Advertised
if a.Info.Messages != nil {
if a.Info.Messages.Sent != nil {
pconf.State.Messages.Sent.Update = a.Info.Messages.Sent.UPDATE
pconf.State.Messages.Sent.Notification = a.Info.Messages.Sent.NOTIFICATION
pconf.State.Messages.Sent.Open = a.Info.Messages.Sent.OPEN
pconf.State.Messages.Sent.Refresh = a.Info.Messages.Sent.REFRESH
pconf.State.Messages.Sent.Keepalive = a.Info.Messages.Sent.KEEPALIVE
pconf.State.Messages.Sent.Discarded = a.Info.Messages.Sent.DISCARDED
pconf.State.Messages.Sent.Total = a.Info.Messages.Sent.TOTAL
}
if a.Info.Messages.Received != nil {
pconf.State.Messages.Received.Update = a.Info.Messages.Received.UPDATE
pconf.State.Messages.Received.Open = a.Info.Messages.Received.OPEN
pconf.State.Messages.Received.Refresh = a.Info.Messages.Received.REFRESH
pconf.State.Messages.Received.Keepalive = a.Info.Messages.Received.KEEPALIVE
pconf.State.Messages.Received.Discarded = a.Info.Messages.Received.DISCARDED
pconf.State.Messages.Received.Total = a.Info.Messages.Received.TOTAL
}
}
}
return pconf, nil
}
func (s *Server) AddNeighbor(ctx context.Context, arg *AddNeighborRequest) (*AddNeighborResponse, error) {
c, err := NewNeighborFromAPIStruct(arg.Peer)
if err != nil {
return nil, err
}
@@ -880,6 +968,70 @@ func NewPrefixFromApiStruct(a *Prefix) (*table.Prefix, error) {
}, nil
}
func NewAPIPrefixFromConfigStruct(c config.Prefix) (*Prefix, error) {
min, max, err := config.ParseMaskLength(c.IpPrefix, c.MasklengthRange)
if err != nil {
return nil, err
}
return &Prefix{
IpPrefix: c.IpPrefix,
MaskLengthMin: uint32(min),
MaskLengthMax: uint32(max),
}, nil
}
func NewAPIDefinedSetFromTableStruct(t table.DefinedSet) (*DefinedSet, error) {
a := &DefinedSet{
Type: DefinedType(t.Type()),
Name: t.Name(),
}
switch t.Type() {
case table.DEFINED_TYPE_PREFIX:
s := t.(*table.PrefixSet)
c := s.ToConfig()
for _, p := range c.PrefixList {
ap, err := NewAPIPrefixFromConfigStruct(p)
if err != nil {
return nil, err
}
a.Prefixes = append(a.Prefixes, ap)
}
case table.DEFINED_TYPE_NEIGHBOR:
s := t.(*table.NeighborSet)
c := s.ToConfig()
for _, n := range c.NeighborInfoList {
a.List = append(a.List, n)
}
case table.DEFINED_TYPE_AS_PATH:
s := t.(*table.AsPathSet)
c := s.ToConfig()
for _, n := range c.AsPathList {
a.List = append(a.List, n)
}
case table.DEFINED_TYPE_COMMUNITY:
s := t.(*table.CommunitySet)
c := s.ToConfig()
for _, n := range c.CommunityList {
a.List = append(a.List, n)
}
case table.DEFINED_TYPE_EXT_COMMUNITY:
s := t.(*table.ExtCommunitySet)
c := s.ToConfig()
for _, n := range c.ExtCommunityList {
a.List = append(a.List, n)
}
case table.DEFINED_TYPE_LARGE_COMMUNITY:
s := t.(*table.LargeCommunitySet)
c := s.ToConfig()
for _, n := range c.LargeCommunityList {
a.List = append(a.List, n)
}
default:
return nil, fmt.Errorf("invalid defined type")
}
return a, nil
}
func NewDefinedSetFromApiStruct(a *DefinedSet) (table.DefinedSet, error) {
if a.Name == "" {
return nil, fmt.Errorf("empty neighbor set name")
@@ -1024,6 +1176,10 @@ func (s *Server) ReplaceDefinedSet(ctx context.Context, arg *ReplaceDefinedSetRe
return &ReplaceDefinedSetResponse{}, s.bgpServer.ReplaceDefinedSet(set)
}
func NewAPIStatementFromTableStruct(t *table.Statement) *Statement {
return toStatementApi(t.ToConfig())
}
func toStatementApi(s *config.Statement) *Statement {
cs := &Conditions{}
if s.Conditions.MatchPrefixSet.PrefixSet != "" {
@@ -1076,8 +1232,7 @@ func toStatementApi(s *config.Statement) *Statement {
RouteAction: func() RouteAction {
if s.Actions.RouteDisposition.AcceptRoute {
return RouteAction_ACCEPT
}
if s.Actions.RouteDisposition.RejectRoute {
} else if s.Actions.RouteDisposition.RejectRoute {
return RouteAction_REJECT
}
return RouteAction_NONE
@@ -1536,6 +1691,10 @@ func (s *Server) ReplaceStatement(ctx context.Context, arg *ReplaceStatementRequ
return &ReplaceStatementResponse{}, err
}
func NewAPIPolicyFromTableStruct(p *table.Policy) *Policy {
return toPolicyApi(p.ToConfig())
}
func toPolicyApi(p *config.PolicyDefinition) *Policy {
return &Policy{
Name: p.Name,
@@ -1549,6 +1708,46 @@ func toPolicyApi(p *config.PolicyDefinition) *Policy {
}
}
func NewAPIPolicyAssignmentFromTableStruct(t *table.PolicyAssignment) *PolicyAssignment {
return &PolicyAssignment{
Type: func() PolicyType {
switch t.Type {
case table.POLICY_DIRECTION_IN:
return PolicyType_IN
case table.POLICY_DIRECTION_IMPORT:
return PolicyType_IMPORT
case table.POLICY_DIRECTION_EXPORT:
return PolicyType_EXPORT
}
log.Errorf("invalid policy-type: %s", t.Type)
return PolicyType(-1)
}(),
Default: func() RouteAction {
switch t.Default {
case table.ROUTE_TYPE_ACCEPT:
return RouteAction_ACCEPT
case table.ROUTE_TYPE_REJECT:
return RouteAction_REJECT
}
return RouteAction_NONE
}(),
Name: t.Name,
Resource: func() Resource {
if t.Name != "" {
return Resource_LOCAL
}
return Resource_GLOBAL
}(),
Policies: func() []*Policy {
l := make([]*Policy, 0)
for _, p := range t.Policies {
l = append(l, NewAPIPolicyFromTableStruct(p))
}
return l
}(),
}
}
func NewPolicyFromApiStruct(a *Policy) (*table.Policy, error) {
if a.Name == "" {
return nil, fmt.Errorf("empty policy name")
@@ -1635,31 +1834,25 @@ func (s *Server) GetPolicyAssignment(ctx context.Context, arg *GetPolicyAssignme
if err != nil {
return nil, err
}
d, a, err := s.bgpServer.GetPolicyAssignment(name, dir)
def, pols, err := s.bgpServer.GetPolicyAssignment(name, dir)
if err != nil {
return nil, err
}
return &GetPolicyAssignmentResponse{
Assignment: &PolicyAssignment{
Default: func() RouteAction {
switch d {
case table.ROUTE_TYPE_ACCEPT:
return RouteAction_ACCEPT
case table.ROUTE_TYPE_REJECT:
return RouteAction_REJECT
}
return RouteAction_NONE
}(),
Policies: func() []*Policy {
l := make([]*Policy, 0)
for _, p := range a {
l = append(l, toPolicyApi(p))
}
return l
}(),
},
}, err
policies := make([]*table.Policy, 0, len(pols))
for _, p := range pols {
t, err := table.NewPolicy(*p)
if err != nil {
return nil, err
}
policies = append(policies, t)
}
t := &table.PolicyAssignment{
Name: name,
Type: dir,
Default: def,
Policies: policies,
}
return &GetPolicyAssignmentResponse{NewAPIPolicyAssignmentFromTableStruct(t)}, err
}
func defaultRouteType(d RouteAction) table.RouteType {
+900
View File
@@ -0,0 +1,900 @@
// 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 client provides a wrapper for GoBGP's gRPC API
package client
import (
"fmt"
"net"
"strconv"
"time"
api "github.com/osrg/gobgp/api"
"github.com/osrg/gobgp/config"
"github.com/osrg/gobgp/packet/bgp"
"github.com/osrg/gobgp/server"
"github.com/osrg/gobgp/table"
"golang.org/x/net/context"
"google.golang.org/grpc"
)
type GoBGPClient struct {
conn *grpc.ClientConn
cli api.GobgpApiClient
}
func defaultGRPCOptions() []grpc.DialOption {
return []grpc.DialOption{grpc.WithTimeout(time.Second), grpc.WithBlock(), grpc.WithInsecure()}
}
func NewGoBGPClient(target string, opts ...grpc.DialOption) (*GoBGPClient, error) {
if target == "" {
target = ":50051"
}
if len(opts) == 0 {
opts = defaultGRPCOptions()
}
conn, err := grpc.Dial(target, opts...)
if err != nil {
return nil, err
}
cli := api.NewGobgpApiClient(conn)
return &GoBGPClient{conn: conn, cli: cli}, nil
}
func (cli *GoBGPClient) Close() error {
return cli.conn.Close()
}
func (cli *GoBGPClient) StartServer(c *config.Global) error {
_, err := cli.cli.StartServer(context.Background(), &api.StartServerRequest{
Global: &api.Global{
As: c.Config.As,
RouterId: c.Config.RouterId,
ListenPort: c.Config.Port,
ListenAddresses: c.Config.LocalAddressList,
UseMultiplePaths: c.UseMultiplePaths.Config.Enabled,
},
})
return err
}
func (cli *GoBGPClient) StopServer() error {
_, err := cli.cli.StopServer(context.Background(), &api.StopServerRequest{})
return err
}
func (cli *GoBGPClient) GetServer() (*config.Global, error) {
ret, err := cli.cli.GetServer(context.Background(), &api.GetServerRequest{})
if err != nil {
return nil, err
}
return &config.Global{
Config: config.GlobalConfig{
As: ret.Global.As,
RouterId: ret.Global.RouterId,
Port: ret.Global.ListenPort,
LocalAddressList: ret.Global.ListenAddresses,
},
UseMultiplePaths: config.UseMultiplePaths{
Config: config.UseMultiplePathsConfig{
Enabled: ret.Global.UseMultiplePaths,
},
},
}, nil
}
func (cli *GoBGPClient) GetNeighbor() ([]*config.Neighbor, error) {
ret, err := cli.cli.GetNeighbor(context.Background(), &api.GetNeighborRequest{})
if err != nil {
return nil, err
}
neighbors := make([]*config.Neighbor, 0, len(ret.Peers))
for _, p := range ret.Peers {
n, err := api.NewNeighborFromAPIStruct(p)
if err != nil {
return nil, err
}
neighbors = append(neighbors, n)
}
return neighbors, nil
}
func (cli *GoBGPClient) AddNeighbor(c *config.Neighbor) error {
peer := api.NewPeerFromConfigStruct(c)
_, err := cli.cli.AddNeighbor(context.Background(), &api.AddNeighborRequest{peer})
return err
}
func (cli *GoBGPClient) DeleteNeighbor(c *config.Neighbor) error {
peer := api.NewPeerFromConfigStruct(c)
_, err := cli.cli.DeleteNeighbor(context.Background(), &api.DeleteNeighborRequest{peer})
return err
}
//func (cli *GoBGPClient) UpdateNeighbor(c *config.Neighbor) (bool, error) {
//}
func (cli *GoBGPClient) ShutdownNeighbor(addr string) error {
_, err := cli.cli.ShutdownNeighbor(context.Background(), &api.ShutdownNeighborRequest{addr})
return err
}
func (cli *GoBGPClient) ResetNeighbor(addr string) error {
_, err := cli.cli.ResetNeighbor(context.Background(), &api.ResetNeighborRequest{addr})
return err
}
func (cli *GoBGPClient) EnableNeighbor(addr string) error {
_, err := cli.cli.EnableNeighbor(context.Background(), &api.EnableNeighborRequest{addr})
return err
}
func (cli *GoBGPClient) DisableNeighbor(addr string) error {
_, err := cli.cli.DisableNeighbor(context.Background(), &api.DisableNeighborRequest{addr})
return err
}
func (cli *GoBGPClient) softreset(addr string, family bgp.RouteFamily, dir api.SoftResetNeighborRequest_SoftResetDirection) error {
_, err := cli.cli.SoftResetNeighbor(context.Background(), &api.SoftResetNeighborRequest{
Address: addr,
Direction: dir,
})
return err
}
func (cli *GoBGPClient) SoftResetIn(addr string, family bgp.RouteFamily) error {
return cli.softreset(addr, family, api.SoftResetNeighborRequest_IN)
}
func (cli *GoBGPClient) SoftResetOut(addr string, family bgp.RouteFamily) error {
return cli.softreset(addr, family, api.SoftResetNeighborRequest_OUT)
}
func (cli *GoBGPClient) SoftReset(addr string, family bgp.RouteFamily) error {
return cli.softreset(addr, family, api.SoftResetNeighborRequest_BOTH)
}
func (cli *GoBGPClient) getRIB(resource api.Resource, name string, family bgp.RouteFamily, prefixes []*table.LookupPrefix) (*table.Table, error) {
dsts := make([]*api.Destination, 0, len(prefixes))
for _, p := range prefixes {
longer := false
shorter := false
if p.LookupOption&table.LOOKUP_LONGER > 0 {
longer = true
}
if p.LookupOption&table.LOOKUP_SHORTER > 0 {
shorter = true
}
dsts = append(dsts, &api.Destination{
Prefix: p.Prefix,
LongerPrefixes: longer,
ShorterPrefixes: shorter,
})
}
res, err := cli.cli.GetRib(context.Background(), &api.GetRibRequest{
Table: &api.Table{
Type: resource,
Family: uint32(family),
Name: name,
Destinations: dsts,
},
})
if err != nil {
return nil, err
}
return res.Table.ToNativeTable()
}
func (cli *GoBGPClient) GetRIB(family bgp.RouteFamily, prefixes []*table.LookupPrefix) (*table.Table, error) {
return cli.getRIB(api.Resource_GLOBAL, "", family, prefixes)
}
func (cli *GoBGPClient) GetLocalRIB(name string, family bgp.RouteFamily, prefixes []*table.LookupPrefix) (*table.Table, error) {
return cli.getRIB(api.Resource_LOCAL, name, family, prefixes)
}
func (cli *GoBGPClient) GetAdjRIBIn(name string, family bgp.RouteFamily, prefixes []*table.LookupPrefix) (*table.Table, error) {
return cli.getRIB(api.Resource_ADJ_IN, name, family, prefixes)
}
func (cli *GoBGPClient) GetAdjRIBOut(name string, family bgp.RouteFamily, prefixes []*table.LookupPrefix) (*table.Table, error) {
return cli.getRIB(api.Resource_ADJ_OUT, name, family, prefixes)
}
func (cli *GoBGPClient) GetVRFRIB(name string, family bgp.RouteFamily, prefixes []*table.LookupPrefix) (*table.Table, error) {
return cli.getRIB(api.Resource_VRF, name, family, prefixes)
}
func (cli *GoBGPClient) getRIBInfo(resource api.Resource, name string, family bgp.RouteFamily) (*table.TableInfo, error) {
res, err := cli.cli.GetRibInfo(context.Background(), &api.GetRibInfoRequest{
Info: &api.TableInfo{
Type: resource,
Name: name,
Family: uint32(family),
},
})
if err != nil {
return nil, err
}
return &table.TableInfo{
NumDestination: int(res.Info.NumDestination),
NumPath: int(res.Info.NumPath),
NumAccepted: int(res.Info.NumAccepted),
}, nil
}
func (cli *GoBGPClient) GetRIBInfo(family bgp.RouteFamily) (*table.TableInfo, error) {
return cli.getRIBInfo(api.Resource_GLOBAL, "", family)
}
func (cli *GoBGPClient) GetLocalRIBInfo(name string, family bgp.RouteFamily) (*table.TableInfo, error) {
return cli.getRIBInfo(api.Resource_LOCAL, name, family)
}
func (cli *GoBGPClient) GetAdjRIBInInfo(name string, family bgp.RouteFamily) (*table.TableInfo, error) {
return cli.getRIBInfo(api.Resource_ADJ_IN, name, family)
}
func (cli *GoBGPClient) GetAdjRIBOutInfo(name string, family bgp.RouteFamily) (*table.TableInfo, error) {
return cli.getRIBInfo(api.Resource_ADJ_OUT, name, family)
}
type AddPathByStreamClient struct {
stream api.GobgpApi_InjectMrtClient
}
func (c *AddPathByStreamClient) Send(paths ...*table.Path) error {
ps := make([]*api.Path, 0, len(paths))
for _, p := range paths {
ps = append(ps, api.ToPathApi(p))
}
return c.stream.Send(&api.InjectMrtRequest{
Resource: api.Resource_GLOBAL,
Paths: ps,
})
}
func (c *AddPathByStreamClient) Close() error {
_, err := c.stream.CloseAndRecv()
return err
}
func (cli *GoBGPClient) AddPathByStream() (*AddPathByStreamClient, error) {
stream, err := cli.cli.InjectMrt(context.Background())
if err != nil {
return nil, err
}
return &AddPathByStreamClient{stream}, nil
}
func (cli *GoBGPClient) addPath(vrfID string, pathList []*table.Path) ([]byte, error) {
resource := api.Resource_GLOBAL
if vrfID != "" {
resource = api.Resource_VRF
}
var uuid []byte
for _, path := range pathList {
r, err := cli.cli.AddPath(context.Background(), &api.AddPathRequest{
Resource: resource,
VrfId: vrfID,
Path: api.ToPathApi(path),
})
if err != nil {
return nil, err
}
uuid = r.Uuid
}
return uuid, nil
}
func (cli *GoBGPClient) AddPath(pathList []*table.Path) ([]byte, error) {
return cli.addPath("", pathList)
}
func (cli *GoBGPClient) AddVRFPath(vrfID string, pathList []*table.Path) ([]byte, error) {
if vrfID == "" {
return nil, fmt.Errorf("VRF ID is empty")
}
return cli.addPath(vrfID, pathList)
}
func (cli *GoBGPClient) deletePath(uuid []byte, f bgp.RouteFamily, vrfID string, pathList []*table.Path) error {
var reqs []*api.DeletePathRequest
resource := api.Resource_GLOBAL
if vrfID != "" {
resource = api.Resource_VRF
}
switch {
case len(pathList) != 0:
for _, path := range pathList {
nlri := path.GetNlri()
n, err := nlri.Serialize()
if err != nil {
return err
}
p := &api.Path{
Nlri: n,
Family: uint32(path.GetRouteFamily()),
}
reqs = append(reqs, &api.DeletePathRequest{
Resource: resource,
VrfId: vrfID,
Path: p,
})
}
default:
reqs = append(reqs, &api.DeletePathRequest{
Resource: resource,
VrfId: vrfID,
Uuid: uuid,
Family: uint32(f),
})
}
for _, req := range reqs {
if _, err := cli.cli.DeletePath(context.Background(), req); err != nil {
return err
}
}
return nil
}
func (cli *GoBGPClient) DeletePath(pathList []*table.Path) error {
return cli.deletePath(nil, bgp.RouteFamily(0), "", pathList)
}
func (cli *GoBGPClient) DeleteVRFPath(vrfID string, pathList []*table.Path) error {
if vrfID == "" {
return fmt.Errorf("VRF ID is empty")
}
return cli.deletePath(nil, bgp.RouteFamily(0), vrfID, pathList)
}
func (cli *GoBGPClient) DeletePathByUUID(uuid []byte) error {
return cli.deletePath(uuid, bgp.RouteFamily(0), "", nil)
}
func (cli *GoBGPClient) DeletePathByFamily(family bgp.RouteFamily) error {
return cli.deletePath(nil, family, "", nil)
}
func (cli *GoBGPClient) GetVRF() ([]*table.Vrf, error) {
ret, err := cli.cli.GetVrf(context.Background(), &api.GetVrfRequest{})
if err != nil {
return nil, err
}
var vrfs []*table.Vrf
f := func(bufs [][]byte) ([]bgp.ExtendedCommunityInterface, error) {
ret := make([]bgp.ExtendedCommunityInterface, 0, len(bufs))
for _, rt := range bufs {
r, err := bgp.ParseExtended(rt)
if err != nil {
return nil, err
}
ret = append(ret, r)
}
return ret, nil
}
for _, vrf := range ret.Vrfs {
importRT, err := f(vrf.ImportRt)
if err != nil {
return nil, err
}
exportRT, err := f(vrf.ExportRt)
if err != nil {
return nil, err
}
vrfs = append(vrfs, &table.Vrf{
Name: vrf.Name,
Id: vrf.Id,
Rd: bgp.GetRouteDistinguisher(vrf.Rd),
ImportRt: importRT,
ExportRt: exportRT,
})
}
return vrfs, nil
}
func (cli *GoBGPClient) AddVRF(name string, id int, rd bgp.RouteDistinguisherInterface, im, ex []bgp.ExtendedCommunityInterface) error {
buf, err := rd.Serialize()
if err != nil {
return err
}
f := func(comms []bgp.ExtendedCommunityInterface) ([][]byte, error) {
var bufs [][]byte
for _, c := range comms {
buf, err := c.Serialize()
if err != nil {
return nil, err
}
bufs = append(bufs, buf)
}
return bufs, err
}
importRT, err := f(im)
if err != nil {
return err
}
exportRT, err := f(ex)
if err != nil {
return err
}
arg := &api.AddVrfRequest{
Vrf: &api.Vrf{
Name: name,
Rd: buf,
Id: uint32(id),
ImportRt: importRT,
ExportRt: exportRT,
},
}
_, err = cli.cli.AddVrf(context.Background(), arg)
return err
}
func (cli *GoBGPClient) DeleteVRF(name string) error {
arg := &api.DeleteVrfRequest{
Vrf: &api.Vrf{
Name: name,
},
}
_, err := cli.cli.DeleteVrf(context.Background(), arg)
return err
}
func (cli *GoBGPClient) GetDefinedSet(typ table.DefinedType) ([]table.DefinedSet, error) {
ret, err := cli.cli.GetDefinedSet(context.Background(), &api.GetDefinedSetRequest{Type: api.DefinedType(typ)})
if err != nil {
return nil, err
}
ds := make([]table.DefinedSet, 0, len(ret.Sets))
for _, s := range ret.Sets {
d, err := api.NewDefinedSetFromApiStruct(s)
if err != nil {
return nil, err
}
ds = append(ds, d)
}
return ds, nil
}
func (cli *GoBGPClient) AddDefinedSet(d table.DefinedSet) error {
a, err := api.NewAPIDefinedSetFromTableStruct(d)
if err != nil {
return err
}
_, err = cli.cli.AddDefinedSet(context.Background(), &api.AddDefinedSetRequest{
Set: a,
})
return err
}
func (cli *GoBGPClient) DeleteDefinedSet(d table.DefinedSet, all bool) error {
a, err := api.NewAPIDefinedSetFromTableStruct(d)
if err != nil {
return err
}
_, err = cli.cli.DeleteDefinedSet(context.Background(), &api.DeleteDefinedSetRequest{
Set: a,
All: all,
})
return err
}
func (cli *GoBGPClient) ReplaceDefinedSet(d table.DefinedSet) error {
a, err := api.NewAPIDefinedSetFromTableStruct(d)
if err != nil {
return err
}
_, err = cli.cli.ReplaceDefinedSet(context.Background(), &api.ReplaceDefinedSetRequest{
Set: a,
})
return err
}
func (cli *GoBGPClient) GetStatement() ([]*table.Statement, error) {
ret, err := cli.cli.GetStatement(context.Background(), &api.GetStatementRequest{})
if err != nil {
return nil, err
}
sts := make([]*table.Statement, 0, len(ret.Statements))
for _, s := range ret.Statements {
st, err := api.NewStatementFromApiStruct(s)
if err != nil {
return nil, err
}
sts = append(sts, st)
}
return sts, nil
}
func (cli *GoBGPClient) AddStatement(t *table.Statement) error {
a := api.NewAPIStatementFromTableStruct(t)
_, err := cli.cli.AddStatement(context.Background(), &api.AddStatementRequest{
Statement: a,
})
return err
}
func (cli *GoBGPClient) DeleteStatement(t *table.Statement, all bool) error {
a := api.NewAPIStatementFromTableStruct(t)
_, err := cli.cli.DeleteStatement(context.Background(), &api.DeleteStatementRequest{
Statement: a,
All: all,
})
return err
}
func (cli *GoBGPClient) ReplaceStatement(t *table.Statement) error {
a := api.NewAPIStatementFromTableStruct(t)
_, err := cli.cli.ReplaceStatement(context.Background(), &api.ReplaceStatementRequest{
Statement: a,
})
return err
}
func (cli *GoBGPClient) GetPolicy() ([]*table.Policy, error) {
ret, err := cli.cli.GetPolicy(context.Background(), &api.GetPolicyRequest{})
if err != nil {
return nil, err
}
pols := make([]*table.Policy, 0, len(ret.Policies))
for _, p := range ret.Policies {
pol, err := api.NewPolicyFromApiStruct(p)
if err != nil {
return nil, err
}
pols = append(pols, pol)
}
return pols, nil
}
func (cli *GoBGPClient) AddPolicy(t *table.Policy, refer bool) error {
a := api.NewAPIPolicyFromTableStruct(t)
_, err := cli.cli.AddPolicy(context.Background(), &api.AddPolicyRequest{
Policy: a,
ReferExistingStatements: refer,
})
return err
}
func (cli *GoBGPClient) DeletePolicy(t *table.Policy, all, preserve bool) error {
a := api.NewAPIPolicyFromTableStruct(t)
_, err := cli.cli.DeletePolicy(context.Background(), &api.DeletePolicyRequest{
Policy: a,
All: all,
PreserveStatements: preserve,
})
return err
}
func (cli *GoBGPClient) ReplacePolicy(t *table.Policy, refer, preserve bool) error {
a := api.NewAPIPolicyFromTableStruct(t)
_, err := cli.cli.ReplacePolicy(context.Background(), &api.ReplacePolicyRequest{
Policy: a,
ReferExistingStatements: refer,
PreserveStatements: preserve,
})
return err
}
func (cli *GoBGPClient) getPolicyAssignment(name string, dir table.PolicyDirection) (*table.PolicyAssignment, error) {
var typ api.PolicyType
switch dir {
case table.POLICY_DIRECTION_IN:
typ = api.PolicyType_IN
case table.POLICY_DIRECTION_IMPORT:
typ = api.PolicyType_IMPORT
case table.POLICY_DIRECTION_EXPORT:
typ = api.PolicyType_EXPORT
}
resource := api.Resource_GLOBAL
if name != "" {
resource = api.Resource_LOCAL
}
ret, err := cli.cli.GetPolicyAssignment(context.Background(), &api.GetPolicyAssignmentRequest{
Assignment: &api.PolicyAssignment{
Name: name,
Resource: resource,
Type: typ,
},
})
if err != nil {
return nil, err
}
def := table.ROUTE_TYPE_ACCEPT
if ret.Assignment.Default == api.RouteAction_REJECT {
def = table.ROUTE_TYPE_REJECT
}
pols := make([]*table.Policy, 0, len(ret.Assignment.Policies))
for _, p := range ret.Assignment.Policies {
pol, err := api.NewPolicyFromApiStruct(p)
if err != nil {
return nil, err
}
pols = append(pols, pol)
}
return &table.PolicyAssignment{
Name: name,
Type: dir,
Policies: pols,
Default: def,
}, nil
}
func (cli *GoBGPClient) GetImportPolicy() (*table.PolicyAssignment, error) {
return cli.getPolicyAssignment("", table.POLICY_DIRECTION_IMPORT)
}
func (cli *GoBGPClient) GetExportPolicy() (*table.PolicyAssignment, error) {
return cli.getPolicyAssignment("", table.POLICY_DIRECTION_EXPORT)
}
func (cli *GoBGPClient) GetRouteServerInPolicy(name string) (*table.PolicyAssignment, error) {
return cli.getPolicyAssignment(name, table.POLICY_DIRECTION_IN)
}
func (cli *GoBGPClient) GetRouteServerImportPolicy(name string) (*table.PolicyAssignment, error) {
return cli.getPolicyAssignment(name, table.POLICY_DIRECTION_IMPORT)
}
func (cli *GoBGPClient) GetRouteServerExportPolicy(name string) (*table.PolicyAssignment, error) {
return cli.getPolicyAssignment(name, table.POLICY_DIRECTION_EXPORT)
}
func (cli *GoBGPClient) AddPolicyAssignment(assignment *table.PolicyAssignment) error {
_, err := cli.cli.AddPolicyAssignment(context.Background(), &api.AddPolicyAssignmentRequest{
api.NewAPIPolicyAssignmentFromTableStruct(assignment),
})
return err
}
func (cli *GoBGPClient) DeletePolicyAssignment(assignment *table.PolicyAssignment, all bool) error {
a := api.NewAPIPolicyAssignmentFromTableStruct(assignment)
_, err := cli.cli.DeletePolicyAssignment(context.Background(), &api.DeletePolicyAssignmentRequest{a, all})
return err
}
func (cli *GoBGPClient) ReplacePolicyAssignment(assignment *table.PolicyAssignment) error {
_, err := cli.cli.ReplacePolicyAssignment(context.Background(), &api.ReplacePolicyAssignmentRequest{
api.NewAPIPolicyAssignmentFromTableStruct(assignment),
})
return err
}
//func (cli *GoBGPClient) EnableMrt(c *config.MrtConfig) error {
//}
//
//func (cli *GoBGPClient) DisableMrt(c *config.MrtConfig) error {
//}
//
func (cli *GoBGPClient) GetRPKI() ([]*config.RpkiServer, error) {
rsp, err := cli.cli.GetRpki(context.Background(), &api.GetRpkiRequest{})
if err != nil {
return nil, err
}
servers := make([]*config.RpkiServer, 0, len(rsp.Servers))
for _, s := range rsp.Servers {
port, err := strconv.Atoi(s.Conf.RemotePort)
if err != nil {
return nil, err
}
server := &config.RpkiServer{
Config: config.RpkiServerConfig{
Address: s.Conf.Address,
Port: uint32(port),
},
State: config.RpkiServerState{
Up: s.State.Up,
SerialNumber: s.State.Serial,
RecordsV4: s.State.RecordIpv4,
RecordsV6: s.State.RecordIpv6,
PrefixesV4: s.State.PrefixIpv4,
PrefixesV6: s.State.PrefixIpv6,
Uptime: s.State.Uptime,
Downtime: s.State.Downtime,
RpkiMessages: config.RpkiMessages{
RpkiReceived: config.RpkiReceived{
SerialNotify: s.State.SerialNotify,
CacheReset: s.State.CacheReset,
CacheResponse: s.State.CacheResponse,
Ipv4Prefix: s.State.ReceivedIpv4,
Ipv6Prefix: s.State.ReceivedIpv6,
EndOfData: s.State.EndOfData,
Error: s.State.Error,
},
RpkiSent: config.RpkiSent{
SerialQuery: s.State.SerialQuery,
ResetQuery: s.State.ResetQuery,
},
},
},
}
servers = append(servers, server)
}
return servers, nil
}
func (cli *GoBGPClient) GetROA(family bgp.RouteFamily) ([]*server.ROA, error) {
rsp, err := cli.cli.GetRoa(context.Background(), &api.GetRoaRequest{
Family: uint32(family),
})
if err != nil {
return nil, err
}
roas := make([]*server.ROA, 0, len(rsp.Roas))
for _, r := range rsp.Roas {
ip := net.ParseIP(r.Prefix)
if ip.To4() != nil {
ip = ip.To4()
}
afi, _ := bgp.RouteFamilyToAfiSafi(family)
roa := server.NewROA(int(afi), []byte(ip), uint8(r.Prefixlen), uint8(r.Maxlen), r.As, net.JoinHostPort(r.Conf.Address, r.Conf.RemotePort))
roas = append(roas, roa)
}
return roas, nil
}
func (cli *GoBGPClient) AddRPKIServer(address string, port, lifetime int) error {
_, err := cli.cli.AddRpki(context.Background(), &api.AddRpkiRequest{
Address: address,
Port: uint32(port),
Lifetime: int64(lifetime),
})
return err
}
func (cli *GoBGPClient) DeleteRPKIServer(address string) error {
_, err := cli.cli.DeleteRpki(context.Background(), &api.DeleteRpkiRequest{
Address: address,
})
return err
}
func (cli *GoBGPClient) EnableRPKIServer(address string) error {
_, err := cli.cli.EnableRpki(context.Background(), &api.EnableRpkiRequest{
Address: address,
})
return err
}
func (cli *GoBGPClient) DisableRPKIServer(address string) error {
_, err := cli.cli.DisableRpki(context.Background(), &api.DisableRpkiRequest{
Address: address,
})
return err
}
func (cli *GoBGPClient) ResetRPKIServer(address string) error {
_, err := cli.cli.ResetRpki(context.Background(), &api.ResetRpkiRequest{
Address: address,
})
return err
}
func (cli *GoBGPClient) SoftResetRPKIServer(address string) error {
_, err := cli.cli.SoftResetRpki(context.Background(), &api.SoftResetRpkiRequest{
Address: address,
})
return err
}
func (cli *GoBGPClient) ValidateRIBWithRPKI(prefixes ...string) error {
req := &api.ValidateRibRequest{}
if len(prefixes) > 1 {
return fmt.Errorf("too many prefixes: %d", len(prefixes))
} else if len(prefixes) == 1 {
req.Prefix = prefixes[0]
}
_, err := cli.cli.ValidateRib(context.Background(), req)
return err
}
func (cli *GoBGPClient) AddBMP(c *config.BmpServerConfig) error {
_, err := cli.cli.AddBmp(context.Background(), &api.AddBmpRequest{
Address: c.Address,
Port: c.Port,
Type: api.AddBmpRequest_MonitoringPolicy(c.RouteMonitoringPolicy.ToInt()),
})
return err
}
func (cli *GoBGPClient) DeleteBMP(c *config.BmpServerConfig) error {
_, err := cli.cli.DeleteBmp(context.Background(), &api.DeleteBmpRequest{
Address: c.Address,
Port: c.Port,
})
return err
}
type MonitorRIBClient struct {
stream api.GobgpApi_MonitorRibClient
}
func (c *MonitorRIBClient) Recv() (*table.Destination, error) {
d, err := c.stream.Recv()
if err != nil {
return nil, err
}
return d.ToNativeDestination()
}
func (cli *GoBGPClient) MonitorRIB(family bgp.RouteFamily) (*MonitorRIBClient, error) {
stream, err := cli.cli.MonitorRib(context.Background(), &api.Table{
Type: api.Resource_GLOBAL,
Family: uint32(family),
})
if err != nil {
return nil, err
}
return &MonitorRIBClient{stream}, nil
}
func (cli *GoBGPClient) MonitorAdjRIBIn(name string, family bgp.RouteFamily) (*MonitorRIBClient, error) {
stream, err := cli.cli.MonitorRib(context.Background(), &api.Table{
Type: api.Resource_ADJ_IN,
Name: name,
Family: uint32(family),
})
if err != nil {
return nil, err
}
return &MonitorRIBClient{stream}, nil
}
type MonitorNeighborStateClient struct {
stream api.GobgpApi_MonitorPeerStateClient
}
func (c *MonitorNeighborStateClient) Recv() (*config.Neighbor, error) {
p, err := c.stream.Recv()
if err != nil {
return nil, err
}
return api.NewNeighborFromAPIStruct(p)
}
func (cli *GoBGPClient) MonitorNeighborState(names ...string) (*MonitorNeighborStateClient, error) {
if len(names) > 1 {
return nil, fmt.Errorf("support one name at most: %d", len(names))
}
name := ""
if len(names) > 0 {
name = names[0]
}
stream, err := cli.cli.MonitorPeerState(context.Background(), &api.Arguments{
Name: name,
})
if err != nil {
return nil, err
}
return &MonitorNeighborStateClient{stream}, nil
}
+42
View File
@@ -17,6 +17,10 @@ package config
import (
"fmt"
"net"
"regexp"
"strconv"
"github.com/osrg/gobgp/packet/bgp"
)
@@ -82,3 +86,41 @@ func CheckAfiSafisChange(x, y []AfiSafi) bool {
}
return false
}
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
}
exp := regexp.MustCompile("(\\d+)\\.\\.(\\d+)")
elems := exp.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.Atoi(elems[1])
max, _ := strconv.Atoi(elems[2])
if min > max {
return 0, 0, fmt.Errorf("invalid mask length range: %s", mask)
}
if ipv4 := ipNet.IP.To4(); ipv4 != nil {
f := func(i int) bool {
return i >= 0 && i <= 32
}
if !f(min) || !f(max) {
return 0, 0, fmt.Errorf("ipv4 mask length range outside scope :%s", mask)
}
} else {
f := func(i int) bool {
return i >= 0 && i <= 128
}
if !f(min) || !f(max) {
return 0, 0, fmt.Errorf("ipv6 mask length range outside scope :%s", mask)
}
}
return min, max, nil
}
+11 -8
View File
@@ -109,7 +109,7 @@ func showNeighbors(vrf string) error {
timeStr := "never"
if p.Timers.State.Uptime != 0 {
t := int64(p.Timers.State.Downtime)
if p.Info.BgpState == "BGP_FSM_ESTABLISHED" {
if p.Info.BgpState == string(config.SESSION_STATE_ESTABLISHED) {
t = int64(p.Timers.State.Uptime)
}
timeStr = formatTimedelta(int64(now.Sub(time.Unix(int64(t), 0)).Seconds()))
@@ -131,18 +131,21 @@ func showNeighbors(vrf string) error {
return "Idle(PfxCt)"
}
if fsm == "BGP_FSM_IDLE" {
switch config.SessionState(fsm) {
case config.SESSION_STATE_IDLE:
return "Idle"
} else if fsm == "BGP_FSM_CONNECT" {
case config.SESSION_STATE_CONNECT:
return "Connect"
} else if fsm == "BGP_FSM_ACTIVE" {
case config.SESSION_STATE_ACTIVE:
return "Active"
} else if fsm == "BGP_FSM_OPENSENT" {
case config.SESSION_STATE_OPENSENT:
return "Sent"
} else if fsm == "BGP_FSM_OPENCONFIRM" {
case config.SESSION_STATE_OPENCONFIRM:
return "Confirm"
} else {
case config.SESSION_STATE_ESTABLISHED:
return "Establ"
default:
return fsm
}
}
@@ -590,7 +593,7 @@ func showNeighborRib(r string, name string, args []string) error {
if err != nil {
return err
}
if peer.Info.BgpState != "BGP_FSM_ESTABLISHED" {
if peer.Info.BgpState != string(config.SESSION_STATE_ESTABLISHED) {
return fmt.Errorf("Neighbor %v's BGP session is not established", name)
}
}
+269 -29
View File
@@ -17,6 +17,7 @@ package table
import (
"bytes"
"encoding/json"
"fmt"
"net"
"reflect"
@@ -178,6 +179,18 @@ const (
ATTRIBUTE_LE
)
func (c AttributeComparison) String() string {
switch c {
case ATTRIBUTE_EQ:
return "="
case ATTRIBUTE_GE:
return ">="
case ATTRIBUTE_LE:
return "<="
}
return "?"
}
const (
ASPATH_REGEXP_MAGIC = "(^|[,{}() ]|$)"
)
@@ -188,10 +201,29 @@ type DefinedSet interface {
Append(DefinedSet) error
Remove(DefinedSet) error
Replace(DefinedSet) error
String() string
List() []string
}
type DefinedSetMap map[DefinedType]map[string]DefinedSet
type DefinedSetList []DefinedSet
func (l DefinedSetList) Len() int {
return len(l)
}
func (l DefinedSetList) Swap(i, j int) {
l[i], l[j] = l[j], l[i]
}
func (l DefinedSetList) Less(i, j int) bool {
if l[i].Type() != l[j].Type() {
return l[i].Type() < l[j].Type()
}
return l[i].Name() < l[j].Name()
}
type Prefix struct {
Prefix *net.IPNet
AddressFamily bgp.RouteFamily
@@ -347,6 +379,18 @@ func (lhs *PrefixSet) Replace(arg DefinedSet) error {
return nil
}
func (s *PrefixSet) List() []string {
var list []string
s.tree.Walk(func(s string, v interface{}) bool {
ps := v.([]*Prefix)
for _, p := range ps {
list = append(list, fmt.Sprintf("%s %d..%d", p.Prefix.String(), p.MasklengthRangeMin, p.MasklengthRangeMax))
}
return false
})
return list
}
func (s *PrefixSet) ToConfig() *config.PrefixSet {
list := make([]config.Prefix, 0, s.tree.Len())
s.tree.Walk(func(s string, v interface{}) bool {
@@ -362,6 +406,14 @@ func (s *PrefixSet) ToConfig() *config.PrefixSet {
}
}
func (s *PrefixSet) String() string {
return strings.Join(s.List(), "\n")
}
func (s *PrefixSet) MarshalJSON() ([]byte, error) {
return json.Marshal(s.ToConfig())
}
func NewPrefixSetFromApiStruct(name string, prefixes []*Prefix) (*PrefixSet, error) {
if name == "" {
return nil, fmt.Errorf("empty prefix set name")
@@ -465,17 +517,29 @@ func (lhs *NeighborSet) Replace(arg DefinedSet) error {
return nil
}
func (s *NeighborSet) ToConfig() *config.NeighborSet {
func (s *NeighborSet) List() []string {
list := make([]string, 0, len(s.list))
for _, n := range s.list {
list = append(list, n.String())
}
return list
}
func (s *NeighborSet) ToConfig() *config.NeighborSet {
return &config.NeighborSet{
NeighborSetName: s.name,
NeighborInfoList: list,
NeighborInfoList: s.List(),
}
}
func (s *NeighborSet) String() string {
return strings.Join(s.List(), "\n")
}
func (s *NeighborSet) MarshalJSON() ([]byte, error) {
return json.Marshal(s.ToConfig())
}
func NewNeighborSetFromApiStruct(name string, list []net.IP) (*NeighborSet, error) {
return &NeighborSet{
name: name,
@@ -667,7 +731,7 @@ func (lhs *AsPathSet) Replace(arg DefinedSet) error {
return nil
}
func (s *AsPathSet) ToConfig() *config.AsPathSet {
func (s *AsPathSet) List() []string {
list := make([]string, 0, len(s.list)+len(s.singleList))
for _, exp := range s.singleList {
list = append(list, exp.String())
@@ -675,12 +739,24 @@ func (s *AsPathSet) ToConfig() *config.AsPathSet {
for _, exp := range s.list {
list = append(list, exp.String())
}
return list
}
func (s *AsPathSet) ToConfig() *config.AsPathSet {
return &config.AsPathSet{
AsPathSetName: s.name,
AsPathList: list,
AsPathList: s.List(),
}
}
func (s *AsPathSet) String() string {
return strings.Join(s.List(), "\n")
}
func (s *AsPathSet) MarshalJSON() ([]byte, error) {
return json.Marshal(s.ToConfig())
}
func NewAsPathSet(c config.AsPathSet) (*AsPathSet, error) {
name := c.AsPathSetName
if name == "" {
@@ -797,17 +873,29 @@ type CommunitySet struct {
regExpSet
}
func (s *CommunitySet) ToConfig() *config.CommunitySet {
func (s *CommunitySet) List() []string {
list := make([]string, 0, len(s.list))
for _, exp := range s.list {
list = append(list, exp.String())
}
return list
}
func (s *CommunitySet) ToConfig() *config.CommunitySet {
return &config.CommunitySet{
CommunitySetName: s.name,
CommunityList: list,
CommunityList: s.List(),
}
}
func (s *CommunitySet) String() string {
return strings.Join(s.List(), "\n")
}
func (s *CommunitySet) MarshalJSON() ([]byte, error) {
return json.Marshal(s.ToConfig())
}
func ParseCommunity(arg string) (uint32, error) {
i, err := strconv.ParseUint(arg, 10, 32)
if err == nil {
@@ -927,7 +1015,7 @@ type ExtCommunitySet struct {
subtypeList []bgp.ExtendedCommunityAttrSubType
}
func (s *ExtCommunitySet) ToConfig() *config.ExtCommunitySet {
func (s *ExtCommunitySet) List() []string {
list := make([]string, 0, len(s.list))
f := func(idx int, arg string) string {
switch s.subtypeList[idx] {
@@ -944,12 +1032,24 @@ func (s *ExtCommunitySet) ToConfig() *config.ExtCommunitySet {
for idx, exp := range s.list {
list = append(list, f(idx, exp.String()))
}
return list
}
func (s *ExtCommunitySet) ToConfig() *config.ExtCommunitySet {
return &config.ExtCommunitySet{
ExtCommunitySetName: s.name,
ExtCommunityList: list,
ExtCommunityList: s.List(),
}
}
func (s *ExtCommunitySet) String() string {
return strings.Join(s.List(), "\n")
}
func (s *ExtCommunitySet) MarshalJSON() ([]byte, error) {
return json.Marshal(s.ToConfig())
}
func NewExtCommunitySet(c config.ExtCommunitySet) (*ExtCommunitySet, error) {
name := c.ExtCommunitySetName
if name == "" {
@@ -982,17 +1082,29 @@ type LargeCommunitySet struct {
regExpSet
}
func (s *LargeCommunitySet) ToConfig() *config.LargeCommunitySet {
func (s *LargeCommunitySet) List() []string {
list := make([]string, 0, len(s.list))
for _, exp := range s.list {
list = append(list, exp.String())
}
return list
}
func (s *LargeCommunitySet) ToConfig() *config.LargeCommunitySet {
return &config.LargeCommunitySet{
LargeCommunitySetName: s.name,
LargeCommunityList: list,
LargeCommunityList: s.List(),
}
}
func (s *LargeCommunitySet) String() string {
return strings.Join(s.List(), "\n")
}
func (s *LargeCommunitySet) MarshalJSON() ([]byte, error) {
return json.Marshal(s.ToConfig())
}
func ParseLargeCommunityRegexp(arg string) (*regexp.Regexp, error) {
if regexp.MustCompile("\\d+:\\d+:\\d+").MatchString(arg) {
return regexp.MustCompile(fmt.Sprintf("^%s$", arg)), nil
@@ -1037,7 +1149,6 @@ type Condition interface {
}
type PrefixCondition struct {
name string
set *PrefixSet
option MatchOption
}
@@ -1096,7 +1207,7 @@ func (c *PrefixCondition) Evaluate(path *Path, _ *PolicyOptions) bool {
return result
}
func (c *PrefixCondition) Name() string { return c.name }
func (c *PrefixCondition) Name() string { return c.set.name }
func NewPrefixCondition(c config.MatchPrefixSet) (*PrefixCondition, error) {
if c.PrefixSet == "" {
@@ -1107,13 +1218,14 @@ func NewPrefixCondition(c config.MatchPrefixSet) (*PrefixCondition, error) {
return nil, err
}
return &PrefixCondition{
name: c.PrefixSet,
set: &PrefixSet{
name: c.PrefixSet,
},
option: o,
}, nil
}
type NeighborCondition struct {
name string
set *NeighborSet
option MatchOption
}
@@ -1165,7 +1277,7 @@ func (c *NeighborCondition) Evaluate(path *Path, options *PolicyOptions) bool {
return result
}
func (c *NeighborCondition) Name() string { return c.name }
func (c *NeighborCondition) Name() string { return c.set.name }
func NewNeighborCondition(c config.MatchNeighborSet) (*NeighborCondition, error) {
if c.NeighborSet == "" {
@@ -1176,13 +1288,14 @@ func NewNeighborCondition(c config.MatchNeighborSet) (*NeighborCondition, error)
return nil, err
}
return &NeighborCondition{
name: c.NeighborSet,
set: &NeighborSet{
name: c.NeighborSet,
},
option: o,
}, nil
}
type AsPathCondition struct {
name string
set *AsPathSet
option MatchOption
}
@@ -1236,7 +1349,7 @@ func (c *AsPathCondition) Evaluate(path *Path, _ *PolicyOptions) bool {
return true
}
func (c *AsPathCondition) Name() string { return c.name }
func (c *AsPathCondition) Name() string { return c.set.name }
func NewAsPathCondition(c config.MatchAsPathSet) (*AsPathCondition, error) {
if c.AsPathSet == "" {
@@ -1247,13 +1360,14 @@ func NewAsPathCondition(c config.MatchAsPathSet) (*AsPathCondition, error) {
return nil, err
}
return &AsPathCondition{
name: c.AsPathSet,
set: &AsPathSet{
name: c.AsPathSet,
},
option: o,
}, nil
}
type CommunityCondition struct {
name string
set *CommunitySet
option MatchOption
}
@@ -1294,7 +1408,7 @@ func (c *CommunityCondition) Evaluate(path *Path, _ *PolicyOptions) bool {
return result
}
func (c *CommunityCondition) Name() string { return c.name }
func (c *CommunityCondition) Name() string { return c.set.name }
func NewCommunityCondition(c config.MatchCommunitySet) (*CommunityCondition, error) {
if c.CommunitySet == "" {
@@ -1305,13 +1419,16 @@ func NewCommunityCondition(c config.MatchCommunitySet) (*CommunityCondition, err
return nil, err
}
return &CommunityCondition{
name: c.CommunitySet,
set: &CommunitySet{
regExpSet: regExpSet{
name: c.CommunitySet,
},
},
option: o,
}, nil
}
type ExtCommunityCondition struct {
name string
set *ExtCommunitySet
option MatchOption
}
@@ -1357,7 +1474,7 @@ func (c *ExtCommunityCondition) Evaluate(path *Path, _ *PolicyOptions) bool {
return result
}
func (c *ExtCommunityCondition) Name() string { return c.name }
func (c *ExtCommunityCondition) Name() string { return c.set.name }
func NewExtCommunityCondition(c config.MatchExtCommunitySet) (*ExtCommunityCondition, error) {
if c.ExtCommunitySet == "" {
@@ -1368,13 +1485,16 @@ func NewExtCommunityCondition(c config.MatchExtCommunitySet) (*ExtCommunityCondi
return nil, err
}
return &ExtCommunityCondition{
name: c.ExtCommunitySet,
set: &ExtCommunitySet{
regExpSet: regExpSet{
name: c.ExtCommunitySet,
},
},
option: o,
}, nil
}
type LargeCommunityCondition struct {
name string
set *LargeCommunitySet
option MatchOption
}
@@ -1415,7 +1535,7 @@ func (c *LargeCommunityCondition) Evaluate(path *Path, _ *PolicyOptions) bool {
return result
}
func (c *LargeCommunityCondition) Name() string { return c.name }
func (c *LargeCommunityCondition) Name() string { return c.set.name }
func NewLargeCommunityCondition(c config.MatchLargeCommunitySet) (*LargeCommunityCondition, error) {
if c.LargeCommunitySet == "" {
@@ -1426,7 +1546,11 @@ func NewLargeCommunityCondition(c config.MatchLargeCommunitySet) (*LargeCommunit
return nil, err
}
return &LargeCommunityCondition{
name: c.LargeCommunitySet,
set: &LargeCommunitySet{
regExpSet: regExpSet{
name: c.LargeCommunitySet,
},
},
option: o,
}, nil
}
@@ -1464,6 +1588,10 @@ func (c *AsPathLengthCondition) Set() DefinedSet {
func (c *AsPathLengthCondition) Name() string { return "" }
func (c *AsPathLengthCondition) String() string {
return fmt.Sprintf("%s%d", c.operator, c.length)
}
func NewAsPathLengthCondition(c config.AsPathLength) (*AsPathLengthCondition, error) {
if c.Value == 0 && c.Operator == "" {
return nil, nil
@@ -1500,6 +1628,10 @@ func (c *RpkiValidationCondition) Set() DefinedSet {
func (c *RpkiValidationCondition) Name() string { return "" }
func (c *RpkiValidationCondition) String() string {
return string(c.result)
}
func NewRpkiValidationCondition(c config.RpkiValidationResultType) (*RpkiValidationCondition, error) {
if c == config.RPKI_VALIDATION_RESULT_TYPE_NONE {
return nil, nil
@@ -1535,6 +1667,10 @@ func (c *RouteTypeCondition) Set() DefinedSet {
func (c *RouteTypeCondition) Name() string { return "" }
func (c *RouteTypeCondition) String() string {
return string(c.typ)
}
func NewRouteTypeCondition(c config.RouteType) (*RouteTypeCondition, error) {
if string(c) == "" || c == config.ROUTE_TYPE_NONE {
return nil, nil
@@ -1550,6 +1686,7 @@ func NewRouteTypeCondition(c config.RouteType) (*RouteTypeCondition, error) {
type Action interface {
Type() ActionType
Apply(*Path, *PolicyOptions) *Path
String() string
}
type RoutingAction struct {
@@ -1567,6 +1704,14 @@ func (a *RoutingAction) Apply(path *Path, _ *PolicyOptions) *Path {
return nil
}
func (a *RoutingAction) String() string {
action := "reject"
if a.AcceptRoute {
action = "accept"
}
return action
}
func NewRoutingAction(c config.RouteDisposition) (*RoutingAction, error) {
if c.AcceptRoute == c.RejectRoute && c.AcceptRoute {
return nil, fmt.Errorf("invalid route disposition")
@@ -1680,6 +1825,17 @@ func (a *CommunityAction) ToConfig() *config.SetCommunity {
}
}
func (a *CommunityAction) MarshalJSON() ([]byte, error) {
return json.Marshal(a.ToConfig())
}
func (a *CommunityAction) String() string {
list := a.ToConfig().SetCommunityMethod.CommunitiesList
exp := regexp.MustCompile("[\\^\\$]")
l := exp.ReplaceAllString(strings.Join(list, ", "), "")
return fmt.Sprintf("%s[%s]", a.action, l)
}
func NewCommunityAction(c config.SetCommunity) (*CommunityAction, error) {
a, ok := CommunityOptionValueMap[strings.ToLower(c.Options)]
if !ok {
@@ -1768,6 +1924,17 @@ func (a *ExtCommunityAction) ToConfig() *config.SetExtCommunity {
}
}
func (a *ExtCommunityAction) String() string {
list := a.ToConfig().SetExtCommunityMethod.CommunitiesList
exp := regexp.MustCompile("[\\^\\$]")
l := exp.ReplaceAllString(strings.Join(list, ", "), "")
return fmt.Sprintf("%s[%s]", a.action, l)
}
func (a *ExtCommunityAction) MarshalJSON() ([]byte, error) {
return json.Marshal(a.ToConfig())
}
func NewExtCommunityAction(c config.SetExtCommunity) (*ExtCommunityAction, error) {
a, ok := CommunityOptionValueMap[strings.ToLower(c.Options)]
if !ok {
@@ -1846,6 +2013,17 @@ func (a *LargeCommunityAction) ToConfig() *config.SetLargeCommunity {
}
}
func (a *LargeCommunityAction) String() string {
list := a.ToConfig().SetLargeCommunityMethod.CommunitiesList
exp := regexp.MustCompile("[\\^\\$]")
l := exp.ReplaceAllString(strings.Join(list, ", "), "")
return fmt.Sprintf("%s[%s]", a.action, l)
}
func (a *LargeCommunityAction) MarshalJSON() ([]byte, error) {
return json.Marshal(a.ToConfig())
}
func NewLargeCommunityAction(c config.SetLargeCommunity) (*LargeCommunityAction, error) {
a, ok := CommunityOptionValueMap[strings.ToLower(string(c.Options))]
if !ok {
@@ -1919,6 +2097,14 @@ func (a *MedAction) ToConfig() config.BgpSetMedType {
return config.BgpSetMedType(fmt.Sprintf("%d", a.value))
}
func (a *MedAction) String() string {
return string(a.ToConfig())
}
func (a *MedAction) MarshalJSON() ([]byte, error) {
return json.Marshal(a.ToConfig())
}
func NewMedAction(c config.BgpSetMedType) (*MedAction, error) {
if string(c) == "" {
return nil, nil
@@ -1961,6 +2147,14 @@ func (a *LocalPrefAction) ToConfig() uint32 {
return a.value
}
func (a *LocalPrefAction) String() string {
return fmt.Sprintf("%d", a.value)
}
func (a *LocalPrefAction) MarshalJSON() ([]byte, error) {
return json.Marshal(a.ToConfig())
}
func NewLocalPrefAction(value uint32) (*LocalPrefAction, error) {
if value == 0 {
return nil, nil
@@ -2020,6 +2214,15 @@ func (a *AsPathPrependAction) ToConfig() *config.SetAsPathPrepend {
}
}
func (a *AsPathPrependAction) String() string {
c := a.ToConfig()
return fmt.Sprintf("prepend %s %d times", c.As, c.RepeatN)
}
func (a *AsPathPrependAction) MarshalJSON() ([]byte, error) {
return json.Marshal(a.ToConfig())
}
// NewAsPathPrependAction creates AsPathPrependAction object.
// If ASN cannot be parsed, nil will be returned.
func NewAsPathPrependAction(action config.SetAsPathPrepend) (*AsPathPrependAction, error) {
@@ -2071,8 +2274,16 @@ func (a *NexthopAction) ToConfig() config.BgpNextHopType {
return config.BgpNextHopType(a.value.String())
}
func (a *NexthopAction) String() string {
return string(a.ToConfig())
}
func (a *NexthopAction) MarshalJSON() ([]byte, error) {
return json.Marshal(a.ToConfig())
}
func NewNexthopAction(c config.BgpNextHopType) (*NexthopAction, error) {
switch string(c) {
switch strings.ToLower(string(c)) {
case "":
return nil, nil
case "self":
@@ -2201,6 +2412,10 @@ func (s *Statement) ToConfig() *config.Statement {
}
}
func (s *Statement) MarshalJSON() ([]byte, error) {
return json.Marshal(s.ToConfig())
}
type opType int
const (
@@ -2483,6 +2698,10 @@ func (lhs *Policy) Replace(rhs *Policy) error {
return nil
}
func (p *Policy) MarshalJSON() ([]byte, error) {
return json.Marshal(p.ToConfig())
}
func NewPolicy(c config.PolicyDefinition) (*Policy, error) {
if c.Name == "" {
return nil, fmt.Errorf("empty policy name")
@@ -2508,6 +2727,20 @@ func NewPolicy(c config.PolicyDefinition) (*Policy, error) {
}, nil
}
type Policies []*Policy
func (p Policies) Len() int {
return len(p)
}
func (p Policies) Swap(i, j int) {
p[i], p[j] = p[j], p[i]
}
func (p Policies) Less(i, j int) bool {
return p[i].Name < p[j].Name
}
type Assignment struct {
inPolicies []*Policy
defaultInPolicy RouteType
@@ -3362,3 +3595,10 @@ func CanImportToVrf(v *Vrf, path *Path) bool {
c.set = set
return c.Evaluate(path, nil)
}
type PolicyAssignment struct {
Name string
Type PolicyDirection
Policies []*Policy
Default RouteType
}
+3 -3
View File
@@ -29,9 +29,9 @@ DEFAULT_TEST_BASE_DIR = '/tmp/gobgp'
TEST_PREFIX = DEFAULT_TEST_PREFIX
TEST_BASE_DIR = DEFAULT_TEST_BASE_DIR
BGP_FSM_IDLE = 'BGP_FSM_IDLE'
BGP_FSM_ACTIVE = 'BGP_FSM_ACTIVE'
BGP_FSM_ESTABLISHED = 'BGP_FSM_ESTABLISHED'
BGP_FSM_IDLE = 'idle'
BGP_FSM_ACTIVE = 'active'
BGP_FSM_ESTABLISHED = 'established'
BGP_ATTR_TYPE_ORIGIN = 1
BGP_ATTR_TYPE_AS_PATH = 2