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 }