mirror of
https://github.com/osrg/gobgp.git
synced 2024-05-11 05:55:10 +00:00
cli: support defined-set configuration
prefix-set modification gobgp policy prefix add p0 10.0.0.0/24 10..15 neighbor-set modification gobgp policy neighbor add n0 10.0.0.1 as-path-set modification gobgp policy aspath add a0 '^100_200_300$' community-set modification gobgp policy community add c0 100:100 ext-community-set modification gobgp policy community add e0 rt:100:100 Signed-off-by: ISHIDA Wataru <[email protected]>
This commit is contained in:
committed by
FUJITA Tomonori
parent
f61709a2a6
commit
16234ccbb3
@@ -35,6 +35,7 @@ const (
|
||||
CMD_ADD = "add"
|
||||
CMD_DEL = "del"
|
||||
CMD_ALL = "all"
|
||||
CMD_SET = "set"
|
||||
CMD_LOCAL = "local"
|
||||
CMD_ADJ_IN = "adj-in"
|
||||
CMD_ADJ_OUT = "adj-out"
|
||||
|
||||
+239
-620
@@ -33,6 +33,9 @@ import (
|
||||
)
|
||||
|
||||
func formatPolicyPrefix(head bool, indent int, psl []*api.DefinedSet) string {
|
||||
if len(psl) == 0 {
|
||||
return "Nothing defined yet\n"
|
||||
}
|
||||
buff := bytes.NewBuffer(make([]byte, 0, 64))
|
||||
sIndent := strings.Repeat(" ", indent)
|
||||
maxNameLen := 0
|
||||
@@ -49,20 +52,24 @@ func formatPolicyPrefix(head bool, indent int, psl []*api.DefinedSet) string {
|
||||
}
|
||||
|
||||
if head {
|
||||
if len("Name") > maxNameLen {
|
||||
maxNameLen = len("Name")
|
||||
if len("NAME") > maxNameLen {
|
||||
maxNameLen = len("NAME")
|
||||
}
|
||||
if len("Prefix") > maxPrefixLen {
|
||||
maxPrefixLen = len("Prefix")
|
||||
if len("PREFIX") > maxPrefixLen {
|
||||
maxPrefixLen = len("PREFIX")
|
||||
}
|
||||
}
|
||||
|
||||
format := fmt.Sprintf("%%-%ds %%-%ds ", maxNameLen, maxPrefixLen)
|
||||
if head {
|
||||
buff.WriteString(fmt.Sprintf(format, "Name", "Prefix"))
|
||||
buff.WriteString(fmt.Sprintf(format, "NAME", "PREFIX"))
|
||||
buff.WriteString("MaskLengthRange\n")
|
||||
}
|
||||
for _, ps := range psl {
|
||||
if len(ps.Prefixes) == 0 {
|
||||
buff.WriteString(fmt.Sprintf(format, ps.Name, ""))
|
||||
buff.WriteString("\n")
|
||||
}
|
||||
for i, p := range ps.Prefixes {
|
||||
if i == 0 {
|
||||
buff.WriteString(fmt.Sprintf(format, ps.Name, p.IpPrefix))
|
||||
@@ -77,168 +84,46 @@ func formatPolicyPrefix(head bool, indent int, psl []*api.DefinedSet) string {
|
||||
return buff.String()
|
||||
}
|
||||
|
||||
func formatPolicyNeighbor(head bool, indent int, nsl []*api.DefinedSet) string {
|
||||
func formatDefinedSet(head bool, typ string, indent int, list []*api.DefinedSet) string {
|
||||
if len(list) == 0 {
|
||||
return "Nothing defined yet\n"
|
||||
}
|
||||
buff := bytes.NewBuffer(make([]byte, 0, 64))
|
||||
sIndent := strings.Repeat(" ", indent)
|
||||
maxNameLen := 0
|
||||
maxAddressLen := 0
|
||||
for _, ns := range nsl {
|
||||
if len(ns.Name) > maxNameLen {
|
||||
maxNameLen = len(ns.Name)
|
||||
maxValueLen := 0
|
||||
for _, s := range list {
|
||||
if len(s.Name) > maxNameLen {
|
||||
maxNameLen = len(s.Name)
|
||||
}
|
||||
for _, n := range ns.List {
|
||||
if len(n) > maxAddressLen {
|
||||
maxAddressLen = len(n)
|
||||
for _, x := range s.List {
|
||||
if len(x) > maxValueLen {
|
||||
maxValueLen = len(x)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if head {
|
||||
if len("Name") > maxNameLen {
|
||||
maxNameLen = len("Name")
|
||||
if len("NAME") > maxNameLen {
|
||||
maxNameLen = len("NAME")
|
||||
}
|
||||
if len("Address") > maxAddressLen {
|
||||
maxAddressLen = len("Address")
|
||||
if len(typ) > maxValueLen {
|
||||
maxValueLen = len(typ)
|
||||
}
|
||||
}
|
||||
|
||||
format := "%-" + fmt.Sprint(maxNameLen) + "s %-" + fmt.Sprint(maxAddressLen) + "s\n"
|
||||
format := fmt.Sprintf("%%-%ds %%-%ds\n", maxNameLen, maxValueLen)
|
||||
if head {
|
||||
buff.WriteString(fmt.Sprintf(format, "Name", "Address"))
|
||||
buff.WriteString(fmt.Sprintf(format, "NAME", typ))
|
||||
}
|
||||
for _, ns := range nsl {
|
||||
for i, n := range ns.List {
|
||||
for _, s := range list {
|
||||
if len(s.List) == 0 {
|
||||
buff.WriteString(fmt.Sprintf(format, s.Name, ""))
|
||||
}
|
||||
for i, x := range s.List {
|
||||
if i == 0 {
|
||||
buff.WriteString(fmt.Sprintf(format, ns.Name, n))
|
||||
buff.WriteString(fmt.Sprintf(format, s.Name, x))
|
||||
} else {
|
||||
buff.WriteString(fmt.Sprintf(sIndent))
|
||||
buff.WriteString(fmt.Sprintf(format, "", n))
|
||||
}
|
||||
}
|
||||
}
|
||||
return buff.String()
|
||||
}
|
||||
|
||||
func formatPolicyAsPath(haed bool, indent int, apsl []*api.DefinedSet) string {
|
||||
buff := bytes.NewBuffer(make([]byte, 0, 64))
|
||||
sIndent := strings.Repeat(" ", indent)
|
||||
maxNameLen := 0
|
||||
maxPathLen := 0
|
||||
for _, aps := range apsl {
|
||||
if len(aps.Name) > maxNameLen {
|
||||
maxNameLen = len(aps.Name)
|
||||
}
|
||||
for _, m := range aps.List {
|
||||
if len(m) > maxPathLen {
|
||||
maxPathLen = len(m)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if haed {
|
||||
if len("Name") > maxNameLen {
|
||||
maxNameLen = len("Name")
|
||||
}
|
||||
if len("AsPath") > maxPathLen {
|
||||
maxPathLen = len("AsPath")
|
||||
}
|
||||
}
|
||||
|
||||
format := "%-" + fmt.Sprint(maxNameLen) + "s %-" + fmt.Sprint(maxPathLen) + "s\n"
|
||||
if haed {
|
||||
buff.WriteString(fmt.Sprintf(format, "Name", "AsPath"))
|
||||
}
|
||||
for _, aps := range apsl {
|
||||
for i, a := range aps.List {
|
||||
if i == 0 {
|
||||
buff.WriteString(fmt.Sprintf(format, aps.Name, a))
|
||||
} else {
|
||||
buff.WriteString(fmt.Sprintf(sIndent))
|
||||
buff.WriteString(fmt.Sprintf(format, "", a))
|
||||
}
|
||||
}
|
||||
}
|
||||
return buff.String()
|
||||
}
|
||||
|
||||
func formatPolicyCommunity(head bool, indent int, csl []*api.DefinedSet) string {
|
||||
buff := bytes.NewBuffer(make([]byte, 0, 64))
|
||||
sIndent := strings.Repeat(" ", indent)
|
||||
maxNameLen := 0
|
||||
maxCommunityLen := 0
|
||||
for _, cs := range csl {
|
||||
if len(cs.Name) > maxNameLen {
|
||||
maxNameLen = len(cs.Name)
|
||||
}
|
||||
for _, m := range cs.List {
|
||||
if len(m) > maxCommunityLen {
|
||||
maxCommunityLen = len(m)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if head {
|
||||
if len("Name") > maxNameLen {
|
||||
maxNameLen = len("Name")
|
||||
}
|
||||
if len("Community") > maxCommunityLen {
|
||||
maxCommunityLen = len("Community")
|
||||
}
|
||||
}
|
||||
|
||||
format := "%-" + fmt.Sprint(maxNameLen) + "s %-" + fmt.Sprint(maxCommunityLen) + "s\n"
|
||||
if head {
|
||||
buff.WriteString(fmt.Sprintf(format, "Name", "Community"))
|
||||
}
|
||||
for _, cs := range csl {
|
||||
for i, c := range cs.List {
|
||||
if i == 0 {
|
||||
buff.WriteString(fmt.Sprintf(format, cs.Name, c))
|
||||
} else {
|
||||
buff.WriteString(fmt.Sprintf(sIndent))
|
||||
buff.WriteString(fmt.Sprintf(format, "", c))
|
||||
}
|
||||
}
|
||||
}
|
||||
return buff.String()
|
||||
}
|
||||
|
||||
func formatPolicyExtCommunity(head bool, indent int, ecsl []*api.DefinedSet) string {
|
||||
buff := bytes.NewBuffer(make([]byte, 0, 64))
|
||||
sIndent := strings.Repeat(" ", indent)
|
||||
maxNameLen := 0
|
||||
maxCommunityLen := 0
|
||||
for _, es := range ecsl {
|
||||
if len(es.Name) > maxNameLen {
|
||||
maxNameLen = len(es.Name)
|
||||
}
|
||||
for _, m := range es.List {
|
||||
if len(m) > maxCommunityLen {
|
||||
maxCommunityLen = len(m)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if head {
|
||||
if len("Name") > maxNameLen {
|
||||
maxNameLen = len("Name")
|
||||
}
|
||||
if len("ExtCommunity") > maxCommunityLen {
|
||||
maxCommunityLen = len("ExtCommunity")
|
||||
}
|
||||
}
|
||||
|
||||
format := "%-" + fmt.Sprint(maxNameLen) + "s %-" + fmt.Sprint(maxCommunityLen) + "s\n"
|
||||
if head {
|
||||
buff.WriteString(fmt.Sprintf(format, "Name", "ExtCommunity"))
|
||||
}
|
||||
for _, ecs := range ecsl {
|
||||
for i, ec := range ecs.List {
|
||||
if i == 0 {
|
||||
buff.WriteString(fmt.Sprintf(format, ecs.Name, ec))
|
||||
} else {
|
||||
buff.WriteString(fmt.Sprintf(sIndent))
|
||||
buff.WriteString(fmt.Sprintf(format, "", ec))
|
||||
buff.WriteString(fmt.Sprintf(format, "", x))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -273,6 +158,9 @@ func show(v string, args []string) error {
|
||||
}
|
||||
m = append(m, p)
|
||||
} else {
|
||||
arg := &api.DefinedSet{
|
||||
Type: int32(typ),
|
||||
}
|
||||
stream, e := client.GetDefinedSets(context.Background(), arg)
|
||||
if e != nil {
|
||||
return e
|
||||
@@ -313,458 +201,202 @@ func show(v string, args []string) error {
|
||||
case CMD_PREFIX:
|
||||
output = formatPolicyPrefix(true, 0, m)
|
||||
case CMD_NEIGHBOR:
|
||||
output = formatPolicyNeighbor(true, 0, m)
|
||||
output = formatDefinedSet(true, "ADDRESS", 0, m)
|
||||
case CMD_ASPATH:
|
||||
output = formatPolicyAsPath(true, 0, m)
|
||||
output = formatDefinedSet(true, "AS-PATH", 0, m)
|
||||
case CMD_COMMUNITY:
|
||||
output = formatPolicyCommunity(true, 0, m)
|
||||
output = formatDefinedSet(true, "COMMUNITY", 0, m)
|
||||
case CMD_EXTCOMMUNITY:
|
||||
output = formatPolicyExtCommunity(true, 0, m)
|
||||
output = formatDefinedSet(true, "EXT-COMMUNITY", 0, m)
|
||||
}
|
||||
fmt.Print(output)
|
||||
return nil
|
||||
}
|
||||
|
||||
func parsePrefixSet(eArgs []string) (*api.DefinedSet, 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])
|
||||
func parsePrefixSet(args []string) (*api.DefinedSet, error) {
|
||||
if len(args) < 1 {
|
||||
return nil, fmt.Errorf("empty neighbor set name")
|
||||
}
|
||||
prefix := &api.Prefix{
|
||||
IpPrefix: eArgs[1],
|
||||
}
|
||||
|
||||
if len(eArgs) == 3 {
|
||||
maskRange := eArgs[2]
|
||||
idx := strings.Index(maskRange, "..")
|
||||
if idx == -1 {
|
||||
return nil, fmt.Errorf("invalid mask length range: %s", maskRange)
|
||||
name := args[0]
|
||||
args = args[1:]
|
||||
var list []*api.Prefix
|
||||
if len(args) > 0 {
|
||||
_, ipNet, err := net.ParseCIDR(args[0])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid prefix: %s\nplease enter ipv4 or ipv6 format", args[1])
|
||||
}
|
||||
var min, max int
|
||||
var e error
|
||||
if idx != 0 {
|
||||
if min, e = strconv.Atoi(maskRange[:idx]); e != nil {
|
||||
l, _ := ipNet.Mask.Size()
|
||||
prefix := &api.Prefix{
|
||||
IpPrefix: args[0],
|
||||
MaskLengthMin: uint32(l),
|
||||
MaskLengthMax: uint32(l),
|
||||
}
|
||||
if len(args) > 1 {
|
||||
maskRange := args[1]
|
||||
exp := regexp.MustCompile("(\\d+)\\.\\.(\\d+)")
|
||||
elems := exp.FindStringSubmatch(maskRange)
|
||||
if len(elems) != 3 {
|
||||
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 {
|
||||
// we've already checked the range is sane by regexp
|
||||
min, _ := strconv.Atoi(elems[1])
|
||||
max, _ := strconv.Atoi(elems[2])
|
||||
if min > max {
|
||||
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 ipv4 := ipNet.IP.To4(); ipv4 != nil {
|
||||
f := func(i int) bool {
|
||||
return i >= 0 && i <= 32
|
||||
}
|
||||
if !f(min) || !f(max) {
|
||||
return nil, fmt.Errorf("ipv4 mask length range outside scope :%s", maskRange)
|
||||
}
|
||||
} else {
|
||||
f := func(i int) bool {
|
||||
return i >= 0 && i <= 128
|
||||
}
|
||||
if !f(min) || !f(max) {
|
||||
return nil, fmt.Errorf("ipv6 mask length range outside scope :%s", maskRange)
|
||||
}
|
||||
}
|
||||
prefix.MaskLengthMin = uint32(min)
|
||||
prefix.MaskLengthMax = uint32(max)
|
||||
}
|
||||
if min >= max {
|
||||
return nil, fmt.Errorf("invalid mask length range: %s\nlarge value to the right from the left", maskRange)
|
||||
}
|
||||
prefix.MaskLengthMin = uint32(min)
|
||||
prefix.MaskLengthMax = uint32(max)
|
||||
list = []*api.Prefix{prefix}
|
||||
}
|
||||
prefixList := []*api.Prefix{prefix}
|
||||
return &api.DefinedSet{
|
||||
Type: int32(table.DEFINED_TYPE_PREFIX),
|
||||
Name: eArgs[0],
|
||||
Prefixes: prefixList,
|
||||
Name: name,
|
||||
Prefixes: list,
|
||||
}, nil
|
||||
}
|
||||
func modPolicy(resource api.Resource, op api.Operation, data interface{}) error {
|
||||
pd := &api.PolicyDefinition{}
|
||||
if resource != api.Resource_POLICY_ROUTEPOLICY {
|
||||
co := &api.Conditions{}
|
||||
switch resource {
|
||||
case api.Resource_POLICY_PREFIX:
|
||||
co.PrefixSet = data.(*api.PrefixSet)
|
||||
case api.Resource_POLICY_NEIGHBOR:
|
||||
co.NeighborSet = data.(*api.MatchSet)
|
||||
case api.Resource_POLICY_ASPATH:
|
||||
co.AsPathSet = data.(*api.MatchSet)
|
||||
case api.Resource_POLICY_COMMUNITY:
|
||||
co.CommunitySet = data.(*api.MatchSet)
|
||||
case api.Resource_POLICY_EXTCOMMUNITY:
|
||||
co.ExtCommunitySet = data.(*api.MatchSet)
|
||||
}
|
||||
pd.Statements = []*api.Statement{{Conditions: co}}
|
||||
} else {
|
||||
pd = data.(*api.PolicyDefinition)
|
||||
}
|
||||
arg := &api.PolicyArguments{
|
||||
Resource: resource,
|
||||
Operation: op,
|
||||
PolicyDefinition: pd,
|
||||
}
|
||||
stream, err := client.ModPolicyRoutePolicy(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
|
||||
func parseNeighborSet(args []string) (*api.DefinedSet, error) {
|
||||
if len(args) < 1 {
|
||||
return nil, fmt.Errorf("empty neighbor set name")
|
||||
}
|
||||
if res.Code != api.Error_SUCCESS {
|
||||
return fmt.Errorf("error: code: %d, msg: %s", res.Code, res.Msg)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func modPolicyPrefix(modtype string, eArgs []string) error {
|
||||
prefixSet := &api.DefinedSet{}
|
||||
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 {
|
||||
return fmt.Errorf("usage: policy prefix del <prefix set name> [<prefix> [<mask length renge>]]")
|
||||
} else if len(eArgs) == 1 {
|
||||
prefixSet = &api.DefinedSet{
|
||||
Name: eArgs[0],
|
||||
}
|
||||
} else {
|
||||
if prefixSet, e = parsePrefixSet(eArgs); e != nil {
|
||||
return e
|
||||
}
|
||||
}
|
||||
operation = api.Operation_DEL
|
||||
case CMD_ALL:
|
||||
if len(eArgs) > 0 {
|
||||
return fmt.Errorf("Argument can not be entered: %s", eArgs[0:])
|
||||
}
|
||||
operation = api.Operation_DEL_ALL
|
||||
default:
|
||||
return fmt.Errorf("invalid modType %s", modtype)
|
||||
}
|
||||
if e = modPolicy(api.Resource_POLICY_PREFIX, operation, prefixSet); e != nil {
|
||||
return e
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func showPolicyNeighbor(args []string) error {
|
||||
arg := &api.DefinedSet{
|
||||
Type: int32(table.DEFINED_TYPE_NEIGHBOR),
|
||||
Name: args[0],
|
||||
}
|
||||
ns, e := client.GetDefinedSet(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.List {
|
||||
fmt.Println(n)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
output := formatPolicyNeighbor(true, 0, []*api.DefinedSet{ns})
|
||||
fmt.Print(output)
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseNeighborSet(eArgs []string) (*api.DefinedSet, 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])
|
||||
name := args[0]
|
||||
args = args[1:]
|
||||
for _, arg := range args {
|
||||
address := net.ParseIP(arg)
|
||||
if address.To4() == nil && address.To16() == nil {
|
||||
return nil, fmt.Errorf("invalid address: %s\nplease enter ipv4 or ipv6 format", arg)
|
||||
}
|
||||
}
|
||||
|
||||
return &api.DefinedSet{
|
||||
Type: int32(table.DEFINED_TYPE_NEIGHBOR),
|
||||
Name: eArgs[0],
|
||||
List: []string{address.String()},
|
||||
Name: name,
|
||||
List: args,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func modPolicyNeighbor(modtype string, eArgs []string) error {
|
||||
neighborSet := &api.DefinedSet{}
|
||||
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 {
|
||||
return fmt.Errorf("usage: policy neighbor del <neighbor set name> [<address>]")
|
||||
} else if len(eArgs) == 1 {
|
||||
neighborSet = &api.DefinedSet{
|
||||
Name: eArgs[0],
|
||||
}
|
||||
} else {
|
||||
if neighborSet, e = parseNeighborSet(eArgs); e != nil {
|
||||
return e
|
||||
}
|
||||
}
|
||||
operation = api.Operation_DEL
|
||||
case CMD_ALL:
|
||||
if len(eArgs) > 0 {
|
||||
return fmt.Errorf("Argument can not be entered: %s", eArgs[0:])
|
||||
}
|
||||
operation = api.Operation_DEL_ALL
|
||||
default:
|
||||
return fmt.Errorf("invalid modType %s", modtype)
|
||||
func parseAsPathSet(args []string) (*api.DefinedSet, error) {
|
||||
if len(args) < 1 {
|
||||
return nil, fmt.Errorf("empty as-path set name")
|
||||
}
|
||||
if e = modPolicy(api.Resource_POLICY_NEIGHBOR, operation, neighborSet); e != nil {
|
||||
return e
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseAsPathSet(eArgs []string) (*api.DefinedSet, error) {
|
||||
as := eArgs[1]
|
||||
isTop := as[:1] == "^"
|
||||
if isTop {
|
||||
as = as[1:]
|
||||
}
|
||||
isEnd := as[len(as)-1:] == "$"
|
||||
if isEnd {
|
||||
as = as[:len(as)-1]
|
||||
}
|
||||
elems := strings.Split(as, "_")
|
||||
for _, el := range elems {
|
||||
if len(el) == 0 {
|
||||
return nil, fmt.Errorf("invalid aspath element: %s \ndo not enter a blank", eArgs[1])
|
||||
}
|
||||
_, err := regexp.Compile(el)
|
||||
name := args[0]
|
||||
args = args[1:]
|
||||
for _, arg := range args {
|
||||
_, err := regexp.Compile(arg)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid aspath element: %s \n"+
|
||||
"can not comple aspath values to regular expressions.", eArgs[1])
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return &api.DefinedSet{
|
||||
Name: eArgs[0],
|
||||
List: []string{eArgs[1]},
|
||||
Type: int32(table.DEFINED_TYPE_AS_PATH),
|
||||
Name: name,
|
||||
List: args,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func modPolicyAsPath(modtype string, eArgs []string) error {
|
||||
asPathSet := &api.DefinedSet{}
|
||||
var e error
|
||||
var operation api.Operation
|
||||
|
||||
switch modtype {
|
||||
case CMD_ADD:
|
||||
if len(eArgs) < 2 {
|
||||
return fmt.Errorf("usage: policy aspath add <aspath set name> <aspath>")
|
||||
}
|
||||
if asPathSet, e = parseAsPathSet(eArgs); e != nil {
|
||||
return e
|
||||
}
|
||||
operation = api.Operation_ADD
|
||||
case CMD_DEL:
|
||||
if len(eArgs) == 0 {
|
||||
return fmt.Errorf("usage: policy aspath del <aspath set name> [<aspath>]")
|
||||
} else if len(eArgs) == 1 {
|
||||
asPathSet = &api.DefinedSet{
|
||||
Name: eArgs[0],
|
||||
}
|
||||
} else {
|
||||
if asPathSet, e = parseAsPathSet(eArgs); e != nil {
|
||||
return e
|
||||
}
|
||||
}
|
||||
operation = api.Operation_DEL
|
||||
case CMD_ALL:
|
||||
if len(eArgs) > 0 {
|
||||
return fmt.Errorf("Argument can not be entered: %s", eArgs[0:])
|
||||
}
|
||||
operation = api.Operation_DEL_ALL
|
||||
default:
|
||||
return fmt.Errorf("invalid modType %s", modtype)
|
||||
func parseCommunitySet(args []string) (*api.DefinedSet, error) {
|
||||
if len(args) < 1 {
|
||||
return nil, fmt.Errorf("empty community set name")
|
||||
}
|
||||
if e = modPolicy(api.Resource_POLICY_ASPATH, operation, asPathSet); e != nil {
|
||||
return e
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkCommunityFormat(comStr string) bool {
|
||||
_, e := table.ParseCommunity(comStr)
|
||||
if e == nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func parseCommunitySet(eArgs []string) (*api.DefinedSet, error) {
|
||||
if !checkCommunityFormat(eArgs[1]) {
|
||||
if _, err := regexp.Compile(eArgs[1]); err != nil {
|
||||
return nil, fmt.Errorf("invalid community: %s\nplease enter community format", eArgs[1])
|
||||
name := args[0]
|
||||
args = args[1:]
|
||||
for _, arg := range args {
|
||||
if _, err := table.ParseCommunityRegexp(arg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
communitySet := &api.DefinedSet{
|
||||
Name: eArgs[0],
|
||||
List: []string{eArgs[1]},
|
||||
}
|
||||
return communitySet, nil
|
||||
}
|
||||
|
||||
func modPolicyCommunity(modtype string, eArgs []string) error {
|
||||
communitySet := &api.DefinedSet{}
|
||||
var e error
|
||||
var operation api.Operation
|
||||
|
||||
switch modtype {
|
||||
case CMD_ADD:
|
||||
if len(eArgs) < 2 {
|
||||
return fmt.Errorf("usage: policy community add <community set name> <community>")
|
||||
}
|
||||
if communitySet, e = parseCommunitySet(eArgs); e != nil {
|
||||
return e
|
||||
}
|
||||
operation = api.Operation_ADD
|
||||
case CMD_DEL:
|
||||
if len(eArgs) == 0 {
|
||||
return fmt.Errorf("usage: policy community add <community set name> [<community>]")
|
||||
} else if len(eArgs) == 1 {
|
||||
communitySet = &api.DefinedSet{
|
||||
Name: eArgs[0],
|
||||
}
|
||||
} else {
|
||||
if communitySet, e = parseCommunitySet(eArgs); e != nil {
|
||||
return e
|
||||
}
|
||||
}
|
||||
operation = api.Operation_DEL
|
||||
case CMD_ALL:
|
||||
if len(eArgs) > 0 {
|
||||
return fmt.Errorf("Argument can not be entered: %s", eArgs[0:])
|
||||
}
|
||||
operation = api.Operation_DEL_ALL
|
||||
default:
|
||||
return fmt.Errorf("invalid modType %s", modtype)
|
||||
}
|
||||
if e = modPolicy(api.Resource_POLICY_COMMUNITY, operation, communitySet); e != nil {
|
||||
return e
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkExtCommunityFormat(eComStr string) bool {
|
||||
// extended community regexp
|
||||
checkSubType := func(eComStr string) (bool, string) {
|
||||
regSubType, _ := regexp.Compile("^(RT|SoO):(.*)$")
|
||||
if regSubType.MatchString(eComStr) {
|
||||
regResult := regSubType.FindStringSubmatch(eComStr)
|
||||
return true, regResult[2]
|
||||
}
|
||||
return false, ""
|
||||
}
|
||||
checkValue := func(eComVal string) (bool, string) {
|
||||
regVal, _ := regexp.Compile("^([0-9\\.]+):([0-9]+)$")
|
||||
if regVal.MatchString(eComVal) {
|
||||
regResult := regVal.FindStringSubmatch(eComVal)
|
||||
return true, regResult[1]
|
||||
}
|
||||
return false, ""
|
||||
}
|
||||
checkElem := func(gAdmin string) bool {
|
||||
addr := net.ParseIP(gAdmin)
|
||||
if addr.To4() != nil {
|
||||
return true
|
||||
}
|
||||
regAs, _ := regexp.Compile("^([0-9]+)$")
|
||||
regAs4, _ := regexp.Compile("^([0-9]+).([0-9]+)$")
|
||||
if regAs.MatchString(gAdmin) || regAs4.MatchString(gAdmin) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
if subTypeOk, eComVal := checkSubType(eComStr); subTypeOk {
|
||||
if valOk, gAdmin := checkValue(eComVal); valOk {
|
||||
if checkElem(gAdmin) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
_, err := regexp.Compile(eComVal)
|
||||
if err == nil {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func parseExtCommunitySet(eArgs []string) (*api.DefinedSet, error) {
|
||||
if !checkExtCommunityFormat(eArgs[1]) {
|
||||
return nil, fmt.Errorf("invalid extended community: %s\nplease enter extended community format", eArgs[1])
|
||||
}
|
||||
return &api.DefinedSet{
|
||||
Name: eArgs[0],
|
||||
List: []string{eArgs[1]},
|
||||
Type: int32(table.DEFINED_TYPE_COMMUNITY),
|
||||
Name: name,
|
||||
List: args,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func modPolicyExtCommunity(modtype string, eArgs []string) error {
|
||||
extCommunitySet := &api.DefinedSet{}
|
||||
var e error
|
||||
var operation api.Operation
|
||||
func parseExtCommunitySet(args []string) (*api.DefinedSet, error) {
|
||||
if len(args) < 1 {
|
||||
return nil, fmt.Errorf("empty ext-community set name")
|
||||
}
|
||||
name := args[0]
|
||||
args = args[1:]
|
||||
for _, arg := range args {
|
||||
if _, _, err := table.ParseExtCommunityRegexp(arg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return &api.DefinedSet{
|
||||
Type: int32(table.DEFINED_TYPE_EXT_COMMUNITY),
|
||||
Name: name,
|
||||
List: args,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func parseDefinedSet(settype string, args []string) (*api.DefinedSet, error) {
|
||||
switch settype {
|
||||
case CMD_PREFIX:
|
||||
return parsePrefixSet(args)
|
||||
case CMD_NEIGHBOR:
|
||||
return parseNeighborSet(args)
|
||||
case CMD_ASPATH:
|
||||
return parseAsPathSet(args)
|
||||
case CMD_COMMUNITY:
|
||||
return parseCommunitySet(args)
|
||||
case CMD_EXTCOMMUNITY:
|
||||
return parseExtCommunitySet(args)
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid setype: %s", settype)
|
||||
}
|
||||
}
|
||||
|
||||
var modPolicyUsageFormat = map[string]string{
|
||||
CMD_PREFIX: "usage: policy prefix %s <name> [<prefix> [<mask range>]]",
|
||||
CMD_NEIGHBOR: "usage: policy neighbor %s <name> [<neighbor address>...]",
|
||||
CMD_ASPATH: "usage: policy aspath %s <name> [<regexp>...]",
|
||||
CMD_COMMUNITY: "usage: policy community %s <name> [<regexp>...]",
|
||||
CMD_EXTCOMMUNITY: "usage: policy extcommunity %s <name> [<regexp>...]",
|
||||
}
|
||||
|
||||
func mod(settype string, modtype string, args []string) error {
|
||||
var d *api.DefinedSet
|
||||
var err error
|
||||
if len(args) < 1 {
|
||||
return fmt.Errorf(modPolicyUsageFormat[settype], modtype)
|
||||
}
|
||||
if d, err = parseDefinedSet(settype, args); err != nil {
|
||||
return err
|
||||
}
|
||||
var op api.Operation
|
||||
switch modtype {
|
||||
case CMD_ADD:
|
||||
if len(eArgs) < 2 {
|
||||
return fmt.Errorf("usage: policy extcommunity add <community set name> <community>")
|
||||
}
|
||||
if extCommunitySet, e = parseExtCommunitySet(eArgs); e != nil {
|
||||
return e
|
||||
}
|
||||
operation = api.Operation_ADD
|
||||
op = api.Operation_ADD
|
||||
case CMD_DEL:
|
||||
if len(eArgs) == 0 {
|
||||
return fmt.Errorf("usage: policy extcommunity add <community set name> [<community>]")
|
||||
} else if len(eArgs) == 1 {
|
||||
extCommunitySet = &api.DefinedSet{
|
||||
Name: eArgs[0],
|
||||
}
|
||||
if len(args) < 2 {
|
||||
op = api.Operation_DEL_ALL
|
||||
} else {
|
||||
if extCommunitySet, e = parseExtCommunitySet(eArgs); e != nil {
|
||||
return e
|
||||
}
|
||||
op = api.Operation_DEL
|
||||
}
|
||||
operation = api.Operation_DEL
|
||||
case CMD_ALL:
|
||||
if len(eArgs) > 0 {
|
||||
return fmt.Errorf("Argument can not be entered: %s", eArgs[0:])
|
||||
}
|
||||
operation = api.Operation_DEL_ALL
|
||||
default:
|
||||
return fmt.Errorf("invalid modType %s", modtype)
|
||||
case CMD_SET:
|
||||
op = api.Operation_REPLACE
|
||||
}
|
||||
if e = modPolicy(api.Resource_POLICY_EXTCOMMUNITY, operation, extCommunitySet); e != nil {
|
||||
return e
|
||||
}
|
||||
return nil
|
||||
_, err = client.ModDefinedSet(context.Background(), &api.ModDefinedSetArguments{
|
||||
Operation: op,
|
||||
Set: d,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func showPolicyStatement(indent int, pd *api.PolicyDefinition) {
|
||||
@@ -1140,6 +772,51 @@ func parseActions() (*api.Actions, error) {
|
||||
return actions, nil
|
||||
}
|
||||
|
||||
func modPolicy(resource api.Resource, op api.Operation, data interface{}) error {
|
||||
pd := &api.PolicyDefinition{}
|
||||
if resource != api.Resource_POLICY_ROUTEPOLICY {
|
||||
co := &api.Conditions{}
|
||||
switch resource {
|
||||
case api.Resource_POLICY_PREFIX:
|
||||
co.PrefixSet = data.(*api.PrefixSet)
|
||||
case api.Resource_POLICY_NEIGHBOR:
|
||||
co.NeighborSet = data.(*api.MatchSet)
|
||||
case api.Resource_POLICY_ASPATH:
|
||||
co.AsPathSet = data.(*api.MatchSet)
|
||||
case api.Resource_POLICY_COMMUNITY:
|
||||
co.CommunitySet = data.(*api.MatchSet)
|
||||
case api.Resource_POLICY_EXTCOMMUNITY:
|
||||
co.ExtCommunitySet = data.(*api.MatchSet)
|
||||
}
|
||||
pd.Statements = []*api.Statement{{Conditions: co}}
|
||||
} else {
|
||||
pd = data.(*api.PolicyDefinition)
|
||||
}
|
||||
arg := &api.PolicyArguments{
|
||||
Resource: resource,
|
||||
Operation: op,
|
||||
PolicyDefinition: pd,
|
||||
}
|
||||
stream, err := client.ModPolicyRoutePolicy(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 modPolicyRoutePolicy(modtype string, eArgs []string) error {
|
||||
var operation api.Operation
|
||||
pd := &api.PolicyDefinition{}
|
||||
@@ -1195,56 +872,6 @@ func modPolicyRoutePolicy(modtype string, eArgs []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewPolicyAddCmd(v string, mod func(string, []string) error) *cobra.Command {
|
||||
policyAddCmd := &cobra.Command{
|
||||
Use: CMD_ADD,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
err := mod(cmd.Use, args)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
},
|
||||
}
|
||||
if v == CMD_ROUTEPOLICY {
|
||||
policyAddCmd.Flags().StringVarP(&conditionOpts.Prefix, "c-prefix", "", "", "a prefix set name of policy condition")
|
||||
policyAddCmd.Flags().StringVarP(&conditionOpts.Neighbor, "c-neighbor", "", "", "a neighbor set name of policy condition")
|
||||
policyAddCmd.Flags().StringVarP(&conditionOpts.AsPath, "c-aspath", "", "", "an as path set name of policy condition")
|
||||
policyAddCmd.Flags().StringVarP(&conditionOpts.Community, "c-community", "", "", "a community set name of policy condition")
|
||||
policyAddCmd.Flags().StringVarP(&conditionOpts.ExtCommunity, "c-extcommunity", "", "", "a extended community set name of policy condition")
|
||||
policyAddCmd.Flags().StringVarP(&conditionOpts.AsPathLength, "c-aslen", "", "", "an as path length of policy condition (<operator>,<numeric>)")
|
||||
policyAddCmd.Flags().StringVarP(&actionOpts.RouteAction, "a-route", "", "", "a route action of policy action (accept | reject)")
|
||||
policyAddCmd.Flags().StringVarP(&actionOpts.CommunityAction, "a-community", "", "", "a community of policy action")
|
||||
policyAddCmd.Flags().StringVarP(&actionOpts.MedAction, "a-med", "", "", "a med of policy action")
|
||||
policyAddCmd.Flags().StringVarP(&actionOpts.AsPathPrependAction, "a-asprepend", "", "", "aspath prepend for policy action")
|
||||
}
|
||||
|
||||
return policyAddCmd
|
||||
}
|
||||
|
||||
func NewPolicyDelCmd(mod func(string, []string) error) *cobra.Command {
|
||||
policyDelCmd := &cobra.Command{
|
||||
Use: CMD_DEL,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
err := mod(cmd.Use, args)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
subcmd := &cobra.Command{
|
||||
Use: CMD_ALL,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
err := mod(cmd.Use, args)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
},
|
||||
}
|
||||
policyDelCmd.AddCommand(subcmd)
|
||||
return policyDelCmd
|
||||
}
|
||||
|
||||
func NewPolicyCmd() *cobra.Command {
|
||||
policyCmd := &cobra.Command{
|
||||
Use: CMD_POLICY,
|
||||
@@ -1262,21 +889,6 @@ func NewPolicyCmd() *cobra.Command {
|
||||
}
|
||||
|
||||
for _, v := range []string{CMD_PREFIX, CMD_NEIGHBOR, CMD_ASPATH, CMD_COMMUNITY, CMD_EXTCOMMUNITY, CMD_ROUTEPOLICY} {
|
||||
var mod func(string, []string) error
|
||||
switch v {
|
||||
case CMD_PREFIX:
|
||||
mod = modPolicyPrefix
|
||||
case CMD_NEIGHBOR:
|
||||
mod = modPolicyNeighbor
|
||||
case CMD_ASPATH:
|
||||
mod = modPolicyAsPath
|
||||
case CMD_COMMUNITY:
|
||||
mod = modPolicyCommunity
|
||||
case CMD_EXTCOMMUNITY:
|
||||
mod = modPolicyExtCommunity
|
||||
case CMD_ROUTEPOLICY:
|
||||
mod = modPolicyRoutePolicy
|
||||
}
|
||||
cmd := &cobra.Command{
|
||||
Use: v,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
@@ -1285,10 +897,17 @@ func NewPolicyCmd() *cobra.Command {
|
||||
}
|
||||
},
|
||||
}
|
||||
policyAddCmd := NewPolicyAddCmd(v, mod)
|
||||
cmd.AddCommand(policyAddCmd)
|
||||
policyDelCmd := NewPolicyDelCmd(mod)
|
||||
cmd.AddCommand(policyDelCmd)
|
||||
for _, w := range []string{CMD_ADD, CMD_DEL, CMD_SET} {
|
||||
subcmd := &cobra.Command{
|
||||
Use: w,
|
||||
Run: func(c *cobra.Command, args []string) {
|
||||
if err := mod(cmd.Use, c.Use, args); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
},
|
||||
}
|
||||
cmd.AddCommand(subcmd)
|
||||
}
|
||||
policyCmd.AddCommand(cmd)
|
||||
}
|
||||
return policyCmd
|
||||
|
||||
+8
-4
@@ -1638,10 +1638,9 @@ func (server *BgpServer) handleGrpc(grpcReq *GrpcRequest) []*SenderMsg {
|
||||
}
|
||||
close(grpcReq.ResponseCh)
|
||||
case REQ_MOD_DEFINED_SET:
|
||||
if err := server.handleGrpcModDefinedSet(grpcReq); err != nil {
|
||||
grpcReq.ResponseCh <- &GrpcResponse{
|
||||
ResponseErr: err,
|
||||
}
|
||||
err := server.handleGrpcModDefinedSet(grpcReq)
|
||||
grpcReq.ResponseCh <- &GrpcResponse{
|
||||
ResponseErr: err,
|
||||
}
|
||||
close(grpcReq.ResponseCh)
|
||||
case REQ_POLICY_ROUTEPOLICY, REQ_POLICY_ROUTEPOLICIES:
|
||||
@@ -1698,6 +1697,7 @@ func (server *BgpServer) handleGrpcGetDefinedSet(grpcReq *GrpcRequest) error {
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid defined-set type: %d", typ)
|
||||
}
|
||||
found := false
|
||||
for _, s := range set {
|
||||
if name != "" && name != s.Name() {
|
||||
continue
|
||||
@@ -1705,10 +1705,14 @@ func (server *BgpServer) handleGrpcGetDefinedSet(grpcReq *GrpcRequest) error {
|
||||
grpcReq.ResponseCh <- &GrpcResponse{
|
||||
Data: s.ToApiStruct(),
|
||||
}
|
||||
found = true
|
||||
if name != "" {
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
return fmt.Errorf("not found %s", name)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
+62
-20
@@ -469,23 +469,43 @@ func (s *regExpSet) Type() DefinedType {
|
||||
}
|
||||
|
||||
func (lhs *regExpSet) Append(arg DefinedSet) error {
|
||||
rhs, ok := arg.(*regExpSet)
|
||||
if !ok {
|
||||
return fmt.Errorf("type cast failed")
|
||||
if lhs.Type() != arg.Type() {
|
||||
return fmt.Errorf("can't append to different type of defined-set")
|
||||
}
|
||||
lhs.list = append(lhs.list, rhs.list...)
|
||||
var list []*regexp.Regexp
|
||||
switch lhs.Type() {
|
||||
case DEFINED_TYPE_AS_PATH:
|
||||
list = arg.(*AsPathSet).list
|
||||
case DEFINED_TYPE_COMMUNITY:
|
||||
list = arg.(*CommunitySet).list
|
||||
case DEFINED_TYPE_EXT_COMMUNITY:
|
||||
list = arg.(*ExtCommunitySet).list
|
||||
default:
|
||||
return fmt.Errorf("invalid defined-set type: %d", lhs.Type())
|
||||
}
|
||||
lhs.list = append(lhs.list, list...)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (lhs *regExpSet) Remove(arg DefinedSet) error {
|
||||
rhs, ok := arg.(*regExpSet)
|
||||
if !ok {
|
||||
return fmt.Errorf("type cast failed")
|
||||
if lhs.Type() != arg.Type() {
|
||||
return fmt.Errorf("can't append to different type of defined-set")
|
||||
}
|
||||
var list []*regexp.Regexp
|
||||
switch lhs.Type() {
|
||||
case DEFINED_TYPE_AS_PATH:
|
||||
list = arg.(*AsPathSet).list
|
||||
case DEFINED_TYPE_COMMUNITY:
|
||||
list = arg.(*CommunitySet).list
|
||||
case DEFINED_TYPE_EXT_COMMUNITY:
|
||||
list = arg.(*ExtCommunitySet).list
|
||||
default:
|
||||
return fmt.Errorf("invalid defined-set type: %d", lhs.Type())
|
||||
}
|
||||
ps := make([]*regexp.Regexp, 0, len(lhs.list))
|
||||
for _, x := range lhs.list {
|
||||
found := false
|
||||
for _, y := range rhs.list {
|
||||
for _, y := range list {
|
||||
if x.String() == y.String() {
|
||||
found = true
|
||||
break
|
||||
@@ -584,7 +604,7 @@ func ParseCommunity(arg string) (uint32, error) {
|
||||
return 0, fmt.Errorf("failed to parse %s as community", arg)
|
||||
}
|
||||
|
||||
func parseExtCommunity(arg string) (bgp.ExtendedCommunityInterface, error) {
|
||||
func ParseExtCommunity(arg string) (bgp.ExtendedCommunityInterface, error) {
|
||||
var subtype bgp.ExtendedCommunityAttrSubType
|
||||
elems := strings.SplitN(arg, ":", 2)
|
||||
if len(elems) < 2 {
|
||||
@@ -601,7 +621,7 @@ func parseExtCommunity(arg string) (bgp.ExtendedCommunityInterface, error) {
|
||||
return bgp.ParseExtendedCommunity(subtype, elems[1])
|
||||
}
|
||||
|
||||
func parseCommunityRegexp(arg string) (*regexp.Regexp, error) {
|
||||
func ParseCommunityRegexp(arg string) (*regexp.Regexp, error) {
|
||||
i, err := strconv.Atoi(arg)
|
||||
if err == nil {
|
||||
return regexp.MustCompile(fmt.Sprintf("^%d:%d$", i>>16, i&0x0000ffff)), nil
|
||||
@@ -621,7 +641,7 @@ func parseCommunityRegexp(arg string) (*regexp.Regexp, error) {
|
||||
return exp, nil
|
||||
}
|
||||
|
||||
func parseExtCommunityRegexp(arg string) (bgp.ExtendedCommunityAttrSubType, *regexp.Regexp, error) {
|
||||
func ParseExtCommunityRegexp(arg string) (bgp.ExtendedCommunityAttrSubType, *regexp.Regexp, error) {
|
||||
var subtype bgp.ExtendedCommunityAttrSubType
|
||||
elems := strings.SplitN(arg, ":", 2)
|
||||
if len(elems) < 2 {
|
||||
@@ -635,7 +655,7 @@ func parseExtCommunityRegexp(arg string) (bgp.ExtendedCommunityAttrSubType, *reg
|
||||
default:
|
||||
return subtype, nil, fmt.Errorf("unknown ext-community subtype. rt, soo is supported")
|
||||
}
|
||||
exp, err := parseCommunityRegexp(elems[1])
|
||||
exp, err := ParseCommunityRegexp(elems[1])
|
||||
return subtype, exp, err
|
||||
}
|
||||
|
||||
@@ -660,7 +680,7 @@ func NewCommunitySet(c config.CommunitySet) (*CommunitySet, error) {
|
||||
}
|
||||
list := make([]*regexp.Regexp, 0, len(c.CommunityList))
|
||||
for _, x := range c.CommunityList {
|
||||
exp, err := parseCommunityRegexp(x.Community)
|
||||
exp, err := ParseCommunityRegexp(x.Community)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -680,6 +700,28 @@ type ExtCommunitySet struct {
|
||||
subtypeList []bgp.ExtendedCommunityAttrSubType
|
||||
}
|
||||
|
||||
func (s *ExtCommunitySet) ToApiStruct() *api.DefinedSet {
|
||||
list := make([]string, 0, len(s.list))
|
||||
f := func(idx int, arg string) string {
|
||||
switch s.subtypeList[idx] {
|
||||
case bgp.EC_SUBTYPE_ROUTE_TARGET:
|
||||
return fmt.Sprintf("rt:%s", arg)
|
||||
case bgp.EC_SUBTYPE_ROUTE_ORIGIN:
|
||||
return fmt.Sprintf("soo:%s", arg)
|
||||
default:
|
||||
return fmt.Sprintf("%d:%s", s.subtypeList[idx])
|
||||
}
|
||||
}
|
||||
for idx, exp := range s.list {
|
||||
list = append(list, f(idx, exp.String()))
|
||||
}
|
||||
return &api.DefinedSet{
|
||||
Type: int32(s.typ),
|
||||
Name: s.name,
|
||||
List: list,
|
||||
}
|
||||
}
|
||||
|
||||
func NewExtCommunitySetFromApiStruct(a *api.DefinedSet) (*ExtCommunitySet, error) {
|
||||
c := config.ExtCommunitySet{
|
||||
ExtCommunitySetName: a.Name,
|
||||
@@ -702,7 +744,7 @@ func NewExtCommunitySet(c config.ExtCommunitySet) (*ExtCommunitySet, error) {
|
||||
list := make([]*regexp.Regexp, 0, len(c.ExtCommunityList))
|
||||
subtypeList := make([]bgp.ExtendedCommunityAttrSubType, 0, len(c.ExtCommunityList))
|
||||
for _, x := range c.ExtCommunityList {
|
||||
subtype, exp, err := parseExtCommunityRegexp(x.ExtCommunity)
|
||||
subtype, exp, err := ParseExtCommunityRegexp(x.ExtCommunity)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1386,7 +1428,7 @@ func NewCommunityActionFromApiStruct(a *api.CommunityAction) (*CommunityAction,
|
||||
}
|
||||
for _, x := range a.Communities {
|
||||
if op == config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE {
|
||||
exp, err := parseCommunityRegexp(x)
|
||||
exp, err := ParseCommunityRegexp(x)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1423,7 +1465,7 @@ func NewCommunityAction(c config.SetCommunity) (*CommunityAction, error) {
|
||||
}
|
||||
for _, x := range c.SetCommunityMethod.Communities {
|
||||
if a == config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE {
|
||||
exp, err := parseCommunityRegexp(x)
|
||||
exp, err := ParseCommunityRegexp(x)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1498,14 +1540,14 @@ func NewExtCommunityActionFromApiStruct(a *api.CommunityAction) (*ExtCommunityAc
|
||||
}
|
||||
for _, x := range a.Communities {
|
||||
if op == config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE {
|
||||
subtype, exp, err := parseExtCommunityRegexp(x)
|
||||
subtype, exp, err := ParseExtCommunityRegexp(x)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
removeList = append(removeList, exp)
|
||||
subtypeList = append(subtypeList, subtype)
|
||||
} else {
|
||||
comm, err := parseExtCommunity(x)
|
||||
comm, err := ParseExtCommunity(x)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1540,14 +1582,14 @@ func NewExtCommunityAction(c config.SetExtCommunity) (*ExtCommunityAction, error
|
||||
}
|
||||
for _, x := range c.SetExtCommunityMethod.Communities {
|
||||
if a == config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE {
|
||||
subtype, exp, err := parseExtCommunityRegexp(x)
|
||||
subtype, exp, err := ParseExtCommunityRegexp(x)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
removeList = append(removeList, exp)
|
||||
subtypeList = append(subtypeList, subtype)
|
||||
} else {
|
||||
comm, err := parseExtCommunity(x)
|
||||
comm, err := ParseExtCommunity(x)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user