openflow-protocol 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/actions/action.rb +26 -0
- data/lib/actions/action_enqueue.rb +12 -0
- data/lib/actions/action_output.rb +10 -0
- data/lib/actions/action_set_destination_port.rb +3 -0
- data/lib/actions/action_set_ip_destination.rb +3 -0
- data/lib/actions/action_set_ip_source.rb +9 -0
- data/lib/actions/action_set_ip_tos.rb +11 -0
- data/lib/actions/action_set_mac_destination.rb +3 -0
- data/lib/actions/action_set_mac_source.rb +11 -0
- data/lib/actions/action_set_source_port.rb +11 -0
- data/lib/actions/action_set_vlan_id.rb +11 -0
- data/lib/actions/action_set_vlan_pcp.rb +11 -0
- data/lib/actions/action_strip_vlan.rb +10 -0
- data/lib/actions/action_vendor.rb +9 -0
- data/lib/actions/actions.rb +28 -0
- data/lib/helpers/enum.rb +45 -0
- data/lib/helpers/flags.rb +49 -0
- data/lib/helpers/ip_address.rb +14 -0
- data/lib/helpers/mac_address.rb +14 -0
- data/lib/helpers/superclass_base.rb +21 -0
- data/lib/messages/barrier_reply.rb +3 -0
- data/lib/messages/barrier_request.rb +3 -0
- data/lib/messages/echo_reply.rb +3 -0
- data/lib/messages/echo_request.rb +9 -0
- data/lib/messages/features_reply.rb +40 -0
- data/lib/messages/features_request.rb +3 -0
- data/lib/messages/flow_mod.rb +20 -0
- data/lib/messages/flow_removed.rb +23 -0
- data/lib/messages/get_config_reply.rb +12 -0
- data/lib/messages/get_config_request.rb +3 -0
- data/lib/messages/hello.rb +3 -0
- data/lib/messages/message.rb +45 -0
- data/lib/messages/packet_in.rb +17 -0
- data/lib/messages/packet_out.rb +13 -0
- data/lib/messages/port_mod.rb +13 -0
- data/lib/messages/port_status.rb +14 -0
- data/lib/messages/set_config.rb +3 -0
- data/lib/messages/statistics.rb +24 -0
- data/lib/messages/statistics_reply.rb +22 -0
- data/lib/messages/statistics_request.rb +14 -0
- data/lib/messages/vendor.rb +10 -0
- data/lib/openflow-protocol.rb +3 -0
- data/lib/statistics/aggregate_statistics_reply.rb +10 -0
- data/lib/statistics/aggregate_statistics_request.rb +3 -0
- data/lib/statistics/description_statistics.rb +28 -0
- data/lib/statistics/flow_statistics_reply.rb +21 -0
- data/lib/statistics/flow_statistics_request.rb +10 -0
- data/lib/statistics/port_statistics_reply.rb +20 -0
- data/lib/statistics/port_statistics_request.rb +8 -0
- data/lib/statistics/queue_statistics_reply.rb +12 -0
- data/lib/statistics/queue_statistics_request.rb +9 -0
- data/lib/statistics/table_statistics.rb +17 -0
- data/lib/statistics/vendor_statistics.rb +7 -0
- data/lib/structs/match.rb +91 -0
- data/lib/structs/physical_port.rb +46 -0
- data/lib/structs/port_number.rb +31 -0
- metadata +100 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 1fc576ecfced9806622867b9ec63625e0547bd50
|
4
|
+
data.tar.gz: ed90aa37d49475ab047c38ae85863ba1f3b8d850
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 679d1d48ba8ee8f06b36d03a2bc0b626b38f8d203c22bdcadc38c34964171011c734427caab89e71d3dfdeaa63d75cda72cfa623b2b22a9ec418183664d7b97c
|
7
|
+
data.tar.gz: 942c5502894b36f8de79c5b5866d129e25587657dbf6102337616dc242534e78432199323ad5df1249ff56c0aea28dba7489a8f7039e77847cb49c91ce069fc2
|
@@ -0,0 +1,26 @@
|
|
1
|
+
(Dir[File.expand_path '../helpers/**/*.rb', __dir__] +
|
2
|
+
Dir[File.expand_path '../structs/**/*.rb', __dir__]).each do |file|
|
3
|
+
require file
|
4
|
+
end
|
5
|
+
|
6
|
+
class OFAction < SuperclassBase
|
7
|
+
HEADER_LENGTH = 4
|
8
|
+
TYPES = [
|
9
|
+
:output,
|
10
|
+
:set_vlan_id,
|
11
|
+
:set_vlan_pcp,
|
12
|
+
:strip_vlan,
|
13
|
+
:set_mac_source, # set_dl_src
|
14
|
+
:set_mac_destination, # set_dl_dst
|
15
|
+
:set_ip_source, # set_nw_src
|
16
|
+
:set_ip_destination, # set_nw_dst
|
17
|
+
:set_ip_tos, # set_nw_tos
|
18
|
+
:set_source_port, # set_tp_src
|
19
|
+
:set_destination_port, # set_tp_dst
|
20
|
+
:enqueue
|
21
|
+
]
|
22
|
+
TYPES[0xffff] = :vendor
|
23
|
+
|
24
|
+
enum16 :type, list: TYPES, asserted_value: -> { type_str.to_sym }
|
25
|
+
uint16 :len, value: -> { HEADER_LENGTH + body_length }
|
26
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
Dir[File.expand_path 'action_*.rb', __dir__].each do |file|
|
2
|
+
require file
|
3
|
+
end
|
4
|
+
|
5
|
+
class OFActions < BinData::Primitive
|
6
|
+
default_parameter length: 0
|
7
|
+
endian :big
|
8
|
+
string :binary, read_length: :length
|
9
|
+
|
10
|
+
def get
|
11
|
+
actions = []
|
12
|
+
tmp = binary
|
13
|
+
until tmp.empty?
|
14
|
+
type_index = BinData::Uint16be.read(tmp)
|
15
|
+
type_str = OFAction::TYPES.fetch(type_index)
|
16
|
+
class_name = 'OFAction' + type_str.to_s.split('_').map(&:capitalize).join
|
17
|
+
klass = Object.const_get class_name
|
18
|
+
action = klass.read(tmp)
|
19
|
+
actions << action
|
20
|
+
tmp = tmp[action.len..-1]
|
21
|
+
end
|
22
|
+
actions
|
23
|
+
end
|
24
|
+
|
25
|
+
def set(value)
|
26
|
+
self.binary = value.map(&:to_binary_s).join
|
27
|
+
end
|
28
|
+
end
|
data/lib/helpers/enum.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'bindata'
|
2
|
+
|
3
|
+
def _def_enum(size)
|
4
|
+
eval %(
|
5
|
+
class Enum#{size} < BinData::Primitive
|
6
|
+
mandatory_parameter :list
|
7
|
+
|
8
|
+
endian :big
|
9
|
+
uint#{size} :enum, initial_value: 0
|
10
|
+
|
11
|
+
def get
|
12
|
+
list.invert.fetch(enum)
|
13
|
+
rescue KeyError
|
14
|
+
enum
|
15
|
+
end
|
16
|
+
|
17
|
+
def set(value)
|
18
|
+
self.enum = list.fetch(value)
|
19
|
+
rescue KeyError
|
20
|
+
self.enum = value
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def list
|
26
|
+
list = eval_parameter(:list)
|
27
|
+
case list
|
28
|
+
when Array
|
29
|
+
shift = 0
|
30
|
+
list.each_with_object({}) do |each, result|
|
31
|
+
result[each] = shift
|
32
|
+
shift += 1
|
33
|
+
result
|
34
|
+
end
|
35
|
+
when Hash
|
36
|
+
list
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
)
|
41
|
+
end
|
42
|
+
|
43
|
+
_def_enum 8
|
44
|
+
_def_enum 16
|
45
|
+
_def_enum 32
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'bindata'
|
2
|
+
|
3
|
+
def _def_flags(size)
|
4
|
+
eval %(
|
5
|
+
class Flags#{size} < BinData::Primitive
|
6
|
+
mandatory_parameter :list
|
7
|
+
|
8
|
+
endian :big
|
9
|
+
uint#{size} :flags, initial_value: 0
|
10
|
+
|
11
|
+
def get
|
12
|
+
list.each_with_object([]) do |(key, value), result|
|
13
|
+
result << key if (flags & value != 0) || (flags == value)
|
14
|
+
result
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def set(value)
|
19
|
+
value.each do |each|
|
20
|
+
fail "Invalid flag: \#{value}" unless list.keys.include?(each)
|
21
|
+
end
|
22
|
+
self.flags = value.empty? ?
|
23
|
+
0 :
|
24
|
+
value.map { |each| list[each] }.inject(:|)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def list
|
30
|
+
list = eval_parameter(:list)
|
31
|
+
case list
|
32
|
+
when Array
|
33
|
+
shift = 0
|
34
|
+
list.each_with_object({}) do |each, result|
|
35
|
+
result[each] = 1 << shift
|
36
|
+
shift += 1
|
37
|
+
result
|
38
|
+
end
|
39
|
+
when Hash
|
40
|
+
list
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
)
|
45
|
+
end
|
46
|
+
|
47
|
+
_def_flags 8
|
48
|
+
_def_flags 16
|
49
|
+
_def_flags 32
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'bindata'
|
2
|
+
|
3
|
+
class MacAddress < BinData::Primitive
|
4
|
+
endian :big
|
5
|
+
array :octets, type: :uint8, initial_length: 6
|
6
|
+
|
7
|
+
def get
|
8
|
+
octets.map { |octet| format('%02x', octet) }.join(':')
|
9
|
+
end
|
10
|
+
|
11
|
+
def set(value)
|
12
|
+
self.octets = value.split(':').map(&:hex)
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'bindata'
|
2
|
+
|
3
|
+
class SuperclassBase < BinData::Record
|
4
|
+
attr_reader :type_str
|
5
|
+
|
6
|
+
endian :big
|
7
|
+
|
8
|
+
def initialize_instance
|
9
|
+
super
|
10
|
+
if self.class.name[2..7] == 'Action'
|
11
|
+
name = self.class.name[8..-1]
|
12
|
+
else
|
13
|
+
name = self.class.name[2..-1]
|
14
|
+
end
|
15
|
+
@type_str = name.gsub(/([A-Z])/, '_\1')[1..-1].downcase
|
16
|
+
end
|
17
|
+
|
18
|
+
def body_length
|
19
|
+
0
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require_relative 'message'
|
2
|
+
|
3
|
+
class OFFeaturesReply < OFMessage
|
4
|
+
uint64 :datapath_id, initial_value: 0
|
5
|
+
uint32 :n_buffers, initial_value: 0
|
6
|
+
uint8 :n_tables, initial_value: 0
|
7
|
+
uint24 :padding
|
8
|
+
hide :padding
|
9
|
+
flags32 :capabilities, list: [
|
10
|
+
:flow_stats,
|
11
|
+
:table_stats,
|
12
|
+
:port_stats,
|
13
|
+
:stp,
|
14
|
+
:reserved,
|
15
|
+
:ip_reasm,
|
16
|
+
:queue_stats,
|
17
|
+
:arp_match_ip
|
18
|
+
]
|
19
|
+
flags32 :actions, list: [
|
20
|
+
:output,
|
21
|
+
:set_vlan_vid,
|
22
|
+
:set_vlan_pcp,
|
23
|
+
:strip_vlan,
|
24
|
+
:set_dl_src,
|
25
|
+
:set_dl_dst,
|
26
|
+
:set_nw_src,
|
27
|
+
:set_nw_dst,
|
28
|
+
:set_nw_tos,
|
29
|
+
:set_tp_src,
|
30
|
+
:set_tp_dst,
|
31
|
+
:enqueue
|
32
|
+
]
|
33
|
+
array :ports,
|
34
|
+
type: :of_physical_port,
|
35
|
+
initial_length: -> { (len - ports.rel_offset) / 48 }
|
36
|
+
|
37
|
+
def body_length
|
38
|
+
24 + ports.to_binary_s.length
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require_relative 'message'
|
2
|
+
|
3
|
+
class OFFlowMod < OFMessage
|
4
|
+
of_match :match
|
5
|
+
uint64 :cookie, initial_value: 0
|
6
|
+
enum16 :command, list: [:add, :modify, :modify_strict, :delete, :delete_strict]
|
7
|
+
uint16 :idle_timeout, initial_value: 0
|
8
|
+
uint16 :hard_timeout, initial_value: 0
|
9
|
+
uint16 :priority, initial_value: 0
|
10
|
+
uint32 :buffer_id, initial_value: 0xffffffff
|
11
|
+
of_port_number :out_port, initial_value: (lambda do
|
12
|
+
/^delete/ =~ command.to_s ? :none : 0
|
13
|
+
end)
|
14
|
+
flags16 :flags, list: [:send_flow_removed, :check_overlapping, :emergency]
|
15
|
+
of_actions :actions, length: -> { len - actions.rel_offset }
|
16
|
+
|
17
|
+
def body_length
|
18
|
+
64 + actions.to_binary_s.length
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require_relative 'message'
|
2
|
+
|
3
|
+
class OFFlowRemoved < OFMessage
|
4
|
+
REASONS = [:idle_timeout, :hard_timeout, :delete]
|
5
|
+
|
6
|
+
of_match :match
|
7
|
+
uint64 :cookie, initial_value: 0
|
8
|
+
uint16 :priority, initial_value: 0
|
9
|
+
enum8 :reason, list: REASONS
|
10
|
+
uint8 :padding
|
11
|
+
hide :padding
|
12
|
+
uint32 :duration_seconds, initial_value: 0
|
13
|
+
uint32 :duration_nanoseconds, initial_value: 0
|
14
|
+
uint16 :idle_timeout, initial_value: 0
|
15
|
+
uint16 :padding2
|
16
|
+
hide :padding2
|
17
|
+
uint64 :packet_count, initial_value: 0
|
18
|
+
uint64 :byte_count, initial_value: 0
|
19
|
+
|
20
|
+
def body_length
|
21
|
+
80
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
(Dir[File.expand_path '../helpers/**/*.rb', __dir__] +
|
2
|
+
Dir[File.expand_path '../structs/**/*.rb', __dir__] +
|
3
|
+
Dir[File.expand_path '../actions/**/*.rb', __dir__] +
|
4
|
+
Dir[File.expand_path '../statistics/**/*.rb', __dir__]).each do |file|
|
5
|
+
require file
|
6
|
+
end
|
7
|
+
|
8
|
+
# TODO: use OFPT_, OFPP_, OFPQ_, ... in place of Symbols?
|
9
|
+
# check: https://github.com/noxrepo/pox/blob/carp/pox/openflow/libopenflow_01.py
|
10
|
+
# -> see decorators
|
11
|
+
# ruby decorators: https://github.com/fredwu/ruby_decorators
|
12
|
+
|
13
|
+
class OFMessage < SuperclassBase
|
14
|
+
OFP_VERSION = 0x1
|
15
|
+
HEADER_LENGTH = 8
|
16
|
+
TYPES = [
|
17
|
+
:hello,
|
18
|
+
:error, # TODO
|
19
|
+
:echo_request,
|
20
|
+
:echo_reply,
|
21
|
+
:vendor,
|
22
|
+
:features_request,
|
23
|
+
:features_reply,
|
24
|
+
:get_config_request,
|
25
|
+
:get_config_reply,
|
26
|
+
:set_config,
|
27
|
+
:packet_in,
|
28
|
+
:flow_removed,
|
29
|
+
:port_status,
|
30
|
+
:packet_out,
|
31
|
+
:flow_mod,
|
32
|
+
:port_mod,
|
33
|
+
:statistics_request,
|
34
|
+
:statistics_reply,
|
35
|
+
:barrier_request,
|
36
|
+
:barrier_reply,
|
37
|
+
:queue_get_config_request, # TODO
|
38
|
+
:queue_get_config_reply # TODO
|
39
|
+
]
|
40
|
+
|
41
|
+
uint8 :version, asserted_value: OFP_VERSION
|
42
|
+
enum8 :type, list: TYPES, asserted_value: -> { type_str.to_sym }
|
43
|
+
uint16 :len, value: -> { HEADER_LENGTH + body_length }
|
44
|
+
uint32 :xid, initial_value: 0
|
45
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require_relative 'message'
|
2
|
+
|
3
|
+
class OFPacketIn < OFMessage
|
4
|
+
REASONS = [:no_match, :action]
|
5
|
+
|
6
|
+
enum32 :buffer_id, list: {none: 0xffffffff}, initial_value: -> { :none }
|
7
|
+
uint16 :total_length, value: -> { data.length }
|
8
|
+
of_port_number :in_port
|
9
|
+
enum8 :reason, list: REASONS
|
10
|
+
uint8 :padding
|
11
|
+
hide :padding
|
12
|
+
string :data, read_length: :total_length
|
13
|
+
|
14
|
+
def body_length
|
15
|
+
10 + data.length
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require_relative 'message'
|
2
|
+
|
3
|
+
class OFPacketOut < OFMessage
|
4
|
+
enum32 :buffer_id, list: {none: 0xffffffff}, initial_value: -> { :none }
|
5
|
+
of_port_number :in_port
|
6
|
+
uint16 :actions_length, value: -> { actions.to_binary_s.length }
|
7
|
+
of_actions :actions, length: -> { actions_length }
|
8
|
+
string :data, read_length: -> { len - data.rel_offset }
|
9
|
+
|
10
|
+
def body_length
|
11
|
+
8 + actions_length + data.length
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require_relative 'message'
|
2
|
+
|
3
|
+
class OFPortMod < OFMessage
|
4
|
+
of_port_number :port_number
|
5
|
+
mac_address :hardware_address
|
6
|
+
flags32 :config, list: OFPhysicalPort::CONFIG
|
7
|
+
flags32 :mask, list: OFPhysicalPort::CONFIG
|
8
|
+
flags32 :advertise, list: OFPhysicalPort::FEATURES
|
9
|
+
|
10
|
+
def body_length
|
11
|
+
24
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require_relative 'message'
|
2
|
+
|
3
|
+
class OFStatistics < OFMessage
|
4
|
+
STATISTICS_TYPES = [
|
5
|
+
:description,
|
6
|
+
:flow,
|
7
|
+
:aggregate,
|
8
|
+
:table,
|
9
|
+
:port,
|
10
|
+
:queue
|
11
|
+
]
|
12
|
+
STATISTICS_TYPES[0xffff] = :vendor
|
13
|
+
|
14
|
+
def flags_list
|
15
|
+
self.class.const_get(:FLAGS)
|
16
|
+
end
|
17
|
+
|
18
|
+
enum16 :statistic_type, list: STATISTICS_TYPES
|
19
|
+
flags16 :flags, list: -> { flags_list }
|
20
|
+
|
21
|
+
def body_length
|
22
|
+
4 + statistics.to_binary_s.length
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require_relative 'statistics'
|
2
|
+
|
3
|
+
class OFStatisticsReply < OFStatistics
|
4
|
+
FLAGS = [:reply_more]
|
5
|
+
|
6
|
+
choice :statistics, selection: -> { statistic_type.to_s } do
|
7
|
+
of_description_statistics 'description'
|
8
|
+
of_flow_statistics_reply 'flow'
|
9
|
+
of_aggregate_statistics_reply 'aggregate'
|
10
|
+
array 'table',
|
11
|
+
type: :of_table_statistics,
|
12
|
+
initial_length: -> { (len - statistics.rel_offset) / 64 }
|
13
|
+
array 'port',
|
14
|
+
type: :of_port_statistics_reply,
|
15
|
+
initial_length: -> { (len - statistics.rel_offset) / 104 }
|
16
|
+
array 'queue',
|
17
|
+
type: :of_queue_statistics_reply,
|
18
|
+
initial_length: -> { (len - statistics.rel_offset) / 32 }
|
19
|
+
of_vendor_statistics 'vendor'
|
20
|
+
rest :default
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require_relative 'statistics'
|
2
|
+
|
3
|
+
class OFStatisticsRequest < OFStatistics
|
4
|
+
FLAGS = []
|
5
|
+
|
6
|
+
choice :statistics, selection: -> { statistic_type.to_s } do
|
7
|
+
of_flow_statistics_request 'flow'
|
8
|
+
of_aggregate_statistics_request 'aggregate'
|
9
|
+
of_port_statistics_request 'port'
|
10
|
+
of_queue_statistics_request 'queue'
|
11
|
+
of_vendor_statistics 'vendor'
|
12
|
+
rest :default
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'bindata'
|
2
|
+
|
3
|
+
class OFDescriptionStatistics < BinData::Record
|
4
|
+
DESCRIPTION_LENGTH = 256
|
5
|
+
SERIAL_NUMBER_LENGTH = 32
|
6
|
+
|
7
|
+
endian :big
|
8
|
+
string :manufacturer_description,
|
9
|
+
length: DESCRIPTION_LENGTH,
|
10
|
+
trim_padding: true,
|
11
|
+
initial_value: ''
|
12
|
+
string :hardware_description,
|
13
|
+
length: DESCRIPTION_LENGTH,
|
14
|
+
trim_padding: true,
|
15
|
+
initial_value: ''
|
16
|
+
string :software_description,
|
17
|
+
length: DESCRIPTION_LENGTH,
|
18
|
+
trim_padding: true,
|
19
|
+
initial_value: ''
|
20
|
+
string :serial_number,
|
21
|
+
length: SERIAL_NUMBER_LENGTH,
|
22
|
+
trim_padding: true,
|
23
|
+
initial_value: ''
|
24
|
+
string :datapath_description,
|
25
|
+
length: DESCRIPTION_LENGTH,
|
26
|
+
trim_padding: true,
|
27
|
+
initial_value: ''
|
28
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require_relative 'table_statistics'
|
2
|
+
|
3
|
+
class OFFlowStatisticsReply < BinData::Record
|
4
|
+
endian :big
|
5
|
+
uint16 :len, initial_value: -> { 88 + actions.to_binary_s.length }
|
6
|
+
enum8 :table_id, list: OFTableStatistics::TABLE_IDS, initial_value: -> { :all }
|
7
|
+
uint8 :padding
|
8
|
+
hide :padding
|
9
|
+
of_match :match
|
10
|
+
uint32 :duration_seconds, initial_value: 0
|
11
|
+
uint32 :duration_nanoseconds, initial_value: 0
|
12
|
+
uint16 :priority, initial_value: 0
|
13
|
+
uint16 :idle_timeout, initial_value: 0
|
14
|
+
uint16 :hard_timeout, initial_value: 0
|
15
|
+
uint48 :padding2
|
16
|
+
hide :padding2
|
17
|
+
uint64 :cookie, initial_value: 0
|
18
|
+
uint64 :packet_count, initial_value: 0
|
19
|
+
uint64 :byte_count, initial_value: 0
|
20
|
+
of_actions :actions, length: -> { len - actions.rel_offset }
|
21
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require_relative 'table_statistics'
|
2
|
+
|
3
|
+
class OFFlowStatisticsRequest < BinData::Record
|
4
|
+
endian :big
|
5
|
+
of_match :match
|
6
|
+
enum8 :table_id, list: OFTableStatistics::TABLE_IDS, initial_value: -> { :all }
|
7
|
+
uint8 :padding
|
8
|
+
hide :padding
|
9
|
+
of_port_number :out_port, initial_value: -> { :none }
|
10
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require_relative '../structs/port_number'
|
2
|
+
|
3
|
+
class OFPortStatisticsReply < BinData::Record
|
4
|
+
endian :big
|
5
|
+
of_port_number :port_number, initial_value: 0
|
6
|
+
uint48 :padding
|
7
|
+
hide :padding
|
8
|
+
uint64 :receive_packets, initial_value: 0
|
9
|
+
uint64 :transmit_packets, initial_value: 0
|
10
|
+
uint64 :receive_bytes, initial_value: 0
|
11
|
+
uint64 :transmit_bytes, initial_value: 0
|
12
|
+
uint64 :receive_dropped, initial_value: 0
|
13
|
+
uint64 :transmit_dropped, initial_value: 0
|
14
|
+
uint64 :receive_errors, initial_value: 0
|
15
|
+
uint64 :transmit_errors, initial_value: 0
|
16
|
+
uint64 :receive_frame_errors, initial_value: 0
|
17
|
+
uint64 :receive_overrun_errors, initial_value: 0
|
18
|
+
uint64 :receive_crc_errors, initial_value: 0
|
19
|
+
uint64 :collisions, initial_value: 0
|
20
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require_relative '../structs/port_number'
|
2
|
+
|
3
|
+
class OFQueueStatisticsReply < BinData::Record
|
4
|
+
endian :big
|
5
|
+
of_port_number :port_number, initial_value: 0
|
6
|
+
uint16 :padding
|
7
|
+
hide :padding
|
8
|
+
uint32 :queue_id, initial_value: 0
|
9
|
+
uint64 :transmit_bytes, initial_value: 0
|
10
|
+
uint64 :transmit_packets, initial_value: 0
|
11
|
+
uint64 :transmit_errors, initial_value: 0
|
12
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require_relative '../structs/port_number'
|
2
|
+
|
3
|
+
class OFQueueStatisticsRequest < BinData::Record
|
4
|
+
endian :big
|
5
|
+
of_port_number :port_number, initial_value: -> { :all }
|
6
|
+
uint16 :padding
|
7
|
+
hide :padding
|
8
|
+
enum32 :queue_id, list: {all: 0xffffffff}, initial_value: -> { :all }
|
9
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require_relative '../structs/match'
|
2
|
+
require_relative '../helpers/flags'
|
3
|
+
|
4
|
+
class OFTableStatistics < BinData::Record
|
5
|
+
TABLE_IDS = {emergency: 0xfe, all: 0xff}
|
6
|
+
|
7
|
+
endian :big
|
8
|
+
enum8 :table_id, list: TABLE_IDS, initial_value: 0
|
9
|
+
uint24 :padding
|
10
|
+
hide :padding
|
11
|
+
string :name, length: 32, trim_padding: true, initial_value: ''
|
12
|
+
flags32 :wildcards, list: OFMatch::Wildcards::FLAGS
|
13
|
+
uint32 :max_entries, initial_value: 0
|
14
|
+
uint32 :active_count, initial_value: 0
|
15
|
+
uint64 :lookup_count, initial_value: 0
|
16
|
+
uint64 :matched_count, initial_value: 0
|
17
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'English'
|
2
|
+
require_relative '../helpers/enum'
|
3
|
+
require_relative '../helpers/mac_address'
|
4
|
+
require_relative '../helpers/ip_address'
|
5
|
+
require_relative 'port_number'
|
6
|
+
|
7
|
+
class OFMatch < BinData::Record
|
8
|
+
class Wildcards < BinData::Primitive
|
9
|
+
FLAGS = {
|
10
|
+
in_port: 1 << 0,
|
11
|
+
vlan_id: 1 << 1,
|
12
|
+
mac_source: 1 << 2,
|
13
|
+
mac_destination: 1 << 3,
|
14
|
+
mac_protocol: 1 << 4,
|
15
|
+
ip_protocol: 1 << 5,
|
16
|
+
source_port: 1 << 6,
|
17
|
+
destination_port: 1 << 7,
|
18
|
+
ip_source0: 1 << 8,
|
19
|
+
ip_source1: 1 << 9,
|
20
|
+
ip_source2: 1 << 10,
|
21
|
+
ip_source3: 1 << 11,
|
22
|
+
ip_source4: 1 << 12,
|
23
|
+
ip_source_all: 1 << 13,
|
24
|
+
ip_destination0: 1 << 14,
|
25
|
+
ip_destination1: 1 << 15,
|
26
|
+
ip_destination2: 1 << 16,
|
27
|
+
ip_destination3: 1 << 17,
|
28
|
+
ip_destination4: 1 << 18,
|
29
|
+
ip_destination_all: 1 << 19,
|
30
|
+
vlan_pcp: 1 << 20,
|
31
|
+
ip_tos: 1 << 21
|
32
|
+
}
|
33
|
+
ALL_FLAGS = Hash[
|
34
|
+
FLAGS.keys.select { |key| /^ip_(source|destination)\d$/ !~ key }
|
35
|
+
.map { |key| [key, true] }
|
36
|
+
]
|
37
|
+
|
38
|
+
endian :big
|
39
|
+
uint32 :flags, initial_value: 0x003820ff # all
|
40
|
+
|
41
|
+
def get
|
42
|
+
FLAGS.each_with_object(Hash.new(0)) do |(key, bit), memo|
|
43
|
+
next if flags & bit == 0
|
44
|
+
if /^(ip_source|ip_destination)(\d)/ =~ key
|
45
|
+
memo[$LAST_MATCH_INFO[1].to_sym] |= 1 << $LAST_MATCH_INFO[2].to_i
|
46
|
+
else
|
47
|
+
memo[key] = true
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def set(value)
|
53
|
+
self.flags = value.inject(0) do |memo, (key, val)|
|
54
|
+
memo |
|
55
|
+
case key
|
56
|
+
when :ip_source, :ip_destination
|
57
|
+
(val & 31) << (key == :ip_source ? 8 : 14)
|
58
|
+
else
|
59
|
+
val ? FLAGS.fetch(key) : 0
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
endian :big
|
66
|
+
wildcards :wildcards
|
67
|
+
of_port_number :in_port, initial_value: 0
|
68
|
+
mac_address :mac_source
|
69
|
+
mac_address :mac_destination
|
70
|
+
uint16 :vlan_id, initial_value: 0xffff
|
71
|
+
uint8 :vlan_pcp, initial_value: 0
|
72
|
+
uint8 :padding
|
73
|
+
hide :padding
|
74
|
+
enum16 :mac_protocol, list: {
|
75
|
+
ip: 0x0800,
|
76
|
+
arp: 0x0806,
|
77
|
+
vlan: 0x8100
|
78
|
+
}, initial_value: 0
|
79
|
+
uint8 :ip_tos, initial_value: 0
|
80
|
+
enum8 :ip_protocol, list: {
|
81
|
+
icmp: 1,
|
82
|
+
tcp: 6,
|
83
|
+
udp: 17
|
84
|
+
}, initial_value: 0
|
85
|
+
uint16 :padding2
|
86
|
+
hide :padding2
|
87
|
+
ip_address :ip_source
|
88
|
+
ip_address :ip_destination
|
89
|
+
uint16 :source_port, initial_value: 0
|
90
|
+
uint16 :destination_port, initial_value: 0
|
91
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require_relative 'port_number'
|
2
|
+
require_relative '../helpers/mac_address'
|
3
|
+
|
4
|
+
class OFPhysicalPort < BinData::Record
|
5
|
+
CONFIG = [
|
6
|
+
:port_down,
|
7
|
+
:no_spanning_tree,
|
8
|
+
:no_receive,
|
9
|
+
:no_receive_spanning_tree,
|
10
|
+
:no_flood,
|
11
|
+
:no_forward,
|
12
|
+
:no_packet_in
|
13
|
+
]
|
14
|
+
STATE = {
|
15
|
+
link_down: 1 << 0,
|
16
|
+
spanning_tree_listen: 0 << 8,
|
17
|
+
spanning_tree_learn: 1 << 8,
|
18
|
+
spanning_tree_forward: 2 << 8,
|
19
|
+
spanning_tree_block: 3 << 8
|
20
|
+
}
|
21
|
+
FEATURES = [
|
22
|
+
:port_10mb_half_duplex,
|
23
|
+
:port_10mb_full_duplex,
|
24
|
+
:port_100mb_half_duplex,
|
25
|
+
:port_100mb_full_duplex,
|
26
|
+
:port_1gb_half_duplex,
|
27
|
+
:port_1gb_full_duplex,
|
28
|
+
:port_10gb_full_duplex,
|
29
|
+
:port_copper,
|
30
|
+
:port_fiber,
|
31
|
+
:port_auto_negotiation,
|
32
|
+
:port_pause,
|
33
|
+
:port_pause_asymmetric
|
34
|
+
]
|
35
|
+
|
36
|
+
endian :big
|
37
|
+
of_port_number :port_number, initial_value: 0
|
38
|
+
mac_address :hardware_address
|
39
|
+
string :name, length: 16, trim_padding: true, initial_value: ''
|
40
|
+
flags32 :config, list: CONFIG
|
41
|
+
flags32 :state, list: STATE
|
42
|
+
flags32 :current_features, list: FEATURES
|
43
|
+
flags32 :advertised_features, list: FEATURES
|
44
|
+
flags32 :supported_features, list: FEATURES
|
45
|
+
flags32 :peer_features, list: FEATURES
|
46
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'bindata'
|
2
|
+
|
3
|
+
class OFPortNumber < BinData::Primitive
|
4
|
+
NUMBERS = {
|
5
|
+
in_port: 0xfff8,
|
6
|
+
table: 0xfff9,
|
7
|
+
normal: 0xfffa,
|
8
|
+
flood: 0xfffb,
|
9
|
+
all: 0xfffc,
|
10
|
+
controller: 0xfffd,
|
11
|
+
local: 0xfffe,
|
12
|
+
none: 0xffff
|
13
|
+
}
|
14
|
+
MAX = 0xff00
|
15
|
+
|
16
|
+
endian :big
|
17
|
+
uint16 :port_number, initial_value: NUMBERS[:none]
|
18
|
+
|
19
|
+
def get
|
20
|
+
NUMBERS.invert.fetch(port_number)
|
21
|
+
rescue KeyError
|
22
|
+
port_number
|
23
|
+
end
|
24
|
+
|
25
|
+
def set(value)
|
26
|
+
self.port_number = NUMBERS.fetch(value)
|
27
|
+
rescue KeyError
|
28
|
+
raise ArgumentError, 'Invalid port number.' unless (0..MAX).include? value
|
29
|
+
self.port_number = value
|
30
|
+
end
|
31
|
+
end
|
metadata
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: openflow-protocol
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jeremy Page
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-04-08 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: An OpenFlow Parser/Serializer.
|
14
|
+
email:
|
15
|
+
- jeremy@jeremypage.me
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- lib/actions/action.rb
|
21
|
+
- lib/actions/action_enqueue.rb
|
22
|
+
- lib/actions/action_output.rb
|
23
|
+
- lib/actions/action_set_destination_port.rb
|
24
|
+
- lib/actions/action_set_ip_destination.rb
|
25
|
+
- lib/actions/action_set_ip_source.rb
|
26
|
+
- lib/actions/action_set_ip_tos.rb
|
27
|
+
- lib/actions/action_set_mac_destination.rb
|
28
|
+
- lib/actions/action_set_mac_source.rb
|
29
|
+
- lib/actions/action_set_source_port.rb
|
30
|
+
- lib/actions/action_set_vlan_id.rb
|
31
|
+
- lib/actions/action_set_vlan_pcp.rb
|
32
|
+
- lib/actions/action_strip_vlan.rb
|
33
|
+
- lib/actions/action_vendor.rb
|
34
|
+
- lib/actions/actions.rb
|
35
|
+
- lib/helpers/enum.rb
|
36
|
+
- lib/helpers/flags.rb
|
37
|
+
- lib/helpers/ip_address.rb
|
38
|
+
- lib/helpers/mac_address.rb
|
39
|
+
- lib/helpers/superclass_base.rb
|
40
|
+
- lib/messages/barrier_reply.rb
|
41
|
+
- lib/messages/barrier_request.rb
|
42
|
+
- lib/messages/echo_reply.rb
|
43
|
+
- lib/messages/echo_request.rb
|
44
|
+
- lib/messages/features_reply.rb
|
45
|
+
- lib/messages/features_request.rb
|
46
|
+
- lib/messages/flow_mod.rb
|
47
|
+
- lib/messages/flow_removed.rb
|
48
|
+
- lib/messages/get_config_reply.rb
|
49
|
+
- lib/messages/get_config_request.rb
|
50
|
+
- lib/messages/hello.rb
|
51
|
+
- lib/messages/message.rb
|
52
|
+
- lib/messages/packet_in.rb
|
53
|
+
- lib/messages/packet_out.rb
|
54
|
+
- lib/messages/port_mod.rb
|
55
|
+
- lib/messages/port_status.rb
|
56
|
+
- lib/messages/set_config.rb
|
57
|
+
- lib/messages/statistics.rb
|
58
|
+
- lib/messages/statistics_reply.rb
|
59
|
+
- lib/messages/statistics_request.rb
|
60
|
+
- lib/messages/vendor.rb
|
61
|
+
- lib/openflow-protocol.rb
|
62
|
+
- lib/statistics/aggregate_statistics_reply.rb
|
63
|
+
- lib/statistics/aggregate_statistics_request.rb
|
64
|
+
- lib/statistics/description_statistics.rb
|
65
|
+
- lib/statistics/flow_statistics_reply.rb
|
66
|
+
- lib/statistics/flow_statistics_request.rb
|
67
|
+
- lib/statistics/port_statistics_reply.rb
|
68
|
+
- lib/statistics/port_statistics_request.rb
|
69
|
+
- lib/statistics/queue_statistics_reply.rb
|
70
|
+
- lib/statistics/queue_statistics_request.rb
|
71
|
+
- lib/statistics/table_statistics.rb
|
72
|
+
- lib/statistics/vendor_statistics.rb
|
73
|
+
- lib/structs/match.rb
|
74
|
+
- lib/structs/physical_port.rb
|
75
|
+
- lib/structs/port_number.rb
|
76
|
+
homepage: https://github.com/jejepage/openflow-protocol
|
77
|
+
licenses:
|
78
|
+
- MIT
|
79
|
+
metadata: {}
|
80
|
+
post_install_message:
|
81
|
+
rdoc_options: []
|
82
|
+
require_paths:
|
83
|
+
- lib
|
84
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
90
|
+
requirements:
|
91
|
+
- - ">="
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
requirements: []
|
95
|
+
rubyforge_project:
|
96
|
+
rubygems_version: 2.4.6
|
97
|
+
signing_key:
|
98
|
+
specification_version: 4
|
99
|
+
summary: OpenFlow Protocol
|
100
|
+
test_files: []
|