github.com/osrg/gobgp@v2.0.0+incompatible/cmd/gobgp/vrf.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  	"sort"
    23  	"strconv"
    24  	"strings"
    25  
    26  	api "github.com/osrg/gobgp/api"
    27  	"github.com/osrg/gobgp/internal/pkg/apiutil"
    28  	"github.com/osrg/gobgp/pkg/packet/bgp"
    29  
    30  	"github.com/golang/protobuf/ptypes/any"
    31  	"github.com/spf13/cobra"
    32  )
    33  
    34  func getVrfs() ([]*api.Vrf, error) {
    35  	stream, err := client.ListVrf(ctx, &api.ListVrfRequest{})
    36  	if err != nil {
    37  		return nil, err
    38  	}
    39  	vrfs := make([]*api.Vrf, 0)
    40  	for {
    41  		r, err := stream.Recv()
    42  		if err == io.EOF {
    43  			break
    44  		} else if err != nil {
    45  			return nil, err
    46  		}
    47  		vrfs = append(vrfs, r.Vrf)
    48  	}
    49  	sort.Slice(vrfs, func(i, j int) bool {
    50  		return vrfs[i].Name < vrfs[j].Name
    51  	})
    52  	return vrfs, nil
    53  }
    54  
    55  func showVrfs() error {
    56  	maxLens := []int{20, 20, 20, 20, 5}
    57  	vrfs, err := getVrfs()
    58  	if err != nil {
    59  		return err
    60  	}
    61  	if globalOpts.Json {
    62  		j, _ := json.Marshal(vrfs)
    63  		fmt.Println(string(j))
    64  		return nil
    65  	}
    66  	if globalOpts.Quiet {
    67  		for _, v := range vrfs {
    68  			fmt.Println(v.Name)
    69  		}
    70  		return nil
    71  	}
    72  	lines := make([][]string, 0, len(vrfs))
    73  	for _, v := range vrfs {
    74  		name := v.Name
    75  		rd, err := apiutil.UnmarshalRD(v.Rd)
    76  		if err != nil {
    77  			return err
    78  		}
    79  		rdStr := rd.String()
    80  
    81  		f := func(rts []*any.Any) (string, error) {
    82  			ret := make([]string, 0, len(rts))
    83  			for _, an := range rts {
    84  				rt, err := apiutil.UnmarshalRT(an)
    85  				if err != nil {
    86  					return "", err
    87  				}
    88  				ret = append(ret, rt.String())
    89  			}
    90  			return strings.Join(ret, ", "), nil
    91  		}
    92  
    93  		importRts, err := f(v.ImportRt)
    94  		if err != nil {
    95  			return err
    96  		}
    97  		exportRts, err := f(v.ExportRt)
    98  		if err != nil {
    99  			return err
   100  		}
   101  		lines = append(lines, []string{name, rdStr, importRts, exportRts, fmt.Sprintf("%d", v.Id)})
   102  
   103  		for i, v := range []int{len(name), len(rdStr), len(importRts), len(exportRts)} {
   104  			if v > maxLens[i] {
   105  				maxLens[i] = v + 4
   106  			}
   107  		}
   108  
   109  	}
   110  	format := fmt.Sprintf("  %%-%ds %%-%ds %%-%ds %%-%ds %%-%ds\n", maxLens[0], maxLens[1], maxLens[2], maxLens[3], maxLens[4])
   111  	fmt.Printf(format, "Name", "RD", "Import RT", "Export RT", "ID")
   112  	for _, l := range lines {
   113  		fmt.Printf(format, l[0], l[1], l[2], l[3], l[4])
   114  	}
   115  	return nil
   116  }
   117  
   118  func showVrf(name string) error {
   119  	return showNeighborRib(cmdVRF, name, nil)
   120  }
   121  
   122  func modVrf(typ string, args []string) error {
   123  	switch typ {
   124  	case cmdAdd:
   125  		a, err := extractReserved(args, map[string]int{
   126  			"rd": paramSingle,
   127  			"rt": paramList,
   128  			"id": paramSingle})
   129  		if err != nil || len(a[""]) != 1 || len(a["rd"]) != 1 || len(a["rt"]) < 2 {
   130  			return fmt.Errorf("Usage: gobgp vrf add <vrf name> [ id <id> ] rd <rd> rt { import | export | both } <rt>...")
   131  		}
   132  		name := a[""][0]
   133  		var rd bgp.RouteDistinguisherInterface
   134  		rd, err = bgp.ParseRouteDistinguisher(a["rd"][0])
   135  		if err != nil {
   136  			return err
   137  		}
   138  		cur := ""
   139  		importRt := make([]bgp.ExtendedCommunityInterface, 0)
   140  		exportRt := make([]bgp.ExtendedCommunityInterface, 0)
   141  		for _, elem := range a["rt"] {
   142  			if elem == "import" || elem == "export" || elem == "both" {
   143  				cur = elem
   144  				continue
   145  			}
   146  			rt, err := bgp.ParseRouteTarget(elem)
   147  			if err != nil {
   148  				return err
   149  			}
   150  			switch cur {
   151  			case "import":
   152  				importRt = append(importRt, rt)
   153  			case "export":
   154  				exportRt = append(exportRt, rt)
   155  			case "both":
   156  				importRt = append(importRt, rt)
   157  				exportRt = append(exportRt, rt)
   158  			default:
   159  				return fmt.Errorf("Usage: gobgp vrf add <vrf name> rd <rd> rt { import | export | both } <rt>...")
   160  			}
   161  		}
   162  		var id uint64
   163  		if len(a["id"]) > 0 {
   164  			id, err = strconv.ParseUint(a["id"][0], 10, 32)
   165  			if err != nil {
   166  				return err
   167  			}
   168  		}
   169  		_, err = client.AddVrf(ctx, &api.AddVrfRequest{
   170  			Vrf: &api.Vrf{
   171  				Name:     name,
   172  				Rd:       apiutil.MarshalRD(rd),
   173  				ImportRt: apiutil.MarshalRTs(importRt),
   174  				ExportRt: apiutil.MarshalRTs(exportRt),
   175  				Id:       uint32(id),
   176  			},
   177  		})
   178  		return err
   179  	case cmdDel:
   180  		if len(args) != 1 {
   181  			return fmt.Errorf("Usage: gobgp vrf del <vrf name>")
   182  		}
   183  		_, err := client.DeleteVrf(ctx, &api.DeleteVrfRequest{
   184  			Name: args[0],
   185  		})
   186  		return err
   187  	}
   188  	return nil
   189  }
   190  
   191  func newVrfCmd() *cobra.Command {
   192  	ribCmd := &cobra.Command{
   193  		Use: cmdRib,
   194  		Run: func(cmd *cobra.Command, args []string) {
   195  			var err error
   196  			if len(args) == 1 {
   197  				err = showVrf(args[0])
   198  			} else {
   199  				err = fmt.Errorf("usage: gobgp vrf <vrf-name> rib")
   200  			}
   201  			if err != nil {
   202  				exitWithError(err)
   203  			}
   204  		},
   205  	}
   206  
   207  	for _, v := range []string{cmdAdd, cmdDel} {
   208  		cmd := &cobra.Command{
   209  			Use: v,
   210  			Run: func(cmd *cobra.Command, args []string) {
   211  				err := modPath(cmdVRF, args[len(args)-1], cmd.Use, args[:len(args)-1])
   212  				if err != nil {
   213  					exitWithError(err)
   214  				}
   215  			},
   216  		}
   217  		ribCmd.AddCommand(cmd)
   218  	}
   219  
   220  	neighborCmd := &cobra.Command{
   221  		Use: cmdNeighbor,
   222  		Run: func(cmd *cobra.Command, args []string) {
   223  			var err error
   224  			if len(args) == 1 {
   225  				var vs []*api.Vrf
   226  				vs, err = getVrfs()
   227  				if err != nil {
   228  					exitWithError(err)
   229  				}
   230  				found := false
   231  				for _, v := range vs {
   232  					if v.Name == args[0] {
   233  						found = true
   234  						break
   235  					}
   236  				}
   237  				if !found {
   238  					err = fmt.Errorf("vrf %s not found", args[0])
   239  				} else {
   240  					err = showNeighbors(args[0])
   241  				}
   242  			} else {
   243  				err = fmt.Errorf("usage: gobgp vrf <vrf-name> neighbor")
   244  			}
   245  			if err != nil {
   246  				exitWithError(err)
   247  			}
   248  		},
   249  	}
   250  
   251  	vrfCmdImpl := &cobra.Command{}
   252  	vrfCmdImpl.AddCommand(ribCmd, neighborCmd)
   253  
   254  	vrfCmd := &cobra.Command{
   255  		Use: cmdVRF,
   256  		Run: func(cmd *cobra.Command, args []string) {
   257  			var err error
   258  			if len(args) == 0 {
   259  				err = showVrfs()
   260  			} else if len(args) == 1 {
   261  			} else {
   262  				args = append(args[1:], args[0])
   263  				vrfCmdImpl.SetArgs(args)
   264  				err = vrfCmdImpl.Execute()
   265  			}
   266  			if err != nil {
   267  				exitWithError(err)
   268  			}
   269  		},
   270  	}
   271  
   272  	for _, v := range []string{cmdAdd, cmdDel} {
   273  		cmd := &cobra.Command{
   274  			Use: v,
   275  			Run: func(cmd *cobra.Command, args []string) {
   276  				err := modVrf(cmd.Use, args)
   277  				if err != nil {
   278  					exitWithError(err)
   279  				}
   280  			},
   281  		}
   282  		vrfCmd.AddCommand(cmd)
   283  	}
   284  	vrfCmd.PersistentFlags().StringVarP(&subOpts.AddressFamily, "address-family", "a", "", "address family")
   285  
   286  	return vrfCmd
   287  }