diff options
author | IWASE Yusuke <iwase.yusuke0@gmail.com> | 2017-08-07 16:55:37 +0900 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2017-08-30 09:24:10 +0900 |
commit | 87b473ad4d7735774f4b74d4b651e0baa1bd1029 (patch) | |
tree | f2bf67eb3d16e352e3ed1a815609eb94d9a83d17 | |
parent | b8a303815ef2b5741f517ae96816ff90ac193edd (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.md | 2 | ||||
-rw-r--r-- | gobgp/cmd/global.go | 75 |
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 |