cisco_node_utils 1.9.0 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +34 -0
  3. data/README.md +14 -0
  4. data/ext/mkrf_conf.rb +1 -1
  5. data/lib/cisco_node_utils/ace.rb +142 -7
  6. data/lib/cisco_node_utils/banner.rb +63 -0
  7. data/lib/cisco_node_utils/bridge_domain.rb +1 -1
  8. data/lib/cisco_node_utils/cisco_cmn_utils.rb +1 -1
  9. data/lib/cisco_node_utils/client/utils.rb +20 -10
  10. data/lib/cisco_node_utils/cmd_ref/acl.yaml +1 -1
  11. data/lib/cisco_node_utils/cmd_ref/banner.yaml +7 -0
  12. data/lib/cisco_node_utils/cmd_ref/fabricpath.yaml +2 -2
  13. data/lib/cisco_node_utils/cmd_ref/hostname.yaml +8 -0
  14. data/lib/cisco_node_utils/cmd_ref/interface.yaml +20 -12
  15. data/lib/cisco_node_utils/cmd_ref/interface_hsrp_group.yaml +3 -3
  16. data/lib/cisco_node_utils/cmd_ref/ip_multicast.yaml +6 -2
  17. data/lib/cisco_node_utils/cmd_ref/snmp_server.yaml +4 -1
  18. data/lib/cisco_node_utils/cmd_ref/syslog_facility.yaml +10 -0
  19. data/lib/cisco_node_utils/cmd_ref/syslog_server.yaml +3 -3
  20. data/lib/cisco_node_utils/cmd_ref/syslog_settings.yaml +16 -0
  21. data/lib/cisco_node_utils/cmd_ref/tacacs_server_host.yaml +2 -2
  22. data/lib/cisco_node_utils/environment.rb +8 -1
  23. data/lib/cisco_node_utils/hostname.rb +62 -0
  24. data/lib/cisco_node_utils/interface.rb +59 -2
  25. data/lib/cisco_node_utils/interface_DEPRECATED.rb +5 -0
  26. data/lib/cisco_node_utils/interface_hsrp_group.rb +17 -6
  27. data/lib/cisco_node_utils/ip_multicast.rb +13 -9
  28. data/lib/cisco_node_utils/node.rb +4 -1
  29. data/lib/cisco_node_utils/syslog_facility.rb +64 -0
  30. data/lib/cisco_node_utils/syslog_server.rb +18 -13
  31. data/lib/cisco_node_utils/syslog_settings.rb +43 -1
  32. data/lib/cisco_node_utils/version.rb +1 -1
  33. data/lib/cisco_node_utils/vlan.rb +1 -1
  34. data/lib/cisco_node_utils/vxlan_vtep_vni.rb +21 -8
  35. data/spec/environment_spec.rb +107 -0
  36. data/tests/ciscotest.rb +8 -1
  37. data/tests/test_ace.rb +60 -3
  38. data/tests/test_banner.rb +85 -0
  39. data/tests/test_bgp_af.rb +1 -1
  40. data/tests/test_hostname.rb +64 -0
  41. data/tests/test_interface.rb +22 -1
  42. data/tests/test_interface_hsrp_group.rb +12 -24
  43. data/tests/test_ip_multicast.rb +32 -21
  44. data/tests/test_nxapi.rb +8 -4
  45. data/tests/test_syslog_facility.rb +80 -0
  46. data/tests/test_syslog_server.rb +3 -2
  47. data/tests/test_syslog_settings.rb +16 -1
  48. data/tests/yum_package.yaml +5 -0
  49. metadata +12 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f41913654bc402d2a30d3c2345e0ac1fbd587ffe
4
- data.tar.gz: a20bebaeb60c419708f83b078c8f5e61464788ec
3
+ metadata.gz: db160cf1dedda53f077ad5e3c246a7106be834ea
4
+ data.tar.gz: 31eac56721204dbbf673355acaa1dd5591af3ed3
5
5
  SHA512:
6
- metadata.gz: daed7260c5c3b320216186f6c10ed0468bf78a6c5038b8bd6a0d5521e61dc606088ba505feda784318e6cf9800b7dfb8414824db66e8950193df8a877f76db22
7
- data.tar.gz: fbab02d4e41a802249bc5b30b1b87392392f5f4cba319c554e825d8bed79ae3bf26a5186d640219b7d0e2da5472b50a2c18f850f31e232e15ee3c15db04f39bb
6
+ metadata.gz: d6330230a4a619e0e497d5c79d5757bfe3141e53605550033fdcfcb9f4e8cfafd93e8aa2a457fd4989ff40c636001f6a070475736abf30c1cd72eb0a09126db5
7
+ data.tar.gz: ac35c7431032dddce3c7fbc92c20028a6843fb25314e218925e1fa37610e6735e0a593e4aaa04ca2812182e20aa96a3d43205e436d5d2c655f850c828fddf78b
@@ -1,6 +1,39 @@
1
1
  Changelog
2
2
  =========
3
3
 
4
+ ## [v1.10.0]
5
+
6
+ ### New Cisco Resources
7
+
8
+ ### Added
9
+ * Added syslog_facility with attribute:
10
+ * `level`
11
+ * Extend syslog_server with attribute:
12
+ * `facility`
13
+ * Extend interface with attributes:
14
+ * `ipv6_redirects`
15
+ * Extend ace with attributes:
16
+ * `proto_option`
17
+ * `vlan`
18
+ * `set_erspan_dscp`
19
+ * `set_erspan_gre_proto`
20
+ * Extend network_dns with attributes:
21
+ * `hostname`
22
+ * Added ability to specify environment at run time
23
+
24
+ Example:
25
+ ```ruby
26
+ env = { host: '192.168.1.1', port: nil, username: 'admin', password: 'admin123', cookie: nil }
27
+ Cisco::Environment.add_env('default', env)
28
+ ```
29
+
30
+ ### Changed
31
+
32
+ ### Removed
33
+
34
+ ### Issues Addressed
35
+ * Removed default values for authentication in `interface_hsrp_group`
36
+
4
37
  ## [v1.9.0]
5
38
 
6
39
  ### New Cisco Resources
@@ -554,6 +587,7 @@ Changelog
554
587
  [git-flow]: https://github.com/petervanderdoes/gitflow-avh
555
588
  [SimpleCov]: https://github.com/colszowka/simplecov
556
589
 
590
+ [v1.10.0]: https://github.com/cisco/cisco-network-node-utils/compare/v1.9.0...v1.10.0
557
591
  [v1.9.0]: https://github.com/cisco/cisco-network-node-utils/compare/v1.8.0...v1.9.0
558
592
  [v1.8.0]: https://github.com/cisco/cisco-network-node-utils/compare/v1.7.0...v1.8.0
559
593
  [v1.7.0]: https://github.com/cisco/cisco-network-node-utils/compare/v1.6.0...v1.7.0
data/README.md CHANGED
@@ -85,6 +85,14 @@ An example configuration file (illustrating each of the above scenarios) is prov
85
85
 
86
86
  *For security purposes, it is highly recommended that access to this file be restricted to only the owning user (`chmod 0600`).*
87
87
 
88
+ Configuration may also be specified at runtime and can be used in the absence of configuration files or to override them.
89
+
90
+ Example:
91
+ ```ruby
92
+ env = { host: '192.168.1.1', port: nil, username: 'admin', password: 'admin123', cookie: nil }
93
+ Cisco::Environment.add_env('default', env)
94
+ ```
95
+
88
96
  ## <a name="documentation">Documentation</a>
89
97
 
90
98
  ### Client
@@ -151,12 +159,18 @@ client2 = Cisco::Client.create('n9k')
151
159
  # Warning: Make sure to exclude devices using the 'no_proxy' environment variable
152
160
  # to ensure successful remote connections.
153
161
 
162
+ # Add runtime configuration for remote device and connect
163
+ env = { host: '192.168.1.1', port: nil, username: 'admin', password: 'admin123', cookie: nil }
164
+ Cisco::Environment.add_env('remote', env)
165
+ client3 = Cisco::Client.create('remote')
166
+
154
167
  # Use connections to get and set device state.
155
168
  client1.set(values: 'feature vtp')
156
169
  client1.set(values: 'vtp domain mycompany.com')
157
170
  puts client1.get(command: 'show vtp status | inc Domain')
158
171
 
159
172
  puts client2.get(command: 'show version')
173
+ puts client3.get(command: 'show version')
160
174
  ```
161
175
 
162
176
  #### High-level Node API
@@ -37,7 +37,7 @@ begin
37
37
  os == 'ios_xr' || deps << Gem::Dependency.new('net_http_unix',
38
38
  '~> 0.2', '>= 0.2.1')
39
39
  # NX-OS doesn't need gRPC
40
- os == 'nexus' || deps << Gem::Dependency.new('grpc', '~> 0.12')
40
+ os == 'nexus' || deps << Gem::Dependency.new('grpc', '~> 1.14.1')
41
41
 
42
42
  deps.each do |dep|
43
43
  installed = dep.matching_specs
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2015-2016 Cisco and/or its affiliates.
1
+ # Copyright (c) 2015-2018 Cisco and/or its affiliates.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -12,6 +12,7 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ require 'ipaddr'
15
16
  require_relative 'node_util'
16
17
 
17
18
  module Cisco
@@ -73,6 +74,9 @@ module Cisco
73
74
  remark = Regexp.new('(?<seqno>\d+) remark (?<remark>.*)').match(str)
74
75
  return remark unless remark.nil?
75
76
 
77
+ # specialized icmp protocol handling
78
+ return icmp_ace_get(str) if str.include?('icmp')
79
+
76
80
  # rubocop:disable Metrics/LineLength
77
81
  regexp = Regexp.new('(?<seqno>\d+) (?<action>\S+)'\
78
82
  ' *(?<proto>\d+|\S+)'\
@@ -95,6 +99,60 @@ module Cisco
95
99
  regexp.match(str)
96
100
  end
97
101
 
102
+ # icmp ace getter
103
+ def icmp_ace_get(str)
104
+ # rubocop:disable Metrics/LineLength
105
+ # fragments is nvgen at a different location than all other
106
+ # proto_option so get rid of it so as not to mess up other fields
107
+ str.sub!('fragments ', '')
108
+ regexp = Regexp.new('(?<seqno>\d+) (?<action>\S+)'\
109
+ ' *(?<proto>\d+|\S+)'\
110
+ ' *(?<src_addr>any|host \S+|[:\.0-9a-fA-F]+ [:\.0-9a-fA-F]+|[:\.0-9a-fA-F]+\/\d+|addrgroup \S+)'\
111
+ ' *(?<dst_addr>any|host \S+|[:\.0-9a-fA-F]+ [:\.0-9a-fA-F]+|[:\.0-9a-fA-F]+\/\d+|addrgroup \S+)'\
112
+ ' *(?<proto_option>\S+)?'\
113
+ ' *(?<precedence>precedence \S+)?'\
114
+ ' *(?<dscp>dscp \S+)?'\
115
+ ' *(?<time_range>time-range \S+)?'\
116
+ ' *(?<packet_length>packet-length (range \d+ \d+|(lt|eq|gt|neq) \d+))?'\
117
+ ' *(?<ttl>ttl \d+)?'\
118
+ ' *(?<vlan>vlan \d+)?'\
119
+ ' *(?<set_erspan_gre_proto>set-erspan-gre-proto \d+)?'\
120
+ ' *(?<set_erspan_dscp>set-erspan-dscp \d+)?'\
121
+ ' *(?<redirect>redirect \S+)?')
122
+ regexp_no_proto_option = Regexp.new('(?<seqno>\d+) (?<action>\S+)'\
123
+ ' *(?<proto>\d+|\S+)'\
124
+ ' *(?<src_addr>any|host \S+|[:\.0-9a-fA-F]+ [:\.0-9a-fA-F]+|[:\.0-9a-fA-F]+\/\d+|addrgroup \S+)'\
125
+ ' *(?<dst_addr>any|host \S+|[:\.0-9a-fA-F]+ [:\.0-9a-fA-F]+|[:\.0-9a-fA-F]+\/\d+|addrgroup \S+)'\
126
+ ' *(?<precedence>precedence \S+)?'\
127
+ ' *(?<dscp>dscp \S+)?'\
128
+ ' *(?<time_range>time-range \S+)?'\
129
+ ' *(?<packet_length>packet-length (range \d+ \d+|(lt|eq|gt|neq) \d+))?'\
130
+ ' *(?<ttl>ttl \d+)?'\
131
+ ' *(?<vlan>vlan \d+)?'\
132
+ ' *(?<set_erspan_gre_proto>set-erspan-gre-proto \d+)?'\
133
+ ' *(?<set_erspan_dscp>set-erspan-dscp \d+)?'\
134
+ ' *(?<redirect>redirect \S+)?')
135
+ temp = regexp.match(str)
136
+ po = temp[:proto_option]
137
+ if po.nil?
138
+ return temp
139
+ # redirect can be proto_option or an actual redirect to interface
140
+ elsif po.strip.match(/redirect$/)
141
+ if str.match(/Ethernet|port-channel/)
142
+ # if proto_option is given as redirect and also redirect to intf
143
+ # we need to do extra processing
144
+ return temp if check_redirect_repeat(str)
145
+ return regexp_no_proto_option.match(str)
146
+ end
147
+ # the reserved keywords check
148
+ elsif po.strip.match(/precedence$|dscp$|time-range$|packet-length$|ttl$|vlan$|set-erspan-gre-proto$|set-erspan-dscp$|log$/)
149
+ return regexp_no_proto_option.match(str)
150
+ else
151
+ return temp
152
+ end
153
+ # rubocop:enable Metrics/LineLength
154
+ end
155
+
98
156
  # common ace setter. Put the values you need in a hash and pass it in.
99
157
  # attrs = {:action=>'permit', :proto=>'tcp', :src =>'host 1.1.1.1'}
100
158
  def ace_set(attrs)
@@ -130,6 +188,10 @@ module Cisco
130
188
  :tcp_option_length,
131
189
  :redirect,
132
190
  :log,
191
+ :proto_option,
192
+ :set_erspan_dscp,
193
+ :set_erspan_gre_proto,
194
+ :vlan,
133
195
  ].each do |p|
134
196
  attrs[p] = '' if attrs[p].nil?
135
197
  send(p.to_s + '=', attrs[p])
@@ -139,6 +201,21 @@ module Cisco
139
201
  config_set('acl', cmd, @set_args)
140
202
  end
141
203
 
204
+ def valid_ipv6?(addr)
205
+ begin
206
+ ret = IPAddr.new(addr.split[0]).ipv6?
207
+ rescue
208
+ ret = false
209
+ end
210
+ ret
211
+ end
212
+
213
+ def check_redirect_repeat(str)
214
+ return false unless str.include?('redirect')
215
+ nstr = str.sub('redirect', '').strip
216
+ nstr.include?('redirect') ? true : false
217
+ end
218
+
142
219
  # PROPERTIES
143
220
  # ----------
144
221
  def seqno
@@ -182,7 +259,7 @@ module Cisco
182
259
  return nil if match.nil? || !match.names.include?('src_addr')
183
260
  addr = match[:src_addr]
184
261
  # Normalize addr. Some platforms zero_pad ipv6 addrs.
185
- addr.gsub!(/^0*/, '').gsub!(/:0*/, ':')
262
+ addr.gsub!(/^0*/, '').gsub!(/:0*/, ':') if valid_ipv6?(addr)
186
263
  addr
187
264
  end
188
265
 
@@ -205,7 +282,7 @@ module Cisco
205
282
  return nil if match.nil? || !match.names.include?('dst_addr')
206
283
  addr = match[:dst_addr]
207
284
  # Normalize addr. Some platforms zero_pad ipv6 addrs.
208
- addr.gsub!(/^0*/, '').gsub!(/:0*/, ':')
285
+ addr.gsub!(/^0*/, '').gsub!(/:0*/, ':') if valid_ipv6?(addr)
209
286
  addr
210
287
  end
211
288
 
@@ -261,6 +338,49 @@ module Cisco
261
338
  @set_args[:dscp] = Utils.attach_prefix(dscp, :dscp)
262
339
  end
263
340
 
341
+ def vlan
342
+ Utils.extract_value(ace_get, 'vlan')
343
+ end
344
+
345
+ def vlan=(vlan)
346
+ @set_args[:vlan] = Utils.attach_prefix(vlan, :vlan)
347
+ end
348
+
349
+ def set_erspan_dscp
350
+ ret = Utils.extract_value(ace_get, 'set_erspan_dscp', 'set-erspan-dscp')
351
+ return ret if ret
352
+ # position of set_erspan_dscp is different in older release so check again
353
+ str = config_get('acl', 'ace', @get_args)
354
+ sstr = str.split
355
+ return sstr[sstr.index('set-erspan-dscp') + 1] if
356
+ sstr.include?('set-erspan-dscp')
357
+ end
358
+
359
+ def set_erspan_dscp=(set_erspan_dscp)
360
+ @set_args[:set_erspan_dscp] = Utils.attach_prefix(set_erspan_dscp,
361
+ :set_erspan_dscp,
362
+ 'set-erspan-dscp')
363
+ end
364
+
365
+ def set_erspan_gre_proto
366
+ ret = Utils.extract_value(ace_get, 'set_erspan_gre_proto',
367
+ 'set-erspan-gre-proto')
368
+ return ret if ret
369
+ # position of set_erspan_gre_proto is different in older release
370
+ # so check again
371
+ str = config_get('acl', 'ace', @get_args)
372
+ sstr = str.split
373
+ return sstr[sstr.index('set-erspan-gre-proto') + 1] if
374
+ sstr.include?('set-erspan-gre-proto')
375
+ end
376
+
377
+ def set_erspan_gre_proto=(set_erspan_gre_proto)
378
+ @set_args[:set_erspan_gre_proto] =
379
+ Utils.attach_prefix(set_erspan_gre_proto,
380
+ :set_erspan_gre_proto,
381
+ 'set-erspan-gre-proto')
382
+ end
383
+
264
384
  def time_range
265
385
  Utils.extract_value(ace_get, 'time_range', 'time-range')
266
386
  end
@@ -317,12 +437,27 @@ module Cisco
317
437
  @set_args[:redirect] = Utils.attach_prefix(redirect, :redirect)
318
438
  end
319
439
 
320
- def log
440
+ def proto_option
321
441
  match = ace_get
442
+ return nil if match.nil? || proto != 'icmp' || !remark.nil?
443
+ # fragments is nvgen at a different location than all other
444
+ # proto_option
445
+ if config_get('acl', 'ace', @get_args).include?('fragments')
446
+ return 'fragments'
447
+ end
448
+ # log is special case
449
+ return nil if !match.names.include?('proto_option') ||
450
+ match[:proto_option] == 'log'
451
+ match[:proto_option]
452
+ end
453
+
454
+ def proto_option=(proto_option)
455
+ @set_args[:proto_option] = proto_option
456
+ end
457
+
458
+ def log
322
459
  return nil unless remark.nil?
323
- return false if match.nil?
324
- return false unless match.names.include?('log')
325
- match[:log] == 'log' ? true : false
460
+ config_get('acl', 'ace', @get_args).include?('log') ? true : false
326
461
  end
327
462
 
328
463
  def log=(log)
@@ -0,0 +1,63 @@
1
+ # Banner provider class
2
+ #
3
+ # Rick Sherman et al., August 2018
4
+ #
5
+ # Copyright (c) 2014-2018 Cisco and/or its affiliates.
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+
19
+ require_relative 'node_util'
20
+
21
+ module Cisco
22
+ # Banner - node utility class for Banner configuration management
23
+ class Banner < NodeUtil
24
+ attr_reader :name
25
+
26
+ def initialize(name)
27
+ fail TypeError unless name.is_a?(String)
28
+ fail ArgumentError,
29
+ "This provider only accepts an id of 'default'" \
30
+ unless name.eql?('default')
31
+ @name = name
32
+ end
33
+
34
+ def self.banners
35
+ hash = {}
36
+ hash['default'] = Banner.new('default')
37
+ hash
38
+ end
39
+
40
+ def ==(other)
41
+ name == other.name
42
+ end
43
+
44
+ def motd
45
+ config_get('banner', 'motd')
46
+ end
47
+
48
+ def motd=(val)
49
+ if val.nil? && (motd != default_motd)
50
+ config_set('banner', 'motd', state: 'no', motd: '')
51
+ elsif !val.nil?
52
+ config_set('banner',
53
+ 'motd',
54
+ state: '',
55
+ motd: "^#{val.gsub(/\n/, '\\n')}^")
56
+ end
57
+ end
58
+
59
+ def default_motd
60
+ config_get_default('banner', 'motd')
61
+ end
62
+ end # class
63
+ end # module
@@ -144,7 +144,7 @@ module Cisco
144
144
  # This type property can be defined only for one bd
145
145
  def fabric_control
146
146
  match = config_get('bridge_domain', 'fabric_control', bd: @bd_ids)
147
- match == @bd_ids ? true : false
147
+ match.to_s == @bd_ids ? true : false
148
148
  end
149
149
 
150
150
  def fabric_control=(val)
@@ -362,7 +362,7 @@ module Cisco
362
362
  end # merge_range
363
363
 
364
364
  def self.add_quotes(value)
365
- return value if image_version?(/7.3.0/)
365
+ return value if image_version?(/7.3/)
366
366
  value = "\"#{value}\"" unless
367
367
  value.start_with?('"') && value.end_with?('"')
368
368
  value
@@ -111,16 +111,26 @@ class Cisco::Client
111
111
  return input.map { |item| to_regexp(item) }
112
112
  else
113
113
  # The string might be explicitly formatted as a regexp
114
- if input[0] == '/' && input[-1] == '/'
115
- # '/foo/' => %r{foo}
116
- return Regexp.new(input[1..-2])
117
- elsif input[0] == '/' && input[-2..-1] == '/i'
118
- # '/foo/i' => %r{foo}i
119
- return Regexp.new(input[1..-3], Regexp::IGNORECASE)
120
- else
121
- # 'foo' => %r{^foo$}i
122
- return Regexp.new("^#{input}$", Regexp::IGNORECASE)
114
+ # Dynamically handle modifiers
115
+ input.match(%r{(?<regex>^\/.*\/)(?<options>[imx]*)?}) do |m|
116
+ options = []
117
+ m['options'].each_char do |c|
118
+ case c
119
+ when 'i'
120
+ options << Regexp::IGNORECASE
121
+ when 'm'
122
+ options << Regexp::MULTILINE
123
+ when 'x'
124
+ options << Regexp::EXTENDED
125
+ end
126
+ end
127
+ return Regexp.new(m['regex'][1..-2], options.reduce(:|))
123
128
  end
129
+ # otherwise this value is a regular string
130
+ # convert to case insensitive regex
131
+ # 'foo' => %r{^foo$}i
132
+ return Regexp.new("^#{input}$", Regexp::IGNORECASE)
133
+
124
134
  end
125
135
  end
126
136
 
@@ -151,7 +161,7 @@ class Cisco::Client
151
161
  end
152
162
  return final
153
163
  end
154
- fail "No key \"#{filter}\" in #{data}" if data[filter].nil?
164
+ fail "No key \"#{filter}\" in #{data}" unless data.key?(filter)
155
165
  data = data[filter]
156
166
  end
157
167
  end
@@ -12,7 +12,7 @@ _template:
12
12
 
13
13
  ace:
14
14
  get_value: '/^<seqno> .+$/'
15
- set_value: '<state> <seqno> <action> <proto> <src_addr> <src_port> <dst_addr> <dst_port> <tcp_flags> <established> <precedence> <dscp> <http_method> <time_range> <packet_length> <ttl> <tcp_option_length> <redirect> <log>'
15
+ set_value: '<state> <seqno> <action> <proto> <src_addr> <src_port> <dst_addr> <dst_port> <proto_option> <tcp_flags> <established> <precedence> <dscp> <http_method> <time_range> <packet_length> <ttl> <tcp_option_length> <vlan> <redirect> <set_erspan_dscp> <set_erspan_gre_proto> <log>'
16
16
 
17
17
  ace_destroy:
18
18
  set_value: 'no <seqno>'