update gobgp pkg

This commit is contained in:
Ian Azpiazu
2022-05-16 13:40:57 -04:00
parent 878ee3a63e
commit 80d743ffa5
652 changed files with 136451 additions and 98241 deletions

View File

@@ -115,17 +115,17 @@ func (b *bmpClient) loop() {
}
if func() bool {
ops := []watchOption{watchPeerState(true)}
ops := []watchOption{watchPeerState(true, false)}
if b.c.RouteMonitoringPolicy == config.BMP_ROUTE_MONITORING_POLICY_TYPE_BOTH {
log.WithFields(
log.Fields{"Topic": "bmp"},
).Warn("both option for route-monitoring-policy is obsoleted")
}
if b.c.RouteMonitoringPolicy == config.BMP_ROUTE_MONITORING_POLICY_TYPE_PRE_POLICY || b.c.RouteMonitoringPolicy == config.BMP_ROUTE_MONITORING_POLICY_TYPE_ALL {
ops = append(ops, watchUpdate(true))
ops = append(ops, watchUpdate(true, ""))
}
if b.c.RouteMonitoringPolicy == config.BMP_ROUTE_MONITORING_POLICY_TYPE_POST_POLICY || b.c.RouteMonitoringPolicy == config.BMP_ROUTE_MONITORING_POLICY_TYPE_ALL {
ops = append(ops, watchPostUpdate(true))
ops = append(ops, watchPostUpdate(true, ""))
}
if b.c.RouteMonitoringPolicy == config.BMP_ROUTE_MONITORING_POLICY_TYPE_LOCAL_RIB || b.c.RouteMonitoringPolicy == config.BMP_ROUTE_MONITORING_POLICY_TYPE_ALL {
ops = append(ops, watchBestPath(true))

View File

@@ -21,6 +21,7 @@ import (
"io"
"math/rand"
"net"
"os"
"strconv"
"sync"
"syscall"
@@ -714,8 +715,11 @@ func capAddPathFromConfig(pConf *config.Neighbor) bgp.ParameterCapabilityInterfa
}
func capabilitiesFromConfig(pConf *config.Neighbor) []bgp.ParameterCapabilityInterface {
fqdn, _ := os.Hostname()
caps := make([]bgp.ParameterCapabilityInterface, 0, 4)
caps = append(caps, bgp.NewCapRouteRefresh())
caps = append(caps, bgp.NewCapFQDN(fqdn, ""))
for _, af := range pConf.AfiSafis {
caps = append(caps, bgp.NewCapMultiProtocol(af.State.Family))
}
@@ -869,7 +873,8 @@ func (h *fsmHandler) afiSafiDisable(rf bgp.RouteFamily) string {
}
func (h *fsmHandler) handlingError(m *bgp.BGPMessage, e error, useRevisedError bool) bgp.ErrorHandling {
handling := bgp.ERROR_HANDLING_NONE
// ineffectual assignment to handling (ineffassign)
var handling bgp.ErrorHandling
if m.Header.Type == bgp.BGP_MSG_UPDATE && useRevisedError {
factor := e.(*bgp.MessageError)
handling = factor.ErrorHandling
@@ -1015,6 +1020,13 @@ func (h *fsmHandler) recvMessageWithError() (*fsmMsg, error) {
case bgp.BGP_MSG_ROUTE_REFRESH:
fmsg.MsgType = fsmMsgRouteRefresh
case bgp.BGP_MSG_UPDATE:
// if the length of h.holdTimerResetCh
// isn't zero, the timer will be reset
// soon anyway.
select {
case h.holdTimerResetCh <- true:
default:
}
body := m.Body.(*bgp.BGPUpdate)
isEBGP := h.fsm.pConf.IsEBGPPeer(h.fsm.gConf)
isConfed := h.fsm.pConf.IsConfederationMember(h.fsm.gConf)
@@ -1266,7 +1278,7 @@ func (h *fsmHandler) opensent(ctx context.Context) (bgp.FSMState, *fsmStateReaso
fsm.lock.RLock()
fsmPeerAS := fsm.pConf.Config.PeerAs
fsm.lock.RUnlock()
peerAs, err := bgp.ValidateOpenMsg(body, fsmPeerAS)
peerAs, err := bgp.ValidateOpenMsg(body, fsmPeerAS, fsm.peerInfo.LocalAS, net.ParseIP(fsm.gConf.Config.RouterId))
if err != nil {
m, _ := fsm.sendNotificationFromErrorMsg(err.(*bgp.MessageError))
return bgp.BGP_FSM_IDLE, newfsmStateReason(fsmInvalidMsg, m, nil)
@@ -1569,6 +1581,14 @@ func (h *fsmHandler) openconfirm(ctx context.Context) (bgp.FSMState, *fsmStateRe
}
func (h *fsmHandler) sendMessageloop(ctx context.Context, wg *sync.WaitGroup) error {
sendToStateReasonCh := func(typ fsmStateReasonType, notif *bgp.BGPMessage) {
// probably doesn't happen but be cautious
select {
case h.stateReasonCh <- *newfsmStateReason(typ, notif, nil):
default:
}
}
defer wg.Done()
conn := h.conn
fsm := h.fsm
@@ -1603,7 +1623,7 @@ func (h *fsmHandler) sendMessageloop(ctx context.Context, wg *sync.WaitGroup) er
err = conn.SetWriteDeadline(time.Now().Add(time.Second * time.Duration(fsm.pConf.Timers.State.NegotiatedHoldTime)))
fsm.lock.RUnlock()
if err != nil {
h.stateReasonCh <- *newfsmStateReason(fsmWriteFailed, nil, nil)
sendToStateReasonCh(fsmWriteFailed, nil)
conn.Close()
return fmt.Errorf("failed to set write deadline")
}
@@ -1617,7 +1637,7 @@ func (h *fsmHandler) sendMessageloop(ctx context.Context, wg *sync.WaitGroup) er
"Data": err,
}).Warn("failed to send")
fsm.lock.RUnlock()
h.stateReasonCh <- *newfsmStateReason(fsmWriteFailed, nil, nil)
sendToStateReasonCh(fsmWriteFailed, nil)
conn.Close()
return fmt.Errorf("closed")
}
@@ -1651,7 +1671,7 @@ func (h *fsmHandler) sendMessageloop(ctx context.Context, wg *sync.WaitGroup) er
}).Warn("sent notification")
fsm.lock.RUnlock()
}
h.stateReasonCh <- *newfsmStateReason(fsmNotificationSent, m, nil)
sendToStateReasonCh(fsmNotificationSent, m)
conn.Close()
return fmt.Errorf("closed")
case bgp.BGP_MSG_UPDATE:

View File

@@ -64,8 +64,9 @@ func (s *server) serve() error {
l := []net.Listener{}
var err error
for _, host := range strings.Split(s.hosts, ",") {
network, address := parseHost(host)
var lis net.Listener
lis, err = net.Listen("tcp", host)
lis, err = net.Listen(network, address)
if err != nil {
log.WithFields(log.Fields{
"Topic": "grpc",
@@ -101,6 +102,38 @@ func (s *server) serve() error {
return nil
}
func (s *server) ListDynamicNeighbor(r *api.ListDynamicNeighborRequest, stream api.GobgpApi_ListDynamicNeighborServer) error {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
fn := func(dn *api.DynamicNeighbor) {
if err := stream.Send(&api.ListDynamicNeighborResponse{DynamicNeighbor: dn}); err != nil {
cancel()
return
}
}
return s.bgpServer.ListDynamicNeighbor(ctx, r, fn)
}
func (s *server) ListPeerGroup(r *api.ListPeerGroupRequest, stream api.GobgpApi_ListPeerGroupServer) error {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
fn := func(pg *api.PeerGroup) {
if err := stream.Send(&api.ListPeerGroupResponse{PeerGroup: pg}); err != nil {
cancel()
return
}
}
return s.bgpServer.ListPeerGroup(ctx, r, fn)
}
func parseHost(host string) (string, string) {
const unixScheme = "unix://"
if strings.HasPrefix(host, unixScheme) {
return "unix", host[len(unixScheme):]
}
return "tcp", host
}
func (s *server) ListPeer(r *api.ListPeerRequest, stream api.GobgpApi_ListPeerServer) error {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
@@ -153,11 +186,26 @@ func toPathAPI(binNlri []byte, binPattrs [][]byte, anyNlri *any.Any, anyPattrs [
return p
}
func toPathApi(path *table.Path, v *table.Validation) *api.Path {
func toPathApi(path *table.Path, v *table.Validation, nlri_binary, attribute_binary bool) *api.Path {
nlri := path.GetNlri()
anyNlri := apiutil.MarshalNLRI(nlri)
anyPattrs := apiutil.MarshalPathAttributes(path.GetPathAttrs())
return toPathAPI(nil, nil, anyNlri, anyPattrs, path, v)
var binNlri []byte
if nlri_binary {
binNlri, _ = nlri.Serialize()
}
var binPattrs [][]byte
if attribute_binary {
pa := path.GetPathAttrs()
binPattrs = make([][]byte, 0, len(pa))
for _, a := range pa {
b, e := a.Serialize()
if e == nil {
binPattrs = append(binPattrs, b)
}
}
}
return toPathAPI(binNlri, binPattrs, anyNlri, anyPattrs, path, v)
}
func getValidation(v map[*table.Path]*table.Validation, p *table.Path) *table.Validation {
@@ -281,6 +329,11 @@ func api2Path(resource api.TableType, path *api.Path, isWithdraw bool) (*table.P
return nil, err
}
// TODO (sbezverk) At this poinnt nlri and path attributes are converted to native mode
// need to check if update with SR Policy nlri comes with mandatory route distinguisher
// extended community or NO_ADVERTISE community, with Tunnel Encapsulation Attribute 23
// and tunnel type 15. If it is not the case ignore update and log an error.
pattrs := make([]bgp.PathAttributeInterface, 0)
seen := make(map[bgp.BGPAttrType]struct{})
for _, attr := range attrList {
@@ -295,6 +348,9 @@ func api2Path(resource api.TableType, path *api.Path, isWithdraw bool) (*table.P
case *bgp.PathAttributeNextHop:
nexthop = a.Value.String()
case *bgp.PathAttributeMpReachNLRI:
if len(a.Value) == 0 {
return nil, fmt.Errorf("invalid mp reach attribute")
}
nlri = a.Value[0]
nexthop = a.Nexthop.String()
default:
@@ -486,20 +542,29 @@ func readApplyPolicyFromAPIStruct(c *config.ApplyPolicy, a *api.ApplyPolicy) {
if c == nil || a == nil {
return
}
f := func(a api.RouteAction) config.DefaultPolicyType {
if a == api.RouteAction_ACCEPT {
return config.DEFAULT_POLICY_TYPE_ACCEPT_ROUTE
} else if a == api.RouteAction_REJECT {
return config.DEFAULT_POLICY_TYPE_REJECT_ROUTE
}
return ""
}
if a.ImportPolicy != nil {
c.Config.DefaultImportPolicy = config.IntToDefaultPolicyTypeMap[int(a.ImportPolicy.DefaultAction)]
c.Config.DefaultImportPolicy = f(a.ImportPolicy.DefaultAction)
for _, p := range a.ImportPolicy.Policies {
c.Config.ImportPolicyList = append(c.Config.ImportPolicyList, p.Name)
}
}
if a.ExportPolicy != nil {
c.Config.DefaultExportPolicy = config.IntToDefaultPolicyTypeMap[int(a.ExportPolicy.DefaultAction)]
c.Config.DefaultExportPolicy = f(a.ExportPolicy.DefaultAction)
for _, p := range a.ExportPolicy.Policies {
c.Config.ExportPolicyList = append(c.Config.ExportPolicyList, p.Name)
}
}
if a.InPolicy != nil {
c.Config.DefaultInPolicy = config.IntToDefaultPolicyTypeMap[int(a.InPolicy.DefaultAction)]
c.Config.DefaultInPolicy = f(a.InPolicy.DefaultAction)
for _, p := range a.InPolicy.Policies {
c.Config.InPolicyList = append(c.Config.InPolicyList, p.Name)
}
@@ -668,6 +733,10 @@ func newNeighborFromAPIStruct(a *api.Peer) (*config.Neighbor, error) {
pconf.EbgpMultihop.Config.Enabled = a.EbgpMultihop.Enabled
pconf.EbgpMultihop.Config.MultihopTtl = uint8(a.EbgpMultihop.MultihopTtl)
}
if a.TtlSecurity != nil {
pconf.TtlSecurity.Config.Enabled = a.TtlSecurity.Enabled
pconf.TtlSecurity.Config.TtlMin = uint8(a.TtlSecurity.TtlMin)
}
if a.State != nil {
pconf.State.SessionState = config.SessionState(strings.ToUpper(string(a.State.SessionState)))
pconf.State.AdminState = config.IntToAdminStateMap[int(a.State.AdminState)]
@@ -771,6 +840,10 @@ func newPeerGroupFromAPIStruct(a *api.PeerGroup) (*config.PeerGroup, error) {
pconf.EbgpMultihop.Config.Enabled = a.EbgpMultihop.Enabled
pconf.EbgpMultihop.Config.MultihopTtl = uint8(a.EbgpMultihop.MultihopTtl)
}
if a.TtlSecurity != nil {
pconf.TtlSecurity.Config.Enabled = a.TtlSecurity.Enabled
pconf.TtlSecurity.Config.TtlMin = uint8(a.TtlSecurity.TtlMin)
}
if a.Info != nil {
pconf.State.TotalPaths = a.Info.TotalPaths
pconf.State.TotalPrefixes = a.Info.TotalPrefixes
@@ -808,6 +881,10 @@ func (s *server) AddDynamicNeighbor(ctx context.Context, r *api.AddDynamicNeighb
return &empty.Empty{}, s.bgpServer.AddDynamicNeighbor(ctx, r)
}
func (s *server) DeleteDynamicNeighbor(ctx context.Context, r *api.DeleteDynamicNeighborRequest) (*empty.Empty, error) {
return &empty.Empty{}, s.bgpServer.DeleteDynamicNeighbor(ctx, r)
}
func newPrefixFromApiStruct(a *api.Prefix) (*table.Prefix, error) {
_, prefix, err := net.ParseCIDR(a.IpPrefix)
if err != nil {
@@ -1135,6 +1212,11 @@ func toStatementApi(s *config.Statement) *api.Statement {
Self: true,
}
}
if string(s.Actions.BgpActions.SetNextHop) == "unchanged" {
return &api.NexthopAction{
Unchanged: true,
}
}
return &api.NexthopAction{
Address: string(s.Actions.BgpActions.SetNextHop),
}
@@ -1410,6 +1492,9 @@ func newNexthopActionFromApiStruct(a *api.NexthopAction) (*table.NexthopAction,
if a.Self {
return "self"
}
if a.Unchanged {
return "unchanged"
}
return a.Address
}(),
))
@@ -1757,3 +1842,7 @@ func (s *server) StopBgp(ctx context.Context, r *api.StopBgpRequest) (*empty.Emp
func (s *server) GetTable(ctx context.Context, r *api.GetTableRequest) (*api.GetTableResponse, error) {
return s.bgpServer.GetTable(ctx, r)
}
func (s *server) SetLogLevel(ctx context.Context, r *api.SetLogLevelRequest) (*empty.Empty, error) {
return &empty.Empty{}, s.bgpServer.SetLogLevel(ctx, r)
}

View File

@@ -51,7 +51,7 @@ func (m *mrtWriter) loop() error {
ops := []watchOption{}
switch m.c.DumpType {
case config.MRT_TYPE_UPDATES:
ops = append(ops, watchUpdate(false))
ops = append(ops, watchUpdate(false, ""))
case config.MRT_TYPE_TABLE:
if len(m.c.TableName) > 0 {
ops = append(ops, watchTableName(m.c.TableName))

View File

@@ -57,6 +57,10 @@ func (pg *peerGroup) AddDynamicNeighbor(c *config.DynamicNeighbor) {
pg.dynamicNeighbors[c.Config.Prefix] = c
}
func (pg *peerGroup) DeleteDynamicNeighbor(prefix string) {
delete(pg.dynamicNeighbors, prefix)
}
func newDynamicPeer(g *config.Global, neighborAddress string, pg *config.PeerGroup, loc *table.TableManager, policy *table.RoutingPolicy) *peer {
conf := config.Neighbor{
Config: config.NeighborConfig{
@@ -131,6 +135,15 @@ func (peer *peer) ID() string {
return peer.fsm.pConf.State.NeighborAddress
}
func (peer *peer) RouterID() string {
peer.fsm.lock.RLock()
defer peer.fsm.lock.RUnlock()
if peer.fsm.peerInfo.ID != nil {
return peer.fsm.peerInfo.ID.String()
}
return ""
}
func (peer *peer) TableID() string {
return peer.tableId
}
@@ -348,7 +361,22 @@ func (peer *peer) stopPeerRestarting() {
}
func (peer *peer) filterPathFromSourcePeer(path, old *table.Path) *table.Path {
if peer.ID() != path.GetSource().Address.String() {
// Consider 3 peers - A, B, C and prefix P originated by C. Parallel eBGP
// sessions exist between A & B, and both have a single session with C.
//
// When A receives the withdraw from C, we enter this func for each peer of
// A, with the following:
// peer: [C, B #1, B #2]
// path: new best for P facing B
// old: old best for P facing C
//
// Our comparison between peer identifier and path source ID must be router
// ID-based (not neighbor address), otherwise we will return early. If we
// return early for one of the two sessions facing B
// (whichever is not the new best path), we fail to send a withdraw towards
// B, and the route is "stuck".
// TODO: considerations for RFC6286
if peer.RouterID() != path.GetSource().ID.String() {
return path
}

View File

@@ -23,6 +23,7 @@ import (
"reflect"
"strconv"
"sync"
"syscall"
"time"
"github.com/eapache/channels"
@@ -52,35 +53,56 @@ func (l *tcpListener) Close() error {
}
// avoid mapped IPv6 address
func newTCPListener(address string, port uint32, ch chan *net.TCPConn) (*tcpListener, error) {
func newTCPListener(address string, port uint32, bindToDev string, ch chan *net.TCPConn) (*tcpListener, error) {
proto := "tcp4"
family := syscall.AF_INET
if ip := net.ParseIP(address); ip == nil {
return nil, fmt.Errorf("can't listen on %s", address)
} else if ip.To4() == nil {
proto = "tcp6"
family = syscall.AF_INET6
}
addr, err := net.ResolveTCPAddr(proto, net.JoinHostPort(address, strconv.Itoa(int(port))))
if err != nil {
return nil, err
addr := net.JoinHostPort(address, strconv.Itoa(int(port)))
var lc net.ListenConfig
lc.Control = func(network, address string, c syscall.RawConn) error {
if bindToDev != "" {
err := setBindToDevSockopt(c, bindToDev)
if err != nil {
log.WithFields(log.Fields{
"Topic": "Peer",
"Key": addr,
"BindToDev": bindToDev,
}).Warnf("failed to bind Listener to device (%s): %s", bindToDev, err)
return err
}
}
// Note: Set TTL=255 for incoming connection listener in order to accept
// connection in case for the neighbor has TTL Security settings.
err := setsockoptIpTtl(c, family, 255)
if err != nil {
log.WithFields(log.Fields{
"Topic": "Peer",
"Key": addr,
}).Warnf("cannot set TTL(=%d) for TCPListener: %s", 255, err)
}
return nil
}
l, err := net.ListenTCP(proto, addr)
l, err := lc.Listen(context.Background(), proto, addr)
if err != nil {
return nil, err
}
// Note: Set TTL=255 for incoming connection listener in order to accept
// connection in case for the neighbor has TTL Security settings.
if err := setListenTCPTTLSockopt(l, 255); err != nil {
log.WithFields(log.Fields{
"Topic": "Peer",
"Key": addr,
}).Warnf("cannot set TTL(=%d) for TCPListener: %s", 255, err)
listener, ok := l.(*net.TCPListener)
if !ok {
err = fmt.Errorf("unexpected connection listener (not for TCP)")
return nil, err
}
closeCh := make(chan struct{})
go func() error {
for {
conn, err := l.AcceptTCP()
conn, err := listener.AcceptTCP()
if err != nil {
close(closeCh)
log.WithFields(log.Fields{
@@ -93,7 +115,7 @@ func newTCPListener(address string, port uint32, ch chan *net.TCPConn) (*tcpList
}
}()
return &tcpListener{
l: l,
l: listener,
ch: closeCh,
}, nil
}
@@ -118,6 +140,7 @@ func GrpcOption(opt []grpc.ServerOption) ServerOption {
}
type BgpServer struct {
apiServer *server
bgpConfig config.Bgp
acceptCh chan *net.TCPConn
incomings []*channels.InfiniteChannel
@@ -158,9 +181,9 @@ func NewBgpServer(opt ...ServerOption) *BgpServer {
s.mrtManager = newMrtManager(s)
if len(opts.grpcAddress) != 0 {
grpc.EnableTracing = false
api := newAPIserver(s, grpc.NewServer(opts.grpcOption...), opts.grpcAddress)
s.apiServer = newAPIserver(s, grpc.NewServer(opts.grpcOption...), opts.grpcAddress)
go func() {
if err := api.serve(); err != nil {
if err := s.apiServer.serve(); err != nil {
log.Fatalf("failed to listen grpc port: %s", err)
}
}()
@@ -169,6 +192,14 @@ func NewBgpServer(opt ...ServerOption) *BgpServer {
return s
}
func (s *BgpServer) Stop() {
s.StopBgp(context.Background(), &api.StopBgpRequest{})
if s.apiServer != nil {
s.apiServer.grpcServer.Stop()
}
}
func (s *BgpServer) addIncoming(ch *channels.InfiniteChannel) {
s.incomings = append(s.incomings, ch)
}
@@ -555,7 +586,7 @@ func filterpath(peer *peer, path, old *table.Path) *table.Path {
return nil
}
if !peer.isRouteServerClient() && isASLoop(peer, path) {
if !peer.isRouteServerClient() && isASLoop(peer, path) && !path.IsLocal() {
return nil
}
return path
@@ -853,8 +884,12 @@ func (s *BgpServer) notifyPostPolicyUpdateWatcher(peer *peer, pathList []*table.
}
func newWatchEventPeerState(peer *peer, m *fsmMsg) *watchEventPeerState {
_, rport := peer.fsm.RemoteHostPort()
laddr, lport := peer.fsm.LocalHostPort()
var laddr string
var rport, lport uint16
if peer.fsm.conn != nil {
_, rport = peer.fsm.RemoteHostPort()
laddr, lport = peer.fsm.LocalHostPort()
}
sentOpen := buildopen(peer.fsm.gConf, peer.fsm.pConf)
peer.fsm.lock.RLock()
recvOpen := peer.fsm.recvOpen
@@ -1296,6 +1331,7 @@ func (s *BgpServer) deleteDynamicNeighbor(peer *peer, oldState bgp.FSMState, e *
peer.fsm.lock.RUnlock()
cleanInfiniteChannel(peer.fsm.outgoingCh)
cleanInfiniteChannel(peer.fsm.incomingCh)
s.delIncoming(peer.fsm.incomingCh)
s.broadcastPeerState(peer, oldState, e)
}
@@ -1696,6 +1732,9 @@ func (s *BgpServer) handleFSMMessage(peer *peer, e *fsmMsg) {
}
func (s *BgpServer) EnableZebra(ctx context.Context, r *api.EnableZebraRequest) error {
if r == nil {
return fmt.Errorf("nil request")
}
return s.mgmtOperation(func() error {
if s.zclient != nil {
return fmt.Errorf("already connected to Zebra")
@@ -1718,6 +1757,9 @@ func (s *BgpServer) EnableZebra(ctx context.Context, r *api.EnableZebraRequest)
}
func (s *BgpServer) AddBmp(ctx context.Context, r *api.AddBmpRequest) error {
if r == nil {
return fmt.Errorf("nil request")
}
return s.mgmtOperation(func() error {
_, ok := api.AddBmpRequest_MonitoringPolicy_name[int32(r.Policy)]
if !ok {
@@ -1735,6 +1777,9 @@ func (s *BgpServer) AddBmp(ctx context.Context, r *api.AddBmpRequest) error {
}
func (s *BgpServer) DeleteBmp(ctx context.Context, r *api.DeleteBmpRequest) error {
if r == nil {
return fmt.Errorf("nil request")
}
return s.mgmtOperation(func() error {
return s.bmpManager.deleteServer(&config.BmpServerConfig{
Address: r.Address,
@@ -1744,6 +1789,9 @@ func (s *BgpServer) DeleteBmp(ctx context.Context, r *api.DeleteBmpRequest) erro
}
func (s *BgpServer) StopBgp(ctx context.Context, r *api.StopBgpRequest) error {
if r == nil {
return fmt.Errorf("nil request")
}
s.mgmtOperation(func() error {
names := make([]string, 0, len(s.neighborMap))
for k := range s.neighborMap {
@@ -1769,11 +1817,15 @@ func (s *BgpServer) StopBgp(ctx context.Context, r *api.StopBgpRequest) error {
if s.shutdownWG != nil {
s.shutdownWG.Wait()
s.shutdownWG = nil
}
return nil
}
func (s *BgpServer) SetPolicies(ctx context.Context, r *api.SetPoliciesRequest) error {
if r == nil {
return fmt.Errorf("nil request")
}
rp, err := newRoutingPolicyFromApiStruct(r)
if err != nil {
return err
@@ -1989,6 +2041,9 @@ func (s *BgpServer) addPathStream(vrfId string, pathList []*table.Path) error {
}
func (s *BgpServer) AddPath(ctx context.Context, r *api.AddPathRequest) (*api.AddPathResponse, error) {
if r == nil || r.Path == nil {
return nil, fmt.Errorf("nil request")
}
var uuidBytes []byte
err := s.mgmtOperation(func() error {
path, err := api2Path(r.TableType, r.Path, false)
@@ -2009,6 +2064,9 @@ func (s *BgpServer) AddPath(ctx context.Context, r *api.AddPathRequest) (*api.Ad
}
func (s *BgpServer) DeletePath(ctx context.Context, r *api.DeletePathRequest) error {
if r == nil {
return fmt.Errorf("nil request")
}
return s.mgmtOperation(func() error {
deletePathList := make([]*table.Path, 0)
@@ -2082,10 +2140,10 @@ func (s *BgpServer) updatePath(vrfId string, pathList []*table.Path) error {
}
func (s *BgpServer) StartBgp(ctx context.Context, r *api.StartBgpRequest) error {
if r == nil || r.Global == nil {
return fmt.Errorf("nil request")
}
return s.mgmtOperation(func() error {
if r == nil || r.Global == nil {
return fmt.Errorf("invalid request")
}
g := r.Global
if net.ParseIP(g.RouterId) == nil {
return fmt.Errorf("invalid router-id format: %s", g.RouterId)
@@ -2099,7 +2157,7 @@ func (s *BgpServer) StartBgp(ctx context.Context, r *api.StartBgpRequest) error
if c.Config.Port > 0 {
acceptCh := make(chan *net.TCPConn, 4096)
for _, addr := range c.Config.LocalAddressList {
l, err := newTCPListener(addr, uint32(c.Config.Port), acceptCh)
l, err := newTCPListener(addr, uint32(c.Config.Port), g.BindToDevice, acceptCh)
if err != nil {
return err
}
@@ -2135,7 +2193,10 @@ func (s *BgpServer) listVrf() (l []*table.Vrf) {
return l
}
func (s *BgpServer) ListVrf(ctx context.Context, _ *api.ListVrfRequest, fn func(*api.Vrf)) error {
func (s *BgpServer) ListVrf(ctx context.Context, r *api.ListVrfRequest, fn func(*api.Vrf)) error {
if r == nil {
return fmt.Errorf("nil request")
}
toApi := func(v *table.Vrf) *api.Vrf {
return &api.Vrf{
Name: v.Name,
@@ -2148,7 +2209,10 @@ func (s *BgpServer) ListVrf(ctx context.Context, _ *api.ListVrfRequest, fn func(
var l []*api.Vrf
s.mgmtOperation(func() error {
l = make([]*api.Vrf, 0, len(s.globalRib.Vrfs))
for _, vrf := range s.globalRib.Vrfs {
for name, vrf := range s.globalRib.Vrfs {
if r.Name != "" && r.Name != name {
continue
}
l = append(l, toApi(vrf.Clone()))
}
return nil
@@ -2165,11 +2229,10 @@ func (s *BgpServer) ListVrf(ctx context.Context, _ *api.ListVrfRequest, fn func(
}
func (s *BgpServer) AddVrf(ctx context.Context, r *api.AddVrfRequest) error {
if r == nil || r.Vrf == nil {
return fmt.Errorf("nil request")
}
return s.mgmtOperation(func() error {
if r == nil || r.Vrf == nil {
return fmt.Errorf("invalid request")
}
name := r.Vrf.Name
id := r.Vrf.Id
@@ -2206,10 +2269,10 @@ func (s *BgpServer) AddVrf(ctx context.Context, r *api.AddVrfRequest) error {
}
func (s *BgpServer) DeleteVrf(ctx context.Context, r *api.DeleteVrfRequest) error {
if r == nil || r.Name == "" {
return fmt.Errorf("nil request")
}
return s.mgmtOperation(func() error {
if r == nil || r.Name == "" {
return fmt.Errorf("invalid request")
}
name := r.Name
for _, n := range s.neighborMap {
n.fsm.lock.RLock()
@@ -2473,6 +2536,9 @@ func (s *BgpServer) getAdjRib(addr string, family bgp.RouteFamily, in bool, enab
}
func (s *BgpServer) ListPath(ctx context.Context, r *api.ListPathRequest, fn func(*api.Destination)) error {
if r == nil {
return fmt.Errorf("nil request")
}
var tbl *table.Table
var v map[*table.Path]*table.Validation
var filtered map[string]*table.Path
@@ -2520,7 +2586,7 @@ func (s *BgpServer) ListPath(ctx context.Context, r *api.ListPathRequest, fn fun
}
knownPathList := dst.GetAllKnownPathList()
for i, path := range knownPathList {
p := toPathApi(path, getValidation(v, path))
p := toPathApi(path, getValidation(v, path), r.EnableNlriBinary, r.EnableAttributeBinary)
if !table.SelectionOptions.DisableBestPathSelection {
if i == 0 {
switch r.TableType {
@@ -2638,8 +2704,8 @@ func (s *BgpServer) getVrfRibInfo(name string, family bgp.RouteFamily) (info *ta
}
func (s *BgpServer) GetTable(ctx context.Context, r *api.GetTableRequest) (*api.GetTableResponse, error) {
if r == nil {
return nil, fmt.Errorf("invalid request")
if r == nil || r.Family == nil {
return nil, fmt.Errorf("nil request")
}
family := bgp.RouteFamily(0)
if r.Family != nil {
@@ -2674,6 +2740,9 @@ func (s *BgpServer) GetTable(ctx context.Context, r *api.GetTableRequest) (*api.
}
func (s *BgpServer) GetBgp(ctx context.Context, r *api.GetBgpRequest) (*api.GetBgpResponse, error) {
if r == nil {
return nil, fmt.Errorf("nil request")
}
var rsp *api.GetBgpResponse
s.mgmtOperation(func() error {
g := s.bgpConfig.Global
@@ -2691,7 +2760,72 @@ func (s *BgpServer) GetBgp(ctx context.Context, r *api.GetBgpRequest) (*api.GetB
return rsp, nil
}
func (s *BgpServer) ListDynamicNeighbor(ctx context.Context, r *api.ListDynamicNeighborRequest, fn func(neighbor *api.DynamicNeighbor)) error {
if r == nil {
return fmt.Errorf("nil request")
}
toApi := func(dn *config.DynamicNeighbor) *api.DynamicNeighbor {
return &api.DynamicNeighbor{
Prefix: dn.Config.Prefix,
PeerGroup: dn.Config.PeerGroup,
}
}
var l []*api.DynamicNeighbor
s.mgmtOperation(func() error {
peerGroupName := r.PeerGroup
for k, group := range s.peerGroupMap {
if peerGroupName != "" && peerGroupName != k {
continue
}
for _, dn := range group.dynamicNeighbors {
l = append(l, toApi(dn))
}
}
return nil
}, false)
for _, dn := range l {
select {
case <-ctx.Done():
return nil
default:
fn(dn)
}
}
return nil
}
func (s *BgpServer) ListPeerGroup(ctx context.Context, r *api.ListPeerGroupRequest, fn func(*api.PeerGroup)) error {
if r == nil {
return fmt.Errorf("nil request")
}
var l []*api.PeerGroup
s.mgmtOperation(func() error {
peerGroupName := r.PeerGroupName
l = make([]*api.PeerGroup, 0, len(s.peerGroupMap))
for k, group := range s.peerGroupMap {
if peerGroupName != "" && peerGroupName != k {
continue
}
pg := config.NewPeerGroupFromConfigStruct(group.Conf)
l = append(l, pg)
}
return nil
}, false)
for _, pg := range l {
select {
case <-ctx.Done():
return nil
default:
fn(pg)
}
}
return nil
}
func (s *BgpServer) ListPeer(ctx context.Context, r *api.ListPeerRequest, fn func(*api.Peer)) error {
if r == nil {
return fmt.Errorf("nil request")
}
var l []*api.Peer
s.mgmtOperation(func() error {
address := r.Address
@@ -2839,6 +2973,9 @@ func (s *BgpServer) addNeighbor(c *config.Neighbor) error {
}
func (s *BgpServer) AddPeerGroup(ctx context.Context, r *api.AddPeerGroupRequest) error {
if r == nil || r.PeerGroup == nil {
return fmt.Errorf("nil request")
}
return s.mgmtOperation(func() error {
c, err := newPeerGroupFromAPIStruct(r.PeerGroup)
if err != nil {
@@ -2849,6 +2986,9 @@ func (s *BgpServer) AddPeerGroup(ctx context.Context, r *api.AddPeerGroupRequest
}
func (s *BgpServer) AddPeer(ctx context.Context, r *api.AddPeerRequest) error {
if r == nil || r.Peer == nil {
return fmt.Errorf("nil request")
}
return s.mgmtOperation(func() error {
c, err := newNeighborFromAPIStruct(r.Peer)
if err != nil {
@@ -2859,6 +2999,9 @@ func (s *BgpServer) AddPeer(ctx context.Context, r *api.AddPeerRequest) error {
}
func (s *BgpServer) AddDynamicNeighbor(ctx context.Context, r *api.AddDynamicNeighborRequest) error {
if r == nil || r.DynamicNeighbor == nil {
return fmt.Errorf("nil request")
}
return s.mgmtOperation(func() error {
c := &config.DynamicNeighbor{Config: config.DynamicNeighborConfig{
Prefix: r.DynamicNeighbor.Prefix,
@@ -2929,6 +3072,9 @@ func (s *BgpServer) deleteNeighbor(c *config.Neighbor, code, subcode uint8) erro
}
func (s *BgpServer) DeletePeerGroup(ctx context.Context, r *api.DeletePeerGroupRequest) error {
if r == nil {
return fmt.Errorf("nil request")
}
return s.mgmtOperation(func() error {
name := r.Name
for _, n := range s.neighborMap {
@@ -2944,6 +3090,9 @@ func (s *BgpServer) DeletePeerGroup(ctx context.Context, r *api.DeletePeerGroupR
}
func (s *BgpServer) DeletePeer(ctx context.Context, r *api.DeletePeerRequest) error {
if r == nil {
return fmt.Errorf("nil request")
}
return s.mgmtOperation(func() error {
c := &config.Neighbor{Config: config.NeighborConfig{
NeighborAddress: r.Address,
@@ -2953,6 +3102,16 @@ func (s *BgpServer) DeletePeer(ctx context.Context, r *api.DeletePeerRequest) er
}, true)
}
func (s *BgpServer) DeleteDynamicNeighbor(ctx context.Context, r *api.DeleteDynamicNeighborRequest) error {
if r == nil {
return fmt.Errorf("nil request")
}
return s.mgmtOperation(func() error {
s.peerGroupMap[r.PeerGroup].DeleteDynamicNeighbor(r.Prefix)
return nil
}, true)
}
func (s *BgpServer) updatePeerGroup(pg *config.PeerGroup) (needsSoftResetIn bool, err error) {
name := pg.Config.PeerGroupName
@@ -2974,6 +3133,9 @@ func (s *BgpServer) updatePeerGroup(pg *config.PeerGroup) (needsSoftResetIn bool
}
func (s *BgpServer) UpdatePeerGroup(ctx context.Context, r *api.UpdatePeerGroupRequest) (rsp *api.UpdatePeerGroupResponse, err error) {
if r == nil || r.PeerGroup == nil {
return nil, fmt.Errorf("nil request")
}
doSoftreset := false
err = s.mgmtOperation(func() error {
pg, err := newPeerGroupFromAPIStruct(r.PeerGroup)
@@ -3081,6 +3243,9 @@ func (s *BgpServer) updateNeighbor(c *config.Neighbor) (needsSoftResetIn bool, e
}
func (s *BgpServer) UpdatePeer(ctx context.Context, r *api.UpdatePeerRequest) (rsp *api.UpdatePeerResponse, err error) {
if r == nil || r.Peer == nil {
return nil, fmt.Errorf("nil request")
}
doSoftReset := false
err = s.mgmtOperation(func() error {
c, err := newNeighborFromAPIStruct(r.Peer)
@@ -3124,12 +3289,18 @@ func (s *BgpServer) sendNotification(op, addr string, subcode uint8, data []byte
}
func (s *BgpServer) ShutdownPeer(ctx context.Context, r *api.ShutdownPeerRequest) error {
if r == nil {
return fmt.Errorf("nil request")
}
return s.mgmtOperation(func() error {
return s.sendNotification("Neighbor shutdown", r.Address, bgp.BGP_ERROR_SUB_ADMINISTRATIVE_SHUTDOWN, newAdministrativeCommunication(r.Communication))
}, true)
}
func (s *BgpServer) ResetPeer(ctx context.Context, r *api.ResetPeerRequest) error {
if r == nil {
return fmt.Errorf("nil request")
}
return s.mgmtOperation(func() error {
addr := r.Address
comm := r.Communication
@@ -3197,18 +3368,27 @@ func (s *BgpServer) setAdminState(addr, communication string, enable bool) error
}
func (s *BgpServer) EnablePeer(ctx context.Context, r *api.EnablePeerRequest) error {
if r == nil {
return fmt.Errorf("nil request")
}
return s.mgmtOperation(func() error {
return s.setAdminState(r.Address, "", true)
}, true)
}
func (s *BgpServer) DisablePeer(ctx context.Context, r *api.DisablePeerRequest) error {
if r == nil {
return fmt.Errorf("nil request")
}
return s.mgmtOperation(func() error {
return s.setAdminState(r.Address, r.Communication, false)
}, true)
}
func (s *BgpServer) ListDefinedSet(ctx context.Context, r *api.ListDefinedSetRequest, fn func(*api.DefinedSet)) error {
if r == nil {
return fmt.Errorf("nil request")
}
var cd *config.DefinedSets
var err error
err = s.mgmtOperation(func() error {
@@ -3303,10 +3483,10 @@ func (s *BgpServer) ListDefinedSet(ctx context.Context, r *api.ListDefinedSetReq
}
func (s *BgpServer) AddDefinedSet(ctx context.Context, r *api.AddDefinedSetRequest) error {
if r == nil || r.DefinedSet == nil {
return fmt.Errorf("nil request")
}
return s.mgmtOperation(func() error {
if r == nil || r.DefinedSet == nil {
return fmt.Errorf("invalid request")
}
set, err := newDefinedSetFromApiStruct(r.DefinedSet)
if err != nil {
return err
@@ -3316,10 +3496,10 @@ func (s *BgpServer) AddDefinedSet(ctx context.Context, r *api.AddDefinedSetReque
}
func (s *BgpServer) DeleteDefinedSet(ctx context.Context, r *api.DeleteDefinedSetRequest) error {
if r == nil || r.DefinedSet == nil {
return fmt.Errorf("nil request")
}
return s.mgmtOperation(func() error {
if r == nil || r.DefinedSet == nil {
return fmt.Errorf("invalid request")
}
set, err := newDefinedSetFromApiStruct(r.DefinedSet)
if err != nil {
return err
@@ -3329,6 +3509,9 @@ func (s *BgpServer) DeleteDefinedSet(ctx context.Context, r *api.DeleteDefinedSe
}
func (s *BgpServer) ListStatement(ctx context.Context, r *api.ListStatementRequest, fn func(*api.Statement)) error {
if r == nil {
return fmt.Errorf("nil request")
}
var l []*api.Statement
s.mgmtOperation(func() error {
s := s.policy.GetStatement(r.Name)
@@ -3350,10 +3533,10 @@ func (s *BgpServer) ListStatement(ctx context.Context, r *api.ListStatementReque
}
func (s *BgpServer) AddStatement(ctx context.Context, r *api.AddStatementRequest) error {
if r == nil || r.Statement == nil {
return fmt.Errorf("nil request")
}
return s.mgmtOperation(func() error {
if r == nil || r.Statement == nil {
return fmt.Errorf("invalid request")
}
st, err := newStatementFromApiStruct(r.Statement)
if err != nil {
return err
@@ -3363,10 +3546,10 @@ func (s *BgpServer) AddStatement(ctx context.Context, r *api.AddStatementRequest
}
func (s *BgpServer) DeleteStatement(ctx context.Context, r *api.DeleteStatementRequest) error {
if r == nil || r.Statement == nil {
return fmt.Errorf("nil request")
}
return s.mgmtOperation(func() error {
if r == nil || r.Statement == nil {
return fmt.Errorf("invalid request")
}
st, err := newStatementFromApiStruct(r.Statement)
if err == nil {
err = s.policy.DeleteStatement(st, r.All)
@@ -3376,6 +3559,9 @@ func (s *BgpServer) DeleteStatement(ctx context.Context, r *api.DeleteStatementR
}
func (s *BgpServer) ListPolicy(ctx context.Context, r *api.ListPolicyRequest, fn func(*api.Policy)) error {
if r == nil {
return fmt.Errorf("nil request")
}
var l []*api.Policy
s.mgmtOperation(func() error {
pl := s.policy.GetPolicy(r.Name)
@@ -3397,10 +3583,10 @@ func (s *BgpServer) ListPolicy(ctx context.Context, r *api.ListPolicyRequest, fn
}
func (s *BgpServer) AddPolicy(ctx context.Context, r *api.AddPolicyRequest) error {
if r == nil || r.Policy == nil {
return fmt.Errorf("nil request")
}
return s.mgmtOperation(func() error {
if r == nil || r.Policy == nil {
return fmt.Errorf("invalid request")
}
p, err := newPolicyFromApiStruct(r.Policy)
if err == nil {
err = s.policy.AddPolicy(p, r.ReferExistingStatements)
@@ -3410,10 +3596,10 @@ func (s *BgpServer) AddPolicy(ctx context.Context, r *api.AddPolicyRequest) erro
}
func (s *BgpServer) DeletePolicy(ctx context.Context, r *api.DeletePolicyRequest) error {
if r == nil || r.Policy == nil {
return fmt.Errorf("nil request")
}
return s.mgmtOperation(func() error {
if r == nil || r.Policy == nil {
return fmt.Errorf("invalid request")
}
p, err := newPolicyFromApiStruct(r.Policy)
if err != nil {
return err
@@ -3456,12 +3642,11 @@ func (s *BgpServer) toPolicyInfo(name string, dir api.PolicyDirection) (string,
}
func (s *BgpServer) ListPolicyAssignment(ctx context.Context, r *api.ListPolicyAssignmentRequest, fn func(*api.PolicyAssignment)) error {
if r == nil {
return fmt.Errorf("nil request")
}
var a []*api.PolicyAssignment
err := s.mgmtOperation(func() error {
if r == nil {
return fmt.Errorf("invalid request")
}
names := make([]string, 0, len(s.neighborMap)+1)
if r.Name == "" {
names = append(names, table.GLOBAL_RIB_NAME)
@@ -3491,9 +3676,6 @@ func (s *BgpServer) ListPolicyAssignment(ctx context.Context, r *api.ListPolicyA
if err != nil {
return err
}
if len(policies) == 0 {
continue
}
t := &table.PolicyAssignment{
Name: name,
Type: dir,
@@ -3519,10 +3701,10 @@ func (s *BgpServer) ListPolicyAssignment(ctx context.Context, r *api.ListPolicyA
}
func (s *BgpServer) AddPolicyAssignment(ctx context.Context, r *api.AddPolicyAssignmentRequest) error {
if r == nil || r.Assignment == nil {
return fmt.Errorf("nil request")
}
return s.mgmtOperation(func() error {
if r == nil || r.Assignment == nil {
return fmt.Errorf("invalid request")
}
id, dir, err := s.toPolicyInfo(r.Assignment.Name, r.Assignment.Direction)
if err != nil {
return err
@@ -3532,10 +3714,10 @@ func (s *BgpServer) AddPolicyAssignment(ctx context.Context, r *api.AddPolicyAss
}
func (s *BgpServer) DeletePolicyAssignment(ctx context.Context, r *api.DeletePolicyAssignmentRequest) error {
if r == nil || r.Assignment == nil {
return fmt.Errorf("nil request")
}
return s.mgmtOperation(func() error {
if r == nil || r.Assignment == nil {
return fmt.Errorf("invalid request")
}
id, dir, err := s.toPolicyInfo(r.Assignment.Name, r.Assignment.Direction)
if err != nil {
return err
@@ -3545,10 +3727,10 @@ func (s *BgpServer) DeletePolicyAssignment(ctx context.Context, r *api.DeletePol
}
func (s *BgpServer) SetPolicyAssignment(ctx context.Context, r *api.SetPolicyAssignmentRequest) error {
if r == nil || r.Assignment == nil {
return fmt.Errorf("nil request")
}
return s.mgmtOperation(func() error {
if r == nil || r.Assignment == nil {
return fmt.Errorf("invalid request")
}
id, dir, err := s.toPolicyInfo(r.Assignment.Name, r.Assignment.Direction)
if err != nil {
return err
@@ -3558,6 +3740,9 @@ func (s *BgpServer) SetPolicyAssignment(ctx context.Context, r *api.SetPolicyAss
}
func (s *BgpServer) EnableMrt(ctx context.Context, r *api.EnableMrtRequest) error {
if r == nil {
return fmt.Errorf("nil request")
}
return s.mgmtOperation(func() error {
return s.mrtManager.enable(&config.MrtConfig{
DumpInterval: r.DumpInterval,
@@ -3569,12 +3754,18 @@ func (s *BgpServer) EnableMrt(ctx context.Context, r *api.EnableMrtRequest) erro
}
func (s *BgpServer) DisableMrt(ctx context.Context, r *api.DisableMrtRequest) error {
if r == nil {
return fmt.Errorf("nil request")
}
return s.mgmtOperation(func() error {
return s.mrtManager.disable(&config.MrtConfig{})
}, false)
}
func (s *BgpServer) ListRpki(ctx context.Context, r *api.ListRpkiRequest, fn func(*api.Rpki)) error {
if r == nil || r.Family == nil {
return fmt.Errorf("nil request")
}
var l []*api.Rpki
err := s.mgmtOperation(func() error {
for _, r := range s.roaManager.GetServers() {
@@ -3623,6 +3814,9 @@ func (s *BgpServer) ListRpki(ctx context.Context, r *api.ListRpkiRequest, fn fun
}
func (s *BgpServer) ListRpkiTable(ctx context.Context, r *api.ListRpkiTableRequest, fn func(*api.Roa)) error {
if r == nil {
return fmt.Errorf("nil request")
}
var l []*api.Roa
err := s.mgmtOperation(func() error {
family := bgp.RouteFamily(0)
@@ -3649,30 +3843,45 @@ func (s *BgpServer) ListRpkiTable(ctx context.Context, r *api.ListRpkiTableReque
}
func (s *BgpServer) AddRpki(ctx context.Context, r *api.AddRpkiRequest) error {
if r == nil {
return fmt.Errorf("nil request")
}
return s.mgmtOperation(func() error {
return s.roaManager.AddServer(net.JoinHostPort(r.Address, strconv.Itoa(int(r.Port))), r.Lifetime)
}, false)
}
func (s *BgpServer) DeleteRpki(ctx context.Context, r *api.DeleteRpkiRequest) error {
if r == nil {
return fmt.Errorf("nil request")
}
return s.mgmtOperation(func() error {
return s.roaManager.DeleteServer(r.Address)
}, false)
}
func (s *BgpServer) EnableRpki(ctx context.Context, r *api.EnableRpkiRequest) error {
if r == nil {
return fmt.Errorf("nil request")
}
return s.mgmtOperation(func() error {
return s.roaManager.Enable(r.Address)
}, false)
}
func (s *BgpServer) DisableRpki(ctx context.Context, r *api.DisableRpkiRequest) error {
if r == nil {
return fmt.Errorf("nil request")
}
return s.mgmtOperation(func() error {
return s.roaManager.Disable(r.Address)
}, false)
}
func (s *BgpServer) ResetRpki(ctx context.Context, r *api.ResetRpkiRequest) error {
if r == nil {
return fmt.Errorf("nil request")
}
return s.mgmtOperation(func() error {
if r.Soft {
return s.roaManager.SoftReset(r.Address)
@@ -3691,9 +3900,9 @@ func (s *BgpServer) MonitorTable(ctx context.Context, r *api.MonitorTableRequest
return s.watch(watchBestPath(r.Current)), nil
case api.TableType_ADJ_IN:
if r.PostPolicy {
return s.watch(watchPostUpdate(r.Current)), nil
return s.watch(watchPostUpdate(r.Current, r.Name)), nil
}
return s.watch(watchUpdate(r.Current)), nil
return s.watch(watchUpdate(r.Current, r.Name)), nil
default:
return nil, fmt.Errorf("unsupported resource type: %v", r.TableType)
}
@@ -3733,11 +3942,14 @@ func (s *BgpServer) MonitorTable(ctx context.Context, r *api.MonitorTableRequest
if path == nil || (r.Family != nil && family != path.GetRouteFamily()) {
continue
}
if len(r.Name) > 0 && r.Name != path.GetSource().Address.String() {
continue
}
select {
case <-ctx.Done():
return
default:
fn(toPathApi(path, nil))
fn(toPathApi(path, nil, false, false))
}
}
case <-ctx.Done():
@@ -3754,7 +3966,13 @@ func (s *BgpServer) MonitorPeer(ctx context.Context, r *api.MonitorPeerRequest,
}
go func() {
w := s.watch(watchPeerState(r.Current))
// So that both flags are not required, assume that if the
// initial_state flag is true, then the caller desires that the initial
// state be returned whether or not it is established and regardless of
// the value of `current`.
current := r.Current || r.InitialState
nonEstablished := r.InitialState
w := s.watch(watchPeerState(current, nonEstablished))
defer func() {
w.Stop()
}()
@@ -3795,6 +4013,22 @@ func (s *BgpServer) MonitorPeer(ctx context.Context, r *api.MonitorPeerRequest,
return nil
}
func (s *BgpServer) SetLogLevel(ctx context.Context, r *api.SetLogLevelRequest) error {
prevLevel := log.GetLevel()
newLevel := log.Level(r.Level)
if prevLevel == newLevel {
log.WithFields(log.Fields{
"Topic": "Config",
}).Infof("Logging level unchanged -- level already set to %v", newLevel)
} else {
log.SetLevel(newLevel)
log.WithFields(log.Fields{
"Topic": "Config",
}).Infof("Logging level changed -- prev: %v, new: %v", prevLevel, newLevel)
}
return nil
}
type watchEventType string
const (
@@ -3879,8 +4113,10 @@ type watchOptions struct {
initUpdate bool
initPostUpdate bool
initPeerState bool
nonEstablished bool
tableName string
recvMessage bool
peerAddress string
}
type watchOption func(*watchOptions)
@@ -3894,29 +4130,34 @@ func watchBestPath(current bool) watchOption {
}
}
func watchUpdate(current bool) watchOption {
func watchUpdate(current bool, peerAddress string) watchOption {
return func(o *watchOptions) {
o.preUpdate = true
if current {
o.initUpdate = true
}
o.peerAddress = peerAddress
}
}
func watchPostUpdate(current bool) watchOption {
func watchPostUpdate(current bool, peerAddress string) watchOption {
return func(o *watchOptions) {
o.postUpdate = true
if current {
o.initPostUpdate = true
}
o.peerAddress = peerAddress
}
}
func watchPeerState(current bool) watchOption {
func watchPeerState(current, includeNonEstablished bool) watchOption {
return func(o *watchOptions) {
o.peerState = true
if current {
o.initPeerState = true
if includeNonEstablished {
o.nonEstablished = true
}
}
}
}
@@ -4071,11 +4312,13 @@ func (s *BgpServer) watch(opts ...watchOption) (w *watcher) {
}
if w.opts.initPeerState {
for _, peer := range s.neighborMap {
peer.fsm.lock.RLock()
notEstablished := peer.fsm.state != bgp.BGP_FSM_ESTABLISHED
peer.fsm.lock.RUnlock()
if notEstablished {
continue
if !w.opts.nonEstablished {
peer.fsm.lock.RLock()
notEstablished := peer.fsm.state != bgp.BGP_FSM_ESTABLISHED
peer.fsm.lock.RUnlock()
if notEstablished {
continue
}
}
w.notify(newWatchEventPeerState(peer, nil))
}
@@ -4090,10 +4333,14 @@ func (s *BgpServer) watch(opts ...watchOption) (w *watcher) {
for _, peer := range s.neighborMap {
peer.fsm.lock.RLock()
notEstablished := peer.fsm.state != bgp.BGP_FSM_ESTABLISHED
peerAddress := peer.fsm.peerInfo.Address.String()
peer.fsm.lock.RUnlock()
if notEstablished {
continue
}
if len(w.opts.peerAddress) > 0 && w.opts.peerAddress != peerAddress {
continue
}
configNeighbor := w.s.toConfig(peer, false)
for _, rf := range peer.configuredRFlist() {
peer.fsm.lock.RLock()
@@ -4148,9 +4395,13 @@ func (s *BgpServer) watch(opts ...watchOption) (w *watcher) {
for peerInfo, paths := range pathsByPeer {
// create copy which can be access to without mutex
var configNeighbor *config.Neighbor
if peer, ok := s.neighborMap[peerInfo.Address.String()]; ok {
peerAddress := peerInfo.Address.String()
if peer, ok := s.neighborMap[peerAddress]; ok {
configNeighbor = w.s.toConfig(peer, false)
}
if w.opts.peerAddress != "" && w.opts.peerAddress != peerAddress {
continue
}
w.notify(&watchEventUpdate{
PeerAS: peerInfo.AS,

View File

@@ -17,6 +17,7 @@
package server
import (
"fmt"
"net"
"syscall"
@@ -27,10 +28,6 @@ func setTCPMD5SigSockopt(l *net.TCPListener, address string, key string) error {
return setTcpMD5SigSockopt(l, address, key)
}
func setListenTCPTTLSockopt(l *net.TCPListener, ttl int) error {
return setListenTcpTTLSockopt(l, ttl)
}
func setTCPTTLSockopt(conn *net.TCPConn, ttl int) error {
return setTcpTTLSockopt(conn, ttl)
}
@@ -39,6 +36,10 @@ func setTCPMinTTLSockopt(conn *net.TCPConn, ttl int) error {
return setTcpMinTTLSockopt(conn, ttl)
}
func setBindToDevSockopt(sc syscall.RawConn, device string) error {
return fmt.Errorf("binding connection to a device is not supported")
}
func dialerControl(network, address string, c syscall.RawConn, ttl, ttlMin uint8, password string, bindInterface string) error {
if password != "" {
log.WithFields(log.Fields{

View File

@@ -35,15 +35,6 @@ func setTcpMD5SigSockopt(l *net.TCPListener, address string, key string) error {
return setsockOptInt(sc, syscall.IPPROTO_TCP, tcpMD5SIG, 1)
}
func setListenTcpTTLSockopt(l *net.TCPListener, ttl int) error {
family := extractFamilyFromTCPListener(l)
sc, err := l.SyscallConn()
if err != nil {
return err
}
return setsockoptIpTtl(sc, family, ttl)
}
func setTcpTTLSockopt(conn *net.TCPConn, ttl int) error {
family := extractFamilyFromTCPConn(conn)
sc, err := conn.SyscallConn()

View File

@@ -27,15 +27,6 @@ func setTcpMD5SigSockopt(l *net.TCPListener, address string, key string) error {
return fmt.Errorf("setting md5 is not supported")
}
func setListenTcpTTLSockopt(l *net.TCPListener, ttl int) error {
family := extractFamilyFromTCPListener(l)
sc, err := l.SyscallConn()
if err != nil {
return err
}
return setsockoptIpTtl(sc, family, ttl)
}
func setTcpTTLSockopt(conn *net.TCPConn, ttl int) error {
family := syscall.AF_INET
if strings.Contains(conn.RemoteAddr().String(), "[") {

View File

@@ -70,13 +70,8 @@ func setTCPMD5SigSockopt(l *net.TCPListener, address string, key string) error {
return setsockOptString(sc, syscall.IPPROTO_TCP, tcpMD5SIG, string(b[:]))
}
func setListenTCPTTLSockopt(l *net.TCPListener, ttl int) error {
family := extractFamilyFromTCPListener(l)
sc, err := l.SyscallConn()
if err != nil {
return err
}
return setsockoptIpTtl(sc, family, ttl)
func setBindToDevSockopt(sc syscall.RawConn, device string) error {
return setsockOptString(sc, syscall.SOL_SOCKET, syscall.SO_BINDTODEVICE, device)
}
func setTCPTTLSockopt(conn *net.TCPConn, ttl int) error {
@@ -162,14 +157,9 @@ func dialerControl(network, address string, c syscall.RawConn, ttl, minTtl uint8
}
}
if bindInterface != "" {
if err := c.Control(func(fd uintptr) {
sockerr = os.NewSyscallError("setsockopt", syscall.SetsockoptString(int(fd), syscall.SOL_SOCKET, syscall.SO_BINDTODEVICE, bindInterface))
}); err != nil {
if err := setBindToDevSockopt(c, bindInterface); err != nil {
return err
}
if sockerr != nil {
return sockerr
}
}
return nil
}

View File

@@ -370,15 +370,6 @@ func setTCPMD5SigSockopt(l *net.TCPListener, address string, key string) error {
return setsockoptTcpMD5Sig(sc, address, key)
}
func setListenTCPTTLSockopt(l *net.TCPListener, ttl int) error {
family := extractFamilyFromTCPListener(l)
sc, err := l.SyscallConn()
if err != nil {
return err
}
return setsockoptIpTtl(sc, family, ttl)
}
func setTCPTTLSockopt(conn *net.TCPConn, ttl int) error {
family := extractFamilyFromTCPConn(conn)
sc, err := conn.SyscallConn()
@@ -403,6 +394,10 @@ func setTCPMinTTLSockopt(conn *net.TCPConn, ttl int) error {
return setsockOptInt(sc, level, name, ttl)
}
func setBindToDevSockopt(sc syscall.RawConn, device string) error {
return fmt.Errorf("binding connection to a device is not supported")
}
func dialerControl(network, address string, c syscall.RawConn, ttl, minTtl uint8, password string, bindInterface string) error {
if password != "" {
log.WithFields(log.Fields{

View File

@@ -59,20 +59,12 @@ func decodeAdministrativeCommunication(data []byte) (string, []byte) {
if communicationLen > bgp.BGP_ERROR_ADMINISTRATIVE_COMMUNICATION_MAX {
communicationLen = bgp.BGP_ERROR_ADMINISTRATIVE_COMMUNICATION_MAX
}
if communicationLen > len(data)+1 {
communicationLen = len(data) + 1
if communicationLen > len(data)-1 {
communicationLen = len(data) - 1
}
return string(data[1 : communicationLen+1]), data[communicationLen+1:]
}
func extractFamilyFromTCPListener(l *net.TCPListener) int {
family := syscall.AF_INET
if strings.Contains(l.Addr().String(), "[") {
family = syscall.AF_INET6
}
return family
}
func extractFamilyFromTCPConn(conn *net.TCPConn) int {
family := syscall.AF_INET
if strings.Contains(conn.RemoteAddr().String(), "[") {

View File

@@ -364,7 +364,7 @@ func (z *zebraClient) updatePathByNexthopCache(paths []*table.Path) {
func (z *zebraClient) loop() {
w := z.server.watch([]watchOption{
watchBestPath(true),
watchPostUpdate(true),
watchPostUpdate(true, ""),
}...)
defer w.Stop()