summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorIWASE Yusuke <iwase.yusuke0@gmail.com>2017-11-22 13:36:42 +0900
committerIWASE Yusuke <iwase.yusuke0@gmail.com>2017-11-24 12:53:14 +0900
commitd2c16ca1b62c92951de936242163cb648f0c3025 (patch)
treeabe330e4fa7e0ef49d24206e41aff5aee0c5db47
parent412548f7e5363c502d26434bbc68ffa03e99c75e (diff)
cli: Improve arguments extraction for FlowSpec rules
Signed-off-by: IWASE Yusuke <iwase.yusuke0@gmail.com>
-rw-r--r--gobgp/cmd/global.go34
-rw-r--r--packet/bgp/bgp.go61
2 files changed, 57 insertions, 38 deletions
diff --git a/gobgp/cmd/global.go b/gobgp/cmd/global.go
index 6ab87024..d1aa38a9 100644
--- a/gobgp/cmd/global.go
+++ b/gobgp/cmd/global.go
@@ -324,19 +324,31 @@ func ParseExtendedCommunities(args []string) ([]bgp.ExtendedCommunityInterface,
}
func ParseFlowSpecArgs(rf bgp.RouteFamily, args []string, rd bgp.RouteDistinguisherInterface) (bgp.AddrPrefixInterface, []string, error) {
- thenPos := len(args)
- for idx, v := range args {
- if v == "then" {
- thenPos = idx
- break
- }
+ // Format:
+ // match <rule>... [then <action>...] [rt <rt>...]
+ req := 3 // match <key1> <arg1> [<key2> <arg2>...]
+ if len(args) < req {
+ return nil, nil, fmt.Errorf("%d args required at least, but got %d", req, len(args))
+ }
+ m := extractReserved(args, []string{"match", "then", "rt"})
+ if len(m["match"]) == 0 {
+ return nil, nil, fmt.Errorf("specify filtering rules with keyword 'match'")
}
- if len(args) < 4 || args[0] != "match" || thenPos > len(args)-2 {
- return nil, nil, fmt.Errorf("invalid format")
+
+ extcomms := m["then"]
+ switch rf {
+ case bgp.RF_FS_IPv4_VPN, bgp.RF_FS_IPv6_VPN, bgp.RF_FS_L2_VPN:
+ if len(m["rt"]) > 0 {
+ extcomms = append(extcomms, "rt")
+ extcomms = append(extcomms, m["rt"]...)
+ }
+ default:
+ if len(m["rt"]) > 0 {
+ return nil, nil, fmt.Errorf("cannot specify rt for %s", rf.String())
+ }
}
- matchArgs := args[1:thenPos]
- rules, err := bgp.ParseFlowSpecComponents(rf, strings.Join(matchArgs, " "))
+ rules, err := bgp.ParseFlowSpecComponents(rf, strings.Join(m["match"], " "))
if err != nil {
return nil, nil, err
}
@@ -357,7 +369,7 @@ func ParseFlowSpecArgs(rf bgp.RouteFamily, args []string, rd bgp.RouteDistinguis
return nil, nil, fmt.Errorf("invalid route family")
}
- return nlri, args[thenPos+1:], nil
+ return nlri, extcomms, nil
}
func ParseEvpnEthernetAutoDiscoveryArgs(args []string) (bgp.AddrPrefixInterface, []string, error) {
diff --git a/packet/bgp/bgp.go b/packet/bgp/bgp.go
index 987bf328..8c4400ba 100644
--- a/packet/bgp/bgp.go
+++ b/packet/bgp/bgp.go
@@ -3364,39 +3364,46 @@ var flowSpecParserMap = map[BGPFlowSpecType]func(RouteFamily, []string) (FlowSpe
FLOW_SPEC_TYPE_INNER_COS: flowSpecNumericParser,
}
-func ParseFlowSpecComponents(rf RouteFamily, input string) ([]FlowSpecComponentInterface, error) {
- idxs := make([]struct {
- t BGPFlowSpecType
- i int
- }, 0, 8)
- args := strings.Split(input, " ")
- for idx, v := range args {
- if t, ok := FlowSpecValueMap[v]; ok {
- idxs = append(idxs, struct {
- t BGPFlowSpecType
- i int
- }{t, idx})
- }
- }
- if len(idxs) == 0 {
- return nil, fmt.Errorf("failed to parse: %s", input)
- }
- cmps := make([]FlowSpecComponentInterface, 0, len(idxs))
- for i, idx := range idxs {
- var a []string
- f := flowSpecParserMap[idx.t]
- if i < len(idxs)-1 {
- a = args[idx.i:idxs[i+1].i]
+func extractFlowSpecArgs(args []string) map[BGPFlowSpecType][]string {
+ m := make(map[BGPFlowSpecType][]string, len(FlowSpecValueMap))
+ var typ BGPFlowSpecType
+ for _, arg := range args {
+ if t, ok := FlowSpecValueMap[arg]; ok {
+ typ = t
+ m[typ] = make([]string, 0)
} else {
- a = args[idx.i:]
+ m[typ] = append(m[typ], arg)
}
- cmp, err := f(rf, a)
+ }
+ return m
+}
+
+func ParseFlowSpecComponents(rf RouteFamily, arg string) ([]FlowSpecComponentInterface, error) {
+ _, safi := RouteFamilyToAfiSafi(rf)
+ switch safi {
+ case SAFI_FLOW_SPEC_UNICAST, SAFI_FLOW_SPEC_VPN:
+ // Valid
+ default:
+ return nil, fmt.Errorf("invalid address family: %s", rf.String())
+ }
+
+ typeArgs := extractFlowSpecArgs(strings.Split(arg, " "))
+ rules := make([]FlowSpecComponentInterface, 0, len(typeArgs))
+ for typ, args := range typeArgs {
+ parser, ok := flowSpecParserMap[typ]
+ if !ok {
+ return nil, fmt.Errorf("unsupported traffic filtering rule type: %s", typ.String())
+ }
+ if len(args) == 0 {
+ return nil, fmt.Errorf("specify traffic filtering rules for %s", typ.String())
+ }
+ rule, err := parser(rf, typ, args)
if err != nil {
return nil, err
}
- cmps = append(cmps, cmp)
+ rules = append(rules, rule)
}
- return cmps, nil
+ return rules, nil
}
func (t BGPFlowSpecType) String() string {