Openflow parser

This commit is contained in:
Eishun Kondoh 2017-11-13 22:52:53 +09:00
parent 70b0d8919e
commit fc02a678de
338 changed files with 9081 additions and 0 deletions

View file

@ -0,0 +1,19 @@
defmodule Openflow.Multipart.Aggregate.Reply do
defstruct(
version: 4,
xid: 0,
datapath_id: nil, # virtual field
flags: [],
packet_count: 0,
byte_count: 0,
flow_count: 0
)
alias __MODULE__
def ofp_type, do: 18
def read(<<packet_count::64, byte_count::64, flow_count::32, _::size(4)-unit(8)>>) do
%Reply{packet_count: packet_count, byte_count: byte_count, flow_count: flow_count}
end
end

View file

@ -0,0 +1,67 @@
defmodule Openflow.Multipart.Aggregate.Request do
defstruct(
version: 4,
xid: 0,
datapath_id: nil, # virtual field
flags: [],
table_id: :all,
out_port: :any,
out_group: :any,
cookie: 0,
cookie_mask: 0,
match: []
)
alias __MODULE__
def ofp_type, do: 18
def new(options) do
table_id = Keyword.get(options, :table_id, :all)
out_port = Keyword.get(options, :out_port, :any)
out_group = Keyword.get(options, :out_group, :any)
cookie = Keyword.get(options, :cookie, 0)
cookie_mask = Keyword.get(options, :cookie, 0)
match = Keyword.get(options, :match, [])
%Request{table_id: table_id,
out_port: out_port,
out_group: out_group,
cookie: cookie,
cookie_mask: cookie_mask,
match: match}
end
def read(<<table_id_int::8, _::size(3)-unit(8),
out_port_int::32, out_group_int::32,
_::size(4)-unit(8), cookie::64,
cookie_mask::64, match_bin::bytes>>) do
table_id = Openflow.Utils.get_enum(table_id_int, :table_id)
out_port = Openflow.Utils.get_enum(out_port_int, :openflow13_port_no)
out_group = Openflow.Utils.get_enum(out_group_int, :group_id)
{match, _rest} = Openflow.Match.read(match_bin)
%Request{table_id: table_id,
out_port: out_port,
out_group: out_group,
cookie: cookie,
cookie_mask: cookie_mask,
match: match}
end
def to_binary(%Request{table_id: table_id,
out_port: out_port,
out_group: out_group,
cookie: cookie,
cookie_mask: cookie_mask,
match: match} = msg) do
table_id_int = Openflow.Utils.get_enum(table_id, :table_id)
out_port_int = Openflow.Utils.get_enum(out_port, :openflow13_port_no)
out_group_int = Openflow.Utils.get_enum(out_group, :group_id)
match_bin = Openflow.Match.to_binary(match)
body_bin = <<table_id_int::8, 0::size(3)-unit(8),
out_port_int::32, out_group_int::32,
0::size(4)-unit(8), cookie::64,
cookie_mask::64, match_bin::bytes>>
header_bin = Openflow.Multipart.Request.header(msg)
<<header_bin::bytes, body_bin::bytes>>
end
end

View file

@ -0,0 +1,30 @@
defmodule Openflow.Multipart.Desc.Reply do
defstruct(
version: 4,
xid: 0,
datapath_id: nil, # virtual field
flags: [],
mfr_desc: "",
hw_desc: "",
sw_desc: "",
serial_num: "",
dp_desc: ""
)
alias __MODULE__
@desc_str_len 256
@serial_num_len 32
def ofp_type, do: 19
def read(<<mfr_desc::size(@desc_str_len)-bytes, hw_desc::size(@desc_str_len)-bytes,
sw_desc::size(@desc_str_len)-bytes, serial_num::size(@serial_num_len)-bytes,
dp_desc::size(@desc_str_len)-bytes>>) do
%Reply{mfr_desc: Openflow.Utils.decode_string(mfr_desc),
hw_desc: Openflow.Utils.decode_string(hw_desc),
sw_desc: Openflow.Utils.decode_string(sw_desc),
serial_num: Openflow.Utils.decode_string(serial_num),
dp_desc: Openflow.Utils.decode_string(dp_desc)}
end
end

View file

@ -0,0 +1,24 @@
defmodule Openflow.Multipart.Desc.Request do
defstruct(
version: 4,
xid: 0,
datapath_id: nil, # virtual field
flags: []
)
alias __MODULE__
def ofp_type, do: 18
def new do
%Request{}
end
def read("") do
%Request{}
end
def to_binary(%Request{} = msg) do
Openflow.Multipart.Request.header(msg)
end
end

View file

@ -0,0 +1,75 @@
defmodule Openflow.Multipart.Flow.Reply do
defstruct(
version: 4,
xid: 0,
datapath_id: nil, # virtual field
flags: [],
flows: []
)
alias __MODULE__
def ofp_type, do: 18
def new(flows \\ []) do
%Reply{flows: flows}
end
def read(<<flows_bin::bytes>>) do
flows = Openflow.Multipart.FlowStats.read(flows_bin)
%Reply{flows: flows}
end
end
defmodule Openflow.Multipart.FlowStats do
defstruct(
table_id: 0,
duration_sec: 0,
duration_nsec: 0,
priority: 0,
idle_timeout: 0,
hard_timeout: 0,
flags: 0,
cookie: 0,
packet_count: 0,
byte_count: 0,
match: [],
instructions: []
)
alias __MODULE__
def read(binary) do
do_read([], binary)
end
# private functions
defp do_read(acc, ""), do: Enum.reverse(acc)
defp do_read(acc, <<length::16, _tail::bytes>> = binary) do
<<flow_stats_bin::size(length)-bytes, rest::bytes>> = binary
do_read([codec(flow_stats_bin)|acc], rest)
end
defp codec(<<_length::16, table_id_int::8, 0::8, duration_sec::32,
duration_nsec::32, priority::16, idle::16, hard::16,
flags_int::16, _::size(4)-unit(8), cookie::64,
packet_count::64, byte_count::64, tail::bytes>>) do
{match, instructions_bin} = Openflow.Match.read(tail)
table_id = Openflow.Utils.get_enum(table_id_int, :table_id)
flags = Openflow.Enums.int_to_flags(flags_int, :flow_mod_flags)
instructions = Openflow.Instruction.read(instructions_bin)
%FlowStats{table_id: table_id,
duration_sec: duration_sec,
duration_nsec: duration_nsec,
priority: priority,
idle_timeout: idle,
hard_timeout: hard,
flags: flags,
cookie: cookie,
packet_count: packet_count,
byte_count: byte_count,
match: match,
instructions: instructions}
end
end

View file

@ -0,0 +1,67 @@
defmodule Openflow.Multipart.Flow.Request do
defstruct(
version: 4,
xid: 0,
datapath_id: nil, # virtual field
flags: [],
table_id: :all,
out_port: :any,
out_group: :any,
cookie: 0,
cookie_mask: 0,
match: []
)
alias __MODULE__
def ofp_type, do: 18
def new(options) do
table_id = Keyword.get(options, :table_id, :all)
out_port = Keyword.get(options, :out_port, :any)
out_group = Keyword.get(options, :out_group, :any)
cookie = Keyword.get(options, :cookie, 0)
cookie_mask = Keyword.get(options, :cookie, 0)
match = Keyword.get(options, :match, [])
%Request{table_id: table_id,
out_port: out_port,
out_group: out_group,
cookie: cookie,
cookie_mask: cookie_mask,
match: match}
end
def read(<<table_id_int::8, _::size(3)-unit(8),
out_port_int::32, out_group_int::32,
_::size(4)-unit(8), cookie::64,
cookie_mask::64, match_bin::bytes>>) do
table_id = Openflow.Utils.get_enum(table_id_int, :table_id)
out_port = Openflow.Utils.get_enum(out_port_int, :openflow13_port_no)
out_group = Openflow.Utils.get_enum(out_group_int, :group_id)
{match, _rest} = Openflow.Match.read(match_bin)
%Request{table_id: table_id,
out_port: out_port,
out_group: out_group,
cookie: cookie,
cookie_mask: cookie_mask,
match: match}
end
def to_binary(%Request{table_id: table_id,
out_port: out_port,
out_group: out_group,
cookie: cookie,
cookie_mask: cookie_mask,
match: match} = msg) do
table_id_int = Openflow.Utils.get_enum(table_id, :table_id)
out_port_int = Openflow.Utils.get_enum(out_port, :openflow13_port_no)
out_group_int = Openflow.Utils.get_enum(out_group, :group_id)
match_bin = Openflow.Match.to_binary(match)
body_bin = <<table_id_int::8, 0::size(3)-unit(8),
out_port_int::32, out_group_int::32,
0::size(4)-unit(8), cookie::64,
cookie_mask::64, match_bin::bytes>>
header_bin = Openflow.Multipart.Request.header(msg)
<<header_bin::bytes, body_bin::bytes>>
end
end

View file

@ -0,0 +1 @@
Replace regexp Queue with: Group

View file

@ -0,0 +1 @@
shun159@shun159.8967:1509553730

View file

@ -0,0 +1,69 @@
defmodule Openflow.Multipart.Group.Reply do
defstruct(
version: 4,
xid: 0,
datapath_id: nil, # virtual field
flags: [],
groups: []
)
alias __MODULE__
def ofp_type, do: 18
def new(groups \\ []) do
%Reply{groups: groups}
end
def read(<<groups_bin::bytes>>) do
groups = Openflow.Multipart.Group.read(groups_bin)
%Reply{groups: groups}
end
end
defmodule Openflow.Multipart.Group do
defstruct(
group_id: 0,
ref_count: 0,
packet_count: 0,
byte_count: 0,
duration_sec: 0,
duration_nsec: 0,
bucket_stats: []
)
@ofp_group_stats_size 40
alias __MODULE__
def read(binary) do
do_read([], binary)
end
# private functions
defp do_read(acc, ""), do: Enum.reverse(acc)
defp do_read(acc, <<length::16, _binary::bytes>> = binary) do
<<group_bin::size(length)-bytes, rest::bytes>> = binary
do_read([codec(group_bin)|acc], rest)
end
defp codec(<<length::16, _::size(2)-unit(8),
group_id::32, ref_count::32,
_::size(4)-unit(8), packet_count::64,
byte_count::64, duration_sec::32,
duration_nsec::32, tail::bytes>>) do
bucket_stats_size = length - @ofp_group_stats_size
<<bucket_stats_bin::size(bucket_stats_size)-bytes, _rest::bytes>> = tail
bucket_stats = for <<packet_count::64, byte_count::64 <- bucket_stats_bin>> do
%{packet_count: packet_count, byte_count: byte_count}
end
%Group{group_id: group_id,
ref_count: ref_count,
packet_count: packet_count,
byte_count: byte_count,
duration_sec: duration_sec,
duration_nsec: duration_nsec,
bucket_stats: bucket_stats}
end
end

View file

@ -0,0 +1,29 @@
defmodule Openflow.Multipart.Group.Request do
defstruct(
version: 4,
xid: 0,
datapath_id: nil, # virtual field
flags: [],
group_id: :all
)
alias __MODULE__
def ofp_type, do: 18
def new(group_id \\ :all) do
%Request{group_id: group_id}
end
def read(<<group_id_int::32, _::size(4)-unit(8)>>) do
group_id = Openflow.Utils.get_enum(group_id_int, :group_id)
%Request{group_id: group_id}
end
def to_binary(%Request{group_id: group_id} = msg) do
group_id_int = Openflow.Utils.get_enum(group_id, :group_id)
body_bin = <<group_id_int::32, 0::size(4)-unit(8)>>
header_bin = Openflow.Multipart.Request.header(msg)
<<header_bin::bytes, body_bin::bytes>>
end
end

View file

@ -0,0 +1,54 @@
defmodule Openflow.Multipart.GroupDesc.Reply do
defstruct(
version: 4,
xid: 0,
datapath_id: nil, # virtual field
flags: [],
groups: []
)
alias __MODULE__
def ofp_type, do: 18
def new(groups \\ []) do
%Reply{groups: groups}
end
def read(<<groups_bin::bytes>>) do
groups = Openflow.Multipart.GroupDescStats.read(groups_bin)
%Reply{groups: groups}
end
end
defmodule Openflow.Multipart.GroupDescStats do
defstruct(
type: :all,
group_id: 0,
buckets: []
)
alias __MODULE__
@ofp_group_desc_size 8
def read(binary) do
do_read([], binary)
end
# private functions
defp do_read(acc, ""), do: Enum.reverse(acc)
defp do_read(acc, <<length::16, _tail::bytes>> = binary) do
<<group_stats_bin::size(length)-bytes, rest::bytes>> = binary
do_read([codec(group_stats_bin)|acc], rest)
end
defp codec(<<length::16, type_int::8, _::8, group_id::32, tail::bytes>>) do
buckets_bin_len = length - @ofp_group_desc_size
<<buckets_bin::size(buckets_bin_len)-bytes, _::bytes>> = tail
type = Openflow.Enums.to_atom(type_int, :group_type)
buckets = Openflow.Bucket.read(buckets_bin)
%GroupDescStats{type: type, group_id: group_id, buckets: buckets}
end
end

View file

@ -0,0 +1,24 @@
defmodule Openflow.Multipart.GroupDesc.Request do
defstruct(
version: 4,
xid: 0,
datapath_id: nil, # virtual field
flags: []
)
alias __MODULE__
def ofp_type, do: 18
def new do
%Request{}
end
def read("") do
%Request{}
end
def to_binary(%Request{} = msg) do
Openflow.Multipart.Request.header(msg)
end
end

View file

@ -0,0 +1,44 @@
defmodule Openflow.Multipart.GroupFeatures.Reply do
defstruct(
version: 4,
xid: 0,
datapath_id: nil, # virtual field
flags: [],
types: 0,
capabilities: [],
max_groups_for_all: 0,
max_groups_for_select: 0,
max_groups_for_indirect: 0,
max_groups_for_fast_failover: 0,
actions_for_all: 0,
actions_for_select: 0,
actions_for_indirect: 0,
actions_for_fast_failover: 0
)
alias __MODULE__
def ofp_type, do: 18
def read(<<types_int::32, capabilities_int::32,
max_groups_for_all_int::32,
max_groups_for_select_int::32,
max_groups_for_indirect_int::32,
max_groups_for_fast_failover_int::32,
actions_for_all_int::32,
actions_for_select_int::32,
actions_for_indirect_int::32,
actions_for_fast_failover_int::32>>) do
capabilities = Openflow.Enums.int_to_flags(capabilities_int, :group_capabilities)
%Reply{types: types_int,
capabilities: capabilities,
max_groups_for_all: max_groups_for_all_int,
max_groups_for_select: max_groups_for_select_int,
max_groups_for_indirect: max_groups_for_indirect_int,
max_groups_for_fast_failover: max_groups_for_fast_failover_int,
actions_for_all: actions_for_all_int,
actions_for_select: actions_for_select_int,
actions_for_indirect: actions_for_indirect_int,
actions_for_fast_failover: actions_for_fast_failover_int}
end
end

View file

@ -0,0 +1,24 @@
defmodule Openflow.Multipart.GroupFeatures.Request do
defstruct(
version: 4,
xid: 0,
datapath_id: nil, # virtual field
flags: []
)
alias __MODULE__
def ofp_type, do: 18
def new do
%Request{}
end
def read("") do
%Request{}
end
def to_binary(%Request{} = msg) do
Openflow.Multipart.Request.header(msg)
end
end

View file

@ -0,0 +1,63 @@
defmodule Openflow.Multipart.Meter.Reply do
defstruct(
version: 4,
xid: 0,
datapath_id: nil, # virtual field
flags: [],
meters: []
)
alias __MODULE__
def ofp_type, do: 18
def read(<<meters_bin::bytes>>) do
meters = Openflow.Multipart.Meter.read(meters_bin)
%Reply{meters: meters}
end
end
defmodule Openflow.Multipart.Meter do
defstruct(
meter_id: 0,
flow_count: 0,
packet_in_count: 0,
byte_in_count: 0,
duration_sec: 0,
duration_nsec: 0,
band_stats: []
)
@ofp_meter_stats_size 40
alias __MODULE__
def read(binary) do
do_read([], binary)
end
# private functions
defp do_read(acc, ""), do: Enum.reverse(acc)
defp do_read(acc, <<_::32, length::16, _binary::bytes>> = binary) do
<<meter_bin::size(length)-bytes, rest::bytes>> = binary
do_read([codec(meter_bin)|acc], rest)
end
defp codec(<<meter_id::32, length::16, _::size(6)-unit(8),
flow_count::32, packet_in_count::64, byte_in_count::64,
duration_sec::32, duration_nsec::32, tail::bytes>>) do
band_stats_size = length - @ofp_meter_stats_size
<<band_stats_bin::size(band_stats_size)-bytes, _rest::bytes>> = tail
band_stats = for <<packet_band_count::64, byte_band_count::64 <- band_stats_bin>> do
%{packet_band_count: packet_band_count,byte_band_count: byte_band_count}
end
%Meter{meter_id: meter_id,
flow_count: flow_count,
packet_in_count: packet_in_count,
byte_in_count: byte_in_count,
duration_sec: duration_sec,
duration_nsec: duration_nsec,
band_stats: band_stats}
end
end

View file

@ -0,0 +1,29 @@
defmodule Openflow.Multipart.Meter.Request do
defstruct(
version: 4,
xid: 0,
datapath_id: nil, # virtual field
flags: [],
meter_id: :all
)
alias __MODULE__
def ofp_type, do: 18
def new(meter_id \\ :all) do
%Request{meter_id: meter_id}
end
def read(<<meter_id_int::32, _::size(4)-unit(8)>>) do
meter_id = Openflow.Utils.get_enum(meter_id_int, :meter_id)
%Request{meter_id: meter_id}
end
def to_binary(%Request{meter_id: meter_id} = msg) do
meter_id_int = Openflow.Utils.get_enum(meter_id, :meter_id)
body_bin = <<meter_id_int::32, 0::size(4)-unit(8)>>
header_bin = Openflow.Multipart.Request.header(msg)
<<header_bin::bytes, body_bin::bytes>>
end
end

View file

@ -0,0 +1,29 @@
defmodule Openflow.Multipart.MeterConfig.Request do
defstruct(
version: 4,
xid: 0,
datapath_id: nil, # virtual field
flags: [],
meter_id: :all
)
alias __MODULE__
def ofp_type, do: 18
def new(meter_id \\ :all) do
%Request{meter_id: meter_id}
end
def read(<<meter_id_int::32, _::size(4)-unit(8)>>) do
meter_id = Openflow.Utils.get_enum(meter_id_int, :meter_id)
%Request{meter_id: meter_id}
end
def to_binary(%Request{meter_id: meter_id} = msg) do
meter_id_int = Openflow.Utils.get_enum(meter_id, :meter_id)
body_bin = <<meter_id_int::32, 0::size(4)-unit(8)>>
header_bin = Openflow.Multipart.Request.header(msg)
<<header_bin::bytes, body_bin::bytes>>
end
end

View file

@ -0,0 +1,78 @@
defmodule Openflow.Multipart.PortStats.Reply do
defstruct(
version: 4,
xid: 0,
datapath_id: nil, # virtual field
flags: [],
ports: []
)
alias __MODULE__
def ofp_type, do: 18
def new(ports \\ []) do
%Reply{ports: ports}
end
def read(<<ports_bin::bytes>>) do
ports = Openflow.Multipart.PortStats.read(ports_bin)
%Reply{ports: ports}
end
end
defmodule Openflow.Multipart.PortStats do
defstruct(
port_number: 0,
rx_packets: 0,
tx_packets: 0,
rx_bytes: 0,
tx_bytes: 0,
rx_dropped: 0,
tx_dropped: 0,
rx_errors: 0,
tx_errors: 0,
rx_frame_err: 0,
rx_over_err: 0,
rx_crc_err: 0,
collisions: 0,
duration_sec: 0,
duration_nsec: 0
)
alias __MODULE__
def read(binary) do
do_read([], binary)
end
# private functions
defp do_read(acc, ""), do: Enum.reverse(acc)
defp do_read(acc, <<port_stats_bin::112-bytes, rest::bytes>>) do
do_read([codec(port_stats_bin)|acc], rest)
end
defp codec(<<port_no::32, _::size(4)-unit(8), rx_packets::64,
tx_packets::64, rx_bytes::64, tx_bytes::64,
rx_dropped::64, tx_dropped::64, rx_errors::64,
tx_errors::64, rx_frame_err::64, rx_over_err::64,
rx_crc_err::64, collisions::64,
duration_sec::32, duration_nsec::32>>) do
%PortStats{port_number: port_no,
rx_packets: rx_packets,
tx_packets: tx_packets,
rx_bytes: rx_bytes,
tx_bytes: tx_bytes,
rx_dropped: rx_dropped,
tx_dropped: tx_dropped,
rx_errors: rx_errors,
tx_errors: tx_errors,
rx_frame_err: rx_frame_err,
rx_over_err: rx_over_err,
rx_crc_err: rx_crc_err,
collisions: collisions,
duration_sec: duration_sec,
duration_nsec: duration_nsec}
end
end

View file

@ -0,0 +1,29 @@
defmodule Openflow.Multipart.PortStats.Request do
defstruct(
version: 4,
xid: 0,
datapath_id: nil, # virtual field
flags: [],
port_number: :any
)
alias __MODULE__
def ofp_type, do: 18
def new(port_no \\ :any) do
%Request{port_number: port_no}
end
def read(<<port_no_int::32, _::size(4)-unit(8)>>) do
port_no = Openflow.Utils.get_enum(port_no_int, :openflow13_port_no)
%Request{port_number: port_no}
end
def to_binary(%Request{port_number: port_no} = msg) do
port_no_int = Openflow.Utils.get_enum(port_no, :openflow13_port_no)
body_bin = <<port_no_int::32, 0::size(4)-unit(8)>>
header_bin = Openflow.Multipart.Request.header(msg)
<<header_bin::bytes, body_bin::bytes>>
end
end

View file

@ -0,0 +1,59 @@
defmodule Openflow.Multipart.Queue.Reply do
defstruct(
version: 4,
xid: 0,
datapath_id: nil, # virtual field
flags: [],
queues: []
)
alias __MODULE__
def ofp_type, do: 18
def new(queues \\ []) do
%Reply{queues: queues}
end
def read(<<queues_bin::bytes>>) do
queues = Openflow.Multipart.Queue.read(queues_bin)
%Reply{queues: queues}
end
end
defmodule Openflow.Multipart.Queue do
defstruct(
port_number: 0,
queue_id: 0,
tx_bytes: 0,
tx_packets: 0,
tx_errors: 0,
duration_sec: 0,
duration_nsec: 0
)
alias __MODULE__
def read(binary) do
do_read([], binary)
end
# private functions
defp do_read(acc, ""), do: Enum.reverse(acc)
defp do_read(acc, <<queue_bin::40-bytes, rest::bytes>>) do
do_read([codec(queue_bin)|acc], rest)
end
defp codec(<<port_no::32, queue_id::32, tx_bytes::64,
tx_packets::64, tx_errors::64,
duration_sec::32, duration_nsec::32>>) do
%Queue{port_number: port_no,
queue_id: queue_id,
tx_bytes: tx_bytes,
tx_packets: tx_packets,
tx_errors: tx_errors,
duration_sec: duration_sec,
duration_nsec: duration_nsec}
end
end

View file

@ -0,0 +1,34 @@
defmodule Openflow.Multipart.Queue.Request do
defstruct(
version: 4,
xid: 0,
datapath_id: nil, # virtual field
flags: [],
port_number: :any,
queue_id: :all
)
alias __MODULE__
def ofp_type, do: 18
def new(options) do
port_no = Keyword.get(options, :port_number, :any)
queue_id = Keyword.get(options, :queue_id, :all)
%Request{port_number: port_no, queue_id: queue_id}
end
def read(<<port_no_int::32, queue_id_int::32>>) do
port_no = Openflow.Utils.get_enum(port_no_int, :openflow13_port_no)
queue_id = Openflow.Utils.get_enum(queue_id_int, :queue_id)
%Request{port_number: port_no, queue_id: queue_id}
end
def to_binary(%Request{port_number: port_no, queue_id: queue_id} = msg) do
port_no_int = Openflow.Utils.get_enum(port_no, :openflow13_port_no)
queue_id_int = Openflow.Utils.get_enum(queue_id, :queue_id)
body_bin = <<port_no_int::32, queue_id_int::32>>
header_bin = Openflow.Multipart.Request.header(msg)
<<header_bin::bytes, body_bin::bytes>>
end
end

View file

@ -0,0 +1,27 @@
defmodule Openflow.Multipart.Reply do
def ofp_type, do: 19
def read(<<type_int::16, flags_int::16, _::size(4)-unit(8), reply_bin::bytes>>) do
codec = Openflow.Enums.to_atom(type_int, :multipart_reply_codec)
flags = Openflow.Enums.int_to_flags(flags_int, :multipart_reply_flags)
reply = codec.read(reply_bin)
%{reply|flags: flags}
end
def to_binary(%{__struct__: codec, flags: flags} = msg) do
flags_int = Openflow.Enums.flags_to_int(flags, :multipart_reply_flags)
type_int = Openflow.Enums.to_int(codec, :multipart_reply_codec)
case codec.to_binary(msg) do
reply_bin when is_binary(reply_bin) ->
<<type_int::16, flags_int::16, 0::size(4)-unit(8), reply_bin::bytes>>
{:error, reason} ->
{:error, reason}
end
end
def header(%{__struct__: codec, flags: flags}) do
flags_int = Openflow.Enums.flags_to_int(flags, :multipart_reply_flags)
type_int = Openflow.Enums.to_int(codec, :multipart_reply_codec)
<<type_int::16, flags_int::16, 0::size(4)-unit(8)>>
end
end

View file

@ -0,0 +1,27 @@
defmodule Openflow.Multipart.Request do
def ofp_type, do: 18
def read(<<type_int::16, flags_int::16, _::size(4)-unit(8), request_bin::bytes>>) do
codec = Openflow.Enums.to_atom(type_int, :multipart_request_codec)
flags = Openflow.Enums.int_to_flags(flags_int, :multipart_request_flags)
request = codec.read(request_bin)
%{request|flags: flags}
end
def to_binary(%{__struct__: codec, flags: flags} = msg) do
flags_int = Openflow.Enums.flags_to_int(flags, :multipart_request_flags)
type_int = Openflow.Enums.to_int(codec, :multipart_request_codec)
case codec.to_binary(msg) do
request_bin when is_binary(request_bin) ->
<<type_int::16, flags_int::16, 0::size(4)-unit(8), request_bin::bytes>>
{:error, reason} ->
{:error, reason}
end
end
def header(%{__struct__: codec, flags: flags}) do
flags_int = Openflow.Enums.flags_to_int(flags, :multipart_request_flags)
type_int = Openflow.Enums.to_int(codec, :multipart_request_codec)
<<type_int::16, flags_int::16, 0::size(4)-unit(8)>>
end
end

View file

@ -0,0 +1,45 @@
defmodule Openflow.Multipart.Table.Reply do
defstruct(
version: 4,
xid: 0,
datapath_id: nil, # virtual field
flags: [],
tables: []
)
alias __MODULE__
def ofp_type, do: 18
def read(<<tables_bin::bytes>>) do
tables = Openflow.Multipart.TableStats.read(tables_bin)
%Reply{tables: tables}
end
end
defmodule Openflow.Multipart.TableStats do
defstruct(
table_id: 0,
active_count: 0,
lookup_count: 0,
matched_count: 0
)
alias __MODULE__
def read(binary) do
do_read([], binary)
end
# private functions
defp do_read(acc, ""), do: Enum.reverse(acc)
defp do_read(acc, <<table_stats_bin::24-bytes, rest::bytes>>) do
do_read([codec(table_stats_bin)|acc], rest)
end
defp codec(<<table_id::8, _::size(3)-unit(8), active_count::32, lookup_count::64, matched_count::64>>) do
%TableStats{table_id: table_id, active_count: active_count,
lookup_count: lookup_count, matched_count: matched_count}
end
end

View file

@ -0,0 +1,24 @@
defmodule Openflow.Multipart.Table.Request do
defstruct(
version: 4,
xid: 0,
datapath_id: nil, # virtual field
flags: []
)
alias __MODULE__
def ofp_type, do: 18
def new do
%Request{}
end
def read("") do
%Request{}
end
def to_binary(%Request{} = msg) do
Openflow.Multipart.Request.header(msg)
end
end