summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorNaoto Hanaue <hanaue.naoto@po.ntts.co.jp>2015-05-27 14:48:02 +0900
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2015-05-28 20:28:28 +0900
commit7ea3a18ef5abffc3c1bb01366b0f7e274a42dcff (patch)
tree726f5b2a0c8dc6be6e03e01e875db68b86db7f35
parent95e538791934a1a6226f4e6bdcc09453a77903a6 (diff)
cli: change structure of the source file
split gobgp/main.go to main.go,global.go,neighbor.go,policy.go and common.go.
-rw-r--r--gobgp/common.go366
-rw-r--r--gobgp/global.go280
-rw-r--r--gobgp/main.go2294
-rw-r--r--gobgp/neighbor.go793
-rw-r--r--gobgp/policy.go957
5 files changed, 2397 insertions, 2293 deletions
diff --git a/gobgp/common.go b/gobgp/common.go
new file mode 100644
index 00000000..5281b5ca
--- /dev/null
+++ b/gobgp/common.go
@@ -0,0 +1,366 @@
+// Copyright (C) 2015 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 main
+
+import (
+ "bytes"
+ "fmt"
+ "github.com/osrg/gobgp/api"
+ "google.golang.org/grpc"
+ "net"
+ "os"
+ "sort"
+ "time"
+)
+
+const (
+ CMD_GLOBAL = "global"
+ CMD_NEIGHBOR = "neighbor"
+ CMD_POLICY = "policy"
+ CMD_RIB = "rib"
+ CMD_ADD = "add"
+ CMD_DEL = "del"
+ CMD_ALL = "all"
+ CMD_LOCAL = "local"
+ CMD_ADJ_IN = "adj-in"
+ CMD_ADJ_OUT = "adj-out"
+ CMD_RESET = "reset"
+ CMD_SOFT_RESET = "softreset"
+ CMD_SOFT_RESET_IN = "softresetin"
+ CMD_SOFT_RESET_OUT = "softresetout"
+ CMD_SHUTDOWN = "shutdown"
+ CMD_ENABLE = "enable"
+ CMD_DISABLE = "disable"
+ CMD_PREFIX = "prefix"
+ CMD_ROUTEPOLICY = "routepolicy"
+ CMD_CONDITIONS = "conditions"
+ CMD_ACTIONS = "actions"
+ CMD_IMPORT = "import"
+ CMD_EXPORT = "export"
+)
+
+var subOpts struct {
+ AddressFamily string `short:"a" long:"address-family" description:"specifying an address family"`
+}
+
+var neighborsOpts struct {
+ Transport string `short:"t" long:"transport" description:"specifying a transport protocol"`
+}
+
+var conditionOpts struct {
+ Prefix string `long:"prefix" description:"specifying a prefix set name of policy"`
+ Neighbor string `long:"neighbor" description:"specifying a neighbor set name of policy"`
+ AsPathLength string `long:"aspath-len" description:"specifying an as path length of policy (<operator>,<numeric>)"`
+ Option string `long:"option" description:"specifying an option of policy (any | all | invert)"`
+}
+
+var actionOpts struct {
+ RouteAction string `long:"route-action" description:"specifying a route action of policy (accept | reject)"`
+}
+
+func formatTimedelta(d int64) string {
+ u := uint64(d)
+ neg := d < 0
+ if neg {
+ u = -u
+ }
+ secs := u % 60
+ u /= 60
+ mins := u % 60
+ u /= 60
+ hours := u % 24
+ days := u / 24
+
+ if days == 0 {
+ return fmt.Sprintf("%02d:%02d:%02d", hours, mins, secs)
+ } else {
+ return fmt.Sprintf("%dd ", days) + fmt.Sprintf("%02d:%02d:%02d", hours, mins, secs)
+ }
+}
+
+func cidr2prefix(cidr string) string {
+ _, n, err := net.ParseCIDR(cidr)
+ if err != nil {
+ return cidr
+ }
+ var buffer bytes.Buffer
+ for i := 0; i < len(n.IP); i++ {
+ buffer.WriteString(fmt.Sprintf("%08b", n.IP[i]))
+ }
+ ones, _ := n.Mask.Size()
+ return buffer.String()[:ones]
+}
+
+type paths []*api.Path
+
+func (p paths) Len() int {
+ return len(p)
+}
+
+func (p paths) Swap(i, j int) {
+ p[i], p[j] = p[j], p[i]
+}
+
+func (p paths) Less(i, j int) bool {
+ if p[i].Nlri.Prefix == p[j].Nlri.Prefix {
+ if p[i].Best {
+ return true
+ }
+ }
+ strings := sort.StringSlice{cidr2prefix(p[i].Nlri.Prefix),
+ cidr2prefix(p[j].Nlri.Prefix)}
+ return strings.Less(0, 1)
+}
+
+type peers []*api.Peer
+
+func (p peers) Len() int {
+ return len(p)
+}
+
+func (p peers) Swap(i, j int) {
+ p[i], p[j] = p[j], p[i]
+}
+
+func (p peers) Less(i, j int) bool {
+ p1 := net.ParseIP(p[i].Conf.RemoteIp)
+ p2 := net.ParseIP(p[j].Conf.RemoteIp)
+ p1Isv4 := p1.To4() != nil
+ p2Isv4 := p2.To4() != nil
+ if p1Isv4 != p2Isv4 {
+ if p1Isv4 {
+ return true
+ }
+ return false
+ }
+ addrlen := 128
+ if p1Isv4 {
+ addrlen = 32
+ }
+ strings := sort.StringSlice{cidr2prefix(fmt.Sprintf("%s/%d", p1.String(), addrlen)),
+ cidr2prefix(fmt.Sprintf("%s/%d", p2.String(), addrlen))}
+ return strings.Less(0, 1)
+}
+
+type capabilities []*api.Capability
+
+func (c capabilities) Len() int {
+ return len(c)
+}
+
+func (c capabilities) Swap(i, j int) {
+ c[i], c[j] = c[j], c[i]
+}
+
+func (c capabilities) Less(i, j int) bool {
+ return c[i].Code < c[j].Code
+}
+
+type prefixes []*api.PrefixSet
+
+func (p prefixes) Len() int {
+ return len(p)
+}
+
+func (p prefixes) Swap(i, j int) {
+ p[i], p[j] = p[j], p[i]
+}
+
+func (p prefixes) Less(i, j int) bool {
+ return p[i].PrefixSetName < p[j].PrefixSetName
+}
+
+type neighbors []*api.NeighborSet
+
+func (n neighbors) Len() int {
+ return len(n)
+}
+
+func (n neighbors) Swap(i, j int) {
+ n[i], n[j] = n[j], n[i]
+}
+
+func (n neighbors) Less(i, j int) bool {
+ return n[i].NeighborSetName < n[j].NeighborSetName
+}
+
+type policyDefinitions []*api.PolicyDefinition
+
+func (p policyDefinitions) Len() int {
+ return len(p)
+}
+
+func (p policyDefinitions) Swap(i, j int) {
+ p[i], p[j] = p[j], p[i]
+}
+
+func (p policyDefinitions) Less(i, j int) bool {
+ return p[i].PolicyDefinitionName < p[j].PolicyDefinitionName
+}
+
+var client api.GrpcClient
+
+func connGrpc() *grpc.ClientConn {
+ timeout := grpc.WithTimeout(time.Second)
+
+ // determine IP address version
+ host := net.ParseIP(globalOpts.Host)
+ target := fmt.Sprintf("%s:%d", globalOpts.Host, globalOpts.Port)
+ if host.To4() == nil {
+ target = fmt.Sprintf("[%s]:%d", globalOpts.Host, globalOpts.Port)
+ }
+
+ conn, err := grpc.Dial(target, timeout)
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ }
+ return conn
+}
+
+func requestGrpc(cmd string, eArgs []string, request interface{}) error {
+ conn := connGrpc()
+ defer conn.Close()
+ client = api.NewGrpcClient(conn)
+
+ switch cmd {
+ case CMD_GLOBAL + "_" + CMD_RIB:
+ return showGlobalRib()
+ case CMD_GLOBAL + "_" + CMD_RIB + "_" + CMD_ADD:
+ return modPath(CMD_ADD, eArgs)
+ case CMD_GLOBAL + "_" + CMD_RIB + "_" + CMD_DEL:
+ return modPath(CMD_DEL, eArgs)
+ case CMD_NEIGHBOR:
+ if len(eArgs) == 0 {
+ return showNeighbors()
+ } else {
+ return showNeighbor(eArgs)
+ }
+ case CMD_NEIGHBOR + "_" + CMD_LOCAL:
+ return showNeighborRib(api.Resource_LOCAL, request.(*NeighborRibCommand))
+ case CMD_NEIGHBOR + "_" + CMD_ADJ_IN:
+ return showNeighborRib(api.Resource_ADJ_IN, request.(*NeighborRibCommand))
+ case CMD_NEIGHBOR + "_" + CMD_ADJ_OUT:
+ return showNeighborRib(api.Resource_ADJ_OUT, request.(*NeighborRibCommand))
+ case CMD_NEIGHBOR + "_" + CMD_RESET:
+ return resetNeighbor(request.(*NeighborResetCommand))
+ case CMD_NEIGHBOR + "_" + CMD_SOFT_RESET:
+ return resetNeighbor(request.(*NeighborResetCommand))
+ case CMD_NEIGHBOR + "_" + CMD_SOFT_RESET_IN:
+ return resetNeighbor(request.(*NeighborResetCommand))
+ case CMD_NEIGHBOR + "_" + CMD_SOFT_RESET_OUT:
+ return resetNeighbor(request.(*NeighborResetCommand))
+ case CMD_NEIGHBOR + "_" + CMD_SHUTDOWN:
+ return stateChangeNeighbor(request.(*NeighborChangeStateCommand))
+ case CMD_NEIGHBOR + "_" + CMD_ENABLE:
+ return stateChangeNeighbor(request.(*NeighborChangeStateCommand))
+ case CMD_NEIGHBOR + "_" + CMD_DISABLE:
+ return stateChangeNeighbor(request.(*NeighborChangeStateCommand))
+ case CMD_NEIGHBOR + "_" + CMD_POLICY:
+ return showNeighborPolicy(request.(*NeighborPolicyCommand))
+ case CMD_NEIGHBOR + "_" + CMD_POLICY + "_" + CMD_ADD:
+ return modNeighborPolicy(eArgs, request.(*NeighborPolicyChangeCommand))
+ case CMD_NEIGHBOR + "_" + CMD_POLICY + "_" + CMD_DEL:
+ return modNeighborPolicy(eArgs, request.(*NeighborPolicyChangeCommand))
+ case CMD_POLICY + "_" + CMD_PREFIX:
+ if len(eArgs) == 0 {
+ return showPolicyPrefixes()
+ } else {
+ return showPolicyPrefix(eArgs)
+ }
+ case CMD_POLICY + "_" + CMD_PREFIX + "_" + CMD_ADD:
+ return modPolicyPrefix(CMD_ADD, eArgs)
+ case CMD_POLICY + "_" + CMD_PREFIX + "_" + CMD_DEL:
+ return modPolicyPrefix(CMD_DEL, eArgs)
+ case CMD_POLICY + "_" + CMD_NEIGHBOR:
+ if len(eArgs) == 0 {
+ return showPolicyNeighbors()
+ } else {
+ return showPolicyNeighbor(eArgs)
+ }
+ case CMD_POLICY + "_" + CMD_NEIGHBOR + "_" + CMD_ADD:
+ return modPolicyNeighbor(CMD_ADD, eArgs)
+ case CMD_POLICY + "_" + CMD_NEIGHBOR + "_" + CMD_DEL:
+ return modPolicyNeighbor(CMD_DEL, eArgs)
+ case CMD_POLICY + "_" + CMD_ROUTEPOLICY:
+ if len(eArgs) == 0 {
+ return showPolicyRoutePolicies()
+ } else {
+ return showPolicyRoutePolicy(eArgs)
+ }
+ case CMD_POLICY + "_" + CMD_ROUTEPOLICY + "_" + CMD_ADD + "_" + CMD_CONDITIONS:
+ return modPolicyRoutePolicy(CMD_ADD, CMD_CONDITIONS, eArgs, request)
+ case CMD_POLICY + "_" + CMD_ROUTEPOLICY + "_" + CMD_ADD + "_" + CMD_ACTIONS:
+ return modPolicyRoutePolicy(CMD_ADD, CMD_ACTIONS, eArgs, request)
+ case CMD_POLICY + "_" + CMD_ROUTEPOLICY + "_" + CMD_DEL:
+ return modPolicyRoutePolicy(CMD_DEL, "", eArgs, nil)
+ }
+ return nil
+}
+
+func extractArgs(head string) []string {
+ eArgs := make([]string, 0)
+ existHead := false
+ existRear := false
+ if head == "" {
+ existHead = true
+ }
+ for _, arg := range os.Args {
+ if existHead {
+ eArgs = append(eArgs, arg)
+ for _, cmd := range cmds {
+ if arg == cmd {
+ existRear = true
+ break
+ }
+ }
+ if existRear {
+ break
+ }
+ } else {
+ if arg == head {
+ existHead = true
+ }
+ }
+ }
+ return eArgs
+}
+
+func checkAddressFamily(ip net.IP) (*api.AddressFamily, error) {
+ var rf *api.AddressFamily
+ var e error
+ switch subOpts.AddressFamily {
+ case "ipv4", "v4", "4":
+ rf = api.AF_IPV4_UC
+ case "ipv6", "v6", "6":
+ rf = api.AF_IPV6_UC
+ case "evpn":
+ rf = api.AF_EVPN
+ case "encap":
+ rf = api.AF_ENCAP
+ case "rtc":
+ rf = api.AF_RTC
+ case "":
+ if len(ip) == 0 || ip.To4() != nil {
+ rf = api.AF_IPV4_UC
+ } else {
+ rf = api.AF_IPV6_UC
+ }
+ default:
+ e = fmt.Errorf("unsupported address family: %s", subOpts.AddressFamily)
+ }
+ return rf, e
+}
diff --git a/gobgp/global.go b/gobgp/global.go
new file mode 100644
index 00000000..d39785bf
--- /dev/null
+++ b/gobgp/global.go
@@ -0,0 +1,280 @@
+// Copyright (C) 2015 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 main
+
+import (
+ "encoding/json"
+ "fmt"
+ "github.com/jessevdk/go-flags"
+ "github.com/osrg/gobgp/api"
+ "golang.org/x/net/context"
+ "io"
+ "net"
+ "os"
+ "sort"
+ "strconv"
+)
+
+type GlobalCommand struct{}
+
+func (x *GlobalCommand) Execute(args []string) error {
+ eArgs := extractArgs(CMD_GLOBAL)
+ parser := flags.NewParser(nil, flags.Default)
+ parser.Usage = "global"
+ parser.AddCommand(CMD_RIB, "subcommand for rib of global", "", &GlobalRibCommand{})
+ if _, err := parser.ParseArgs(eArgs); err != nil {
+ os.Exit(1)
+ }
+ return nil
+}
+
+type GlobalRibCommand struct{}
+
+func showGlobalRib() error {
+ rt, err := checkAddressFamily(net.IP{})
+ if err != nil {
+ return err
+ }
+ arg := &api.Arguments{
+ Resource: api.Resource_GLOBAL,
+ Af: rt,
+ }
+
+ stream, e := client.GetRib(context.Background(), arg)
+ if e != nil {
+ return e
+ }
+ ds := []*api.Destination{}
+ for {
+ d, e := stream.Recv()
+ if e == io.EOF {
+ break
+ } else if e != nil {
+ return e
+ }
+ ds = append(ds, d)
+ }
+
+ if globalOpts.Json {
+ j, _ := json.Marshal(ds)
+ fmt.Println(string(j))
+ return nil
+ }
+
+ ps := paths{}
+ for _, d := range ds {
+ for idx, p := range d.Paths {
+ if idx == int(d.BestPathIdx) {
+ p.Best = true
+ }
+ ps = append(ps, p)
+ }
+ }
+
+ sort.Sort(ps)
+
+ showRoute(ps, true, true)
+ return nil
+}
+func (x *GlobalRibCommand) Execute(args []string) error {
+
+ eArgs := extractArgs(CMD_RIB)
+ parser := flags.NewParser(&subOpts, flags.Default)
+ if len(eArgs) == 0 || (len(eArgs) < 3 && eArgs[0] == "-a") {
+ if _, err := parser.ParseArgs(eArgs); err != nil {
+ os.Exit(1)
+ }
+ if err := requestGrpc(CMD_GLOBAL+"_"+CMD_RIB, eArgs, nil); err != nil {
+ return err
+ }
+ } else {
+ parser.Usage = "global rib [OPTIONS]\n gobgp global rib"
+ parser.AddCommand(CMD_ADD, "subcommand to add route to global rib", "", &GlobalRibAddCommand{})
+ parser.AddCommand(CMD_DEL, "subcommand to delete route from global rib", "", &GlobalRibDelCommand{})
+ if _, err := parser.ParseArgs(eArgs); err != nil {
+ os.Exit(1)
+ }
+ }
+ return nil
+}
+
+type GlobalRibAddCommand struct{}
+
+func modPath(modtype string, eArgs []string) error {
+ rf, err := checkAddressFamily(net.IP{})
+ if err != nil {
+ return err
+ }
+
+ path := &api.Path{}
+ var prefix, macAddr, ipAddr string
+ switch rf {
+ case api.AF_IPV4_UC, api.AF_IPV6_UC:
+ if len(eArgs) == 1 || len(eArgs) == 3 {
+ prefix = eArgs[0]
+ } else {
+ return fmt.Errorf("usage: global rib %s <prefix> -a { ipv4 | ipv6 }", modtype)
+ }
+ path.Nlri = &api.Nlri{
+ Af: rf,
+ Prefix: prefix,
+ }
+ case api.AF_EVPN:
+ if len(eArgs) == 4 {
+ macAddr = eArgs[0]
+ ipAddr = eArgs[1]
+ } else {
+ return fmt.Errorf("usage: global rib %s <mac address> <ip address> -a evpn", modtype)
+ }
+ path.Nlri = &api.Nlri{
+ Af: rf,
+ EvpnNlri: &api.EVPNNlri{
+ Type: api.EVPN_TYPE_ROUTE_TYPE_MAC_IP_ADVERTISEMENT,
+ MacIpAdv: &api.EvpnMacIpAdvertisement{
+ MacAddr: macAddr,
+ IpAddr: ipAddr,
+ },
+ },
+ }
+ case api.AF_ENCAP:
+ if len(eArgs) < 3 {
+ return fmt.Errorf("usage: global rib %s <end point ip address> [<vni>] -a encap", modtype)
+ }
+ prefix = eArgs[0]
+
+ path.Nlri = &api.Nlri{
+ Af: rf,
+ Prefix: prefix,
+ }
+
+ if len(eArgs) > 3 {
+ vni, err := strconv.Atoi(eArgs[1])
+ if err != nil {
+ return fmt.Errorf("invalid vni: %s", eArgs[1])
+ }
+ subTlv := &api.TunnelEncapSubTLV{
+ Type: api.ENCAP_SUBTLV_TYPE_COLOR,
+ Color: uint32(vni),
+ }
+ tlv := &api.TunnelEncapTLV{
+ Type: api.TUNNEL_TYPE_VXLAN,
+ SubTlv: []*api.TunnelEncapSubTLV{subTlv},
+ }
+ attr := &api.PathAttr{
+ Type: api.BGP_ATTR_TYPE_TUNNEL_ENCAP,
+ TunnelEncap: []*api.TunnelEncapTLV{tlv},
+ }
+
+ path.Attrs = append(path.Attrs, attr)
+ }
+ case api.AF_RTC:
+ if !(len(eArgs) == 3 && eArgs[0] == "default") && len(eArgs) < 4 {
+ return fmt.Errorf("usage: global rib add <asn> <local admin> -a rtc")
+ }
+ var asn, admin int
+
+ if eArgs[0] != "default" {
+ asn, err = strconv.Atoi(eArgs[0])
+ if err != nil {
+ return fmt.Errorf("invalid asn: %s", eArgs[0])
+ }
+ admin, err = strconv.Atoi(eArgs[1])
+ if err != nil {
+ return fmt.Errorf("invalid local admin: %s", eArgs[1])
+ }
+ }
+ path.Nlri = &api.Nlri{
+ Af: rf,
+ RtNlri: &api.RTNlri{
+ Target: &api.ExtendedCommunity{
+ Type: api.EXTENDED_COMMUNITIE_TYPE_TWO_OCTET_AS_SPECIFIC,
+ Subtype: api.EXTENDED_COMMUNITIE_SUBTYPE_ROUTE_TARGET,
+ Asn: uint32(asn),
+ LocalAdmin: uint32(admin),
+ },
+ },
+ }
+ }
+ switch modtype {
+ case CMD_ADD:
+ path.IsWithdraw = false
+ case CMD_DEL:
+ path.IsWithdraw = true
+ }
+
+ arg := &api.ModPathArguments{
+ Resource: api.Resource_GLOBAL,
+ Path: path,
+ }
+ stream, err := client.ModPath(context.Background())
+ if err != nil {
+ return err
+ }
+ err = stream.Send(arg)
+ if err != nil {
+ return err
+ }
+ stream.CloseSend()
+
+ res, e := stream.Recv()
+ if e != nil {
+ return e
+ }
+ if res.Code != api.Error_SUCCESS {
+ return fmt.Errorf("error: code: %d, msg: %s", res.Code, res.Msg)
+ }
+ return nil
+}
+
+func (x *GlobalRibAddCommand) Execute(args []string) error {
+ eArgs := extractArgs(CMD_ADD)
+ parser := flags.NewParser(&subOpts, flags.Default)
+ parser.Usage = "global rib add <prefix> -a { ipv4 | ipv6 }\n" +
+ " -> if -a option is ipv4 or ipv6\n" +
+ " gobgp global rib add <mac address> <ip address> -a evpn\n" +
+ " -> if -a option is evpn"
+ parser.ParseArgs(eArgs)
+ if len(eArgs) == 1 {
+ if eArgs[0] == "-h" || eArgs[0] == "--help" {
+ return nil
+ }
+ }
+ if err := requestGrpc(CMD_GLOBAL+"_"+CMD_RIB+"_"+CMD_ADD, eArgs, nil); err != nil {
+ return err
+ }
+ return nil
+}
+
+type GlobalRibDelCommand struct{}
+
+func (x *GlobalRibDelCommand) Execute(args []string) error {
+ eArgs := extractArgs(CMD_DEL)
+ parser := flags.NewParser(&subOpts, flags.Default)
+ parser.Usage = "global rib del <prefix> -a { ipv4 | ipv6 }\n" +
+ " -> if -a option is ipv4 or ipv6\n" +
+ " gobgp global rib del <mac address> <ip address> -a evpn\n" +
+ " -> if -a option is evpn"
+ parser.ParseArgs(eArgs)
+ if len(eArgs) == 1 {
+ if eArgs[0] == "-h" || eArgs[0] == "--help" {
+ return nil
+ }
+ }
+ if err := requestGrpc(CMD_GLOBAL+"_"+CMD_RIB+"_"+CMD_DEL, eArgs, nil); err != nil {
+ return err
+ }
+ return nil
+}
diff --git a/gobgp/main.go b/gobgp/main.go
index 96e47a72..d44be981 100644
--- a/gobgp/main.go
+++ b/gobgp/main.go
@@ -16,2285 +16,10 @@
package main
import (
- "bytes"
- "encoding/json"
- "fmt"
"github.com/jessevdk/go-flags"
- "github.com/osrg/gobgp/api"
- "github.com/osrg/gobgp/policy"
- "golang.org/x/net/context"
- "google.golang.org/grpc"
- "io"
- "net"
"os"
- "sort"
- "strconv"
- "strings"
- "time"
)
-const (
- CMD_GLOBAL = "global"
- CMD_NEIGHBOR = "neighbor"
- CMD_POLICY = "policy"
- CMD_RIB = "rib"
- CMD_ADD = "add"
- CMD_DEL = "del"
- CMD_ALL = "all"
- CMD_LOCAL = "local"
- CMD_ADJ_IN = "adj-in"
- CMD_ADJ_OUT = "adj-out"
- CMD_RESET = "reset"
- CMD_SOFT_RESET = "softreset"
- CMD_SOFT_RESET_IN = "softresetin"
- CMD_SOFT_RESET_OUT = "softresetout"
- CMD_SHUTDOWN = "shutdown"
- CMD_ENABLE = "enable"
- CMD_DISABLE = "disable"
- CMD_PREFIX = "prefix"
- CMD_ROUTEPOLICY = "routepolicy"
- CMD_CONDITIONS = "conditions"
- CMD_ACTIONS = "actions"
- CMD_IMPORT = "import"
- CMD_EXPORT = "export"
-)
-
-func formatTimedelta(d int64) string {
- u := uint64(d)
- neg := d < 0
- if neg {
- u = -u
- }
- secs := u % 60
- u /= 60
- mins := u % 60
- u /= 60
- hours := u % 24
- days := u / 24
-
- if days == 0 {
- return fmt.Sprintf("%02d:%02d:%02d", hours, mins, secs)
- } else {
- return fmt.Sprintf("%dd ", days) + fmt.Sprintf("%02d:%02d:%02d", hours, mins, secs)
- }
-}
-
-func cidr2prefix(cidr string) string {
- _, n, err := net.ParseCIDR(cidr)
- if err != nil {
- return cidr
- }
- var buffer bytes.Buffer
- for i := 0; i < len(n.IP); i++ {
- buffer.WriteString(fmt.Sprintf("%08b", n.IP[i]))
- }
- ones, _ := n.Mask.Size()
- return buffer.String()[:ones]
-}
-
-type paths []*api.Path
-
-func (p paths) Len() int {
- return len(p)
-}
-
-func (p paths) Swap(i, j int) {
- p[i], p[j] = p[j], p[i]
-}
-
-func (p paths) Less(i, j int) bool {
- if p[i].Nlri.Prefix == p[j].Nlri.Prefix {
- if p[i].Best {
- return true
- }
- }
- strings := sort.StringSlice{cidr2prefix(p[i].Nlri.Prefix),
- cidr2prefix(p[j].Nlri.Prefix)}
- return strings.Less(0, 1)
-}
-
-type peers []*api.Peer
-
-func (p peers) Len() int {
- return len(p)
-}
-
-func (p peers) Swap(i, j int) {
- p[i], p[j] = p[j], p[i]
-}
-
-func (p peers) Less(i, j int) bool {
- p1 := net.ParseIP(p[i].Conf.RemoteIp)
- p2 := net.ParseIP(p[j].Conf.RemoteIp)
- p1Isv4 := p1.To4() != nil
- p2Isv4 := p2.To4() != nil
- if p1Isv4 != p2Isv4 {
- if p1Isv4 {
- return true
- }
- return false
- }
- addrlen := 128
- if p1Isv4 {
- addrlen = 32
- }
- strings := sort.StringSlice{cidr2prefix(fmt.Sprintf("%s/%d", p1.String(), addrlen)),
- cidr2prefix(fmt.Sprintf("%s/%d", p2.String(), addrlen))}
- return strings.Less(0, 1)
-}
-
-type prefixes []*api.PrefixSet
-
-func (p prefixes) Len() int {
- return len(p)
-}
-
-func (p prefixes) Swap(i, j int) {
- p[i], p[j] = p[j], p[i]
-}
-
-func (p prefixes) Less(i, j int) bool {
- return p[i].PrefixSetName < p[j].PrefixSetName
-}
-
-type neighbors []*api.NeighborSet
-
-func (n neighbors) Len() int {
- return len(n)
-}
-
-func (n neighbors) Swap(i, j int) {
- n[i], n[j] = n[j], n[i]
-}
-
-func (n neighbors) Less(i, j int) bool {
- return n[i].NeighborSetName < n[j].NeighborSetName
-}
-
-type policyDefinitions []*api.PolicyDefinition
-
-func (p policyDefinitions) Len() int {
- return len(p)
-}
-
-func (p policyDefinitions) Swap(i, j int) {
- p[i], p[j] = p[j], p[i]
-}
-
-func (p policyDefinitions) Less(i, j int) bool {
- return p[i].PolicyDefinitionName < p[j].PolicyDefinitionName
-}
-
-func connGrpc() *grpc.ClientConn {
- timeout := grpc.WithTimeout(time.Second)
-
- // determine IP address version
- host := net.ParseIP(globalOpts.Host)
- target := fmt.Sprintf("%s:%d", globalOpts.Host, globalOpts.Port)
- if host.To4() == nil {
- target = fmt.Sprintf("[%s]:%d", globalOpts.Host, globalOpts.Port)
- }
-
- conn, err := grpc.Dial(target, timeout)
- if err != nil {
- fmt.Println(err)
- os.Exit(1)
- }
- return conn
-}
-
-func requestGrpc(cmd string, eArgs []string, request interface{}) error {
- conn := connGrpc()
- defer conn.Close()
- client = api.NewGrpcClient(conn)
-
- switch cmd {
- case CMD_GLOBAL + "_" + CMD_RIB:
- return showGlobalRib()
- case CMD_GLOBAL + "_" + CMD_RIB + "_" + CMD_ADD:
- return modPath(CMD_ADD, eArgs)
- case CMD_GLOBAL + "_" + CMD_RIB + "_" + CMD_DEL:
- return modPath(CMD_DEL, eArgs)
- case CMD_NEIGHBOR:
- if len(eArgs) == 0 {
- return showNeighbors()
- } else {
- return showNeighbor(eArgs)
- }
- case CMD_NEIGHBOR + "_" + CMD_LOCAL:
- return showNeighborRib(api.Resource_LOCAL, request.(*NeighborRibCommand))
- case CMD_NEIGHBOR + "_" + CMD_ADJ_IN:
- return showNeighborRib(api.Resource_ADJ_IN, request.(*NeighborRibCommand))
- case CMD_NEIGHBOR + "_" + CMD_ADJ_OUT:
- return showNeighborRib(api.Resource_ADJ_OUT, request.(*NeighborRibCommand))
- case CMD_NEIGHBOR + "_" + CMD_RESET:
- return resetNeighbor(request.(*NeighborResetCommand))
- case CMD_NEIGHBOR + "_" + CMD_SOFT_RESET:
- return resetNeighbor(request.(*NeighborResetCommand))
- case CMD_NEIGHBOR + "_" + CMD_SOFT_RESET_IN:
- return resetNeighbor(request.(*NeighborResetCommand))
- case CMD_NEIGHBOR + "_" + CMD_SOFT_RESET_OUT:
- return resetNeighbor(request.(*NeighborResetCommand))
- case CMD_NEIGHBOR + "_" + CMD_SHUTDOWN:
- return stateChangeNeighbor(request.(*NeighborChangeStateCommand))
- case CMD_NEIGHBOR + "_" + CMD_ENABLE:
- return stateChangeNeighbor(request.(*NeighborChangeStateCommand))
- case CMD_NEIGHBOR + "_" + CMD_DISABLE:
- return stateChangeNeighbor(request.(*NeighborChangeStateCommand))
- case CMD_NEIGHBOR + "_" + CMD_POLICY:
- return showNeighborPolicy(request.(*NeighborPolicyCommand))
- case CMD_NEIGHBOR + "_" + CMD_POLICY + "_" + CMD_ADD:
- return modNeighborPolicy(eArgs, request.(*NeighborPolicyChangeCommand))
- case CMD_NEIGHBOR + "_" + CMD_POLICY + "_" + CMD_DEL:
- return modNeighborPolicy(eArgs, request.(*NeighborPolicyChangeCommand))
- case CMD_POLICY + "_" + CMD_PREFIX:
- if len(eArgs) == 0 {
- return showPolicyPrefixes()
- } else {
- return showPolicyPrefix(eArgs)
- }
- case CMD_POLICY + "_" + CMD_PREFIX + "_" + CMD_ADD:
- return modPolicyPrefix(CMD_ADD, eArgs)
- case CMD_POLICY + "_" + CMD_PREFIX + "_" + CMD_DEL:
- return modPolicyPrefix(CMD_DEL, eArgs)
- case CMD_POLICY + "_" + CMD_NEIGHBOR:
- if len(eArgs) == 0 {
- return showPolicyNeighbors()
- } else {
- return showPolicyNeighbor(eArgs)
- }
- case CMD_POLICY + "_" + CMD_NEIGHBOR + "_" + CMD_ADD:
- return modPolicyNeighbor(CMD_ADD, eArgs)
- case CMD_POLICY + "_" + CMD_NEIGHBOR + "_" + CMD_DEL:
- return modPolicyNeighbor(CMD_DEL, eArgs)
- case CMD_POLICY + "_" + CMD_ROUTEPOLICY:
- if len(eArgs) == 0 {
- return showPolicyRoutePolicies()
- } else {
- return showPolicyRoutePolicy(eArgs)
- }
- case CMD_POLICY + "_" + CMD_ROUTEPOLICY + "_" + CMD_ADD + "_" + CMD_CONDITIONS:
- return modPolicyRoutePolicy(CMD_ADD, CMD_CONDITIONS, eArgs, request)
- case CMD_POLICY + "_" + CMD_ROUTEPOLICY + "_" + CMD_ADD + "_" + CMD_ACTIONS:
- return modPolicyRoutePolicy(CMD_ADD, CMD_ACTIONS, eArgs, request)
- case CMD_POLICY + "_" + CMD_ROUTEPOLICY + "_" + CMD_DEL:
- return modPolicyRoutePolicy(CMD_DEL, "", eArgs, nil)
- }
- return nil
-}
-
-var cmds []string
-
-func extractArgs(head string) []string {
- eArgs := make([]string, 0)
- existHead := false
- existRear := false
- if head == "" {
- existHead = true
- }
- for _, arg := range os.Args {
- if existHead {
- eArgs = append(eArgs, arg)
- for _, cmd := range cmds {
- if arg == cmd {
- existRear = true
- break
- }
- }
- if existRear {
- break
- }
- } else {
- if arg == head {
- existHead = true
- }
- }
- }
- return eArgs
-}
-
-func checkAddressFamily(ip net.IP) (*api.AddressFamily, error) {
- var rf *api.AddressFamily
- var e error
- switch subOpts.AddressFamily {
- case "ipv4", "v4", "4":
- rf = api.AF_IPV4_UC
- case "ipv6", "v6", "6":
- rf = api.AF_IPV6_UC
- case "evpn":
- rf = api.AF_EVPN
- case "encap":
- rf = api.AF_ENCAP
- case "rtc":
- rf = api.AF_RTC
- case "":
- if len(ip) == 0 || ip.To4() != nil {
- rf = api.AF_IPV4_UC
- } else {
- rf = api.AF_IPV6_UC
- }
- default:
- e = fmt.Errorf("unsupported address family: %s", subOpts.AddressFamily)
- }
- return rf, e
-}
-
-var client api.GrpcClient
-
-type GlobalCommand struct{}
-
-func (x *GlobalCommand) Execute(args []string) error {
- eArgs := extractArgs(CMD_GLOBAL)
- parser := flags.NewParser(nil, flags.Default)
- parser.Usage = "global"
- parser.AddCommand(CMD_RIB, "subcommand for rib of global", "", &GlobalRibCommand{})
- if _, err := parser.ParseArgs(eArgs); err != nil {
- os.Exit(1)
- }
- return nil
-}
-
-type GlobalRibCommand struct{}
-
-func showGlobalRib() error {
- rt, err := checkAddressFamily(net.IP{})
- if err != nil {
- return err
- }
- arg := &api.Arguments{
- Resource: api.Resource_GLOBAL,
- Af: rt,
- }
-
- stream, e := client.GetRib(context.Background(), arg)
- if e != nil {
- return e
- }
- ds := []*api.Destination{}
- for {
- d, e := stream.Recv()
- if e == io.EOF {
- break
- } else if e != nil {
- return e
- }
- ds = append(ds, d)
- }
-
- if globalOpts.Json {
- j, _ := json.Marshal(ds)
- fmt.Println(string(j))
- return nil
- }
-
- ps := paths{}
- for _, d := range ds {
- for idx, p := range d.Paths {
- if idx == int(d.BestPathIdx) {
- p.Best = true
- }
- ps = append(ps, p)
- }
- }
-
- sort.Sort(ps)
-
- showRoute(ps, true, true)
- return nil
-}
-func (x *GlobalRibCommand) Execute(args []string) error {
-
- eArgs := extractArgs(CMD_RIB)
- parser := flags.NewParser(&subOpts, flags.Default)
- if len(eArgs) == 0 || (len(eArgs) < 3 && eArgs[0] == "-a") {
- if _, err := parser.ParseArgs(eArgs); err != nil {
- os.Exit(1)
- }
- if err := requestGrpc(CMD_GLOBAL+"_"+CMD_RIB, eArgs, nil); err != nil {
- return err
- }
- } else {
- parser.Usage = "global rib [OPTIONS]\n gobgp global rib"
- parser.AddCommand(CMD_ADD, "subcommand to add route to global rib", "", &GlobalRibAddCommand{})
- parser.AddCommand(CMD_DEL, "subcommand to delete route from global rib", "", &GlobalRibDelCommand{})
- if _, err := parser.ParseArgs(eArgs); err != nil {
- os.Exit(1)
- }
- }
- return nil
-}
-
-type GlobalRibAddCommand struct{}
-
-func modPath(modtype string, eArgs []string) error {
- rf, err := checkAddressFamily(net.IP{})
- if err != nil {
- return err
- }
-
- path := &api.Path{}
- var prefix, macAddr, ipAddr string
- switch rf {
- case api.AF_IPV4_UC, api.AF_IPV6_UC:
- if len(eArgs) == 1 || len(eArgs) == 3 {
- prefix = eArgs[0]
- } else {
- return fmt.Errorf("usage: global rib %s <prefix> -a { ipv4 | ipv6 }", modtype)
- }
- path.Nlri = &api.Nlri{
- Af: rf,
- Prefix: prefix,
- }
- case api.AF_EVPN:
- if len(eArgs) == 4 {
- macAddr = eArgs[0]
- ipAddr = eArgs[1]
- } else {
- return fmt.Errorf("usage: global rib %s <mac address> <ip address> -a evpn", modtype)
- }
- path.Nlri = &api.Nlri{
- Af: rf,
- EvpnNlri: &api.EVPNNlri{
- Type: api.EVPN_TYPE_ROUTE_TYPE_MAC_IP_ADVERTISEMENT,
- MacIpAdv: &api.EvpnMacIpAdvertisement{
- MacAddr: macAddr,
- IpAddr: ipAddr,
- },
- },
- }
- case api.AF_ENCAP:
- if len(eArgs) < 3 {
- return fmt.Errorf("usage: global rib %s <end point ip address> [<vni>] -a encap", modtype)
- }
- prefix = eArgs[0]
-
- path.Nlri = &api.Nlri{
- Af: rf,
- Prefix: prefix,
- }
-
- if len(eArgs) > 3 {
- vni, err := strconv.Atoi(eArgs[1])
- if err != nil {
- return fmt.Errorf("invalid vni: %s", eArgs[1])
- }
- subTlv := &api.TunnelEncapSubTLV{
- Type: api.ENCAP_SUBTLV_TYPE_COLOR,
- Color: uint32(vni),
- }
- tlv := &api.TunnelEncapTLV{
- Type: api.TUNNEL_TYPE_VXLAN,
- SubTlv: []*api.TunnelEncapSubTLV{subTlv},
- }
- attr := &api.PathAttr{
- Type: api.BGP_ATTR_TYPE_TUNNEL_ENCAP,
- TunnelEncap: []*api.TunnelEncapTLV{tlv},
- }
-
- path.Attrs = append(path.Attrs, attr)
- }
- case api.AF_RTC:
- if !(len(eArgs) == 3 && eArgs[0] == "default") && len(eArgs) < 4 {
- return fmt.Errorf("usage: global rib add <asn> <local admin> -a rtc")
- }
- var asn, admin int
-
- if eArgs[0] != "default" {
- asn, err = strconv.Atoi(eArgs[0])
- if err != nil {
- return fmt.Errorf("invalid asn: %s", eArgs[0])
- }
- admin, err = strconv.Atoi(eArgs[1])
- if err != nil {
- return fmt.Errorf("invalid local admin: %s", eArgs[1])
- }
- }
- path.Nlri = &api.Nlri{
- Af: rf,
- RtNlri: &api.RTNlri{
- Target: &api.ExtendedCommunity{
- Type: api.EXTENDED_COMMUNITIE_TYPE_TWO_OCTET_AS_SPECIFIC,
- Subtype: api.EXTENDED_COMMUNITIE_SUBTYPE_ROUTE_TARGET,
- Asn: uint32(asn),
- LocalAdmin: uint32(admin),
- },
- },
- }
- }
- switch modtype {
- case CMD_ADD:
- path.IsWithdraw = false
- case CMD_DEL:
- path.IsWithdraw = true
- }
-
- arg := &api.ModPathArguments{
- Resource: api.Resource_GLOBAL,
- Path: path,
- }
- stream, err := client.ModPath(context.Background())
- if err != nil {
- return err
- }
- err = stream.Send(arg)
- if err != nil {
- return err
- }
- stream.CloseSend()
-
- res, e := stream.Recv()
- if e != nil {
- return e
- }
- if res.Code != api.Error_SUCCESS {
- return fmt.Errorf("error: code: %d, msg: %s", res.Code, res.Msg)
- }
- return nil
-}
-
-func (x *GlobalRibAddCommand) Execute(args []string) error {
- eArgs := extractArgs(CMD_ADD)
- parser := flags.NewParser(&subOpts, flags.Default)
- parser.Usage = "global rib add <prefix> -a { ipv4 | ipv6 }\n" +
- " -> if -a option is ipv4 or ipv6\n" +
- " gobgp global rib add <mac address> <ip address> -a evpn\n" +
- " -> if -a option is evpn"
- parser.ParseArgs(eArgs)
- if len(eArgs) == 1 {
- if eArgs[0] == "-h" || eArgs[0] == "--help" {
- return nil
- }
- }
- if err := requestGrpc(CMD_GLOBAL+"_"+CMD_RIB+"_"+CMD_ADD, eArgs, nil); err != nil {
- return err
- }
- return nil
-}
-
-type GlobalRibDelCommand struct{}
-
-func (x *GlobalRibDelCommand) Execute(args []string) error {
- eArgs := extractArgs(CMD_DEL)
- parser := flags.NewParser(&subOpts, flags.Default)
- parser.Usage = "global rib del <prefix> -a { ipv4 | ipv6 }\n" +
- " -> if -a option is ipv4 or ipv6\n" +
- " gobgp global rib del <mac address> <ip address> -a evpn\n" +
- " -> if -a option is evpn"
- parser.ParseArgs(eArgs)
- if len(eArgs) == 1 {
- if eArgs[0] == "-h" || eArgs[0] == "--help" {
- return nil
- }
- }
- if err := requestGrpc(CMD_GLOBAL+"_"+CMD_RIB+"_"+CMD_DEL, eArgs, nil); err != nil {
- return err
- }
- return nil
-}
-
-type NeighborCommand struct {
-}
-
-func showNeighbors() error {
- arg := &api.Arguments{}
- stream, e := client.GetNeighbors(context.Background(), arg)
- if e != nil {
- fmt.Println(e)
- return e
- }
- m := peers{}
- for {
- p, e := stream.Recv()
- if e == io.EOF {
- break
- } else if e != nil {
- return e
- }
- if neighborsOpts.Transport != "" {
- addr := net.ParseIP(p.Conf.RemoteIp)
- if addr.To4() != nil {
- if neighborsOpts.Transport != "ipv4" {
- continue
- }
- } else {
- if neighborsOpts.Transport != "ipv6" {
- continue
- }
- }
- }
- m = append(m, p)
- }
-
- if globalOpts.Json {
- j, _ := json.Marshal(m)
- fmt.Println(string(j))
- return nil
- }
-
- if globalOpts.Quiet {
- for _, p := range m {
- fmt.Println(p.Conf.RemoteIp)
- }
- return nil
- }
- maxaddrlen := 0
- maxaslen := 0
- maxtimelen := len("Up/Down")
- timedelta := []string{}
-
- sort.Sort(m)
-
- for _, p := range m {
- if len(p.Conf.RemoteIp) > maxaddrlen {
- maxaddrlen = len(p.Conf.RemoteIp)
- }
-
- if len(fmt.Sprint(p.Conf.RemoteAs)) > maxaslen {
- maxaslen = len(fmt.Sprint(p.Conf.RemoteAs))
- }
- var t string
- if p.Info.Uptime == 0 {
- t = "never"
- } else if p.Info.BgpState == "BGP_FSM_ESTABLISHED" {
- t = formatTimedelta(p.Info.Uptime)
- } else {
- t = formatTimedelta(p.Info.Downtime)
- }
- if len(t) > maxtimelen {
- maxtimelen = len(t)
- }
- timedelta = append(timedelta, t)
- }
- var format string
- format = "%-" + fmt.Sprint(maxaddrlen) + "s" + " %" + fmt.Sprint(maxaslen) + "s" + " %" + fmt.Sprint(maxtimelen) + "s"
- format += " %-11s |%11s %8s %8s\n"
- fmt.Printf(format, "Peer", "AS", "Up/Down", "State", "#Advertised", "Received", "Accepted")
- format_fsm := func(admin, fsm string) string {
- if admin == "ADMIN_STATE_DOWN" {
- return "Idle(Admin)"
- }
-
- if fsm == "BGP_FSM_IDLE" {
- return "Idle"
- } else if fsm == "BGP_FSM_CONNECT" {
- return "Connect"
- } else if fsm == "BGP_FSM_ACTIVE" {
- return "Active"
- } else if fsm == "BGP_FSM_OPENSENT" {
- return "Sent"
- } else if fsm == "BGP_FSM_OPENCONFIRM" {
- return "Confirm"
- } else {
- return "Establ"
- }
- }
-
- for i, p := range m {
- fmt.Printf(format, p.Conf.RemoteIp, fmt.Sprint(p.Conf.RemoteAs), timedelta[i], format_fsm(p.Info.AdminState, p.Info.BgpState), fmt.Sprint(p.Info.Advertized), fmt.Sprint(p.Info.Received), fmt.Sprint(p.Info.Accepted))
- }
-
- return nil
-}
-
-type capabilities []*api.Capability
-
-func (c capabilities) Len() int {
- return len(c)
-}
-
-func (c capabilities) Swap(i, j int) {
- c[i], c[j] = c[j], c[i]
-}
-
-func (c capabilities) Less(i, j int) bool {
- return c[i].Code < c[j].Code
-}
-
-func showNeighbor(args []string) error {
- id := &api.Arguments{
- RouterId: args[0],
- }
- p, e := client.GetNeighbor(context.Background(), id)
- if e != nil {
- fmt.Println(e)
- return e
- }
-
- if globalOpts.Json {
- j, _ := json.Marshal(p)
- fmt.Println(string(j))
- return nil
- }
-
- fmt.Printf("BGP neighbor is %s, remote AS %d\n", p.Conf.RemoteIp, p.Conf.RemoteAs)
- fmt.Printf(" BGP version 4, remote router ID %s\n", p.Conf.Id)
- fmt.Printf(" BGP state = %s, up for %s\n", p.Info.BgpState, formatTimedelta(p.Info.Uptime))
- fmt.Printf(" BGP OutQ = %d, Flops = %d\n", p.Info.OutQ, p.Info.Flops)
- fmt.Printf(" Hold time is %d, keepalive interval is %d seconds\n", p.Info.NegotiatedHoldtime, p.Info.KeepaliveInterval)
- fmt.Printf(" Configured hold time is %d, keepalive interval is %d seconds\n", p.Conf.Holdtime, p.Conf.KeepaliveInterval)
-
- fmt.Printf(" Neighbor capabilities:\n")
- caps := capabilities{}
- lookup := func(val *api.Capability, l capabilities) *api.Capability {
- for _, v := range l {
- if v.Code == val.Code {
- if v.Code == api.BGP_CAPABILITY_MULTIPROTOCOL {
- if v.MultiProtocol.Equal(val.MultiProtocol) {
- return v
- }
- continue
- }
- return v
- }
- }
- return nil
- }
- caps = append(caps, p.Conf.LocalCap...)
- for _, v := range p.Conf.RemoteCap {
- if lookup(v, caps) == nil {
- caps = append(caps, v)
- }
- }
-
- sort.Sort(caps)
-
- for _, c := range caps {
- support := ""
- if m := lookup(c, p.Conf.LocalCap); m != nil {
- support += "advertised"
- }
- if lookup(c, p.Conf.RemoteCap) != nil {
- if len(support) != 0 {
- support += " and "
- }
- support += "received"
- }
-
- if c.Code != api.BGP_CAPABILITY_MULTIPROTOCOL {
- fmt.Printf(" %s: %s\n", c.Code, support)
- } else {
- fmt.Printf(" %s(%s,%s): %s\n", c.Code, c.MultiProtocol.Afi, c.MultiProtocol.Safi, support)
- }
- }
- fmt.Print(" Message statistics:\n")
- fmt.Print(" Sent Rcvd\n")
- fmt.Printf(" Opens: %10d %10d\n", p.Info.OpenMessageOut, p.Info.OpenMessageIn)
- fmt.Printf(" Notifications: %10d %10d\n", p.Info.NotificationOut, p.Info.NotificationIn)
- fmt.Printf(" Updates: %10d %10d\n", p.Info.UpdateMessageOut, p.Info.UpdateMessageIn)
- fmt.Printf(" Keepalives: %10d %10d\n", p.Info.KeepAliveMessageOut, p.Info.KeepAliveMessageIn)
- fmt.Printf(" Route Refesh: %10d %10d\n", p.Info.RefreshMessageOut, p.Info.RefreshMessageIn)
- fmt.Printf(" Discarded: %10d %10d\n", p.Info.DiscardedOut, p.Info.DiscardedIn)
- fmt.Printf(" Total: %10d %10d\n", p.Info.TotalMessageOut, p.Info.TotalMessageIn)
-
- return nil
-}
-
-func (x *NeighborCommand) Execute(args []string) error {
- eArgs := extractArgs(CMD_NEIGHBOR)
-
- if len(eArgs) == 0 || (strings.HasPrefix(eArgs[0], "-") && !(eArgs[0] == "-h" || eArgs[0] == "--help")) {
- parser := flags.NewParser(&neighborsOpts, flags.Default)
- if _, err := parser.ParseArgs(eArgs); err != nil {
- os.Exit(1)
- }
- if err := requestGrpc(CMD_NEIGHBOR, []string{}, nil); err != nil {
- return err
- }
- } else if len(eArgs) == 1 && !(eArgs[0] == "-h" || eArgs[0] == "--help") {
- if err := requestGrpc(CMD_NEIGHBOR, eArgs, nil); err != nil {
- return err
- }
- } else {
- parser := flags.NewParser(nil, flags.Default)
- parser.Usage = "neighbor [ <neighbor address> ]\n gobgp neighbor"
- parser.AddCommand(CMD_LOCAL, "subcommand for local-rib of neighbor", "", NewNeighborRibCommand(eArgs[0], api.Resource_LOCAL, CMD_LOCAL))
- parser.AddCommand(CMD_ADJ_IN, "subcommand for adj-rib-in of neighbor", "", NewNeighborRibCommand(eArgs[0], api.Resource_ADJ_IN, CMD_ADJ_IN))
- parser.AddCommand(CMD_ADJ_OUT, "subcommand for adj-rib-out of neighbor", "", NewNeighborRibCommand(eArgs[0], api.Resource_ADJ_OUT, CMD_ADJ_OUT))
- parser.AddCommand(CMD_RESET, "subcommand for reset the rib of neighbor", "", NewNeighborResetCommand(eArgs[0], CMD_RESET))
- parser.AddCommand(CMD_SOFT_RESET, "subcommand for softreset the rib of neighbor", "", NewNeighborResetCommand(eArgs[0], CMD_SOFT_RESET))
- parser.AddCommand(CMD_SOFT_RESET_IN, "subcommand for softreset the adj-rib-in of neighbor", "", NewNeighborResetCommand(eArgs[0], CMD_SOFT_RESET_IN))
- parser.AddCommand(CMD_SOFT_RESET_OUT, "subcommand for softreset the adj-rib-out of neighbor", "", NewNeighborResetCommand(eArgs[0], CMD_SOFT_RESET_OUT))
- parser.AddCommand(CMD_SHUTDOWN, "subcommand for shutdown to neighbor", "", NewNeighborChangeStateCommand(eArgs[0], CMD_SHUTDOWN))
- parser.AddCommand(CMD_ENABLE, "subcommand for enable to neighbor", "", NewNeighborChangeStateCommand(eArgs[0], CMD_ENABLE))
- parser.AddCommand(CMD_DISABLE, "subcommand for disable to neighbor", "", NewNeighborChangeStateCommand(eArgs[0], CMD_DISABLE))
- parser.AddCommand(CMD_POLICY, "subcommand for policy of neighbor", "", NewNeighborPolicyCommand(eArgs[0]))
- if _, err := parser.ParseArgs(eArgs); err != nil {
- os.Exit(1)
- }
- }
- return nil
-}
-
-type NeighborRibCommand struct {
- remoteIP net.IP
- resource api.Resource
- command string
-}
-
-func NewNeighborRibCommand(addr string, resource api.Resource, cmd string) *NeighborRibCommand {
- return &NeighborRibCommand{
- remoteIP: net.ParseIP(addr),
- resource: resource,
- command: cmd,
- }
-}
-
-func showRoute(pathList []*api.Path, showAge bool, showBest bool) {
-
- var pathStrs [][]interface{}
- maxPrefixLen := len("Network")
- maxNexthopLen := len("Next Hop")
- maxAsPathLen := len("AS_PATH")
-
- for _, p := range pathList {
- aspath := func(attrs []*api.PathAttr) string {
- s := bytes.NewBuffer(make([]byte, 0, 64))
- s.WriteString("[")
- for _, a := range attrs {
- if a.Type == api.BGP_ATTR_TYPE_AS_PATH {
- var ss []string
- for _, as := range a.AsPath {
- ss = append(ss, fmt.Sprintf("%d", as))
- }
- s.WriteString(strings.Join(ss, " "))
- }
- }
- s.WriteString("]")
- return s.String()
- }
- formatAttrs := func(attrs []*api.PathAttr) string {
- s := []string{}
- for _, a := range attrs {
- switch a.Type {
- case api.BGP_ATTR_TYPE_ORIGIN:
- s = append(s, fmt.Sprintf("{Origin: %s}", a.Origin))
- case api.BGP_ATTR_TYPE_MULTI_EXIT_DISC:
- s = append(s, fmt.Sprintf("{Med: %d}", a.Metric))
- case api.BGP_ATTR_TYPE_LOCAL_PREF:
- s = append(s, fmt.Sprintf("{LocalPref: %v}", a.Pref))
- case api.BGP_ATTR_TYPE_ATOMIC_AGGREGATE:
- s = append(s, "AtomicAggregate")
- case api.BGP_ATTR_TYPE_AGGREGATOR:
- s = append(s, fmt.Sprintf("{Aggregate: {AS: %d, Address: %s}", a.GetAggregator().As, a.GetAggregator().Address))
- case api.BGP_ATTR_TYPE_COMMUNITIES:
- l := []string{}
- known := map[uint32]string{
- 0xffff0000: "planned-shut",
- 0xffff0001: "accept-own",
- 0xffff0002: "ROUTE_FILTER_TRANSLATED_v4",
- 0xffff0003: "ROUTE_FILTER_v4",
- 0xffff0004: "ROUTE_FILTER_TRANSLATED_v6",
- 0xffff0005: "ROUTE_FILTER_v6",
- 0xffff0006: "LLGR_STALE",
- 0xffff0007: "NO_LLGR",
- 0xFFFFFF01: "NO_EXPORT",
- 0xFFFFFF02: "NO_ADVERTISE",
- 0xFFFFFF03: "NO_EXPORT_SUBCONFED",
- 0xFFFFFF04: "NOPEER"}
-
- for _, v := range a.Communites {
- k, found := known[v]
- if found {
- l = append(l, fmt.Sprint(k))
- } else {
- l = append(l, fmt.Sprintf("%d:%d", (0xffff0000&v)>>16, 0xffff&v))
- }
- }
- s = append(s, fmt.Sprintf("{Community: %v}", l))
- case api.BGP_ATTR_TYPE_ORIGINATOR_ID:
- s = append(s, fmt.Sprintf("{Originator: %v}", a.Originator))
- case api.BGP_ATTR_TYPE_CLUSTER_LIST:
- s = append(s, fmt.Sprintf("{Cluster: %v}", a.Cluster))
- case api.BGP_ATTR_TYPE_TUNNEL_ENCAP:
- s1 := bytes.NewBuffer(make([]byte, 0, 64))
- s1.WriteString("{Encap: ")
- var s2 []string
- for _, tlv := range a.TunnelEncap {
- s3 := bytes.NewBuffer(make([]byte, 0, 64))
- s3.WriteString(fmt.Sprintf("< %s | ", tlv.Type))
- var s4 []string
- for _, subTlv := range tlv.SubTlv {
- if subTlv.Type == api.ENCAP_SUBTLV_TYPE_COLOR {
- s4 = append(s4, fmt.Sprintf("color: %d", subTlv.Color))
- }
- }
- s3.WriteString(strings.Join(s4, ","))
- s3.WriteString(" >")
- s2 = append(s2, s3.String())
- }
- s1.WriteString(strings.Join(s2, "|"))
- s1.WriteString("}")
- s = append(s, s1.String())
- case api.BGP_ATTR_TYPE_AS4_PATH, api.BGP_ATTR_TYPE_MP_REACH_NLRI, api.BGP_ATTR_TYPE_MP_UNREACH_NLRI, api.BGP_ATTR_TYPE_NEXT_HOP, api.BGP_ATTR_TYPE_AS_PATH:
- default:
- s = append(s, fmt.Sprintf("{%v: %v}", a.Type, a.Value))
- }
- }
- return fmt.Sprint(s)
- }
- best := ""
- if showBest {
- if p.Best {
- best = "*>"
- } else {
- best = "* "
- }
- }
-
- if maxPrefixLen < len(p.Nlri.Prefix) {
- maxPrefixLen = len(p.Nlri.Prefix)
- }
-
- if maxNexthopLen < len(p.Nexthop) {
- maxNexthopLen = len(p.Nexthop)
- }
-
- if maxAsPathLen < len(aspath(p.Attrs)) {
- maxAsPathLen = len(aspath(p.Attrs))
- }
-
- if showAge {
- pathStrs = append(pathStrs, []interface{}{best, p.Nlri.Prefix, p.Nexthop, aspath(p.Attrs), formatTimedelta(p.Age), formatAttrs(p.Attrs)})
- } else {
- pathStrs = append(pathStrs, []interface{}{best, p.Nlri.Prefix, p.Nexthop, aspath(p.Attrs), formatAttrs(p.Attrs)})
- }
- }
-
- var format string
- if showAge {
- format = fmt.Sprintf("%%-2s %%-%ds %%-%ds %%-%ds %%-10s %%-s\n", maxPrefixLen, maxNexthopLen, maxAsPathLen)
- fmt.Printf(format, "", "Network", "Next Hop", "AS_PATH", "Age", "Attrs")
- } else {
- format = fmt.Sprintf("%%-2s %%-%ds %%-%ds %%-%ds %%-s\n", maxPrefixLen, maxNexthopLen, maxAsPathLen)
- fmt.Printf(format, "", "Network", "Next Hop", "AS_PATH", "Attrs")
- }
-
- for _, pathStr := range pathStrs {
- fmt.Printf(format, pathStr...)
- }
-}
-
-func showNeighborRib(resource api.Resource, request *NeighborRibCommand) error {
- remoteIP := request.remoteIP
- rt, err := checkAddressFamily(remoteIP)
- if err != nil {
- return err
- }
- arg := &api.Arguments{
- Resource: resource,
- Af: rt,
- RouterId: remoteIP.String(),
- }
-
- ps := paths{}
- showBest := false
- showAge := true
- switch resource {
- case api.Resource_LOCAL:
- showBest = true
- stream, e := client.GetRib(context.Background(), arg)
- if e != nil {
- return e
- }
-
- ds := []*api.Destination{}
- for {
- d, e := stream.Recv()
- if e == io.EOF {
- break
- } else if e != nil {
- return e
- }
- ds = append(ds, d)
- }
-
- if globalOpts.Json {
- j, _ := json.Marshal(ds)
- fmt.Println(string(j))
- return nil
- }
-
- for _, d := range ds {
- for idx, p := range d.Paths {
- if idx == int(d.BestPathIdx) {
- p.Best = true
- }
- ps = append(ps, p)
- }
- }
- case api.Resource_ADJ_OUT:
- showAge = false
- fallthrough
- case api.Resource_ADJ_IN:
- stream, e := client.GetAdjRib(context.Background(), arg)
- if e != nil {
- return e
- }
- for {
- p, e := stream.Recv()
- if e == io.EOF {
- break
- } else if e != nil {
- return e
- }
- ps = append(ps, p)
- }
- if globalOpts.Json {
- j, _ := json.Marshal(ps)
- fmt.Println(string(j))
- return nil
- }
- }
-
- sort.Sort(ps)
- showRoute(ps, showAge, showBest)
- return nil
-}
-
-func (x *NeighborRibCommand) Execute(args []string) error {
- eArgs := extractArgs(x.command)
- parser := flags.NewParser(&subOpts, flags.Default)
- parser.Usage = fmt.Sprintf("neighbor <neighbor address> %s [OPTIONS]", x.command)
- parser.ParseArgs(eArgs)
- if len(eArgs) != 0 && (eArgs[0] == "-h" || eArgs[0] == "--help") {
- return nil
- }
- if err := requestGrpc(CMD_NEIGHBOR+"_"+x.command, eArgs, x); err != nil {
- return err
- }
- return nil
-}
-
-type NeighborResetCommand struct {
- remoteIP net.IP
- command string
-}
-
-func NewNeighborResetCommand(addr string, cmd string) *NeighborResetCommand {
- return &NeighborResetCommand{
- remoteIP: net.ParseIP(addr),
- command: cmd,
- }
-}
-
-func resetNeighbor(request *NeighborResetCommand) error {
- remoteIP := request.remoteIP
- cmd := request.command
- rt, err := checkAddressFamily(remoteIP)
- if err != nil {
- return err
- }
- arg := &api.Arguments{
- RouterId: remoteIP.String(),
- Af: rt,
- }
- switch cmd {
- case CMD_RESET:
- client.Reset(context.Background(), arg)
- case CMD_SOFT_RESET:
- client.SoftReset(context.Background(), arg)
- case CMD_SOFT_RESET_IN:
- client.SoftResetIn(context.Background(), arg)
- case CMD_SOFT_RESET_OUT:
- client.SoftResetOut(context.Background(), arg)
- }
- return nil
-}
-
-func (x *NeighborResetCommand) Execute(args []string) error {
- eArgs := extractArgs(x.command)
- parser := flags.NewParser(&subOpts, flags.Default)
- parser.Usage = fmt.Sprintf("neighbor <neighbor address> %s [OPTIONS]", x.command)
- parser.ParseArgs(eArgs)
- if len(eArgs) != 0 && (eArgs[0] == "-h" || eArgs[0] == "--help") {
- return nil
- }
- if err := requestGrpc(CMD_NEIGHBOR+"_"+x.command, eArgs, x); err != nil {
- return err
- }
- return nil
-}
-
-type NeighborChangeStateCommand struct {
- remoteIP net.IP
- command string
-}
-
-func NewNeighborChangeStateCommand(addr string, cmd string) *NeighborChangeStateCommand {
- return &NeighborChangeStateCommand{
- remoteIP: net.ParseIP(addr),
- command: cmd,
- }
-}
-
-func stateChangeNeighbor(request *NeighborChangeStateCommand) error {
- remoteIP := request.remoteIP
- cmd := request.command
- arg := &api.Arguments{
- RouterId: remoteIP.String(),
- }
- switch cmd {
- case CMD_SHUTDOWN:
- client.Shutdown(context.Background(), arg)
- case CMD_ENABLE:
- client.Enable(context.Background(), arg)
- case CMD_DISABLE:
- client.Disable(context.Background(), arg)
- }
- return nil
-}
-
-func (x *NeighborChangeStateCommand) Execute(args []string) error {
- eArgs := extractArgs(x.command)
- if err := requestGrpc(CMD_NEIGHBOR+"_"+x.command, eArgs, x); err != nil {
- return err
- }
- return nil
-}
-
-type NeighborPolicyCommand struct {
- remoteIP net.IP
-}
-
-func NewNeighborPolicyCommand(addr string) *NeighborPolicyCommand {
- return &NeighborPolicyCommand{
- remoteIP: net.ParseIP(addr),
- }
-}
-
-func showNeighborPolicy(request *NeighborPolicyCommand) error {
- remoteIP := request.remoteIP
- rt, err := checkAddressFamily(net.IP{})
- if err != nil {
- return err
- }
- arg := &api.Arguments{
- Af: rt,
- RouterId: remoteIP.String(),
- }
-
- ap, e := client.GetNeighborPolicy(context.Background(), arg)
- if e != nil {
- return e
- }
-
- if globalOpts.Json {
- j, _ := json.Marshal(ap)
- fmt.Println(string(j))
- return nil
- }
-
- fmt.Printf("DefaultImportPolicy: %s\n", ap.DefaultImportPolicy)
- fmt.Printf("DefaultExportPolicy: %s\n", ap.DefaultExportPolicy)
- fmt.Printf("ImportPolicies:\n")
-
- for _, inPolicy := range ap.ImportPolicies {
- fmt.Printf(" PolicyName %s:\n", inPolicy.PolicyDefinitionName)
- showPolicyStatement(" ", inPolicy)
- }
- fmt.Printf("ExportPolicies:\n")
- for _, outPolicy := range ap.ExportPolicies {
- fmt.Printf(" PolicyName %s:\n", outPolicy.PolicyDefinitionName)
- showPolicyStatement(" ", outPolicy)
- }
- return nil
-}
-
-func (x *NeighborPolicyCommand) Execute(args []string) error {
- eArgs := extractArgs(CMD_POLICY)
- parser := flags.NewParser(nil, flags.Default)
- if len(eArgs) == 0 {
- if _, err := parser.ParseArgs(eArgs); err != nil {
- os.Exit(1)
- }
- if err := requestGrpc(CMD_NEIGHBOR+"_"+CMD_POLICY, eArgs, x); err != nil {
- return err
- }
- } else {
- parser.Usage = "neighbor <neighbor address> policy \n gobgp neighbor <neighbor address> policy"
- parser.AddCommand(CMD_ADD, "subcommand to add routing policy", "", NewNeighborPolicyAddCommand(x.remoteIP))
- parser.AddCommand(CMD_DEL, "subcommand to delete routing policy", "", NewNeighborPolicyDelCommand(x.remoteIP))
- if _, err := parser.ParseArgs(eArgs); err != nil {
- os.Exit(1)
- }
- }
- return nil
-}
-
-type NeighborPolicyAddCommand struct {
- remoteIP net.IP
-}
-
-func NewNeighborPolicyAddCommand(addr net.IP) *NeighborPolicyAddCommand {
- return &NeighborPolicyAddCommand{
- remoteIP: addr,
- }
-}
-func (x *NeighborPolicyAddCommand) Execute(args []string) error {
- eArgs := extractArgs(CMD_ADD)
- parser := flags.NewParser(nil, flags.Default)
- parser.Usage = "neighbor <neighbor address> policy add"
- parser.AddCommand(CMD_IMPORT, "subcommand to add import policies to neighbor", "", NewNeighborPolicyChangeCommand(CMD_ADD, CMD_IMPORT, x.remoteIP))
- parser.AddCommand(CMD_EXPORT, "subcommand to add export policies to neighbor", "", NewNeighborPolicyChangeCommand(CMD_ADD, CMD_EXPORT, x.remoteIP))
- if _, err := parser.ParseArgs(eArgs); err != nil {
- os.Exit(1)
- }
- return nil
-}
-
-type NeighborPolicyDelCommand struct {
- remoteIP net.IP
-}
-
-func NewNeighborPolicyDelCommand(addr net.IP) *NeighborPolicyDelCommand {
- return &NeighborPolicyDelCommand{
- remoteIP: addr,
- }
-}
-
-func (x *NeighborPolicyDelCommand) Execute(args []string) error {
- eArgs := extractArgs(CMD_DEL)
- parser := flags.NewParser(nil, flags.Default)
- parser.Usage = "neighbor <neighbor address> policy del"
- parser.AddCommand(CMD_IMPORT, "subcommand to delete import policies from neighbor", "", NewNeighborPolicyChangeCommand(CMD_DEL, CMD_IMPORT, x.remoteIP))
- parser.AddCommand(CMD_EXPORT, "subcommand to delete export policies from neighbor", "", NewNeighborPolicyChangeCommand(CMD_DEL, CMD_EXPORT, x.remoteIP))
- if _, err := parser.ParseArgs(eArgs); err != nil {
- os.Exit(1)
- }
- return nil
-}
-
-type NeighborPolicyChangeCommand struct {
- operation string
- policyOperation string
- remoteIP net.IP
-}
-
-func NewNeighborPolicyChangeCommand(operation string, pOperation string, addr net.IP) *NeighborPolicyChangeCommand {
- return &NeighborPolicyChangeCommand{
- operation: operation,
- policyOperation: pOperation,
- remoteIP: addr,
- }
-}
-
-func parseRouteAction(rType string) (string, error) {
- routeActionUpper := strings.ToUpper(rType)
- var routeAction string
- switch routeActionUpper {
- case policy.ROUTE_ACCEPT, policy.ROUTE_REJECT:
- routeAction = routeActionUpper
- default:
- return "", fmt.Errorf("invalid route action: %s\nPlease enter the accept or reject", rType)
- }
- return routeAction, nil
-}
-
-func parsePolicy(pNames string) []*api.PolicyDefinition {
- pList := strings.Split(pNames, ",")
- policyList := make([]*api.PolicyDefinition, 0)
- for _, p := range pList {
- if p != "" {
- policy := &api.PolicyDefinition{
- PolicyDefinitionName: p,
- }
- policyList = append(policyList, policy)
- }
- }
- return policyList
-}
-
-func modNeighborPolicy(eArg []string, request *NeighborPolicyChangeCommand) error {
- var operation api.Operation
- pol := &api.ApplyPolicy{}
- switch request.operation {
- case CMD_ADD:
- policies := parsePolicy(eArg[0])
- defaultPolicy, err := parseRouteAction(eArg[1])
- if err != nil {
- return err
- }
- switch request.policyOperation {
- case CMD_IMPORT:
- pol.ImportPolicies = policies
- pol.DefaultImportPolicy = defaultPolicy
- case CMD_EXPORT:
- pol.ExportPolicies = policies
- pol.DefaultExportPolicy = defaultPolicy
- }
- operation = api.Operation_ADD
-
- case CMD_DEL:
- operation = api.Operation_DEL
- }
- arg := &api.PolicyArguments{
- Resource: api.Resource_POLICY_ROUTEPOLICY,
- Operation: operation,
- RouterId: request.remoteIP.String(),
- Name: request.policyOperation,
- ApplyPolicy: pol,
- }
- stream, err := client.ModNeighborPolicy(context.Background())
- if err != nil {
- return err
- }
- err = stream.Send(arg)
- if err != nil {
- return err
- }
- stream.CloseSend()
-
- res, e := stream.Recv()
- if e != nil {
- return e
- }
- if res.Code != api.Error_SUCCESS {
- return fmt.Errorf("error: code: %d, msg: %s", res.Code, res.Msg)
- }
- return nil
-}
-
-func (x *NeighborPolicyChangeCommand) Execute(args []string) error {
- eArgs := extractArgs(x.policyOperation)
- if x.operation == CMD_ADD && len(eArgs) != 2 {
- return fmt.Errorf("usage: neighbor <neighbor address> policy %s %s <%s policy name> <default %s policy>",
- x.operation, x.policyOperation, x.policyOperation, x.policyOperation)
- } else if x.operation == CMD_DEL && len(eArgs) != 0 {
- return fmt.Errorf("usage: neighbor <neighbor address> policy %s %s", x.operation, x.policyOperation)
- } else {
- if err := requestGrpc(CMD_NEIGHBOR+"_"+CMD_POLICY+"_"+x.operation, eArgs, x); err != nil {
- return err
- }
- }
- return nil
-}
-
-type PolicyCommand struct{}
-
-func (x *PolicyCommand) Execute(args []string) error {
- eArgs := extractArgs(CMD_POLICY)
- parser := flags.NewParser(nil, flags.Default)
- parser.Usage = "policy"
- parser.AddCommand(CMD_PREFIX, "subcommand for prefix of policy", "", &PolicyPrefixCommand{})
- parser.AddCommand(CMD_NEIGHBOR, "subcommand for neighbor of policy", "", &PolicyNeighborCommand{})
- parser.AddCommand(CMD_ROUTEPOLICY, "subcommand for routepolicy of policy", "", &PolicyRoutePolicyCommand{})
- if _, err := parser.ParseArgs(eArgs); err != nil {
- os.Exit(1)
- }
- return nil
-}
-
-type PolicyPrefixCommand struct{}
-
-func formatPolicyPrefix(prefixSetList []*api.PrefixSet) (string, string) {
- maxNameLen := len("Name")
- maxPrefixLen := len("Prefix")
- maxRangeLen := len("MaskRange")
- for _, ps := range prefixSetList {
- if len(ps.PrefixSetName) > maxNameLen {
- maxNameLen = len(ps.PrefixSetName)
- }
- for _, p := range ps.PrefixList {
- if len(p.Address)+len(fmt.Sprint(p.MaskLength))+1 > maxPrefixLen {
- maxPrefixLen = len(p.Address) + len(fmt.Sprint(p.MaskLength)) + 1
- }
- if len(p.MaskLengthRange) > maxRangeLen {
- maxRangeLen = len(p.MaskLengthRange)
- }
- }
- }
- formatPrefixSet := "%-" + fmt.Sprint(maxNameLen) + "s %-" + fmt.Sprint(maxPrefixLen) + "s %-" + fmt.Sprint(maxRangeLen) + "s\n"
- formatPrefixListOnly := "%-" + fmt.Sprint(maxPrefixLen) + "s %-" + fmt.Sprint(maxRangeLen) + "s\n"
- return formatPrefixSet, formatPrefixListOnly
-}
-
-func showPolicyPrefixes() error {
- arg := &api.PolicyArguments{
- Resource: api.Resource_POLICY_PREFIX,
- }
- stream, e := client.GetPolicyPrefixes(context.Background(), arg)
- if e != nil {
- fmt.Println(e)
- return e
- }
- m := prefixes{}
- for {
- p, e := stream.Recv()
- if e == io.EOF {
- break
- } else if e != nil {
- return e
- }
- m = append(m, p)
- }
-
- if globalOpts.Json {
- j, _ := json.Marshal(m)
- fmt.Println(string(j))
- return nil
- }
-
- if globalOpts.Quiet {
- for _, p := range m {
- fmt.Println(p.PrefixSetName)
- }
- return nil
- }
- sort.Sort(m)
-
- format, _ := formatPolicyPrefix(m)
- fmt.Printf(format, "Name", "Prefix", "MaskRange")
- for _, ps := range m {
- for i, p := range ps.PrefixList {
- prefix := fmt.Sprintf("%s/%d", p.Address, p.MaskLength)
- if i == 0 {
- fmt.Printf(format, ps.PrefixSetName, prefix, p.MaskLengthRange)
- } else {
- fmt.Printf(format, "", prefix, p.MaskLengthRange)
- }
- }
- }
- return nil
-}
-
-func showPolicyPrefix(args []string) error {
- arg := &api.PolicyArguments{
- Resource: api.Resource_POLICY_PREFIX,
- Name: args[0],
- }
- ps, e := client.GetPolicyPrefix(context.Background(), arg)
- if e != nil {
- return e
- }
-
- if globalOpts.Json {
- j, _ := json.Marshal(ps)
- fmt.Println(string(j))
- return nil
- }
- if globalOpts.Quiet {
- for _, p := range ps.PrefixList {
- fmt.Printf("%s/%d %s\n", p.Address, p.MaskLength, p.MaskLengthRange)
- }
- return nil
- }
- format, _ := formatPolicyPrefix([]*api.PrefixSet{ps})
- fmt.Printf(format, "Name", "Prefix", "MaskRange")
- for i, p := range ps.PrefixList {
- prefix := fmt.Sprintf("%s/%d", p.Address, p.MaskLength)
- if i == 0 {
- fmt.Printf(format, ps.PrefixSetName, prefix, p.MaskLengthRange)
- } else {
- fmt.Printf(format, "", prefix, p.MaskLengthRange)
- }
- }
- return nil
-}
-
-func (x *PolicyPrefixCommand) Execute(args []string) error {
- eArgs := extractArgs(CMD_PREFIX)
- if len(eArgs) == 0 {
- if err := requestGrpc(CMD_POLICY+"_"+CMD_PREFIX, eArgs, nil); err != nil {
- return err
- }
- return nil
- } else if len(eArgs) >= 1 && !(eArgs[0] == "-h" || eArgs[0] == "--help" || eArgs[0] == CMD_ADD || eArgs[0] == CMD_DEL) {
- if len(eArgs) != 1 {
- return fmt.Errorf("Argument can not be entered: %s", eArgs[1:])
- }
- if err := requestGrpc(CMD_POLICY+"_"+CMD_PREFIX, eArgs, nil); err != nil {
- return err
- }
- return nil
- }
- parser := flags.NewParser(nil, flags.Default)
- parser.Usage = "policy prefix [<prefix set name>],\n gobgp policy prefix"
- parser.AddCommand(CMD_ADD, "subcommand to add prefix condition to policy", "", &PolicyPrefixAddCommand{})
- parser.AddCommand(CMD_DEL, "subcommand to delete prefix condition from policy", "", &PolicyPrefixDelCommand{})
- if _, err := parser.ParseArgs(eArgs); err != nil {
- os.Exit(1)
- }
- return nil
-}
-
-type PolicyPrefixAddCommand struct{}
-
-func parsePrefixSet(eArgs []string) (*api.PrefixSet, error) {
- _, ipNet, e := net.ParseCIDR(eArgs[1])
- if e != nil {
- return nil, fmt.Errorf("invalid prefix: %s\nplease enter ipv4 or ipv6 format", eArgs[1])
- }
- mask, _ := ipNet.Mask.Size()
- prefix := &api.Prefix{
- Address: ipNet.IP.String(),
- MaskLength: uint32(mask),
- }
-
- if len(eArgs) == 3 {
- maskRange := eArgs[2]
- idx := strings.Index(maskRange, "..")
- if idx == -1 {
- return nil, fmt.Errorf("invalid mask length range: %s", maskRange)
- }
- var min, max int
- var e error
- if idx != 0 {
- if min, e = strconv.Atoi(maskRange[:idx]); e != nil {
- return nil, fmt.Errorf("invalid mask length range: %s", maskRange)
- }
- }
- if idx != len(maskRange)-1 {
- if max, e = strconv.Atoi(maskRange[idx+2:]); e != nil {
- return nil, fmt.Errorf("invalid mask length range: %s", maskRange)
- }
- }
- if ipv4 := ipNet.IP.To4(); ipv4 != nil {
- if min < 0 || 32 < max {
- return nil, fmt.Errorf("ipv4 mask length range outside scope :%s", maskRange)
- }
- } else {
- if min < 0 || 128 < max {
- return nil, fmt.Errorf("ipv6 mask length range outside scope :%s", maskRange)
- }
- }
- if min >= max {
- return nil, fmt.Errorf("invalid mask length range: %s\nlarge value to the right from the left", maskRange)
- }
- prefix.MaskLengthRange = maskRange
- }
- prefixList := []*api.Prefix{prefix}
- prefixSet := &api.PrefixSet{
- PrefixSetName: eArgs[0],
- PrefixList: prefixList,
- }
- return prefixSet, nil
-}
-
-func modPolicyPrefix(modtype string, eArgs []string) error {
- prefixSet := &api.PrefixSet{}
- var e error
- var operation api.Operation
-
- switch modtype {
- case CMD_ADD:
- if len(eArgs) < 2 {
- return fmt.Errorf("usage: policy prefix add <prefix set name> <prefix> [<mask length renge>]")
- }
- if prefixSet, e = parsePrefixSet(eArgs); e != nil {
- return e
- }
- operation = api.Operation_ADD
- case CMD_DEL:
- if len(eArgs) == 0 {
- operation = api.Operation_DEL_ALL
- } else if len(eArgs) == 1 {
- prefixSet = &api.PrefixSet{
- PrefixSetName: eArgs[0],
- PrefixList: nil,
- }
- operation = api.Operation_DEL
- } else {
- if prefixSet, e = parsePrefixSet(eArgs); e != nil {
- return e
- }
- operation = api.Operation_DEL
- }
- }
-
- arg := &api.PolicyArguments{
- Resource: api.Resource_POLICY_PREFIX,
- Operation: operation,
- PrefixSet: prefixSet,
- }
- stream, err := client.ModPolicyPrefix(context.Background())
- if err != nil {
- return err
- }
- err = stream.Send(arg)
- if err != nil {
- return err
- }
- stream.CloseSend()
-
- res, e := stream.Recv()
- if e != nil {
- return e
- }
- if res.Code != api.Error_SUCCESS {
- return fmt.Errorf("error: code: %d, msg: %s", res.Code, res.Msg)
- }
- return nil
-}
-
-func (x *PolicyPrefixAddCommand) Execute(args []string) error {
- eArgs := extractArgs(CMD_ADD)
- if len(eArgs) == 0 || len(eArgs) > 3 {
- return fmt.Errorf("usage: policy prefix add <prefix set name> <prefix> [<mask length renge> ]")
- } else {
- if err := requestGrpc(CMD_POLICY+"_"+CMD_PREFIX+"_"+CMD_ADD, eArgs, nil); err != nil {
- return err
- }
- }
- return nil
-}
-
-type PolicyPrefixDelCommand struct{}
-
-func (x *PolicyPrefixDelCommand) Execute(args []string) error {
- eArgs := extractArgs(CMD_DEL)
- if len(eArgs) > 3 {
- return fmt.Errorf("usage: policy prefix del <prefix set name> [<prefix> [<mask length range>]] ")
- } else if len(eArgs) > 0 && !(eArgs[0] == "-h" || eArgs[0] == "--help" || eArgs[0] == "all") {
- if err := requestGrpc(CMD_POLICY+"_"+CMD_PREFIX+"_"+CMD_DEL, eArgs, nil); err != nil {
- return err
- }
- return nil
- }
- parser := flags.NewParser(nil, flags.Default)
- parser.Usage = "policy prefix del <prefix set name> [<prefix> [<mask length range>]],\n gobgp policy prefix del"
- parser.AddCommand(CMD_ALL, "subcommand to delete all prefix condition from policy", "", &PolicyPrefixDelAllCommand{})
- if _, err := parser.ParseArgs(eArgs); err != nil {
- os.Exit(1)
- }
- return nil
-}
-
-type PolicyPrefixDelAllCommand struct{}
-
-func (x *PolicyPrefixDelAllCommand) Execute(args []string) error {
- eArgs := extractArgs(CMD_ALL)
- if len(eArgs) > 0 {
- return fmt.Errorf("Argument can not be entered: %s", eArgs)
- }
- if err := requestGrpc(CMD_POLICY+"_"+CMD_PREFIX+"_"+CMD_DEL, eArgs, nil); err != nil {
- return err
- }
- return nil
-}
-
-type PolicyNeighborCommand struct{}
-
-func formatPolicyNeighbor(neighborSetList []*api.NeighborSet) string {
- maxNameLen := len("Name")
- maxAddressLen := len("Address")
- for _, ns := range neighborSetList {
- if len(ns.NeighborSetName) > maxNameLen {
- maxNameLen = len(ns.NeighborSetName)
- }
- for _, n := range ns.NeighborList {
- if len(n.Address) > maxAddressLen {
- maxAddressLen = len(n.Address)
- }
- }
- }
- format := "%-" + fmt.Sprint(maxNameLen) + "s %-" + fmt.Sprint(maxAddressLen) + "s\n"
- return format
-}
-
-func showPolicyNeighbors() error {
- arg := &api.PolicyArguments{
- Resource: api.Resource_POLICY_NEIGHBOR,
- }
- stream, e := client.GetPolicyNeighbors(context.Background(), arg)
- if e != nil {
- fmt.Println(e)
- return e
- }
- m := neighbors{}
- for {
- n, e := stream.Recv()
- if e == io.EOF {
- break
- } else if e != nil {
- return e
- }
- m = append(m, n)
- }
-
- if globalOpts.Json {
- j, _ := json.Marshal(m)
- fmt.Println(string(j))
- return nil
- }
-
- if globalOpts.Quiet {
- for _, n := range m {
- fmt.Println(n.NeighborSetName)
- }
- return nil
- }
- sort.Sort(m)
-
- format := formatPolicyNeighbor(m)
- fmt.Printf(format, "Name", "Address")
- for _, ns := range m {
- for i, n := range ns.NeighborList {
- if i == 0 {
- fmt.Printf(format, ns.NeighborSetName, n.Address)
- } else {
- fmt.Printf(format, "", n.Address)
- }
- }
- }
- return nil
-}
-
-func showPolicyNeighbor(args []string) error {
- arg := &api.PolicyArguments{
- Resource: api.Resource_POLICY_NEIGHBOR,
- Name: args[0],
- }
- ns, e := client.GetPolicyNeighbor(context.Background(), arg)
- if e != nil {
- return e
- }
-
- if globalOpts.Json {
- j, _ := json.Marshal(ns)
- fmt.Println(string(j))
- return nil
- }
- if globalOpts.Quiet {
- for _, n := range ns.NeighborList {
- fmt.Println(n.Address)
- }
- return nil
- }
- format := formatPolicyNeighbor([]*api.NeighborSet{ns})
- fmt.Printf(format, "Name", "Address")
- for i, n := range ns.NeighborList {
- if i == 0 {
- fmt.Printf(format, ns.NeighborSetName, n.Address)
- } else {
- fmt.Printf(format, "", n.Address)
-
- }
- }
- return nil
-}
-
-func (x *PolicyNeighborCommand) Execute(args []string) error {
- eArgs := extractArgs(CMD_NEIGHBOR)
- if len(eArgs) == 0 {
- if err := requestGrpc(CMD_POLICY+"_"+CMD_NEIGHBOR, eArgs, nil); err != nil {
- return err
- }
- return nil
- } else if len(eArgs) >= 1 && !(eArgs[0] == "-h" || eArgs[0] == "--help" || eArgs[0] == CMD_ADD || eArgs[0] == CMD_DEL) {
- if len(eArgs) != 1 {
- return fmt.Errorf("Argument can not be entered: %s", eArgs[1:])
- }
- if err := requestGrpc(CMD_POLICY+"_"+CMD_NEIGHBOR, eArgs, nil); err != nil {
- return err
- }
- return nil
- }
- parser := flags.NewParser(nil, flags.Default)
- parser.Usage = "policy neighbor [<neighbor set name>],\n gobgp policy neighbor"
- parser.AddCommand(CMD_ADD, "subcommand to add neighbor condition to policy", "", &PolicyNeighborAddCommand{})
- parser.AddCommand(CMD_DEL, "subcommand to delete neighbor condition from policy", "", &PolicyNeighborDelCommand{})
- if _, err := parser.ParseArgs(eArgs); err != nil {
- os.Exit(1)
- }
- return nil
-}
-
-type PolicyNeighborAddCommand struct{}
-
-func parseNeighborSet(eArgs []string) (*api.NeighborSet, error) {
- address := net.ParseIP(eArgs[1])
- if address.To4() == nil {
- if address.To16() == nil {
- return nil, fmt.Errorf("invalid address: %s\nplease enter ipv4 or ipv6 format", eArgs[1])
- }
- }
-
- neighbor := &api.Neighbor{
- Address: address.String(),
- }
- neighborList := []*api.Neighbor{neighbor}
- neighborSet := &api.NeighborSet{
- NeighborSetName: eArgs[0],
- NeighborList: neighborList,
- }
- return neighborSet, nil
-}
-
-func modPolicyNeighbor(modtype string, eArgs []string) error {
- neighborSet := &api.NeighborSet{}
- var e error
- var operation api.Operation
-
- switch modtype {
- case CMD_ADD:
- if len(eArgs) < 2 {
- return fmt.Errorf("usage: policy neighbor add <neighbor set name> <address>")
- }
- if neighborSet, e = parseNeighborSet(eArgs); e != nil {
- return e
- }
- operation = api.Operation_ADD
- case CMD_DEL:
- if len(eArgs) == 0 {
- operation = api.Operation_DEL_ALL
- } else if len(eArgs) == 1 {
- neighborSet = &api.NeighborSet{
- NeighborSetName: eArgs[0],
- NeighborList: nil,
- }
- operation = api.Operation_DEL
- } else {
- if neighborSet, e = parseNeighborSet(eArgs); e != nil {
- return e
- }
- operation = api.Operation_DEL
- }
- }
-
- arg := &api.PolicyArguments{
- Resource: api.Resource_POLICY_NEIGHBOR,
- Operation: operation,
- NeighborSet: neighborSet,
- }
- stream, err := client.ModPolicyNeighbor(context.Background())
- if err != nil {
- return err
- }
- err = stream.Send(arg)
- if err != nil {
- return err
- }
- stream.CloseSend()
-
- res, e := stream.Recv()
- if e != nil {
- return e
- }
- if res.Code != api.Error_SUCCESS {
- return fmt.Errorf("error: code: %d, msg: %s", res.Code, res.Msg)
- }
- return nil
-}
-
-func (x *PolicyNeighborAddCommand) Execute(args []string) error {
- eArgs := extractArgs(CMD_ADD)
- if len(eArgs) == 0 || len(eArgs) > 2 {
- return fmt.Errorf("usage: policy neighbor add <neighbor set name> <address>")
- } else {
- if err := requestGrpc(CMD_POLICY+"_"+CMD_NEIGHBOR+"_"+CMD_ADD, eArgs, nil); err != nil {
- return err
- }
- }
- return nil
-}
-
-type PolicyNeighborDelCommand struct{}
-
-func (x *PolicyNeighborDelCommand) Execute(args []string) error {
- eArgs := extractArgs(CMD_DEL)
- if len(eArgs) > 3 {
- return fmt.Errorf("usage: policy neighbor del [<neighbor set name> [<address>]]")
- } else if len(eArgs) > 0 && !(eArgs[0] == "-h" || eArgs[0] == "--help" || eArgs[0] == "all") {
- if err := requestGrpc(CMD_POLICY+"_"+CMD_NEIGHBOR+"_"+CMD_DEL, eArgs, nil); err != nil {
- return err
- }
- return nil
- }
- parser := flags.NewParser(nil, flags.Default)
- parser.Usage = "policy neighbor del [<neighbor set name> [<address>]],\n gobgp policy neighbor del"
- parser.AddCommand(CMD_ALL, "subcommand to delete all neighbor condition from policy", "", &PolicyNeighborDelAllCommand{})
- if _, err := parser.ParseArgs(eArgs); err != nil {
- os.Exit(1)
- }
- return nil
-}
-
-type PolicyNeighborDelAllCommand struct{}
-
-func (x *PolicyNeighborDelAllCommand) Execute(args []string) error {
- eArgs := extractArgs(CMD_ALL)
- if len(eArgs) > 0 {
- return fmt.Errorf("Argument can not be entered: %s", eArgs)
- }
- if err := requestGrpc(CMD_POLICY+"_"+CMD_NEIGHBOR+"_"+CMD_DEL, eArgs, nil); err != nil {
- return err
- }
- return nil
-}
-
-type PolicyRoutePolicyCommand struct{}
-
-func showPolicyStatement(head string, pd *api.PolicyDefinition) {
- for _, st := range pd.StatementList {
- fmt.Printf("%s StatementName %s:\n", head, st.StatementNeme)
- fmt.Printf("%s Conditions:\n", head)
- prefixSet := st.Conditions.MatchPrefixSet
- fmt.Printf("%s PrefixSet: %s ", head, prefixSet.PrefixSetName)
- if len(prefixSet.PrefixList) != 0 {
- nameFormat := "%-" + fmt.Sprint(len(prefixSet.PrefixSetName)+2) + "s"
- _, format := formatPolicyPrefix([]*api.PrefixSet{st.Conditions.MatchPrefixSet})
- for i, prefix := range prefixSet.PrefixList {
- p := fmt.Sprintf("%s/%d", prefix.Address, prefix.MaskLength)
- if i != 0 {
- fmt.Printf("%s ", head)
- fmt.Printf(nameFormat, "")
- }
- fmt.Printf(format, p, prefix.MaskLengthRange)
- }
- } else {
- fmt.Print("\n")
- }
- neighborSet := st.Conditions.MatchNeighborSet
- fmt.Printf("%s NeighborSet: %s ", head, neighborSet.NeighborSetName)
- if len(neighborSet.NeighborList) != 0 {
- nameFormat := "%-" + fmt.Sprint(len(neighborSet.NeighborSetName)+2) + "s"
- for i, neighbor := range neighborSet.NeighborList {
- if i != 0 {
- fmt.Printf("%s ", head)
- fmt.Printf(nameFormat, "")
- }
- fmt.Println(neighbor.Address)
- }
- } else {
- fmt.Print("\n")
- }
- asPathLentgh := st.Conditions.MatchAsPathLength
- fmt.Printf("%s AsPathLength: %s %s\n", head, asPathLentgh.Operator, asPathLentgh.Value)
- fmt.Printf("%s MatchOption: %s\n", head, st.Conditions.MatchSetOptions)
- fmt.Printf("%s Actions:\n", head)
- fmt.Printf("%s %s\n", head, st.Actions.RouteAction)
- }
-
-}
-
-func showPolicyRoutePolicies() error {
- arg := &api.PolicyArguments{
- Resource: api.Resource_POLICY_ROUTEPOLICY,
- }
- stream, e := client.GetPolicyRoutePolicies(context.Background(), arg)
- if e != nil {
- fmt.Println(e)
- return e
- }
- m := policyDefinitions{}
- for {
- n, e := stream.Recv()
- if e == io.EOF {
- break
- } else if e != nil {
- return e
- }
- m = append(m, n)
- }
-
- if globalOpts.Json {
- j, _ := json.Marshal(m)
- fmt.Println(string(j))
- return nil
- }
- if globalOpts.Quiet {
- for _, p := range m {
- fmt.Println(p.PolicyDefinitionName)
- }
- return nil
- }
- sort.Sort(m)
-
- for _, pd := range m {
- fmt.Printf("PolicyName %s:\n", pd.PolicyDefinitionName)
- showPolicyStatement("", pd)
- }
- return nil
-}
-
-func showPolicyRoutePolicy(args []string) error {
- arg := &api.PolicyArguments{
- Resource: api.Resource_POLICY_ROUTEPOLICY,
- Name: args[0],
- }
- pd, e := client.GetPolicyRoutePolicy(context.Background(), arg)
- if e != nil {
- return e
- }
-
- if globalOpts.Json {
- j, _ := json.Marshal(pd)
- fmt.Println(string(j))
- return nil
- }
-
- if globalOpts.Quiet {
- for _, st := range pd.StatementList {
- fmt.Println(st.StatementNeme)
- }
- return nil
- }
-
- fmt.Printf("PolicyName %s:\n", pd.PolicyDefinitionName)
- showPolicyStatement("", pd)
- return nil
-}
-
-func (x *PolicyRoutePolicyCommand) Execute(args []string) error {
- eArgs := extractArgs(CMD_ROUTEPOLICY)
- if len(eArgs) == 0 {
- if err := requestGrpc(CMD_POLICY+"_"+CMD_ROUTEPOLICY, eArgs, nil); err != nil {
- return err
- }
- return nil
- } else if len(eArgs) >= 1 && !(eArgs[0] == "-h" || eArgs[0] == "--help" || eArgs[0] == CMD_ADD || eArgs[0] == CMD_DEL) {
- if len(eArgs) != 1 {
- return fmt.Errorf("Argument can not be entered: %s", eArgs[1:])
- }
- if err := requestGrpc(CMD_POLICY+"_"+CMD_ROUTEPOLICY, eArgs, nil); err != nil {
- return err
- }
- return nil
- }
- parser := flags.NewParser(nil, flags.Default)
- parser.Usage = "policy routepolicy [<policy name>],\n gobgp policy routepolicy"
- parser.AddCommand(CMD_ADD, "subcommand to add routing policy", "", &PolicyRoutePolicyAddCommand{})
- parser.AddCommand(CMD_DEL, "subcommand to delete routing policy", "", &PolicyRoutePolicyDelCommand{})
- if _, err := parser.ParseArgs(eArgs); err != nil {
- os.Exit(1)
- }
- return nil
-}
-
-type PolicyRoutePolicyAddCommand struct{}
-
-func parseConditions() (*api.Conditions, error) {
- conditions := &api.Conditions{}
- if conditionOpts.Prefix != "" {
- conditions.MatchPrefixSet = &api.PrefixSet{
- PrefixSetName: conditionOpts.Prefix,
- }
- }
- if conditionOpts.Neighbor != "" {
- conditions.MatchNeighborSet = &api.NeighborSet{
- NeighborSetName: conditionOpts.Neighbor,
- }
- }
- if conditionOpts.AsPathLength != "" {
- asPathLen := conditionOpts.AsPathLength
- idx := strings.Index(asPathLen, ",")
- if idx == -1 {
- return nil, fmt.Errorf("invalid as path length: %s\nPlease enter the <value>,<operator>", asPathLen)
- }
- operator := asPathLen[:idx]
- value := asPathLen[idx+1:]
- if _, err := strconv.ParseUint(value, 10, 32); err != nil {
- return nil, fmt.Errorf("invalid as path length: %s\nPlease enter a numeric", value)
- }
- conditions.MatchAsPathLength = &api.AsPathLength{
- Value: value,
- Operator: operator,
- }
- }
- if conditionOpts.Option != "" {
- optionUpper := strings.ToUpper(conditionOpts.Option)
- var option string
- switch optionUpper {
- case policy.OPTIONS_ANY, policy.OPTIONS_ALL, policy.OPTIONS_INVERT:
- option = optionUpper
- default:
- return nil, fmt.Errorf("invalid condition option: %s\nPlease enter the any or all or invert",
- conditionOpts.Option)
- }
- conditions.MatchSetOptions = option
- }
- return conditions, nil
-}
-
-func parseActions() (*api.Actions, error) {
- actions := &api.Actions{}
- if actionOpts.RouteAction != "" {
- routeAction, e := parseRouteAction(actionOpts.RouteAction)
- if e != nil {
- return nil, e
- }
- actions.RouteAction = routeAction
- }
- return actions, nil
-}
-
-func modPolicyRoutePolicy(modtype string, stmtType string, eArgs []string, request interface{}) error {
- var e error
- var operation api.Operation
- pd := &api.PolicyDefinition{}
- switch modtype {
- case CMD_ADD:
- stmt := &api.Statement{}
- switch stmtType {
- case CMD_CONDITIONS:
- conditions, err := parseConditions()
- if err != nil {
- return err
- }
- stmt.StatementNeme = request.(*PolicyRoutePolicyAddConditionsCommand).statementName
- stmt.Conditions = conditions
- pd.PolicyDefinitionName = request.(*PolicyRoutePolicyAddConditionsCommand).policyName
- case CMD_ACTIONS:
- actions, err := parseActions()
- if err != nil {
- return err
- }
- stmt.StatementNeme = request.(*PolicyRoutePolicyAddActionsCommand).statementName
- stmt.Actions = actions
- pd.PolicyDefinitionName = request.(*PolicyRoutePolicyAddActionsCommand).policyName
- }
- pd.StatementList = []*api.Statement{stmt}
- operation = api.Operation_ADD
-
- case CMD_DEL:
- if len(eArgs) == 0 {
- operation = api.Operation_DEL_ALL
- } else if len(eArgs) == 1 {
- pd.PolicyDefinitionName = eArgs[0]
- operation = api.Operation_DEL
- } else if len(eArgs) == 2 {
- stmt := &api.Statement{
- StatementNeme: eArgs[1],
- }
- pd.PolicyDefinitionName = eArgs[0]
- pd.StatementList = []*api.Statement{stmt}
- operation = api.Operation_DEL
- }
- }
- arg := &api.PolicyArguments{
- Resource: api.Resource_POLICY_ROUTEPOLICY,
- Operation: operation,
- PolicyDifinition: pd,
- }
- stream, err := client.ModPolicyNeighbor(context.Background())
- if err != nil {
- return err
- }
- err = stream.Send(arg)
- if err != nil {
- return err
- }
- stream.CloseSend()
-
- res, e := stream.Recv()
- if e != nil {
- return e
- }
- if res.Code != api.Error_SUCCESS {
- return fmt.Errorf("error: code: %d, msg: %s", res.Code, res.Msg)
- }
- return nil
-}
-
-func (x *PolicyRoutePolicyAddCommand) Execute(args []string) error {
- eArgs := extractArgs(CMD_ADD)
- parser := flags.NewParser(nil, flags.Default)
- if len(eArgs) < 2 {
- return fmt.Errorf("usage: policy routepolicy add <routing policy name> <statement name>")
- }
- parser.Usage = "policy routepolicy add <routing policy name> <statement name>"
- parser.AddCommand(CMD_CONDITIONS, "subcommand for routing policy conditions", "", NewPolicyRoutePolicyAddConditionsCommand(eArgs[0], eArgs[1]))
- parser.AddCommand(CMD_ACTIONS, "subcommand for routing policy actions", "", NewPolicyRoutePolicyAddActionsCommand(eArgs[0], eArgs[1]))
- if _, err := parser.ParseArgs(eArgs); err != nil {
- os.Exit(1)
- }
- return nil
-}
-
-type PolicyRoutePolicyAddConditionsCommand struct {
- policyName string
- statementName string
-}
-
-func NewPolicyRoutePolicyAddConditionsCommand(pName string, sName string) *PolicyRoutePolicyAddConditionsCommand {
- return &PolicyRoutePolicyAddConditionsCommand{
- policyName: pName,
- statementName: sName,
- }
-}
-
-func (x *PolicyRoutePolicyAddConditionsCommand) Execute(args []string) error {
- eArgs := extractArgs(CMD_CONDITIONS)
- parser := flags.NewParser(&conditionOpts, flags.Default)
- parser.Usage = "policy routepolicy add <routing policy name> <statement name> conditions [OPTIONS]"
- if _, err := parser.ParseArgs(eArgs); err != nil {
- os.Exit(1)
- }
- if len(eArgs) == 0 {
- return fmt.Errorf("usage: policy routepolicy add <routing policy name> <statement name> conditions [OPTIONS]")
- } else if !(eArgs[0] == "-h" || eArgs[0] == "--help") {
- if err := requestGrpc(CMD_POLICY+"_"+CMD_ROUTEPOLICY+"_"+CMD_ADD+"_"+CMD_CONDITIONS, eArgs, x); err != nil {
- return err
- }
- }
-
- return nil
-}
-
-type PolicyRoutePolicyAddActionsCommand struct {
- policyName string
- statementName string
-}
-
-func NewPolicyRoutePolicyAddActionsCommand(pName string, sName string) *PolicyRoutePolicyAddActionsCommand {
- return &PolicyRoutePolicyAddActionsCommand{
- policyName: pName,
- statementName: sName,
- }
-}
-
-func (x *PolicyRoutePolicyAddActionsCommand) Execute(args []string) error {
- eArgs := extractArgs(CMD_ACTIONS)
- parser := flags.NewParser(&actionOpts, flags.Default)
- parser.Usage = "policy routepolicy add <routing policy name> <statement name> actions [OPTIONS]"
- if _, err := parser.ParseArgs(eArgs); err != nil {
- os.Exit(1)
- }
- if len(eArgs) == 0 {
- return fmt.Errorf("usage: policy routepolicy add <routing policy name> <statement name> actions [OPTIONS]")
- } else if !(eArgs[0] == "-h" || eArgs[0] == "--help") {
- if err := requestGrpc(CMD_POLICY+"_"+CMD_ROUTEPOLICY+"_"+CMD_ADD+"_"+CMD_ACTIONS, eArgs, x); err != nil {
- return err
- }
- }
- return nil
-}
-
-type PolicyRoutePolicyDelCommand struct{}
-
-func (x *PolicyRoutePolicyDelCommand) Execute(args []string) error {
- eArgs := extractArgs(CMD_DEL)
- if len(eArgs) > 0 && !(eArgs[0] == "-h" || eArgs[0] == "--help" || eArgs[0] == "all") {
- if len(eArgs) > 2 {
- return fmt.Errorf("Argument can not be entered: %s", eArgs[2:])
- }
- if err := requestGrpc(CMD_POLICY+"_"+CMD_ROUTEPOLICY+"_"+CMD_DEL, eArgs, nil); err != nil {
- return err
- }
- return nil
- }
- parser := flags.NewParser(nil, flags.Default)
- parser.Usage = "policy routepolicy del <routing policy name> [<statement name>],\n gobgp policy routepolicy del"
- parser.AddCommand(CMD_ALL, "subcommand to delete all routing policy", "", &PolicyRoutePolicyDelAllCommand{})
- if _, err := parser.ParseArgs(eArgs); err != nil {
- os.Exit(1)
- }
- return nil
-}
-
-type PolicyRoutePolicyDelAllCommand struct{}
-
-func (x *PolicyRoutePolicyDelAllCommand) Execute(args []string) error {
- eArgs := extractArgs(CMD_ALL)
- if len(eArgs) > 0 {
- return fmt.Errorf("Argument can not be entered: %s", eArgs)
- }
- if err := requestGrpc(CMD_POLICY+"_"+CMD_ROUTEPOLICY+"_"+CMD_DEL, eArgs, nil); err != nil {
- return err
- }
- return nil
-}
-
var globalOpts struct {
Host string `short:"u" long:"url" description:"specifying an url" default:"127.0.0.1"`
Port int `short:"p" long:"port" description:"specifying a port" default:"8080"`
@@ -2303,24 +28,7 @@ var globalOpts struct {
Json bool `short:"j" long:"json" description:"use json format to output format"`
}
-var subOpts struct {
- AddressFamily string `short:"a" long:"address-family" description:"specifying an address family"`
-}
-
-var neighborsOpts struct {
- Transport string `short:"t" long:"transport" description:"specifying a transport protocol"`
-}
-
-var conditionOpts struct {
- Prefix string `long:"prefix" description:"specifying a prefix set name of policy"`
- Neighbor string `long:"neighbor" description:"specifying a neighbor set name of policy"`
- AsPathLength string `long:"aspath-len" description:"specifying an as path length of policy (<operator>,<numeric>)"`
- Option string `long:"option" description:"specifying an option of policy (any | all | invert)"`
-}
-
-var actionOpts struct {
- RouteAction string `long:"route-action" description:"specifying a route action of policy (accept | reject)"`
-}
+var cmds []string
func main() {
cmds = []string{CMD_GLOBAL, CMD_NEIGHBOR, CMD_POLICY, CMD_RIB, CMD_ADD, CMD_DEL, CMD_ALL, CMD_LOCAL, CMD_ADJ_IN,
diff --git a/gobgp/neighbor.go b/gobgp/neighbor.go
new file mode 100644
index 00000000..71044386
--- /dev/null
+++ b/gobgp/neighbor.go
@@ -0,0 +1,793 @@
+// Copyright (C) 2015 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 main
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "github.com/jessevdk/go-flags"
+ "github.com/osrg/gobgp/api"
+ "github.com/osrg/gobgp/policy"
+ "golang.org/x/net/context"
+ "io"
+ "net"
+ "os"
+ "sort"
+ "strings"
+)
+
+type NeighborCommand struct {
+}
+
+func showNeighbors() error {
+ arg := &api.Arguments{}
+ stream, e := client.GetNeighbors(context.Background(), arg)
+ if e != nil {
+ fmt.Println(e)
+ return e
+ }
+ m := peers{}
+ for {
+ p, e := stream.Recv()
+ if e == io.EOF {
+ break
+ } else if e != nil {
+ return e
+ }
+ if neighborsOpts.Transport != "" {
+ addr := net.ParseIP(p.Conf.RemoteIp)
+ if addr.To4() != nil {
+ if neighborsOpts.Transport != "ipv4" {
+ continue
+ }
+ } else {
+ if neighborsOpts.Transport != "ipv6" {
+ continue
+ }
+ }
+ }
+ m = append(m, p)
+ }
+
+ if globalOpts.Json {
+ j, _ := json.Marshal(m)
+ fmt.Println(string(j))
+ return nil
+ }
+
+ if globalOpts.Quiet {
+ for _, p := range m {
+ fmt.Println(p.Conf.RemoteIp)
+ }
+ return nil
+ }
+ maxaddrlen := 0
+ maxaslen := 0
+ maxtimelen := len("Up/Down")
+ timedelta := []string{}
+
+ sort.Sort(m)
+
+ for _, p := range m {
+ if len(p.Conf.RemoteIp) > maxaddrlen {
+ maxaddrlen = len(p.Conf.RemoteIp)
+ }
+
+ if len(fmt.Sprint(p.Conf.RemoteAs)) > maxaslen {
+ maxaslen = len(fmt.Sprint(p.Conf.RemoteAs))
+ }
+ var t string
+ if p.Info.Uptime == 0 {
+ t = "never"
+ } else if p.Info.BgpState == "BGP_FSM_ESTABLISHED" {
+ t = formatTimedelta(p.Info.Uptime)
+ } else {
+ t = formatTimedelta(p.Info.Downtime)
+ }
+ if len(t) > maxtimelen {
+ maxtimelen = len(t)
+ }
+ timedelta = append(timedelta, t)
+ }
+ var format string
+ format = "%-" + fmt.Sprint(maxaddrlen) + "s" + " %" + fmt.Sprint(maxaslen) + "s" + " %" + fmt.Sprint(maxtimelen) + "s"
+ format += " %-11s |%11s %8s %8s\n"
+ fmt.Printf(format, "Peer", "AS", "Up/Down", "State", "#Advertised", "Received", "Accepted")
+ format_fsm := func(admin, fsm string) string {
+ if admin == "ADMIN_STATE_DOWN" {
+ return "Idle(Admin)"
+ }
+
+ if fsm == "BGP_FSM_IDLE" {
+ return "Idle"
+ } else if fsm == "BGP_FSM_CONNECT" {
+ return "Connect"
+ } else if fsm == "BGP_FSM_ACTIVE" {
+ return "Active"
+ } else if fsm == "BGP_FSM_OPENSENT" {
+ return "Sent"
+ } else if fsm == "BGP_FSM_OPENCONFIRM" {
+ return "Confirm"
+ } else {
+ return "Establ"
+ }
+ }
+
+ for i, p := range m {
+ fmt.Printf(format, p.Conf.RemoteIp, fmt.Sprint(p.Conf.RemoteAs), timedelta[i], format_fsm(p.Info.AdminState, p.Info.BgpState), fmt.Sprint(p.Info.Advertized), fmt.Sprint(p.Info.Received), fmt.Sprint(p.Info.Accepted))
+ }
+
+ return nil
+}
+
+func showNeighbor(args []string) error {
+ id := &api.Arguments{
+ RouterId: args[0],
+ }
+ p, e := client.GetNeighbor(context.Background(), id)
+ if e != nil {
+ return e
+ }
+
+ if globalOpts.Json {
+ j, _ := json.Marshal(p)
+ fmt.Println(string(j))
+ return nil
+ }
+
+ fmt.Printf("BGP neighbor is %s, remote AS %d\n", p.Conf.RemoteIp, p.Conf.RemoteAs)
+ fmt.Printf(" BGP version 4, remote router ID %s\n", p.Conf.Id)
+ fmt.Printf(" BGP state = %s, up for %s\n", p.Info.BgpState, formatTimedelta(p.Info.Uptime))
+ fmt.Printf(" BGP OutQ = %d, Flops = %d\n", p.Info.OutQ, p.Info.Flops)
+ fmt.Printf(" Hold time is %d, keepalive interval is %d seconds\n", p.Info.NegotiatedHoldtime, p.Info.KeepaliveInterval)
+ fmt.Printf(" Configured hold time is %d, keepalive interval is %d seconds\n", p.Conf.Holdtime, p.Conf.KeepaliveInterval)
+
+ fmt.Printf(" Neighbor capabilities:\n")
+ caps := capabilities{}
+ lookup := func(val *api.Capability, l capabilities) *api.Capability {
+ for _, v := range l {
+ if v.Code == val.Code {
+ if v.Code == api.BGP_CAPABILITY_MULTIPROTOCOL {
+ if v.MultiProtocol.Equal(val.MultiProtocol) {
+ return v
+ }
+ continue
+ }
+ return v
+ }
+ }
+ return nil
+ }
+ caps = append(caps, p.Conf.LocalCap...)
+ for _, v := range p.Conf.RemoteCap {
+ if lookup(v, caps) == nil {
+ caps = append(caps, v)
+ }
+ }
+
+ sort.Sort(caps)
+
+ for _, c := range caps {
+ support := ""
+ if m := lookup(c, p.Conf.LocalCap); m != nil {
+ support += "advertised"
+ }
+ if lookup(c, p.Conf.RemoteCap) != nil {
+ if len(support) != 0 {
+ support += " and "
+ }
+ support += "received"
+ }
+
+ if c.Code != api.BGP_CAPABILITY_MULTIPROTOCOL {
+ fmt.Printf(" %s: %s\n", c.Code, support)
+ } else {
+ fmt.Printf(" %s(%s,%s): %s\n", c.Code, c.MultiProtocol.Afi, c.MultiProtocol.Safi, support)
+ }
+ }
+ fmt.Print(" Message statistics:\n")
+ fmt.Print(" Sent Rcvd\n")
+ fmt.Printf(" Opens: %10d %10d\n", p.Info.OpenMessageOut, p.Info.OpenMessageIn)
+ fmt.Printf(" Notifications: %10d %10d\n", p.Info.NotificationOut, p.Info.NotificationIn)
+ fmt.Printf(" Updates: %10d %10d\n", p.Info.UpdateMessageOut, p.Info.UpdateMessageIn)
+ fmt.Printf(" Keepalives: %10d %10d\n", p.Info.KeepAliveMessageOut, p.Info.KeepAliveMessageIn)
+ fmt.Printf(" Route Refesh: %10d %10d\n", p.Info.RefreshMessageOut, p.Info.RefreshMessageIn)
+ fmt.Printf(" Discarded: %10d %10d\n", p.Info.DiscardedOut, p.Info.DiscardedIn)
+ fmt.Printf(" Total: %10d %10d\n", p.Info.TotalMessageOut, p.Info.TotalMessageIn)
+
+ return nil
+}
+
+func (x *NeighborCommand) Execute(args []string) error {
+ eArgs := extractArgs(CMD_NEIGHBOR)
+
+ if len(eArgs) == 0 || (strings.HasPrefix(eArgs[0], "-") && !(eArgs[0] == "-h" || eArgs[0] == "--help")) {
+ parser := flags.NewParser(&neighborsOpts, flags.Default)
+ if _, err := parser.ParseArgs(eArgs); err != nil {
+ os.Exit(1)
+ }
+ if err := requestGrpc(CMD_NEIGHBOR, []string{}, nil); err != nil {
+ return err
+ }
+ } else if len(eArgs) == 1 && !(eArgs[0] == "-h" || eArgs[0] == "--help") {
+ if err := requestGrpc(CMD_NEIGHBOR, eArgs, nil); err != nil {
+ return err
+ }
+ } else {
+ parser := flags.NewParser(nil, flags.Default)
+ parser.Usage = "neighbor [ <neighbor address> ]\n gobgp neighbor"
+ parser.AddCommand(CMD_LOCAL, "subcommand for local-rib of neighbor", "", NewNeighborRibCommand(eArgs[0], api.Resource_LOCAL, CMD_LOCAL))
+ parser.AddCommand(CMD_ADJ_IN, "subcommand for adj-rib-in of neighbor", "", NewNeighborRibCommand(eArgs[0], api.Resource_ADJ_IN, CMD_ADJ_IN))
+ parser.AddCommand(CMD_ADJ_OUT, "subcommand for adj-rib-out of neighbor", "", NewNeighborRibCommand(eArgs[0], api.Resource_ADJ_OUT, CMD_ADJ_OUT))
+ parser.AddCommand(CMD_RESET, "subcommand for reset the rib of neighbor", "", NewNeighborResetCommand(eArgs[0], CMD_RESET))
+ parser.AddCommand(CMD_SOFT_RESET, "subcommand for softreset the rib of neighbor", "", NewNeighborResetCommand(eArgs[0], CMD_SOFT_RESET))
+ parser.AddCommand(CMD_SOFT_RESET_IN, "subcommand for softreset the adj-rib-in of neighbor", "", NewNeighborResetCommand(eArgs[0], CMD_SOFT_RESET_IN))
+ parser.AddCommand(CMD_SOFT_RESET_OUT, "subcommand for softreset the adj-rib-out of neighbor", "", NewNeighborResetCommand(eArgs[0], CMD_SOFT_RESET_OUT))
+ parser.AddCommand(CMD_SHUTDOWN, "subcommand for shutdown to neighbor", "", NewNeighborChangeStateCommand(eArgs[0], CMD_SHUTDOWN))
+ parser.AddCommand(CMD_ENABLE, "subcommand for enable to neighbor", "", NewNeighborChangeStateCommand(eArgs[0], CMD_ENABLE))
+ parser.AddCommand(CMD_DISABLE, "subcommand for disable to neighbor", "", NewNeighborChangeStateCommand(eArgs[0], CMD_DISABLE))
+ parser.AddCommand(CMD_POLICY, "subcommand for policy of neighbor", "", NewNeighborPolicyCommand(eArgs[0]))
+ if _, err := parser.ParseArgs(eArgs); err != nil {
+ os.Exit(1)
+ }
+ }
+ return nil
+}
+
+type NeighborRibCommand struct {
+ remoteIP net.IP
+ resource api.Resource
+ command string
+}
+
+func NewNeighborRibCommand(addr string, resource api.Resource, cmd string) *NeighborRibCommand {
+ return &NeighborRibCommand{
+ remoteIP: net.ParseIP(addr),
+ resource: resource,
+ command: cmd,
+ }
+}
+
+func showRoute(pathList []*api.Path, showAge bool, showBest bool) {
+
+ var pathStrs [][]interface{}
+ maxPrefixLen := len("Network")
+ maxNexthopLen := len("Next Hop")
+ maxAsPathLen := len("AS_PATH")
+
+ for _, p := range pathList {
+ aspath := func(attrs []*api.PathAttr) string {
+ s := bytes.NewBuffer(make([]byte, 0, 64))
+ s.WriteString("[")
+ for _, a := range attrs {
+ if a.Type == api.BGP_ATTR_TYPE_AS_PATH {
+ var ss []string
+ for _, as := range a.AsPath {
+ ss = append(ss, fmt.Sprintf("%d", as))
+ }
+ s.WriteString(strings.Join(ss, " "))
+ }
+ }
+ s.WriteString("]")
+ return s.String()
+ }
+ formatAttrs := func(attrs []*api.PathAttr) string {
+ s := []string{}
+ for _, a := range attrs {
+ switch a.Type {
+ case api.BGP_ATTR_TYPE_ORIGIN:
+ s = append(s, fmt.Sprintf("{Origin: %s}", a.Origin))
+ case api.BGP_ATTR_TYPE_MULTI_EXIT_DISC:
+ s = append(s, fmt.Sprintf("{Med: %d}", a.Metric))
+ case api.BGP_ATTR_TYPE_LOCAL_PREF:
+ s = append(s, fmt.Sprintf("{LocalPref: %v}", a.Pref))
+ case api.BGP_ATTR_TYPE_ATOMIC_AGGREGATE:
+ s = append(s, "AtomicAggregate")
+ case api.BGP_ATTR_TYPE_AGGREGATOR:
+ s = append(s, fmt.Sprintf("{Aggregate: {AS: %d, Address: %s}", a.GetAggregator().As, a.GetAggregator().Address))
+ case api.BGP_ATTR_TYPE_COMMUNITIES:
+ l := []string{}
+ known := map[uint32]string{
+ 0xffff0000: "planned-shut",
+ 0xffff0001: "accept-own",
+ 0xffff0002: "ROUTE_FILTER_TRANSLATED_v4",
+ 0xffff0003: "ROUTE_FILTER_v4",
+ 0xffff0004: "ROUTE_FILTER_TRANSLATED_v6",
+ 0xffff0005: "ROUTE_FILTER_v6",
+ 0xffff0006: "LLGR_STALE",
+ 0xffff0007: "NO_LLGR",
+ 0xFFFFFF01: "NO_EXPORT",
+ 0xFFFFFF02: "NO_ADVERTISE",
+ 0xFFFFFF03: "NO_EXPORT_SUBCONFED",
+ 0xFFFFFF04: "NOPEER"}
+
+ for _, v := range a.Communites {
+ k, found := known[v]
+ if found {
+ l = append(l, fmt.Sprint(k))
+ } else {
+ l = append(l, fmt.Sprintf("%d:%d", (0xffff0000&v)>>16, 0xffff&v))
+ }
+ }
+ s = append(s, fmt.Sprintf("{Community: %v}", l))
+ case api.BGP_ATTR_TYPE_ORIGINATOR_ID:
+ s = append(s, fmt.Sprintf("{Originator: %v}", a.Originator))
+ case api.BGP_ATTR_TYPE_CLUSTER_LIST:
+ s = append(s, fmt.Sprintf("{Cluster: %v}", a.Cluster))
+ case api.BGP_ATTR_TYPE_TUNNEL_ENCAP:
+ s1 := bytes.NewBuffer(make([]byte, 0, 64))
+ s1.WriteString("{Encap: ")
+ var s2 []string
+ for _, tlv := range a.TunnelEncap {
+ s3 := bytes.NewBuffer(make([]byte, 0, 64))
+ s3.WriteString(fmt.Sprintf("< %s | ", tlv.Type))
+ var s4 []string
+ for _, subTlv := range tlv.SubTlv {
+ if subTlv.Type == api.ENCAP_SUBTLV_TYPE_COLOR {
+ s4 = append(s4, fmt.Sprintf("color: %d", subTlv.Color))
+ }
+ }
+ s3.WriteString(strings.Join(s4, ","))
+ s3.WriteString(" >")
+ s2 = append(s2, s3.String())
+ }
+ s1.WriteString(strings.Join(s2, "|"))
+ s1.WriteString("}")
+ s = append(s, s1.String())
+ case api.BGP_ATTR_TYPE_AS4_PATH, api.BGP_ATTR_TYPE_MP_REACH_NLRI, api.BGP_ATTR_TYPE_MP_UNREACH_NLRI, api.BGP_ATTR_TYPE_NEXT_HOP, api.BGP_ATTR_TYPE_AS_PATH:
+ default:
+ s = append(s, fmt.Sprintf("{%v: %v}", a.Type, a.Value))
+ }
+ }
+ return fmt.Sprint(s)
+ }
+ best := ""
+ if showBest {
+ if p.Best {
+ best = "*>"
+ } else {
+ best = "* "
+ }
+ }
+
+ if maxPrefixLen < len(p.Nlri.Prefix) {
+ maxPrefixLen = len(p.Nlri.Prefix)
+ }
+
+ if maxNexthopLen < len(p.Nexthop) {
+ maxNexthopLen = len(p.Nexthop)
+ }
+
+ if maxAsPathLen < len(aspath(p.Attrs)) {
+ maxAsPathLen = len(aspath(p.Attrs))
+ }
+
+ if showAge {
+ pathStrs = append(pathStrs, []interface{}{best, p.Nlri.Prefix, p.Nexthop, aspath(p.Attrs), formatTimedelta(p.Age), formatAttrs(p.Attrs)})
+ } else {
+ pathStrs = append(pathStrs, []interface{}{best, p.Nlri.Prefix, p.Nexthop, aspath(p.Attrs), formatAttrs(p.Attrs)})
+ }
+ }
+
+ var format string
+ if showAge {
+ format = fmt.Sprintf("%%-2s %%-%ds %%-%ds %%-%ds %%-10s %%-s\n", maxPrefixLen, maxNexthopLen, maxAsPathLen)
+ fmt.Printf(format, "", "Network", "Next Hop", "AS_PATH", "Age", "Attrs")
+ } else {
+ format = fmt.Sprintf("%%-2s %%-%ds %%-%ds %%-%ds %%-s\n", maxPrefixLen, maxNexthopLen, maxAsPathLen)
+ fmt.Printf(format, "", "Network", "Next Hop", "AS_PATH", "Attrs")
+ }
+
+ for _, pathStr := range pathStrs {
+ fmt.Printf(format, pathStr...)
+ }
+}
+
+func showNeighborRib(resource api.Resource, request *NeighborRibCommand) error {
+ remoteIP := request.remoteIP
+ rt, err := checkAddressFamily(remoteIP)
+ if err != nil {
+ return err
+ }
+ arg := &api.Arguments{
+ Resource: resource,
+ Af: rt,
+ RouterId: remoteIP.String(),
+ }
+
+ ps := paths{}
+ showBest := false
+ showAge := true
+ switch resource {
+ case api.Resource_LOCAL:
+ showBest = true
+ stream, e := client.GetRib(context.Background(), arg)
+ if e != nil {
+ return e
+ }
+
+ ds := []*api.Destination{}
+ for {
+ d, e := stream.Recv()
+ if e == io.EOF {
+ break
+ } else if e != nil {
+ return e
+ }
+ ds = append(ds, d)
+ }
+
+ if globalOpts.Json {
+ j, _ := json.Marshal(ds)
+ fmt.Println(string(j))
+ return nil
+ }
+
+ for _, d := range ds {
+ for idx, p := range d.Paths {
+ if idx == int(d.BestPathIdx) {
+ p.Best = true
+ }
+ ps = append(ps, p)
+ }
+ }
+ case api.Resource_ADJ_OUT:
+ showAge = false
+ fallthrough
+ case api.Resource_ADJ_IN:
+ stream, e := client.GetAdjRib(context.Background(), arg)
+ if e != nil {
+ return e
+ }
+ for {
+ p, e := stream.Recv()
+ if e == io.EOF {
+ break
+ } else if e != nil {
+ return e
+ }
+ ps = append(ps, p)
+ }
+ if globalOpts.Json {
+ j, _ := json.Marshal(ps)
+ fmt.Println(string(j))
+ return nil
+ }
+ }
+
+ sort.Sort(ps)
+ showRoute(ps, showAge, showBest)
+ return nil
+}
+
+func (x *NeighborRibCommand) Execute(args []string) error {
+ eArgs := extractArgs(x.command)
+ parser := flags.NewParser(&subOpts, flags.Default)
+ parser.Usage = fmt.Sprintf("neighbor <neighbor address> %s [OPTIONS]", x.command)
+ parser.ParseArgs(eArgs)
+ if len(eArgs) != 0 && (eArgs[0] == "-h" || eArgs[0] == "--help") {
+ return nil
+ }
+ if err := requestGrpc(CMD_NEIGHBOR+"_"+x.command, eArgs, x); err != nil {
+ return err
+ }
+ return nil
+}
+
+type NeighborResetCommand struct {
+ remoteIP net.IP
+ command string
+}
+
+func NewNeighborResetCommand(addr string, cmd string) *NeighborResetCommand {
+ return &NeighborResetCommand{
+ remoteIP: net.ParseIP(addr),
+ command: cmd,
+ }
+}
+
+func resetNeighbor(request *NeighborResetCommand) error {
+ remoteIP := request.remoteIP
+ cmd := request.command
+ rt, err := checkAddressFamily(remoteIP)
+ if err != nil {
+ return err
+ }
+ arg := &api.Arguments{
+ RouterId: remoteIP.String(),
+ Af: rt,
+ }
+ switch cmd {
+ case CMD_RESET:
+ client.Reset(context.Background(), arg)
+ case CMD_SOFT_RESET:
+ client.SoftReset(context.Background(), arg)
+ case CMD_SOFT_RESET_IN:
+ client.SoftResetIn(context.Background(), arg)
+ case CMD_SOFT_RESET_OUT:
+ client.SoftResetOut(context.Background(), arg)
+ }
+ return nil
+}
+
+func (x *NeighborResetCommand) Execute(args []string) error {
+ eArgs := extractArgs(x.command)
+ parser := flags.NewParser(&subOpts, flags.Default)
+ parser.Usage = fmt.Sprintf("neighbor <neighbor address> %s [OPTIONS]", x.command)
+ parser.ParseArgs(eArgs)
+ if len(eArgs) != 0 && (eArgs[0] == "-h" || eArgs[0] == "--help") {
+ return nil
+ }
+ if err := requestGrpc(CMD_NEIGHBOR+"_"+x.command, eArgs, x); err != nil {
+ return err
+ }
+ return nil
+}
+
+type NeighborChangeStateCommand struct {
+ remoteIP net.IP
+ command string
+}
+
+func NewNeighborChangeStateCommand(addr string, cmd string) *NeighborChangeStateCommand {
+ return &NeighborChangeStateCommand{
+ remoteIP: net.ParseIP(addr),
+ command: cmd,
+ }
+}
+
+func stateChangeNeighbor(request *NeighborChangeStateCommand) error {
+ remoteIP := request.remoteIP
+ cmd := request.command
+ arg := &api.Arguments{
+ RouterId: remoteIP.String(),
+ }
+ switch cmd {
+ case CMD_SHUTDOWN:
+ client.Shutdown(context.Background(), arg)
+ case CMD_ENABLE:
+ client.Enable(context.Background(), arg)
+ case CMD_DISABLE:
+ client.Disable(context.Background(), arg)
+ }
+ return nil
+}
+
+func (x *NeighborChangeStateCommand) Execute(args []string) error {
+ eArgs := extractArgs(x.command)
+ if err := requestGrpc(CMD_NEIGHBOR+"_"+x.command, eArgs, x); err != nil {
+ return err
+ }
+ return nil
+}
+
+type NeighborPolicyCommand struct {
+ remoteIP net.IP
+}
+
+func NewNeighborPolicyCommand(addr string) *NeighborPolicyCommand {
+ return &NeighborPolicyCommand{
+ remoteIP: net.ParseIP(addr),
+ }
+}
+
+func showNeighborPolicy(request *NeighborPolicyCommand) error {
+ remoteIP := request.remoteIP
+ rt, err := checkAddressFamily(net.IP{})
+ if err != nil {
+ return err
+ }
+ arg := &api.Arguments{
+ Af: rt,
+ RouterId: remoteIP.String(),
+ }
+
+ ap, e := client.GetNeighborPolicy(context.Background(), arg)
+ if e != nil {
+ return e
+ }
+
+ if globalOpts.Json {
+ j, _ := json.Marshal(ap)
+ fmt.Println(string(j))
+ return nil
+ }
+
+ fmt.Printf("DefaultImportPolicy: %s\n", ap.DefaultImportPolicy)
+ fmt.Printf("DefaultExportPolicy: %s\n", ap.DefaultExportPolicy)
+ fmt.Printf("ImportPolicies:\n")
+
+ for _, inPolicy := range ap.ImportPolicies {
+ fmt.Printf(" PolicyName %s:\n", inPolicy.PolicyDefinitionName)
+ showPolicyStatement(" ", inPolicy)
+ }
+ fmt.Printf("ExportPolicies:\n")
+ for _, outPolicy := range ap.ExportPolicies {
+ fmt.Printf(" PolicyName %s:\n", outPolicy.PolicyDefinitionName)
+ showPolicyStatement(" ", outPolicy)
+ }
+ return nil
+}
+
+func (x *NeighborPolicyCommand) Execute(args []string) error {
+ eArgs := extractArgs(CMD_POLICY)
+ parser := flags.NewParser(nil, flags.Default)
+ if len(eArgs) == 0 {
+ if _, err := parser.ParseArgs(eArgs); err != nil {
+ os.Exit(1)
+ }
+ if err := requestGrpc(CMD_NEIGHBOR+"_"+CMD_POLICY, eArgs, x); err != nil {
+ return err
+ }
+ } else {
+ parser.Usage = "neighbor <neighbor address> policy \n gobgp neighbor <neighbor address> policy"
+ parser.AddCommand(CMD_ADD, "subcommand to add routing policy", "", NewNeighborPolicyAddCommand(x.remoteIP))
+ parser.AddCommand(CMD_DEL, "subcommand to delete routing policy", "", NewNeighborPolicyDelCommand(x.remoteIP))
+ if _, err := parser.ParseArgs(eArgs); err != nil {
+ os.Exit(1)
+ }
+ }
+ return nil
+}
+
+type NeighborPolicyAddCommand struct {
+ remoteIP net.IP
+}
+
+func NewNeighborPolicyAddCommand(addr net.IP) *NeighborPolicyAddCommand {
+ return &NeighborPolicyAddCommand{
+ remoteIP: addr,
+ }
+}
+func (x *NeighborPolicyAddCommand) Execute(args []string) error {
+ eArgs := extractArgs(CMD_ADD)
+ parser := flags.NewParser(nil, flags.Default)
+ parser.Usage = "neighbor <neighbor address> policy add"
+ parser.AddCommand(CMD_IMPORT, "subcommand to add import policies to neighbor", "", NewNeighborPolicyChangeCommand(CMD_ADD, CMD_IMPORT, x.remoteIP))
+ parser.AddCommand(CMD_EXPORT, "subcommand to add export policies to neighbor", "", NewNeighborPolicyChangeCommand(CMD_ADD, CMD_EXPORT, x.remoteIP))
+ if _, err := parser.ParseArgs(eArgs); err != nil {
+ os.Exit(1)
+ }
+ return nil
+}
+
+type NeighborPolicyDelCommand struct {
+ remoteIP net.IP
+}
+
+func NewNeighborPolicyDelCommand(addr net.IP) *NeighborPolicyDelCommand {
+ return &NeighborPolicyDelCommand{
+ remoteIP: addr,
+ }
+}
+
+func (x *NeighborPolicyDelCommand) Execute(args []string) error {
+ eArgs := extractArgs(CMD_DEL)
+ parser := flags.NewParser(nil, flags.Default)
+ parser.Usage = "neighbor <neighbor address> policy del"
+ parser.AddCommand(CMD_IMPORT, "subcommand to delete import policies from neighbor", "", NewNeighborPolicyChangeCommand(CMD_DEL, CMD_IMPORT, x.remoteIP))
+ parser.AddCommand(CMD_EXPORT, "subcommand to delete export policies from neighbor", "", NewNeighborPolicyChangeCommand(CMD_DEL, CMD_EXPORT, x.remoteIP))
+ if _, err := parser.ParseArgs(eArgs); err != nil {
+ os.Exit(1)
+ }
+ return nil
+}
+
+type NeighborPolicyChangeCommand struct {
+ operation string
+ policyOperation string
+ remoteIP net.IP
+}
+
+func NewNeighborPolicyChangeCommand(operation string, pOperation string, addr net.IP) *NeighborPolicyChangeCommand {
+ return &NeighborPolicyChangeCommand{
+ operation: operation,
+ policyOperation: pOperation,
+ remoteIP: addr,
+ }
+}
+
+func parseRouteAction(rType string) (string, error) {
+ routeActionUpper := strings.ToUpper(rType)
+ var routeAction string
+ switch routeActionUpper {
+ case policy.ROUTE_ACCEPT, policy.ROUTE_REJECT:
+ routeAction = routeActionUpper
+ default:
+ return "", fmt.Errorf("invalid route action: %s\nPlease enter the accept or reject", rType)
+ }
+ return routeAction, nil
+}
+
+func parsePolicy(pNames string) []*api.PolicyDefinition {
+ pList := strings.Split(pNames, ",")
+ policyList := make([]*api.PolicyDefinition, 0)
+ for _, p := range pList {
+ if p != "" {
+ policy := &api.PolicyDefinition{
+ PolicyDefinitionName: p,
+ }
+ policyList = append(policyList, policy)
+ }
+ }
+ return policyList
+}
+
+func modNeighborPolicy(eArg []string, request *NeighborPolicyChangeCommand) error {
+ var operation api.Operation
+ pol := &api.ApplyPolicy{}
+ switch request.operation {
+ case CMD_ADD:
+ policies := parsePolicy(eArg[0])
+ defaultPolicy, err := parseRouteAction(eArg[1])
+ if err != nil {
+ return err
+ }
+ switch request.policyOperation {
+ case CMD_IMPORT:
+ pol.ImportPolicies = policies
+ pol.DefaultImportPolicy = defaultPolicy
+ case CMD_EXPORT:
+ pol.ExportPolicies = policies
+ pol.DefaultExportPolicy = defaultPolicy
+ }
+ operation = api.Operation_ADD
+
+ case CMD_DEL:
+ operation = api.Operation_DEL
+ }
+ arg := &api.PolicyArguments{
+ Resource: api.Resource_POLICY_ROUTEPOLICY,
+ Operation: operation,
+ RouterId: request.remoteIP.String(),
+ Name: request.policyOperation,
+ ApplyPolicy: pol,
+ }
+ stream, err := client.ModNeighborPolicy(context.Background())
+ if err != nil {
+ return err
+ }
+ err = stream.Send(arg)
+ if err != nil {
+ return err
+ }
+ stream.CloseSend()
+
+ res, e := stream.Recv()
+ if e != nil {
+ return e
+ }
+ if res.Code != api.Error_SUCCESS {
+ return fmt.Errorf("error: code: %d, msg: %s", res.Code, res.Msg)
+ }
+ return nil
+}
+
+func (x *NeighborPolicyChangeCommand) Execute(args []string) error {
+ eArgs := extractArgs(x.policyOperation)
+ if x.operation == CMD_ADD && len(eArgs) != 2 {
+ return fmt.Errorf("usage: neighbor <neighbor address> policy %s %s <%s policy name> <default %s policy>",
+ x.operation, x.policyOperation, x.policyOperation, x.policyOperation)
+ } else if x.operation == CMD_DEL && len(eArgs) != 0 {
+ return fmt.Errorf("usage: neighbor <neighbor address> policy %s %s", x.operation, x.policyOperation)
+ } else {
+ if err := requestGrpc(CMD_NEIGHBOR+"_"+CMD_POLICY+"_"+x.operation, eArgs, x); err != nil {
+ return err
+ }
+ }
+ return nil
+}
diff --git a/gobgp/policy.go b/gobgp/policy.go
new file mode 100644
index 00000000..f0f6acf4
--- /dev/null
+++ b/gobgp/policy.go
@@ -0,0 +1,957 @@
+// Copyright (C) 2015 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 main
+
+import (
+ "encoding/json"
+ "fmt"
+ "github.com/jessevdk/go-flags"
+ "github.com/osrg/gobgp/api"
+ "github.com/osrg/gobgp/policy"
+ "golang.org/x/net/context"
+ "io"
+ "net"
+ "os"
+ "sort"
+ "strconv"
+ "strings"
+)
+
+type PolicyCommand struct{}
+
+func (x *PolicyCommand) Execute(args []string) error {
+ eArgs := extractArgs(CMD_POLICY)
+ parser := flags.NewParser(nil, flags.Default)
+ parser.Usage = "policy"
+ parser.AddCommand(CMD_PREFIX, "subcommand for prefix of policy", "", &PolicyPrefixCommand{})
+ parser.AddCommand(CMD_NEIGHBOR, "subcommand for neighbor of policy", "", &PolicyNeighborCommand{})
+ parser.AddCommand(CMD_ROUTEPOLICY, "subcommand for routepolicy of policy", "", &PolicyRoutePolicyCommand{})
+ if _, err := parser.ParseArgs(eArgs); err != nil {
+ os.Exit(1)
+ }
+ return nil
+}
+
+type PolicyPrefixCommand struct{}
+
+func formatPolicyPrefix(prefixSetList []*api.PrefixSet) (string, string) {
+ maxNameLen := len("Name")
+ maxPrefixLen := len("Prefix")
+ maxRangeLen := len("MaskRange")
+ for _, ps := range prefixSetList {
+ if len(ps.PrefixSetName) > maxNameLen {
+ maxNameLen = len(ps.PrefixSetName)
+ }
+ for _, p := range ps.PrefixList {
+ if len(p.Address)+len(fmt.Sprint(p.MaskLength))+1 > maxPrefixLen {
+ maxPrefixLen = len(p.Address) + len(fmt.Sprint(p.MaskLength)) + 1
+ }
+ if len(p.MaskLengthRange) > maxRangeLen {
+ maxRangeLen = len(p.MaskLengthRange)
+ }
+ }
+ }
+ formatPrefixSet := "%-" + fmt.Sprint(maxNameLen) + "s %-" + fmt.Sprint(maxPrefixLen) + "s %-" + fmt.Sprint(maxRangeLen) + "s\n"
+ formatPrefixListOnly := "%-" + fmt.Sprint(maxPrefixLen) + "s %-" + fmt.Sprint(maxRangeLen) + "s\n"
+ return formatPrefixSet, formatPrefixListOnly
+}
+
+func showPolicyPrefixes() error {
+ arg := &api.PolicyArguments{
+ Resource: api.Resource_POLICY_PREFIX,
+ }
+ stream, e := client.GetPolicyPrefixes(context.Background(), arg)
+ if e != nil {
+ fmt.Println(e)
+ return e
+ }
+ m := prefixes{}
+ for {
+ p, e := stream.Recv()
+ if e == io.EOF {
+ break
+ } else if e != nil {
+ return e
+ }
+ m = append(m, p)
+ }
+
+ if globalOpts.Json {
+ j, _ := json.Marshal(m)
+ fmt.Println(string(j))
+ return nil
+ }
+
+ if globalOpts.Quiet {
+ for _, p := range m {
+ fmt.Println(p.PrefixSetName)
+ }
+ return nil
+ }
+ sort.Sort(m)
+
+ format, _ := formatPolicyPrefix(m)
+ fmt.Printf(format, "Name", "Prefix", "MaskRange")
+ for _, ps := range m {
+ for i, p := range ps.PrefixList {
+ prefix := fmt.Sprintf("%s/%d", p.Address, p.MaskLength)
+ if i == 0 {
+ fmt.Printf(format, ps.PrefixSetName, prefix, p.MaskLengthRange)
+ } else {
+ fmt.Printf(format, "", prefix, p.MaskLengthRange)
+ }
+ }
+ }
+ return nil
+}
+
+func showPolicyPrefix(args []string) error {
+ arg := &api.PolicyArguments{
+ Resource: api.Resource_POLICY_PREFIX,
+ Name: args[0],
+ }
+ ps, e := client.GetPolicyPrefix(context.Background(), arg)
+ if e != nil {
+ return e
+ }
+
+ if globalOpts.Json {
+ j, _ := json.Marshal(ps)
+ fmt.Println(string(j))
+ return nil
+ }
+ if globalOpts.Quiet {
+ for _, p := range ps.PrefixList {
+ fmt.Printf("%s/%d %s\n", p.Address, p.MaskLength, p.MaskLengthRange)
+ }
+ return nil
+ }
+ format, _ := formatPolicyPrefix([]*api.PrefixSet{ps})
+ fmt.Printf(format, "Name", "Prefix", "MaskRange")
+ for i, p := range ps.PrefixList {
+ prefix := fmt.Sprintf("%s/%d", p.Address, p.MaskLength)
+ if i == 0 {
+ fmt.Printf(format, ps.PrefixSetName, prefix, p.MaskLengthRange)
+ } else {
+ fmt.Printf(format, "", prefix, p.MaskLengthRange)
+ }
+ }
+ return nil
+}
+
+func (x *PolicyPrefixCommand) Execute(args []string) error {
+ eArgs := extractArgs(CMD_PREFIX)
+ if len(eArgs) == 0 {
+ if err := requestGrpc(CMD_POLICY+"_"+CMD_PREFIX, eArgs, nil); err != nil {
+ return err
+ }
+ return nil
+ } else if len(eArgs) >= 1 && !(eArgs[0] == "-h" || eArgs[0] == "--help" || eArgs[0] == CMD_ADD || eArgs[0] == CMD_DEL) {
+ if len(eArgs) != 1 {
+ return fmt.Errorf("Argument can not be entered: %s", eArgs[1:])
+ }
+ if err := requestGrpc(CMD_POLICY+"_"+CMD_PREFIX, eArgs, nil); err != nil {
+ return err
+ }
+ return nil
+ }
+ parser := flags.NewParser(nil, flags.Default)
+ parser.Usage = "policy prefix [<prefix set name>],\n gobgp policy prefix"
+ parser.AddCommand(CMD_ADD, "subcommand to add prefix condition to policy", "", &PolicyPrefixAddCommand{})
+ parser.AddCommand(CMD_DEL, "subcommand to delete prefix condition from policy", "", &PolicyPrefixDelCommand{})
+ if _, err := parser.ParseArgs(eArgs); err != nil {
+ os.Exit(1)
+ }
+ return nil
+}
+
+type PolicyPrefixAddCommand struct{}
+
+func parsePrefixSet(eArgs []string) (*api.PrefixSet, error) {
+ _, ipNet, e := net.ParseCIDR(eArgs[1])
+ if e != nil {
+ return nil, fmt.Errorf("invalid prefix: %s\nplease enter ipv4 or ipv6 format", eArgs[1])
+ }
+ mask, _ := ipNet.Mask.Size()
+ prefix := &api.Prefix{
+ Address: ipNet.IP.String(),
+ MaskLength: uint32(mask),
+ }
+
+ if len(eArgs) == 3 {
+ maskRange := eArgs[2]
+ idx := strings.Index(maskRange, "..")
+ if idx == -1 {
+ return nil, fmt.Errorf("invalid mask length range: %s", maskRange)
+ }
+ var min, max int
+ var e error
+ if idx != 0 {
+ if min, e = strconv.Atoi(maskRange[:idx]); e != nil {
+ return nil, fmt.Errorf("invalid mask length range: %s", maskRange)
+ }
+ }
+ if idx != len(maskRange)-1 {
+ if max, e = strconv.Atoi(maskRange[idx+2:]); e != nil {
+ return nil, fmt.Errorf("invalid mask length range: %s", maskRange)
+ }
+ }
+ if ipv4 := ipNet.IP.To4(); ipv4 != nil {
+ if min < 0 || 32 < max {
+ return nil, fmt.Errorf("ipv4 mask length range outside scope :%s", maskRange)
+ }
+ } else {
+ if min < 0 || 128 < max {
+ return nil, fmt.Errorf("ipv6 mask length range outside scope :%s", maskRange)
+ }
+ }
+ if min >= max {
+ return nil, fmt.Errorf("invalid mask length range: %s\nlarge value to the right from the left", maskRange)
+ }
+ prefix.MaskLengthRange = maskRange
+ }
+ prefixList := []*api.Prefix{prefix}
+ prefixSet := &api.PrefixSet{
+ PrefixSetName: eArgs[0],
+ PrefixList: prefixList,
+ }
+ return prefixSet, nil
+}
+
+func modPolicyPrefix(modtype string, eArgs []string) error {
+ prefixSet := &api.PrefixSet{}
+ var e error
+ var operation api.Operation
+
+ switch modtype {
+ case CMD_ADD:
+ if len(eArgs) < 2 {
+ return fmt.Errorf("usage: policy prefix add <prefix set name> <prefix> [<mask length renge>]")
+ }
+ if prefixSet, e = parsePrefixSet(eArgs); e != nil {
+ return e
+ }
+ operation = api.Operation_ADD
+ case CMD_DEL:
+ if len(eArgs) == 0 {
+ operation = api.Operation_DEL_ALL
+ } else if len(eArgs) == 1 {
+ prefixSet = &api.PrefixSet{
+ PrefixSetName: eArgs[0],
+ PrefixList: nil,
+ }
+ operation = api.Operation_DEL
+ } else {
+ if prefixSet, e = parsePrefixSet(eArgs); e != nil {
+ return e
+ }
+ operation = api.Operation_DEL
+ }
+ }
+
+ arg := &api.PolicyArguments{
+ Resource: api.Resource_POLICY_PREFIX,
+ Operation: operation,
+ PrefixSet: prefixSet,
+ }
+ stream, err := client.ModPolicyPrefix(context.Background())
+ if err != nil {
+ return err
+ }
+ err = stream.Send(arg)
+ if err != nil {
+ return err
+ }
+ stream.CloseSend()
+
+ res, e := stream.Recv()
+ if e != nil {
+ return e
+ }
+ if res.Code != api.Error_SUCCESS {
+ return fmt.Errorf("error: code: %d, msg: %s", res.Code, res.Msg)
+ }
+ return nil
+}
+
+func (x *PolicyPrefixAddCommand) Execute(args []string) error {
+ eArgs := extractArgs(CMD_ADD)
+ if len(eArgs) == 0 || len(eArgs) > 3 {
+ return fmt.Errorf("usage: policy prefix add <prefix set name> <prefix> [<mask length renge> ]")
+ } else {
+ if err := requestGrpc(CMD_POLICY+"_"+CMD_PREFIX+"_"+CMD_ADD, eArgs, nil); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+type PolicyPrefixDelCommand struct{}
+
+func (x *PolicyPrefixDelCommand) Execute(args []string) error {
+ eArgs := extractArgs(CMD_DEL)
+ if len(eArgs) > 3 {
+ return fmt.Errorf("usage: policy prefix del <prefix set name> [<prefix> [<mask length range>]] ")
+ } else if len(eArgs) > 0 && !(eArgs[0] == "-h" || eArgs[0] == "--help" || eArgs[0] == "all") {
+ if err := requestGrpc(CMD_POLICY+"_"+CMD_PREFIX+"_"+CMD_DEL, eArgs, nil); err != nil {
+ return err
+ }
+ return nil
+ }
+ parser := flags.NewParser(nil, flags.Default)
+ parser.Usage = "policy prefix del <prefix set name> [<prefix> [<mask length range>]],\n gobgp policy prefix del"
+ parser.AddCommand(CMD_ALL, "subcommand to delete all prefix condition from policy", "", &PolicyPrefixDelAllCommand{})
+ if _, err := parser.ParseArgs(eArgs); err != nil {
+ os.Exit(1)
+ }
+ return nil
+}
+
+type PolicyPrefixDelAllCommand struct{}
+
+func (x *PolicyPrefixDelAllCommand) Execute(args []string) error {
+ eArgs := extractArgs(CMD_ALL)
+ if len(eArgs) > 0 {
+ return fmt.Errorf("Argument can not be entered: %s", eArgs)
+ }
+ if err := requestGrpc(CMD_POLICY+"_"+CMD_PREFIX+"_"+CMD_DEL, eArgs, nil); err != nil {
+ return err
+ }
+ return nil
+}
+
+type PolicyNeighborCommand struct{}
+
+func formatPolicyNeighbor(neighborSetList []*api.NeighborSet) string {
+ maxNameLen := len("Name")
+ maxAddressLen := len("Address")
+ for _, ns := range neighborSetList {
+ if len(ns.NeighborSetName) > maxNameLen {
+ maxNameLen = len(ns.NeighborSetName)
+ }
+ for _, n := range ns.NeighborList {
+ if len(n.Address) > maxAddressLen {
+ maxAddressLen = len(n.Address)
+ }
+ }
+ }
+ format := "%-" + fmt.Sprint(maxNameLen) + "s %-" + fmt.Sprint(maxAddressLen) + "s\n"
+ return format
+}
+
+func showPolicyNeighbors() error {
+ arg := &api.PolicyArguments{
+ Resource: api.Resource_POLICY_NEIGHBOR,
+ }
+ stream, e := client.GetPolicyNeighbors(context.Background(), arg)
+ if e != nil {
+ fmt.Println(e)
+ return e
+ }
+ m := neighbors{}
+ for {
+ n, e := stream.Recv()
+ if e == io.EOF {
+ break
+ } else if e != nil {
+ return e
+ }
+ m = append(m, n)
+ }
+
+ if globalOpts.Json {
+ j, _ := json.Marshal(m)
+ fmt.Println(string(j))
+ return nil
+ }
+
+ if globalOpts.Quiet {
+ for _, n := range m {
+ fmt.Println(n.NeighborSetName)
+ }
+ return nil
+ }
+ sort.Sort(m)
+
+ format := formatPolicyNeighbor(m)
+ fmt.Printf(format, "Name", "Address")
+ for _, ns := range m {
+ for i, n := range ns.NeighborList {
+ if i == 0 {
+ fmt.Printf(format, ns.NeighborSetName, n.Address)
+ } else {
+ fmt.Printf(format, "", n.Address)
+ }
+ }
+ }
+ return nil
+}
+
+func showPolicyNeighbor(args []string) error {
+ arg := &api.PolicyArguments{
+ Resource: api.Resource_POLICY_NEIGHBOR,
+ Name: args[0],
+ }
+ ns, e := client.GetPolicyNeighbor(context.Background(), arg)
+ if e != nil {
+ return e
+ }
+
+ if globalOpts.Json {
+ j, _ := json.Marshal(ns)
+ fmt.Println(string(j))
+ return nil
+ }
+ if globalOpts.Quiet {
+ for _, n := range ns.NeighborList {
+ fmt.Println(n.Address)
+ }
+ return nil
+ }
+ format := formatPolicyNeighbor([]*api.NeighborSet{ns})
+ fmt.Printf(format, "Name", "Address")
+ for i, n := range ns.NeighborList {
+ if i == 0 {
+ fmt.Printf(format, ns.NeighborSetName, n.Address)
+ } else {
+ fmt.Printf(format, "", n.Address)
+
+ }
+ }
+ return nil
+}
+
+func (x *PolicyNeighborCommand) Execute(args []string) error {
+ eArgs := extractArgs(CMD_NEIGHBOR)
+ if len(eArgs) == 0 {
+ if err := requestGrpc(CMD_POLICY+"_"+CMD_NEIGHBOR, eArgs, nil); err != nil {
+ return err
+ }
+ return nil
+ } else if len(eArgs) >= 1 && !(eArgs[0] == "-h" || eArgs[0] == "--help" || eArgs[0] == CMD_ADD || eArgs[0] == CMD_DEL) {
+ if len(eArgs) != 1 {
+ return fmt.Errorf("Argument can not be entered: %s", eArgs[1:])
+ }
+ if err := requestGrpc(CMD_POLICY+"_"+CMD_NEIGHBOR, eArgs, nil); err != nil {
+ return err
+ }
+ return nil
+ }
+ parser := flags.NewParser(nil, flags.Default)
+ parser.Usage = "policy neighbor [<neighbor set name>],\n gobgp policy neighbor"
+ parser.AddCommand(CMD_ADD, "subcommand to add neighbor condition to policy", "", &PolicyNeighborAddCommand{})
+ parser.AddCommand(CMD_DEL, "subcommand to delete neighbor condition from policy", "", &PolicyNeighborDelCommand{})
+ if _, err := parser.ParseArgs(eArgs); err != nil {
+ os.Exit(1)
+ }
+ return nil
+}
+
+type PolicyNeighborAddCommand struct{}
+
+func parseNeighborSet(eArgs []string) (*api.NeighborSet, error) {
+ address := net.ParseIP(eArgs[1])
+ if address.To4() == nil {
+ if address.To16() == nil {
+ return nil, fmt.Errorf("invalid address: %s\nplease enter ipv4 or ipv6 format", eArgs[1])
+ }
+ }
+
+ neighbor := &api.Neighbor{
+ Address: address.String(),
+ }
+ neighborList := []*api.Neighbor{neighbor}
+ neighborSet := &api.NeighborSet{
+ NeighborSetName: eArgs[0],
+ NeighborList: neighborList,
+ }
+ return neighborSet, nil
+}
+
+func modPolicyNeighbor(modtype string, eArgs []string) error {
+ neighborSet := &api.NeighborSet{}
+ var e error
+ var operation api.Operation
+
+ switch modtype {
+ case CMD_ADD:
+ if len(eArgs) < 2 {
+ return fmt.Errorf("usage: policy neighbor add <neighbor set name> <address>")
+ }
+ if neighborSet, e = parseNeighborSet(eArgs); e != nil {
+ return e
+ }
+ operation = api.Operation_ADD
+ case CMD_DEL:
+ if len(eArgs) == 0 {
+ operation = api.Operation_DEL_ALL
+ } else if len(eArgs) == 1 {
+ neighborSet = &api.NeighborSet{
+ NeighborSetName: eArgs[0],
+ NeighborList: nil,
+ }
+ operation = api.Operation_DEL
+ } else {
+ if neighborSet, e = parseNeighborSet(eArgs); e != nil {
+ return e
+ }
+ operation = api.Operation_DEL
+ }
+ }
+
+ arg := &api.PolicyArguments{
+ Resource: api.Resource_POLICY_NEIGHBOR,
+ Operation: operation,
+ NeighborSet: neighborSet,
+ }
+ stream, err := client.ModPolicyNeighbor(context.Background())
+ if err != nil {
+ return err
+ }
+ err = stream.Send(arg)
+ if err != nil {
+ return err
+ }
+ stream.CloseSend()
+
+ res, e := stream.Recv()
+ if e != nil {
+ return e
+ }
+ if res.Code != api.Error_SUCCESS {
+ return fmt.Errorf("error: code: %d, msg: %s", res.Code, res.Msg)
+ }
+ return nil
+}
+
+func (x *PolicyNeighborAddCommand) Execute(args []string) error {
+ eArgs := extractArgs(CMD_ADD)
+ if len(eArgs) == 0 || len(eArgs) > 2 {
+ return fmt.Errorf("usage: policy neighbor add <neighbor set name> <address>")
+ } else {
+ if err := requestGrpc(CMD_POLICY+"_"+CMD_NEIGHBOR+"_"+CMD_ADD, eArgs, nil); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+type PolicyNeighborDelCommand struct{}
+
+func (x *PolicyNeighborDelCommand) Execute(args []string) error {
+ eArgs := extractArgs(CMD_DEL)
+ if len(eArgs) > 3 {
+ return fmt.Errorf("usage: policy neighbor del [<neighbor set name> [<address>]]")
+ } else if len(eArgs) > 0 && !(eArgs[0] == "-h" || eArgs[0] == "--help" || eArgs[0] == "all") {
+ if err := requestGrpc(CMD_POLICY+"_"+CMD_NEIGHBOR+"_"+CMD_DEL, eArgs, nil); err != nil {
+ return err
+ }
+ return nil
+ }
+ parser := flags.NewParser(nil, flags.Default)
+ parser.Usage = "policy neighbor del [<neighbor set name> [<address>]],\n gobgp policy neighbor del"
+ parser.AddCommand(CMD_ALL, "subcommand to delete all neighbor condition from policy", "", &PolicyNeighborDelAllCommand{})
+ if _, err := parser.ParseArgs(eArgs); err != nil {
+ os.Exit(1)
+ }
+ return nil
+}
+
+type PolicyNeighborDelAllCommand struct{}
+
+func (x *PolicyNeighborDelAllCommand) Execute(args []string) error {
+ eArgs := extractArgs(CMD_ALL)
+ if len(eArgs) > 0 {
+ return fmt.Errorf("Argument can not be entered: %s", eArgs)
+ }
+ if err := requestGrpc(CMD_POLICY+"_"+CMD_NEIGHBOR+"_"+CMD_DEL, eArgs, nil); err != nil {
+ return err
+ }
+ return nil
+}
+
+type PolicyRoutePolicyCommand struct{}
+
+func showPolicyStatement(head string, pd *api.PolicyDefinition) {
+ for _, st := range pd.StatementList {
+ fmt.Printf("%s StatementName %s:\n", head, st.StatementNeme)
+ fmt.Printf("%s Conditions:\n", head)
+ prefixSet := st.Conditions.MatchPrefixSet
+ fmt.Printf("%s PrefixSet: %s ", head, prefixSet.PrefixSetName)
+ if len(prefixSet.PrefixList) != 0 {
+ nameFormat := "%-" + fmt.Sprint(len(prefixSet.PrefixSetName)+2) + "s"
+ _, format := formatPolicyPrefix([]*api.PrefixSet{st.Conditions.MatchPrefixSet})
+ for i, prefix := range prefixSet.PrefixList {
+ p := fmt.Sprintf("%s/%d", prefix.Address, prefix.MaskLength)
+ if i != 0 {
+ fmt.Printf("%s ", head)
+ fmt.Printf(nameFormat, "")
+ }
+ fmt.Printf(format, p, prefix.MaskLengthRange)
+ }
+ } else {
+ fmt.Print("\n")
+ }
+ neighborSet := st.Conditions.MatchNeighborSet
+ fmt.Printf("%s NeighborSet: %s ", head, neighborSet.NeighborSetName)
+ if len(neighborSet.NeighborList) != 0 {
+ nameFormat := "%-" + fmt.Sprint(len(neighborSet.NeighborSetName)+2) + "s"
+ for i, neighbor := range neighborSet.NeighborList {
+ if i != 0 {
+ fmt.Printf("%s ", head)
+ fmt.Printf(nameFormat, "")
+ }
+ fmt.Println(neighbor.Address)
+ }
+ } else {
+ fmt.Print("\n")
+ }
+ asPathLentgh := st.Conditions.MatchAsPathLength
+ fmt.Printf("%s AsPathLength: %s %s\n", head, asPathLentgh.Operator, asPathLentgh.Value)
+ fmt.Printf("%s MatchOption: %s\n", head, st.Conditions.MatchSetOptions)
+ fmt.Printf("%s Actions:\n", head)
+ fmt.Printf("%s %s\n", head, st.Actions.RouteAction)
+ }
+
+}
+
+func showPolicyRoutePolicies() error {
+ arg := &api.PolicyArguments{
+ Resource: api.Resource_POLICY_ROUTEPOLICY,
+ }
+ stream, e := client.GetPolicyRoutePolicies(context.Background(), arg)
+ if e != nil {
+ fmt.Println(e)
+ return e
+ }
+ m := policyDefinitions{}
+ for {
+ n, e := stream.Recv()
+ if e == io.EOF {
+ break
+ } else if e != nil {
+ return e
+ }
+ m = append(m, n)
+ }
+
+ if globalOpts.Json {
+ j, _ := json.Marshal(m)
+ fmt.Println(string(j))
+ return nil
+ }
+ if globalOpts.Quiet {
+ for _, p := range m {
+ fmt.Println(p.PolicyDefinitionName)
+ }
+ return nil
+ }
+ sort.Sort(m)
+
+ for _, pd := range m {
+ fmt.Printf("PolicyName %s:\n", pd.PolicyDefinitionName)
+ showPolicyStatement("", pd)
+ }
+ return nil
+}
+
+func showPolicyRoutePolicy(args []string) error {
+ arg := &api.PolicyArguments{
+ Resource: api.Resource_POLICY_ROUTEPOLICY,
+ Name: args[0],
+ }
+ pd, e := client.GetPolicyRoutePolicy(context.Background(), arg)
+ if e != nil {
+ return e
+ }
+
+ if globalOpts.Json {
+ j, _ := json.Marshal(pd)
+ fmt.Println(string(j))
+ return nil
+ }
+
+ if globalOpts.Quiet {
+ for _, st := range pd.StatementList {
+ fmt.Println(st.StatementNeme)
+ }
+ return nil
+ }
+
+ fmt.Printf("PolicyName %s:\n", pd.PolicyDefinitionName)
+ showPolicyStatement("", pd)
+ return nil
+}
+
+func (x *PolicyRoutePolicyCommand) Execute(args []string) error {
+ eArgs := extractArgs(CMD_ROUTEPOLICY)
+ if len(eArgs) == 0 {
+ if err := requestGrpc(CMD_POLICY+"_"+CMD_ROUTEPOLICY, eArgs, nil); err != nil {
+ return err
+ }
+ return nil
+ } else if len(eArgs) >= 1 && !(eArgs[0] == "-h" || eArgs[0] == "--help" || eArgs[0] == CMD_ADD || eArgs[0] == CMD_DEL) {
+ if len(eArgs) != 1 {
+ return fmt.Errorf("Argument can not be entered: %s", eArgs[1:])
+ }
+ if err := requestGrpc(CMD_POLICY+"_"+CMD_ROUTEPOLICY, eArgs, nil); err != nil {
+ return err
+ }
+ return nil
+ }
+ parser := flags.NewParser(nil, flags.Default)
+ parser.Usage = "policy routepolicy [<policy name>],\n gobgp policy routepolicy"
+ parser.AddCommand(CMD_ADD, "subcommand to add routing policy", "", &PolicyRoutePolicyAddCommand{})
+ parser.AddCommand(CMD_DEL, "subcommand to delete routing policy", "", &PolicyRoutePolicyDelCommand{})
+ if _, err := parser.ParseArgs(eArgs); err != nil {
+ os.Exit(1)
+ }
+ return nil
+}
+
+type PolicyRoutePolicyAddCommand struct{}
+
+func parseConditions() (*api.Conditions, error) {
+ conditions := &api.Conditions{}
+ if conditionOpts.Prefix != "" {
+ conditions.MatchPrefixSet = &api.PrefixSet{
+ PrefixSetName: conditionOpts.Prefix,
+ }
+ }
+ if conditionOpts.Neighbor != "" {
+ conditions.MatchNeighborSet = &api.NeighborSet{
+ NeighborSetName: conditionOpts.Neighbor,
+ }
+ }
+ if conditionOpts.AsPathLength != "" {
+ asPathLen := conditionOpts.AsPathLength
+ idx := strings.Index(asPathLen, ",")
+ if idx == -1 {
+ return nil, fmt.Errorf("invalid as path length: %s\nPlease enter the <value>,<operator>", asPathLen)
+ }
+ operator := asPathLen[:idx]
+ value := asPathLen[idx+1:]
+ if _, err := strconv.ParseUint(value, 10, 32); err != nil {
+ return nil, fmt.Errorf("invalid as path length: %s\nPlease enter a numeric", value)
+ }
+ conditions.MatchAsPathLength = &api.AsPathLength{
+ Value: value,
+ Operator: operator,
+ }
+ }
+ if conditionOpts.Option != "" {
+ optionUpper := strings.ToUpper(conditionOpts.Option)
+ var option string
+ switch optionUpper {
+ case policy.OPTIONS_ANY, policy.OPTIONS_ALL, policy.OPTIONS_INVERT:
+ option = optionUpper
+ default:
+ return nil, fmt.Errorf("invalid condition option: %s\nPlease enter the any or all or invert",
+ conditionOpts.Option)
+ }
+ conditions.MatchSetOptions = option
+ }
+ return conditions, nil
+}
+
+func parseActions() (*api.Actions, error) {
+ actions := &api.Actions{}
+ if actionOpts.RouteAction != "" {
+ routeAction, e := parseRouteAction(actionOpts.RouteAction)
+ if e != nil {
+ return nil, e
+ }
+ actions.RouteAction = routeAction
+ }
+ return actions, nil
+}
+
+func modPolicyRoutePolicy(modtype string, stmtType string, eArgs []string, request interface{}) error {
+ var e error
+ var operation api.Operation
+ pd := &api.PolicyDefinition{}
+ switch modtype {
+ case CMD_ADD:
+ stmt := &api.Statement{}
+ switch stmtType {
+ case CMD_CONDITIONS:
+ conditions, err := parseConditions()
+ if err != nil {
+ return err
+ }
+ stmt.StatementNeme = request.(*PolicyRoutePolicyAddConditionsCommand).statementName
+ stmt.Conditions = conditions
+ pd.PolicyDefinitionName = request.(*PolicyRoutePolicyAddConditionsCommand).policyName
+ case CMD_ACTIONS:
+ actions, err := parseActions()
+ if err != nil {
+ return err
+ }
+ stmt.StatementNeme = request.(*PolicyRoutePolicyAddActionsCommand).statementName
+ stmt.Actions = actions
+ pd.PolicyDefinitionName = request.(*PolicyRoutePolicyAddActionsCommand).policyName
+ }
+ pd.StatementList = []*api.Statement{stmt}
+ operation = api.Operation_ADD
+
+ case CMD_DEL:
+ if len(eArgs) == 0 {
+ operation = api.Operation_DEL_ALL
+ } else if len(eArgs) == 1 {
+ pd.PolicyDefinitionName = eArgs[0]
+ operation = api.Operation_DEL
+ } else if len(eArgs) == 2 {
+ stmt := &api.Statement{
+ StatementNeme: eArgs[1],
+ }
+ pd.PolicyDefinitionName = eArgs[0]
+ pd.StatementList = []*api.Statement{stmt}
+ operation = api.Operation_DEL
+ }
+ }
+ arg := &api.PolicyArguments{
+ Resource: api.Resource_POLICY_ROUTEPOLICY,
+ Operation: operation,
+ PolicyDifinition: pd,
+ }
+ stream, err := client.ModPolicyNeighbor(context.Background())
+ if err != nil {
+ return err
+ }
+ err = stream.Send(arg)
+ if err != nil {
+ return err
+ }
+ stream.CloseSend()
+
+ res, e := stream.Recv()
+ if e != nil {
+ return e
+ }
+ if res.Code != api.Error_SUCCESS {
+ return fmt.Errorf("error: code: %d, msg: %s", res.Code, res.Msg)
+ }
+ return nil
+}
+
+func (x *PolicyRoutePolicyAddCommand) Execute(args []string) error {
+ eArgs := extractArgs(CMD_ADD)
+ parser := flags.NewParser(nil, flags.Default)
+ if len(eArgs) < 2 {
+ return fmt.Errorf("usage: policy routepolicy add <routing policy name> <statement name>")
+ }
+ parser.Usage = "policy routepolicy add <routing policy name> <statement name>"
+ parser.AddCommand(CMD_CONDITIONS, "subcommand for routing policy conditions", "", NewPolicyRoutePolicyAddConditionsCommand(eArgs[0], eArgs[1]))
+ parser.AddCommand(CMD_ACTIONS, "subcommand for routing policy actions", "", NewPolicyRoutePolicyAddActionsCommand(eArgs[0], eArgs[1]))
+ if _, err := parser.ParseArgs(eArgs); err != nil {
+ os.Exit(1)
+ }
+ return nil
+}
+
+type PolicyRoutePolicyAddConditionsCommand struct {
+ policyName string
+ statementName string
+}
+
+func NewPolicyRoutePolicyAddConditionsCommand(pName string, sName string) *PolicyRoutePolicyAddConditionsCommand {
+ return &PolicyRoutePolicyAddConditionsCommand{
+ policyName: pName,
+ statementName: sName,
+ }
+}
+
+func (x *PolicyRoutePolicyAddConditionsCommand) Execute(args []string) error {
+ eArgs := extractArgs(CMD_CONDITIONS)
+ parser := flags.NewParser(&conditionOpts, flags.Default)
+ parser.Usage = "policy routepolicy add <routing policy name> <statement name> conditions [OPTIONS]"
+ if _, err := parser.ParseArgs(eArgs); err != nil {
+ os.Exit(1)
+ }
+ if len(eArgs) == 0 {
+ return fmt.Errorf("usage: policy routepolicy add <routing policy name> <statement name> conditions [OPTIONS]")
+ } else if !(eArgs[0] == "-h" || eArgs[0] == "--help") {
+ if err := requestGrpc(CMD_POLICY+"_"+CMD_ROUTEPOLICY+"_"+CMD_ADD+"_"+CMD_CONDITIONS, eArgs, x); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+type PolicyRoutePolicyAddActionsCommand struct {
+ policyName string
+ statementName string
+}
+
+func NewPolicyRoutePolicyAddActionsCommand(pName string, sName string) *PolicyRoutePolicyAddActionsCommand {
+ return &PolicyRoutePolicyAddActionsCommand{
+ policyName: pName,
+ statementName: sName,
+ }
+}
+
+func (x *PolicyRoutePolicyAddActionsCommand) Execute(args []string) error {
+ eArgs := extractArgs(CMD_ACTIONS)
+ parser := flags.NewParser(&actionOpts, flags.Default)
+ parser.Usage = "policy routepolicy add <routing policy name> <statement name> actions [OPTIONS]"
+ if _, err := parser.ParseArgs(eArgs); err != nil {
+ os.Exit(1)
+ }
+ if len(eArgs) == 0 {
+ return fmt.Errorf("usage: policy routepolicy add <routing policy name> <statement name> actions [OPTIONS]")
+ } else if !(eArgs[0] == "-h" || eArgs[0] == "--help") {
+ if err := requestGrpc(CMD_POLICY+"_"+CMD_ROUTEPOLICY+"_"+CMD_ADD+"_"+CMD_ACTIONS, eArgs, x); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+type PolicyRoutePolicyDelCommand struct{}
+
+func (x *PolicyRoutePolicyDelCommand) Execute(args []string) error {
+ eArgs := extractArgs(CMD_DEL)
+ if len(eArgs) > 0 && !(eArgs[0] == "-h" || eArgs[0] == "--help" || eArgs[0] == "all") {
+ if len(eArgs) > 2 {
+ return fmt.Errorf("Argument can not be entered: %s", eArgs[2:])
+ }
+ if err := requestGrpc(CMD_POLICY+"_"+CMD_ROUTEPOLICY+"_"+CMD_DEL, eArgs, nil); err != nil {
+ return err
+ }
+ return nil
+ }
+ parser := flags.NewParser(nil, flags.Default)
+ parser.Usage = "policy routepolicy del <routing policy name> [<statement name>],\n gobgp policy routepolicy del"
+ parser.AddCommand(CMD_ALL, "subcommand to delete all routing policy", "", &PolicyRoutePolicyDelAllCommand{})
+ if _, err := parser.ParseArgs(eArgs); err != nil {
+ os.Exit(1)
+ }
+ return nil
+}
+
+type PolicyRoutePolicyDelAllCommand struct{}
+
+func (x *PolicyRoutePolicyDelAllCommand) Execute(args []string) error {
+ eArgs := extractArgs(CMD_ALL)
+ if len(eArgs) > 0 {
+ return fmt.Errorf("Argument can not be entered: %s", eArgs)
+ }
+ if err := requestGrpc(CMD_POLICY+"_"+CMD_ROUTEPOLICY+"_"+CMD_DEL, eArgs, nil); err != nil {
+ return err
+ }
+ return nil
+}