summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorIWASE Yusuke <iwase.yusuke0@gmail.com>2017-08-07 16:55:37 +0900
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2017-08-30 09:24:10 +0900
commit87b473ad4d7735774f4b74d4b651e0baa1bd1029 (patch)
treef2bf67eb3d16e352e3ed1a815609eb94d9a83d17
parentb8a303815ef2b5741f517ae96816ff90ac193edd (diff)
cli: Enable to specify AS_PATH
This patch enables to specify AS_PATH in "gobgp" client command. The syntax is similar to the output of AS_PATH in "global rib" show command. Signed-off-by: IWASE Yusuke <iwase.yusuke0@gmail.com>
-rw-r--r--docs/sources/cli-command-syntax.md2
-rw-r--r--gobgp/cmd/global.go75
2 files changed, 75 insertions, 2 deletions
diff --git a/docs/sources/cli-command-syntax.md b/docs/sources/cli-command-syntax.md
index 7167d6c5..580eb323 100644
--- a/docs/sources/cli-command-syntax.md
+++ b/docs/sources/cli-command-syntax.md
@@ -59,6 +59,8 @@ If you want to remove routes with the address of the ipv6 from global rib:
```shell
% gobgp global rib add -a ipv4 10.0.0.0/24 origin igp
% gobgp global rib add -a ipv4 10.0.0.0/24 origin egp
+% gobgp global rib add -a ipv4 10.0.0.0/24 aspath 10,20,100.100
+% gobgp global rib add -a ipv4 10.0.0.0/24 aspath "10 20 {30,40} 50"
% gobgp global rib add -a ipv4 10.0.0.0/24 nexthop 20.20.20.20
% gobgp global rib add -a ipv4 10.0.0.0/24 med 10
% gobgp global rib add -a ipv4 10.0.0.0/24 local-pref 110
diff --git a/gobgp/cmd/global.go b/gobgp/cmd/global.go
index 92b1f52d..15379430 100644
--- a/gobgp/cmd/global.go
+++ b/gobgp/cmd/global.go
@@ -513,6 +513,76 @@ func extractOrigin(args []string) ([]string, bgp.PathAttributeInterface, error)
}
return args, bgp.NewPathAttributeOrigin(uint8(typ)), nil
}
+
+func toAs4Value(s string) (uint32, error) {
+ if strings.Contains(s, ".") {
+ v := strings.Split(s, ".")
+ upper, err := strconv.Atoi(v[0])
+ if err != nil {
+ return 0, nil
+ }
+ lower, err := strconv.Atoi(v[1])
+ if err != nil {
+ return 0, nil
+ }
+ return uint32(upper)<<16 + uint32(lower), nil
+ }
+ i, err := strconv.Atoi(s)
+ if err != nil {
+ return 0, err
+ }
+ return uint32(i), nil
+}
+
+func newAsPath(aspath string) (bgp.PathAttributeInterface, error) {
+ // For the first step, parses "aspath" into a list of uint32 list.
+ // e.g.) "10 20 {30,40} 50" -> [][]uint32{{10, 20}, {30, 40}, {50}}
+ exp := regexp.MustCompile("[{}]")
+ segments := exp.Split(aspath, -1)
+ asPathPrams := make([]bgp.AsPathParamInterface, 0, len(segments))
+ exp = regexp.MustCompile(",|\\s+")
+ for idx, segment := range segments {
+ if segment == "" {
+ continue
+ }
+ nums := exp.Split(segment, -1)
+ asNums := make([]uint32, 0, len(nums))
+ for _, n := range nums {
+ if n == "" {
+ continue
+ }
+ if asn, err := toAs4Value(n); err != nil {
+ return nil, err
+ } else {
+ asNums = append(asNums, uint32(asn))
+ }
+ }
+ // Assumes "idx" is even, the given "segment" is of type AS_SEQUENCE,
+ // otherwise AS_SET, because the "segment" enclosed in parentheses is
+ // of type AS_SET.
+ if idx%2 == 0 {
+ asPathPrams = append(asPathPrams, bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, asNums))
+ } else {
+ asPathPrams = append(asPathPrams, bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SET, asNums))
+ }
+ }
+ return bgp.NewPathAttributeAsPath(asPathPrams), nil
+}
+
+func extractAsPath(args []string) ([]string, bgp.PathAttributeInterface, error) {
+ for idx, arg := range args {
+ if arg == "aspath" && len(args) > (idx+1) {
+ attr, err := newAsPath(args[idx+1])
+ if err != nil {
+ return nil, nil, err
+ }
+ args = append(args[:idx], args[idx+2:]...)
+ return args, attr, nil
+ }
+ }
+ return args, nil, nil
+}
+
func extractNexthop(rf bgp.RouteFamily, args []string) ([]string, string, error) {
afi, _ := bgp.RouteFamilyToAfiSafi(rf)
nexthop := "0.0.0.0"
@@ -666,6 +736,7 @@ func ParsePath(rf bgp.RouteFamily, args []string) (*table.Path, error) {
attrs := table.PathAttrs(make([]bgp.PathAttributeInterface, 0, 1))
fns := []func([]string) ([]string, bgp.PathAttributeInterface, error){
+ extractAsPath,
extractOrigin,
extractMed,
extractLocalPref,
@@ -879,8 +950,8 @@ func modPath(resource string, name, modtype string, args []string) error {
}
etherTypes := strings.Join(ss, ", ")
helpErrMap := map[bgp.RouteFamily]error{}
- helpErrMap[bgp.RF_IPv4_UC] = fmt.Errorf("usage: %s rib %s <PREFIX> [identifier <VALUE>] [origin { igp | egp | incomplete }] [nexthop <ADDRESS>] [med <VALUE>] [local-pref <VALUE>] [community <VALUE>] [aigp metric <METRIC>] [large-community <VALUE> ] -a ipv4", cmdstr, modtype)
- helpErrMap[bgp.RF_IPv6_UC] = fmt.Errorf("usage: %s rib %s <PREFIX> [identifier <VALUE>] [origin { igp | egp | incomplete }] [nexthop <ADDRESS>] [med <VALUE>] [local-pref <VALUE>] [community <VALUE>] [aigp metric <METRIC>] [large-community <VALUE> ] -a ipv6", cmdstr, modtype)
+ helpErrMap[bgp.RF_IPv4_UC] = fmt.Errorf("usage: %s rib %s <PREFIX> [identifier <VALUE>] [origin { igp | egp | incomplete }] [aspath <VALUE>] [nexthop <ADDRESS>] [med <VALUE>] [local-pref <VALUE>] [community <VALUE>] [aigp metric <METRIC>] [large-community <VALUE> ] -a ipv4", cmdstr, modtype)
+ helpErrMap[bgp.RF_IPv6_UC] = fmt.Errorf("usage: %s rib %s <PREFIX> [identifier <VALUE>] [origin { igp | egp | incomplete }] [aspath <VALUE>] [nexthop <ADDRESS>] [med <VALUE>] [local-pref <VALUE>] [community <VALUE>] [aigp metric <METRIC>] [large-community <VALUE> ] -a ipv6", cmdstr, modtype)
fsHelpMsgFmt := fmt.Sprintf(`err: %s
usage: %s rib %s%%smatch <MATCH_EXPR> then <THEN_EXPR> -a %%s
%%s