cli: change structure of the source file

split gobgp/main.go to main.go,global.go,neighbor.go,policy.go and common.go.
This commit is contained in:
Naoto Hanaue
2015-05-28 20:28:28 +09:00
committed by FUJITA Tomonori
parent 95e5387919
commit 7ea3a18ef5
5 changed files with 2397 additions and 2293 deletions
+366
View File
@@ -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
}
+280
View File
@@ -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
}
+1 -2293
View File
File diff suppressed because it is too large Load Diff
+793
View File
@@ -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
}
+957
View File
@@ -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
}