github.com/osrg/gobgp@v2.0.0+incompatible/cmd/gobgp/monitor.go (about)

     1  // Copyright (C) 2015 Nippon Telegraph and Telephone Corporation.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //    http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
    12  // implied.
    13  // See the License for the specific language governing permissions and
    14  // limitations under the License.
    15  
    16  package main
    17  
    18  import (
    19  	"encoding/json"
    20  	"fmt"
    21  	"io"
    22  	"net"
    23  	"time"
    24  
    25  	"github.com/spf13/cobra"
    26  
    27  	api "github.com/osrg/gobgp/api"
    28  	"github.com/osrg/gobgp/internal/pkg/apiutil"
    29  	"github.com/osrg/gobgp/pkg/packet/bgp"
    30  )
    31  
    32  func makeMonitorRouteArgs(p *api.Path, showIdentifier bgp.BGPAddPathMode) []interface{} {
    33  	pathStr := make([]interface{}, 0)
    34  
    35  	// Title
    36  	title := "ROUTE"
    37  	if p.IsWithdraw {
    38  		title = "DELROUTE"
    39  	}
    40  	pathStr = append(pathStr, title)
    41  
    42  	// NLRI
    43  	// If Add-Path required, append Path Identifier.
    44  	nlri, _ := apiutil.GetNativeNlri(p)
    45  	if showIdentifier != bgp.BGP_ADD_PATH_NONE {
    46  		pathStr = append(pathStr, p.GetIdentifier())
    47  	}
    48  	pathStr = append(pathStr, nlri)
    49  
    50  	attrs, _ := apiutil.GetNativePathAttributes(p)
    51  	// Next Hop
    52  	nexthop := "fictitious"
    53  	if n := getNextHopFromPathAttributes(attrs); n != nil {
    54  		nexthop = n.String()
    55  	}
    56  	pathStr = append(pathStr, nexthop)
    57  
    58  	// AS_PATH
    59  	aspathstr := func() string {
    60  		for _, attr := range attrs {
    61  			switch a := attr.(type) {
    62  			case *bgp.PathAttributeAsPath:
    63  				return bgp.AsPathString(a)
    64  			}
    65  		}
    66  		return ""
    67  	}()
    68  	pathStr = append(pathStr, aspathstr)
    69  
    70  	// Path Attributes
    71  	pathStr = append(pathStr, getPathAttributeString(nlri, attrs))
    72  
    73  	return pathStr
    74  }
    75  
    76  func monitorRoute(pathList []*api.Path, showIdentifier bgp.BGPAddPathMode) {
    77  	var pathStrs [][]interface{}
    78  
    79  	for _, p := range pathList {
    80  		pathStrs = append(pathStrs, makeMonitorRouteArgs(p, showIdentifier))
    81  	}
    82  
    83  	format := time.Now().UTC().Format(time.RFC3339)
    84  	if showIdentifier == bgp.BGP_ADD_PATH_NONE {
    85  		format += " [%s] %s via %s aspath [%s] attrs %s\n"
    86  	} else {
    87  		format += " [%s] %d:%s via %s aspath [%s] attrs %s\n"
    88  	}
    89  	for _, pathStr := range pathStrs {
    90  		fmt.Printf(format, pathStr...)
    91  	}
    92  }
    93  
    94  func newMonitorCmd() *cobra.Command {
    95  
    96  	var current bool
    97  
    98  	monitor := func(recver interface {
    99  		Recv() (*api.MonitorTableResponse, error)
   100  	}, showIdentifier bgp.BGPAddPathMode) {
   101  		for {
   102  			r, err := recver.Recv()
   103  			if err == io.EOF {
   104  				break
   105  			} else if err != nil {
   106  				exitWithError(err)
   107  			}
   108  			if globalOpts.Json {
   109  				j, _ := json.Marshal(apiutil.NewDestination(&api.Destination{Paths: []*api.Path{r.Path}}))
   110  				fmt.Println(string(j))
   111  			} else {
   112  				monitorRoute([]*api.Path{r.Path}, bgp.BGP_ADD_PATH_NONE)
   113  			}
   114  		}
   115  	}
   116  
   117  	ribCmd := &cobra.Command{
   118  		Use: cmdRib,
   119  		Run: func(cmd *cobra.Command, args []string) {
   120  			family, err := checkAddressFamily(ipv4UC)
   121  			if err != nil {
   122  				exitWithError(err)
   123  			}
   124  			recver, err := client.MonitorTable(ctx, &api.MonitorTableRequest{
   125  				TableType: api.TableType_GLOBAL,
   126  				Family:    family,
   127  				Current:   current,
   128  			})
   129  			if err != nil {
   130  				exitWithError(err)
   131  			}
   132  			monitor(recver, bgp.BGP_ADD_PATH_NONE)
   133  		},
   134  	}
   135  	ribCmd.PersistentFlags().StringVarP(&subOpts.AddressFamily, "address-family", "a", "", "address family")
   136  
   137  	globalCmd := &cobra.Command{
   138  		Use: cmdGlobal,
   139  	}
   140  	globalCmd.AddCommand(ribCmd)
   141  
   142  	neighborCmd := &cobra.Command{
   143  		Use:  fmt.Sprintf("%s [<neighbor address>]", cmdNeighbor),
   144  		Args: cobra.MaximumNArgs(1),
   145  		Run: func(cmd *cobra.Command, args []string) {
   146  			name := ""
   147  			if len(args) > 0 {
   148  				name = args[0]
   149  			}
   150  			stream, err := client.MonitorPeer(ctx, &api.MonitorPeerRequest{
   151  				Address: name,
   152  				Current: current,
   153  			})
   154  			if err != nil {
   155  				exitWithError(err)
   156  			}
   157  			for {
   158  				r, err := stream.Recv()
   159  				if err == io.EOF {
   160  					break
   161  				} else if err != nil {
   162  					exitWithError(err)
   163  				}
   164  				s := r.Peer
   165  				if globalOpts.Json {
   166  					j, _ := json.Marshal(s)
   167  					fmt.Println(string(j))
   168  				} else {
   169  					addr := s.Conf.NeighborAddress
   170  					if s.Conf.NeighborInterface != "" {
   171  						addr = fmt.Sprintf("%s(%s)", addr, s.Conf.NeighborInterface)
   172  					}
   173  					fmt.Printf("%s [NEIGH] %s fsm: %s admin: %s\n", time.Now().UTC().Format(time.RFC3339), addr, s.State.SessionState, s.State.AdminState)
   174  				}
   175  			}
   176  		},
   177  	}
   178  
   179  	adjInCmd := &cobra.Command{
   180  		Use: cmdAdjIn,
   181  		Run: func(cmd *cobra.Command, args []string) {
   182  			name := ""
   183  			if len(args) > 0 {
   184  				remoteIP := net.ParseIP(args[0])
   185  				if remoteIP == nil {
   186  					exitWithError(fmt.Errorf("invalid ip address: %s", args[0]))
   187  				}
   188  				name = args[0]
   189  			}
   190  			family, err := checkAddressFamily(ipv4UC)
   191  			if err != nil {
   192  				exitWithError(err)
   193  			}
   194  			recver, err := client.MonitorTable(ctx, &api.MonitorTableRequest{
   195  				TableType: api.TableType_ADJ_IN,
   196  				Name:      name,
   197  				Family:    family,
   198  				Current:   current,
   199  			})
   200  			if err != nil {
   201  				exitWithError(err)
   202  			}
   203  			monitor(recver, bgp.BGP_ADD_PATH_RECEIVE)
   204  		},
   205  	}
   206  	adjInCmd.PersistentFlags().StringVarP(&subOpts.AddressFamily, "address-family", "a", "", "address family")
   207  
   208  	monitorCmd := &cobra.Command{
   209  		Use: cmdMonitor,
   210  	}
   211  	monitorCmd.AddCommand(globalCmd)
   212  	monitorCmd.AddCommand(neighborCmd)
   213  	monitorCmd.AddCommand(adjInCmd)
   214  
   215  	monitorCmd.PersistentFlags().BoolVarP(&current, "current", "", false, "dump current contents")
   216  
   217  	return monitorCmd
   218  }