Formatted
This commit is contained in:
parent
5fc01a9bec
commit
7635272fbd
150 changed files with 5055 additions and 4032 deletions
|
|
@ -1,13 +1,14 @@
|
|||
defmodule Openflow.Multipart.Aggregate.Reply do
|
||||
defstruct(
|
||||
version: 4,
|
||||
xid: 0,
|
||||
datapath_id: nil, # virtual field
|
||||
aux_id: nil,
|
||||
flags: [],
|
||||
version: 4,
|
||||
xid: 0,
|
||||
# virtual field
|
||||
datapath_id: nil,
|
||||
aux_id: nil,
|
||||
flags: [],
|
||||
packet_count: 0,
|
||||
byte_count: 0,
|
||||
flow_count: 0
|
||||
byte_count: 0,
|
||||
flow_count: 0
|
||||
)
|
||||
|
||||
alias __MODULE__
|
||||
|
|
|
|||
|
|
@ -1,15 +1,16 @@
|
|||
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: []
|
||||
version: 4,
|
||||
xid: 0,
|
||||
# virtual field
|
||||
datapath_id: nil,
|
||||
flags: [],
|
||||
table_id: :all,
|
||||
out_port: :any,
|
||||
out_group: :any,
|
||||
cookie: 0,
|
||||
cookie_mask: 0,
|
||||
match: []
|
||||
)
|
||||
|
||||
alias __MODULE__
|
||||
|
|
@ -23,44 +24,55 @@ defmodule Openflow.Multipart.Aggregate.Request do
|
|||
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}
|
||||
|
||||
%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
|
||||
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}
|
||||
|
||||
%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
|
||||
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>>
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -1,31 +1,36 @@
|
|||
defmodule Openflow.Multipart.Desc.Reply do
|
||||
defstruct(
|
||||
version: 4,
|
||||
xid: 0,
|
||||
datapath_id: nil, # virtual field
|
||||
aux_id: nil,
|
||||
flags: [],
|
||||
mfr_desc: "",
|
||||
hw_desc: "",
|
||||
sw_desc: "",
|
||||
serial_num: "",
|
||||
dp_desc: ""
|
||||
version: 4,
|
||||
xid: 0,
|
||||
# virtual field
|
||||
datapath_id: nil,
|
||||
aux_id: nil,
|
||||
flags: [],
|
||||
mfr_desc: "",
|
||||
hw_desc: "",
|
||||
sw_desc: "",
|
||||
serial_num: "",
|
||||
dp_desc: ""
|
||||
)
|
||||
|
||||
alias __MODULE__
|
||||
|
||||
@desc_str_len 256
|
||||
@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)}
|
||||
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
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
defmodule Openflow.Multipart.Desc.Request do
|
||||
defstruct(
|
||||
version: 4,
|
||||
xid: 0,
|
||||
datapath_id: nil, # virtual field
|
||||
version: 4,
|
||||
xid: 0,
|
||||
# virtual field
|
||||
datapath_id: nil,
|
||||
flags: []
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
defmodule Openflow.Multipart.Flow.Reply do
|
||||
defstruct(
|
||||
version: 4,
|
||||
xid: 0,
|
||||
datapath_id: nil, # virtual field
|
||||
aux_id: nil,
|
||||
flags: [],
|
||||
flows: []
|
||||
version: 4,
|
||||
xid: 0,
|
||||
# virtual field
|
||||
datapath_id: nil,
|
||||
aux_id: nil,
|
||||
flags: [],
|
||||
flows: []
|
||||
)
|
||||
|
||||
alias __MODULE__
|
||||
|
|
@ -22,29 +23,32 @@ defmodule Openflow.Multipart.Flow.Reply do
|
|||
end
|
||||
|
||||
def append_body(%Reply{flows: flows} = message, %Reply{flags: [:more], flows: continue}) do
|
||||
%{message|flows: [continue|flows]}
|
||||
%{message | flows: [continue | flows]}
|
||||
end
|
||||
|
||||
def append_body(%Reply{flows: flows} = message, %Reply{flags: [], flows: continue}) do
|
||||
new_flows = [continue|flows]
|
||||
|> Enum.reverse
|
||||
|> List.flatten
|
||||
%{message|flows: new_flows}
|
||||
new_flows =
|
||||
[continue | flows]
|
||||
|> Enum.reverse()
|
||||
|> List.flatten()
|
||||
|
||||
%{message | flows: new_flows}
|
||||
end
|
||||
end
|
||||
|
||||
defmodule Openflow.Multipart.FlowStats do
|
||||
defstruct(
|
||||
table_id: 0,
|
||||
duration_sec: 0,
|
||||
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: [],
|
||||
priority: 0,
|
||||
idle_timeout: 0,
|
||||
hard_timeout: 0,
|
||||
flags: 0,
|
||||
cookie: 0,
|
||||
packet_count: 0,
|
||||
byte_count: 0,
|
||||
match: [],
|
||||
instructions: []
|
||||
)
|
||||
|
||||
|
|
@ -57,30 +61,35 @@ defmodule Openflow.Multipart.FlowStats do
|
|||
# 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)
|
||||
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
|
||||
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}
|
||||
|
||||
%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
|
||||
|
|
|
|||
|
|
@ -1,15 +1,16 @@
|
|||
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: []
|
||||
version: 4,
|
||||
xid: 0,
|
||||
# virtual field
|
||||
datapath_id: nil,
|
||||
flags: [],
|
||||
table_id: :all,
|
||||
out_port: :any,
|
||||
out_group: :any,
|
||||
cookie: 0,
|
||||
cookie_mask: 0,
|
||||
match: []
|
||||
)
|
||||
|
||||
alias __MODULE__
|
||||
|
|
@ -22,45 +23,56 @@ defmodule Openflow.Multipart.Flow.Request do
|
|||
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, Openflow.Match.new)
|
||||
%Request{table_id: table_id,
|
||||
out_port: out_port,
|
||||
out_group: out_group,
|
||||
cookie: cookie,
|
||||
cookie_mask: cookie_mask,
|
||||
match: match}
|
||||
match = Keyword.get(options, :match, Openflow.Match.new())
|
||||
|
||||
%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
|
||||
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}
|
||||
|
||||
%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
|
||||
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>>
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
defmodule Openflow.Multipart.Group.Reply do
|
||||
defstruct(
|
||||
version: 4,
|
||||
xid: 0,
|
||||
datapath_id: nil, # virtual field
|
||||
aux_id: nil,
|
||||
flags: [],
|
||||
groups: []
|
||||
version: 4,
|
||||
xid: 0,
|
||||
# virtual field
|
||||
datapath_id: nil,
|
||||
aux_id: nil,
|
||||
flags: [],
|
||||
groups: []
|
||||
)
|
||||
|
||||
alias __MODULE__
|
||||
|
|
@ -22,25 +23,28 @@ defmodule Openflow.Multipart.Group.Reply do
|
|||
end
|
||||
|
||||
def append_body(%Reply{groups: groups} = message, %Reply{flags: [:more], groups: continue}) do
|
||||
%{message|groups: [continue|groups]}
|
||||
%{message | groups: [continue | groups]}
|
||||
end
|
||||
|
||||
def append_body(%Reply{groups: groups} = message, %Reply{flags: [], groups: continue}) do
|
||||
new_groups = [continue|groups]
|
||||
|> Enum.reverse
|
||||
|> List.flatten
|
||||
%{message|groups: new_groups}
|
||||
new_groups =
|
||||
[continue | groups]
|
||||
|> Enum.reverse()
|
||||
|> List.flatten()
|
||||
|
||||
%{message | groups: new_groups}
|
||||
end
|
||||
end
|
||||
|
||||
defmodule Openflow.Multipart.Group do
|
||||
defstruct(
|
||||
group_id: 0,
|
||||
ref_count: 0,
|
||||
packet_count: 0,
|
||||
byte_count: 0,
|
||||
duration_sec: 0,
|
||||
group_id: 0,
|
||||
ref_count: 0,
|
||||
packet_count: 0,
|
||||
byte_count: 0,
|
||||
duration_sec: 0,
|
||||
duration_nsec: 0,
|
||||
bucket_stats: []
|
||||
bucket_stats: []
|
||||
)
|
||||
|
||||
@ofp_group_stats_size 40
|
||||
|
|
@ -54,27 +58,32 @@ defmodule Openflow.Multipart.Group do
|
|||
# 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)
|
||||
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
|
||||
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}
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
defmodule Openflow.Multipart.Group.Request do
|
||||
defstruct(
|
||||
version: 4,
|
||||
xid: 0,
|
||||
datapath_id: nil, # virtual field
|
||||
version: 4,
|
||||
xid: 0,
|
||||
# virtual field
|
||||
datapath_id: nil,
|
||||
flags: [],
|
||||
group_id: :all
|
||||
group_id: :all
|
||||
)
|
||||
|
||||
alias __MODULE__
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
defmodule Openflow.Multipart.GroupDesc.Reply do
|
||||
defstruct(
|
||||
version: 4,
|
||||
xid: 0,
|
||||
datapath_id: nil, # virtual field
|
||||
flags: [],
|
||||
groups: []
|
||||
version: 4,
|
||||
xid: 0,
|
||||
# virtual field
|
||||
datapath_id: nil,
|
||||
flags: [],
|
||||
groups: []
|
||||
)
|
||||
|
||||
alias __MODULE__
|
||||
|
|
@ -21,21 +22,24 @@ defmodule Openflow.Multipart.GroupDesc.Reply do
|
|||
end
|
||||
|
||||
def append_body(%Reply{groups: groups} = message, %Reply{flags: [:more], groups: continue}) do
|
||||
%{message|groups: [continue|groups]}
|
||||
%{message | groups: [continue | groups]}
|
||||
end
|
||||
|
||||
def append_body(%Reply{groups: groups} = message, %Reply{flags: [], groups: continue}) do
|
||||
new_groups = [continue|groups]
|
||||
|> Enum.reverse
|
||||
|> List.flatten
|
||||
%{message|groups: new_groups}
|
||||
new_groups =
|
||||
[continue | groups]
|
||||
|> Enum.reverse()
|
||||
|> List.flatten()
|
||||
|
||||
%{message | groups: new_groups}
|
||||
end
|
||||
end
|
||||
|
||||
defmodule Openflow.Multipart.GroupDescStats do
|
||||
defstruct(
|
||||
type: :all,
|
||||
group_id: 0,
|
||||
buckets: []
|
||||
type: :all,
|
||||
group_id: 0,
|
||||
buckets: []
|
||||
)
|
||||
|
||||
alias __MODULE__
|
||||
|
|
@ -49,9 +53,10 @@ defmodule Openflow.Multipart.GroupDescStats do
|
|||
# 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)
|
||||
do_read([codec(group_stats_bin) | acc], rest)
|
||||
end
|
||||
|
||||
defp codec(<<length::16, type_int::8, _::8, group_id::32, tail::bytes>>) do
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
defmodule Openflow.Multipart.GroupDesc.Request do
|
||||
defstruct(
|
||||
version: 4,
|
||||
xid: 0,
|
||||
datapath_id: nil, # virtual field
|
||||
version: 4,
|
||||
xid: 0,
|
||||
# virtual field
|
||||
datapath_id: nil,
|
||||
flags: []
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,45 +1,47 @@
|
|||
defmodule Openflow.Multipart.GroupFeatures.Reply do
|
||||
defstruct(
|
||||
version: 4,
|
||||
xid: 0,
|
||||
datapath_id: nil, # virtual field
|
||||
aux_id: nil,
|
||||
flags: [],
|
||||
types: 0,
|
||||
version: 4,
|
||||
xid: 0,
|
||||
# virtual field
|
||||
datapath_id: nil,
|
||||
aux_id: nil,
|
||||
flags: [],
|
||||
types: 0,
|
||||
capabilities: [],
|
||||
max_groups_for_all: 0,
|
||||
max_groups_for_select: 0,
|
||||
max_groups_for_indirect: 0,
|
||||
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
|
||||
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
|
||||
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}
|
||||
|
||||
%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
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
defmodule Openflow.Multipart.GroupFeatures.Request do
|
||||
defstruct(
|
||||
version: 4,
|
||||
xid: 0,
|
||||
datapath_id: nil, # virtual field
|
||||
version: 4,
|
||||
xid: 0,
|
||||
# virtual field
|
||||
datapath_id: nil,
|
||||
flags: []
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
defmodule Openflow.Multipart.Meter.Reply do
|
||||
defstruct(
|
||||
version: 4,
|
||||
xid: 0,
|
||||
datapath_id: nil, # virtual field
|
||||
aux_id: nil,
|
||||
flags: [],
|
||||
meters: []
|
||||
version: 4,
|
||||
xid: 0,
|
||||
# virtual field
|
||||
datapath_id: nil,
|
||||
aux_id: nil,
|
||||
flags: [],
|
||||
meters: []
|
||||
)
|
||||
|
||||
alias __MODULE__
|
||||
|
|
@ -18,25 +19,28 @@ defmodule Openflow.Multipart.Meter.Reply do
|
|||
end
|
||||
|
||||
def append_body(%Reply{meters: meters} = message, %Reply{flags: [:more], meters: continue}) do
|
||||
%{message|meters: [continue|meters]}
|
||||
%{message | meters: [continue | meters]}
|
||||
end
|
||||
|
||||
def append_body(%Reply{meters: meters} = message, %Reply{flags: [], meters: continue}) do
|
||||
new_meters = [continue|meters]
|
||||
|> Enum.reverse
|
||||
|> List.flatten
|
||||
%{message|meters: new_meters}
|
||||
new_meters =
|
||||
[continue | meters]
|
||||
|> Enum.reverse()
|
||||
|> List.flatten()
|
||||
|
||||
%{message | meters: new_meters}
|
||||
end
|
||||
end
|
||||
|
||||
defmodule Openflow.Multipart.Meter do
|
||||
defstruct(
|
||||
meter_id: 0,
|
||||
flow_count: 0,
|
||||
meter_id: 0,
|
||||
flow_count: 0,
|
||||
packet_in_count: 0,
|
||||
byte_in_count: 0,
|
||||
duration_sec: 0,
|
||||
duration_nsec: 0,
|
||||
band_stats: []
|
||||
byte_in_count: 0,
|
||||
duration_sec: 0,
|
||||
duration_nsec: 0,
|
||||
band_stats: []
|
||||
)
|
||||
|
||||
@ofp_meter_stats_size 40
|
||||
|
|
@ -50,25 +54,32 @@ defmodule Openflow.Multipart.Meter do
|
|||
# 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)
|
||||
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
|
||||
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}
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
defmodule Openflow.Multipart.Meter.Request do
|
||||
defstruct(
|
||||
version: 4,
|
||||
xid: 0,
|
||||
datapath_id: nil, # virtual field
|
||||
version: 4,
|
||||
xid: 0,
|
||||
# virtual field
|
||||
datapath_id: nil,
|
||||
flags: [],
|
||||
meter_id: :all
|
||||
meter_id: :all
|
||||
)
|
||||
|
||||
alias __MODULE__
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
defmodule Openflow.Multipart.MeterConfig.Request do
|
||||
defstruct(
|
||||
version: 4,
|
||||
xid: 0,
|
||||
datapath_id: nil, # virtual field
|
||||
version: 4,
|
||||
xid: 0,
|
||||
# virtual field
|
||||
datapath_id: nil,
|
||||
flags: [],
|
||||
meter_id: :all
|
||||
meter_id: :all
|
||||
)
|
||||
|
||||
alias __MODULE__
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
defmodule Openflow.Multipart.PortDesc.Reply do
|
||||
defstruct(
|
||||
version: 4,
|
||||
xid: 0,
|
||||
datapath_id: nil, # virtual field
|
||||
aux_id: nil,
|
||||
flags: [],
|
||||
ports: []
|
||||
version: 4,
|
||||
xid: 0,
|
||||
# virtual field
|
||||
datapath_id: nil,
|
||||
aux_id: nil,
|
||||
flags: [],
|
||||
ports: []
|
||||
)
|
||||
|
||||
alias __MODULE__
|
||||
|
|
@ -17,17 +18,20 @@ defmodule Openflow.Multipart.PortDesc.Reply do
|
|||
end
|
||||
|
||||
def read(<<ports_bin::bytes>>) do
|
||||
ports = for (<<port_bin::64-bytes <- ports_bin>>), do: Openflow.Port.read(port_bin)
|
||||
ports = for <<port_bin::64-bytes <- ports_bin>>, do: Openflow.Port.read(port_bin)
|
||||
%Reply{ports: Enum.reverse(ports)}
|
||||
end
|
||||
|
||||
def append_body(%Reply{ports: ports} = message, %Reply{flags: [:more], ports: continue}) do
|
||||
%{message|ports: [continue|ports]}
|
||||
%{message | ports: [continue | ports]}
|
||||
end
|
||||
|
||||
def append_body(%Reply{ports: ports} = message, %Reply{flags: [], ports: continue}) do
|
||||
new_ports = [continue|ports]
|
||||
|> Enum.reverse
|
||||
|> List.flatten
|
||||
%{message|ports: new_ports}
|
||||
new_ports =
|
||||
[continue | ports]
|
||||
|> Enum.reverse()
|
||||
|> List.flatten()
|
||||
|
||||
%{message | ports: new_ports}
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
defmodule Openflow.Multipart.PortDesc.Request do
|
||||
defstruct(
|
||||
version: 4,
|
||||
xid: 0,
|
||||
datapath_id: nil, # virtual field
|
||||
version: 4,
|
||||
xid: 0,
|
||||
# virtual field
|
||||
datapath_id: nil,
|
||||
flags: []
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
defmodule Openflow.Multipart.PortStats.Reply do
|
||||
defstruct(
|
||||
version: 4,
|
||||
xid: 0,
|
||||
datapath_id: nil, # virtual field
|
||||
aux_id: nil,
|
||||
flags: [],
|
||||
ports: []
|
||||
version: 4,
|
||||
xid: 0,
|
||||
# virtual field
|
||||
datapath_id: nil,
|
||||
aux_id: nil,
|
||||
flags: [],
|
||||
ports: []
|
||||
)
|
||||
|
||||
alias __MODULE__
|
||||
|
|
@ -22,32 +23,35 @@ defmodule Openflow.Multipart.PortStats.Reply do
|
|||
end
|
||||
|
||||
def append_body(%Reply{ports: ports} = message, %Reply{flags: [:more], ports: continue}) do
|
||||
%{message|ports: [continue|ports]}
|
||||
%{message | ports: [continue | ports]}
|
||||
end
|
||||
|
||||
def append_body(%Reply{ports: ports} = message, %Reply{flags: [], ports: continue}) do
|
||||
new_ports = [continue|ports]
|
||||
|> Enum.reverse
|
||||
|> List.flatten
|
||||
%{message|ports: new_ports}
|
||||
new_ports =
|
||||
[continue | ports]
|
||||
|> Enum.reverse()
|
||||
|> List.flatten()
|
||||
|
||||
%{message | ports: new_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,
|
||||
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
|
||||
)
|
||||
|
||||
|
|
@ -60,30 +64,33 @@ defmodule Openflow.Multipart.PortStats do
|
|||
# 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)
|
||||
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}
|
||||
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
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
defmodule Openflow.Multipart.PortStats.Request do
|
||||
defstruct(
|
||||
version: 4,
|
||||
xid: 0,
|
||||
datapath_id: nil, # virtual field
|
||||
version: 4,
|
||||
xid: 0,
|
||||
# virtual field
|
||||
datapath_id: nil,
|
||||
flags: [],
|
||||
port_number: :any
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
defmodule Openflow.Multipart.Queue.Reply do
|
||||
defstruct(
|
||||
version: 4,
|
||||
xid: 0,
|
||||
datapath_id: nil, # virtual field
|
||||
aux_id: nil,
|
||||
flags: [],
|
||||
queues: []
|
||||
version: 4,
|
||||
xid: 0,
|
||||
# virtual field
|
||||
datapath_id: nil,
|
||||
aux_id: nil,
|
||||
flags: [],
|
||||
queues: []
|
||||
)
|
||||
|
||||
alias __MODULE__
|
||||
|
|
@ -22,24 +23,27 @@ defmodule Openflow.Multipart.Queue.Reply do
|
|||
end
|
||||
|
||||
def append_body(%Reply{queues: queues} = message, %Reply{flags: [:more], queues: continue}) do
|
||||
%{message|queues: [continue|queues]}
|
||||
%{message | queues: [continue | queues]}
|
||||
end
|
||||
|
||||
def append_body(%Reply{queues: queues} = message, %Reply{flags: [], queues: continue}) do
|
||||
new_queues = [continue|queues]
|
||||
|> Enum.reverse
|
||||
|> List.flatten
|
||||
%{message|queues: new_queues}
|
||||
new_queues =
|
||||
[continue | queues]
|
||||
|> Enum.reverse()
|
||||
|> List.flatten()
|
||||
|
||||
%{message | queues: new_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,
|
||||
port_number: 0,
|
||||
queue_id: 0,
|
||||
tx_bytes: 0,
|
||||
tx_packets: 0,
|
||||
tx_errors: 0,
|
||||
duration_sec: 0,
|
||||
duration_nsec: 0
|
||||
)
|
||||
|
||||
|
|
@ -52,19 +56,23 @@ defmodule Openflow.Multipart.Queue do
|
|||
# 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)
|
||||
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}
|
||||
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
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
defmodule Openflow.Multipart.Queue.Request do
|
||||
defstruct(
|
||||
version: 4,
|
||||
xid: 0,
|
||||
datapath_id: nil, # virtual field
|
||||
version: 4,
|
||||
xid: 0,
|
||||
# virtual field
|
||||
datapath_id: nil,
|
||||
flags: [],
|
||||
port_number: :any,
|
||||
queue_id: :all
|
||||
queue_id: :all
|
||||
)
|
||||
|
||||
alias __MODULE__
|
||||
|
|
|
|||
|
|
@ -5,15 +5,17 @@ defmodule Openflow.Multipart.Reply 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}
|
||||
%{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
|
||||
|
|
|
|||
|
|
@ -5,15 +5,17 @@ defmodule Openflow.Multipart.Request 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}
|
||||
%{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
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
defmodule Openflow.Multipart.Table.Reply do
|
||||
defstruct(
|
||||
version: 4,
|
||||
xid: 0,
|
||||
datapath_id: nil, # virtual field
|
||||
aux_id: nil,
|
||||
flags: [],
|
||||
tables: []
|
||||
version: 4,
|
||||
xid: 0,
|
||||
# virtual field
|
||||
datapath_id: nil,
|
||||
aux_id: nil,
|
||||
flags: [],
|
||||
tables: []
|
||||
)
|
||||
|
||||
alias __MODULE__
|
||||
|
|
@ -18,21 +19,24 @@ defmodule Openflow.Multipart.Table.Reply do
|
|||
end
|
||||
|
||||
def append_body(%Reply{tables: tables} = message, %Reply{flags: [:more], tables: continue}) do
|
||||
%{message|tables: [continue|tables]}
|
||||
%{message | tables: [continue | tables]}
|
||||
end
|
||||
|
||||
def append_body(%Reply{tables: tables} = message, %Reply{flags: [], tables: continue}) do
|
||||
new_tables = [continue|tables]
|
||||
|> Enum.reverse
|
||||
|> List.flatten
|
||||
%{message|tables: new_tables}
|
||||
new_tables =
|
||||
[continue | tables]
|
||||
|> Enum.reverse()
|
||||
|> List.flatten()
|
||||
|
||||
%{message | tables: new_tables}
|
||||
end
|
||||
end
|
||||
|
||||
defmodule Openflow.Multipart.TableStats do
|
||||
defstruct(
|
||||
table_id: 0,
|
||||
active_count: 0,
|
||||
lookup_count: 0,
|
||||
table_id: 0,
|
||||
active_count: 0,
|
||||
lookup_count: 0,
|
||||
matched_count: 0
|
||||
)
|
||||
|
||||
|
|
@ -45,12 +49,20 @@ defmodule Openflow.Multipart.TableStats do
|
|||
# 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)
|
||||
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}
|
||||
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
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
defmodule Openflow.Multipart.Table.Request do
|
||||
defstruct(
|
||||
version: 4,
|
||||
xid: 0,
|
||||
datapath_id: nil, # virtual field
|
||||
version: 4,
|
||||
xid: 0,
|
||||
# virtual field
|
||||
datapath_id: nil,
|
||||
flags: []
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,46 +1,44 @@
|
|||
defmodule Openflow.Multipart.TableFeatures.Body do
|
||||
defstruct [
|
||||
table_id: 0,
|
||||
name: "",
|
||||
metadata_match: 0,
|
||||
metadata_write: 0,
|
||||
config: [],
|
||||
max_entries: 0,
|
||||
instructions: nil,
|
||||
instructions_miss: nil,
|
||||
next_tables: nil,
|
||||
next_tables_miss: nil,
|
||||
write_actions: nil,
|
||||
write_actions_miss: nil,
|
||||
apply_actions: nil,
|
||||
apply_actions_miss: nil,
|
||||
match: nil,
|
||||
wildcards: nil,
|
||||
write_setfield: nil,
|
||||
write_setfield_miss: nil,
|
||||
apply_setfield: nil,
|
||||
apply_setfield_miss: nil
|
||||
]
|
||||
defstruct table_id: 0,
|
||||
name: "",
|
||||
metadata_match: 0,
|
||||
metadata_write: 0,
|
||||
config: [],
|
||||
max_entries: 0,
|
||||
instructions: nil,
|
||||
instructions_miss: nil,
|
||||
next_tables: nil,
|
||||
next_tables_miss: nil,
|
||||
write_actions: nil,
|
||||
write_actions_miss: nil,
|
||||
apply_actions: nil,
|
||||
apply_actions_miss: nil,
|
||||
match: nil,
|
||||
wildcards: nil,
|
||||
write_setfield: nil,
|
||||
write_setfield_miss: nil,
|
||||
apply_setfield: nil,
|
||||
apply_setfield_miss: nil
|
||||
|
||||
alias __MODULE__
|
||||
|
||||
@max_table_name_len 32
|
||||
@prop_header_length 4
|
||||
@max_table_name_len 32
|
||||
@prop_header_length 4
|
||||
@table_features_length 64
|
||||
|
||||
@instructions 0
|
||||
@instructions_miss 1
|
||||
@next_tables 2
|
||||
@next_tables_miss 3
|
||||
@write_actions 4
|
||||
@write_actions_miss 5
|
||||
@apply_actions 6
|
||||
@apply_actions_miss 7
|
||||
@match 8
|
||||
@wildcards 10
|
||||
@write_setfield 12
|
||||
@instructions 0
|
||||
@instructions_miss 1
|
||||
@next_tables 2
|
||||
@next_tables_miss 3
|
||||
@write_actions 4
|
||||
@write_actions_miss 5
|
||||
@apply_actions 6
|
||||
@apply_actions_miss 7
|
||||
@match 8
|
||||
@wildcards 10
|
||||
@write_setfield 12
|
||||
@write_setfield_miss 13
|
||||
@apply_setfield 14
|
||||
@apply_setfield 14
|
||||
@apply_setfield_miss 15
|
||||
|
||||
@prop_keys [
|
||||
|
|
@ -62,25 +60,25 @@ defmodule Openflow.Multipart.TableFeatures.Body do
|
|||
|
||||
def new(options) do
|
||||
%Body{
|
||||
table_id: options[:table_id] || 0,
|
||||
name: options[:name] || "",
|
||||
metadata_match: options[:metadata_match] || 0,
|
||||
metadata_write: options[:metadata_write] || 0,
|
||||
config: options[:config] || [],
|
||||
max_entries: options[:max_entries] || 0,
|
||||
instructions: options[:instructions],
|
||||
instructions_miss: options[:instructions_miss],
|
||||
next_tables: options[:next_tables],
|
||||
next_tables_miss: options[:next_tables_miss],
|
||||
write_actions: options[:write_actions],
|
||||
write_actions_miss: options[:write_actions_miss],
|
||||
apply_actions: options[:apply_actions],
|
||||
apply_actions_miss: options[:apply_actions_miss],
|
||||
match: options[:match],
|
||||
wildcards: options[:wildcards],
|
||||
write_setfield: options[:write_setfield],
|
||||
table_id: options[:table_id] || 0,
|
||||
name: options[:name] || "",
|
||||
metadata_match: options[:metadata_match] || 0,
|
||||
metadata_write: options[:metadata_write] || 0,
|
||||
config: options[:config] || [],
|
||||
max_entries: options[:max_entries] || 0,
|
||||
instructions: options[:instructions],
|
||||
instructions_miss: options[:instructions_miss],
|
||||
next_tables: options[:next_tables],
|
||||
next_tables_miss: options[:next_tables_miss],
|
||||
write_actions: options[:write_actions],
|
||||
write_actions_miss: options[:write_actions_miss],
|
||||
apply_actions: options[:apply_actions],
|
||||
apply_actions_miss: options[:apply_actions_miss],
|
||||
match: options[:match],
|
||||
wildcards: options[:wildcards],
|
||||
write_setfield: options[:write_setfield],
|
||||
write_setfield_miss: options[:write_setfield_miss],
|
||||
apply_setfield: options[:apply_setfield],
|
||||
apply_setfield: options[:apply_setfield],
|
||||
apply_setfield_miss: options[:apply_setfield_miss]
|
||||
}
|
||||
end
|
||||
|
|
@ -96,102 +94,120 @@ defmodule Openflow.Multipart.TableFeatures.Body do
|
|||
# private functions
|
||||
|
||||
defp do_to_binary(acc, []), do: acc
|
||||
defp do_to_binary(acc, [table|rest]) do
|
||||
do_to_binary(<<acc::bytes, (encode(table))::bytes>>, rest)
|
||||
|
||||
defp do_to_binary(acc, [table | rest]) do
|
||||
do_to_binary(<<acc::bytes, encode(table)::bytes>>, rest)
|
||||
end
|
||||
|
||||
defp do_read(acc, ""), do: Enum.reverse(acc)
|
||||
|
||||
defp do_read(acc, <<length::16, _::bytes>> = binary) do
|
||||
<<features_bin::size(length)-bytes, rest::bytes>> = binary
|
||||
do_read([decode(features_bin)|acc], rest)
|
||||
do_read([decode(features_bin) | acc], rest)
|
||||
end
|
||||
|
||||
defp decode(<<_length::16, table_id::8, _::size(5)-unit(8),
|
||||
name_bin::size(@max_table_name_len)-bytes,
|
||||
metadata_match::64, metadata_write::64,
|
||||
config_int::32, max_entries::32, props_bin::bytes>>) do
|
||||
defp decode(
|
||||
<<_length::16, table_id::8, _::size(5)-unit(8),
|
||||
name_bin::size(@max_table_name_len)-bytes, metadata_match::64, metadata_write::64,
|
||||
config_int::32, max_entries::32, props_bin::bytes>>
|
||||
) do
|
||||
name = Openflow.Utils.decode_string(name_bin)
|
||||
config = Openflow.Enums.int_to_flags(config_int, :table_config)
|
||||
body = %Body{table_id: table_id,
|
||||
name: name,
|
||||
metadata_match: metadata_match,
|
||||
metadata_write: metadata_write,
|
||||
config: config,
|
||||
max_entries: max_entries}
|
||||
|
||||
body = %Body{
|
||||
table_id: table_id,
|
||||
name: name,
|
||||
metadata_match: metadata_match,
|
||||
metadata_write: metadata_write,
|
||||
config: config,
|
||||
max_entries: max_entries
|
||||
}
|
||||
|
||||
decode_props(body, props_bin)
|
||||
end
|
||||
|
||||
defp encode(table) do
|
||||
filter_fn = fn(key) -> not is_nil(Map.get(table, key)) end
|
||||
filter_fn = fn key -> not is_nil(Map.get(table, key)) end
|
||||
keys = Enum.filter(@prop_keys, filter_fn)
|
||||
props_bin = encode_props("", table, keys)
|
||||
length = @table_features_length + byte_size(props_bin)
|
||||
%Body{table_id: table_id,
|
||||
name: name,
|
||||
metadata_match: metadata_match,
|
||||
metadata_write: metadata_write,
|
||||
config: config,
|
||||
max_entries: max_entries} = table
|
||||
|
||||
%Body{
|
||||
table_id: table_id,
|
||||
name: name,
|
||||
metadata_match: metadata_match,
|
||||
metadata_write: metadata_write,
|
||||
config: config,
|
||||
max_entries: max_entries
|
||||
} = table
|
||||
|
||||
config_int = Openflow.Enums.flags_to_int(config, :table_config)
|
||||
name_bin = Openflow.Utils.encode_string(name, @max_table_name_len)
|
||||
<<length::16, table_id::8, 0::size(5)-unit(8),
|
||||
name_bin::bytes, metadata_match::64, metadata_write::64,
|
||||
config_int::32, max_entries::32, props_bin::bytes>>
|
||||
|
||||
<<length::16, table_id::8, 0::size(5)-unit(8), name_bin::bytes, metadata_match::64,
|
||||
metadata_write::64, config_int::32, max_entries::32, props_bin::bytes>>
|
||||
end
|
||||
|
||||
defp decode_props(body, ""), do: body
|
||||
|
||||
defp decode_props(body, <<type_int::16, length::16, tail::bytes>>)
|
||||
when type_int == @instructions or type_int == @instructions_miss do
|
||||
when type_int == @instructions or type_int == @instructions_miss do
|
||||
pad_length = Openflow.Utils.pad_length(length, 8)
|
||||
value_length = length - @prop_header_length
|
||||
<<instructions_bin::size(value_length)-bytes, _::size(pad_length)-unit(8), rest::bytes>> = tail
|
||||
|
||||
<<instructions_bin::size(value_length)-bytes, _::size(pad_length)-unit(8), rest::bytes>> =
|
||||
tail
|
||||
|
||||
instructions = decode_instructions([], instructions_bin)
|
||||
type = Openflow.Enums.to_atom(type_int, :table_feature_prop_type)
|
||||
|
||||
body
|
||||
|> struct(%{type => instructions})
|
||||
|> decode_props(rest)
|
||||
end
|
||||
|
||||
defp decode_props(body, <<type_int::16, length::16, tail::bytes>>)
|
||||
when type_int == @next_tables or type_int == @next_tables_miss do
|
||||
when type_int == @next_tables or type_int == @next_tables_miss do
|
||||
pad_length = Openflow.Utils.pad_length(length, 8)
|
||||
value_length = length - @prop_header_length
|
||||
<<next_tables_bin::size(value_length)-bytes, _::size(pad_length)-unit(8), rest::bytes>> = tail
|
||||
next_tables = for <<table_id::8 <- next_tables_bin>>, do: table_id
|
||||
type = Openflow.Enums.to_atom(type_int, :table_feature_prop_type)
|
||||
|
||||
body
|
||||
|> struct(%{type => next_tables})
|
||||
|> decode_props(rest)
|
||||
end
|
||||
|
||||
defp decode_props(body, <<type_int::16, length::16, tail::bytes>>)
|
||||
when type_int == @write_actions or
|
||||
type_int == @write_actions_miss or
|
||||
type_int == @apply_actions or
|
||||
type_int == @apply_actions_miss do
|
||||
when type_int == @write_actions or type_int == @write_actions_miss or
|
||||
type_int == @apply_actions or type_int == @apply_actions_miss do
|
||||
pad_length = Openflow.Utils.pad_length(length, 8)
|
||||
value_length = length - @prop_header_length
|
||||
<<actions_bin::size(value_length)-bytes, _::size(pad_length)-unit(8), rest::bytes>> = tail
|
||||
actions = decode_actions([], actions_bin)
|
||||
type = Openflow.Enums.to_atom(type_int, :table_feature_prop_type)
|
||||
|
||||
body
|
||||
|> struct(%{type => actions})
|
||||
|> decode_props(rest)
|
||||
end
|
||||
|
||||
defp decode_props(body, <<type_int::16, length::16, tail::bytes>>)
|
||||
when type_int == @match or
|
||||
type_int == @wildcards or
|
||||
type_int == @write_setfield or
|
||||
type_int == @write_setfield_miss or
|
||||
type_int == @apply_setfield or
|
||||
type_int == @apply_setfield_miss do
|
||||
when type_int == @match or type_int == @wildcards or type_int == @write_setfield or
|
||||
type_int == @write_setfield_miss or type_int == @apply_setfield or
|
||||
type_int == @apply_setfield_miss do
|
||||
pad_length = Openflow.Utils.pad_length(length, 8)
|
||||
value_length = length - @prop_header_length
|
||||
<<matches_bin::size(value_length)-bytes, _::size(pad_length)-unit(8), rest::bytes>> = tail
|
||||
matches = decode_matches([], matches_bin)
|
||||
type = Openflow.Enums.to_atom(type_int, :table_feature_prop_type)
|
||||
|
||||
body
|
||||
|> struct(%{type => matches})
|
||||
|> decode_props(rest)
|
||||
end
|
||||
|
||||
defp decode_props(body, <<_type_int::16, length::16, tail::bytes>>) do
|
||||
pad_length = Openflow.Utils.pad_length(length, 8)
|
||||
value_length = length - @prop_header_length
|
||||
|
|
@ -200,8 +216,9 @@ defmodule Openflow.Multipart.TableFeatures.Body do
|
|||
end
|
||||
|
||||
defp encode_props(acc, _table, []), do: acc
|
||||
defp encode_props(acc, table, [type|rest])
|
||||
when type == :instructions or type == :instructions_miss do
|
||||
|
||||
defp encode_props(acc, table, [type | rest])
|
||||
when type == :instructions or type == :instructions_miss do
|
||||
type_int = Openflow.Enums.to_int(type, :table_feature_prop_type)
|
||||
instructions_bin = encode_instructions("", Map.get(table, type))
|
||||
length = @prop_header_length + byte_size(instructions_bin)
|
||||
|
|
@ -209,8 +226,9 @@ defmodule Openflow.Multipart.TableFeatures.Body do
|
|||
body = <<instructions_bin::bytes, 0::size(pad_length)-unit(8)>>
|
||||
encode_props(<<acc::bytes, type_int::16, length::16, body::bytes>>, table, rest)
|
||||
end
|
||||
defp encode_props(acc, table, [type|rest])
|
||||
when type == :next_tables or type == :next_tables_miss do
|
||||
|
||||
defp encode_props(acc, table, [type | rest])
|
||||
when type == :next_tables or type == :next_tables_miss do
|
||||
type_int = Openflow.Enums.to_int(type, :table_feature_prop_type)
|
||||
next_tables_bin = to_string(Map.get(table, type))
|
||||
length = @prop_header_length + byte_size(next_tables_bin)
|
||||
|
|
@ -218,11 +236,10 @@ defmodule Openflow.Multipart.TableFeatures.Body do
|
|||
body = <<next_tables_bin::bytes, 0::size(pad_length)-unit(8)>>
|
||||
encode_props(<<acc::bytes, type_int::16, length::16, body::bytes>>, table, rest)
|
||||
end
|
||||
defp encode_props(acc, table, [type|rest])
|
||||
when (type == :write_actions or
|
||||
type == :write_actions_miss or
|
||||
type == :apply_actions or
|
||||
type == :apply_actions_miss) do
|
||||
|
||||
defp encode_props(acc, table, [type | rest])
|
||||
when type == :write_actions or type == :write_actions_miss or type == :apply_actions or
|
||||
type == :apply_actions_miss do
|
||||
type_int = Openflow.Enums.to_int(type, :table_feature_prop_type)
|
||||
actions_bin = encode_actions("", Map.get(table, type))
|
||||
length = @prop_header_length + byte_size(actions_bin)
|
||||
|
|
@ -230,13 +247,11 @@ defmodule Openflow.Multipart.TableFeatures.Body do
|
|||
body = <<actions_bin::bytes, 0::size(pad_length)-unit(8)>>
|
||||
encode_props(<<acc::bytes, type_int::16, length::16, body::bytes>>, table, rest)
|
||||
end
|
||||
defp encode_props(acc, table, [type|rest])
|
||||
when (type == :match or
|
||||
type == :wildcards or
|
||||
type == :write_setfield or
|
||||
type == :write_setfield_miss or
|
||||
type == :apply_setfield or
|
||||
type == :apply_setfield_miss) do
|
||||
|
||||
defp encode_props(acc, table, [type | rest])
|
||||
when type == :match or type == :wildcards or type == :write_setfield or
|
||||
type == :write_setfield_miss or type == :apply_setfield or
|
||||
type == :apply_setfield_miss do
|
||||
type_int = Openflow.Enums.to_int(type, :table_feature_prop_type)
|
||||
matches_bin = encode_matches("", Map.get(table, type))
|
||||
length = @prop_header_length + byte_size(matches_bin)
|
||||
|
|
@ -246,51 +261,61 @@ defmodule Openflow.Multipart.TableFeatures.Body do
|
|||
end
|
||||
|
||||
defp decode_instructions(acc, ""), do: Enum.reverse(acc)
|
||||
defp decode_instructions(acc, <<0xffff::16, _::16, exp_id::32, rest::bytes>>) do
|
||||
decode_instructions([Openflow.Instruction.Experimenter.new(exp_id)|acc], rest)
|
||||
|
||||
defp decode_instructions(acc, <<0xFFFF::16, _::16, exp_id::32, rest::bytes>>) do
|
||||
decode_instructions([Openflow.Instruction.Experimenter.new(exp_id) | acc], rest)
|
||||
end
|
||||
|
||||
defp decode_instructions(acc, <<type_int::16, _::16, rest::bytes>>) do
|
||||
instruction = Openflow.Enums.to_atom(type_int, :instruction_type)
|
||||
decode_instructions([instruction|acc], rest)
|
||||
decode_instructions([instruction | acc], rest)
|
||||
end
|
||||
|
||||
defp encode_instructions(acc, []), do: acc
|
||||
defp encode_instructions(acc, [%Openflow.Instruction.Experimenter{exp_id: exp_id}|rest]) do
|
||||
encode_instructions(<<acc::bytes, 0xffff::16, 8::16, exp_id::32>>, rest)
|
||||
|
||||
defp encode_instructions(acc, [%Openflow.Instruction.Experimenter{exp_id: exp_id} | rest]) do
|
||||
encode_instructions(<<acc::bytes, 0xFFFF::16, 8::16, exp_id::32>>, rest)
|
||||
end
|
||||
defp encode_instructions(acc, [type|rest]) do
|
||||
|
||||
defp encode_instructions(acc, [type | rest]) do
|
||||
type_int = Openflow.Enums.to_int(type, :instruction_type)
|
||||
encode_instructions(<<acc::bytes, type_int::16, 4::16>>, rest)
|
||||
end
|
||||
|
||||
defp decode_actions(acc, ""), do: Enum.reverse(acc)
|
||||
defp decode_actions(acc, <<0xffff::16, _::16, exp_id::32, rest::bytes>>) do
|
||||
decode_actions([Openflow.Action.Experimenter.new(exp_id)|acc], rest)
|
||||
|
||||
defp decode_actions(acc, <<0xFFFF::16, _::16, exp_id::32, rest::bytes>>) do
|
||||
decode_actions([Openflow.Action.Experimenter.new(exp_id) | acc], rest)
|
||||
end
|
||||
|
||||
defp decode_actions(acc, <<type_int::16, _::16, rest::bytes>>) do
|
||||
action = Openflow.Enums.to_atom(type_int, :action_type)
|
||||
decode_actions([action|acc], rest)
|
||||
decode_actions([action | acc], rest)
|
||||
end
|
||||
|
||||
defp encode_actions(acc, []), do: acc
|
||||
defp encode_actions(acc, [%Openflow.Action.Experimenter{exp_id: exp_id}|rest]) do
|
||||
encode_actions(<<acc::bytes, 0xffff::16, 8::16, exp_id::32>>, rest)
|
||||
|
||||
defp encode_actions(acc, [%Openflow.Action.Experimenter{exp_id: exp_id} | rest]) do
|
||||
encode_actions(<<acc::bytes, 0xFFFF::16, 8::16, exp_id::32>>, rest)
|
||||
end
|
||||
defp encode_actions(acc, [type|rest]) do
|
||||
|
||||
defp encode_actions(acc, [type | rest]) do
|
||||
type_int = Openflow.Enums.to_int(type, :action_type)
|
||||
encode_actions(<<acc::bytes, type_int::16, 4::16>>, rest)
|
||||
end
|
||||
|
||||
defp decode_matches(acc, ""), do: Enum.reverse(acc)
|
||||
|
||||
defp decode_matches(acc, binary) do
|
||||
length = Openflow.Match.header_size(binary)
|
||||
<<header_bin::size(length)-bytes, rest::bytes>> = binary
|
||||
field = Openflow.Match.codec_header(header_bin)
|
||||
decode_matches([field|acc], rest)
|
||||
decode_matches([field | acc], rest)
|
||||
end
|
||||
|
||||
defp encode_matches(acc, []), do: acc
|
||||
defp encode_matches(acc, [field|rest]) do
|
||||
|
||||
defp encode_matches(acc, [field | rest]) do
|
||||
header_bin = Openflow.Match.codec_header(field)
|
||||
encode_matches(<<acc::bytes, header_bin::bytes>>, rest)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
defmodule Openflow.Multipart.TableFeatures.Reply do
|
||||
defstruct(
|
||||
version: 4,
|
||||
xid: 0,
|
||||
datapath_id: nil, # virtual field
|
||||
aux_id: nil,
|
||||
flags: [],
|
||||
tables: []
|
||||
version: 4,
|
||||
xid: 0,
|
||||
# virtual field
|
||||
datapath_id: nil,
|
||||
aux_id: nil,
|
||||
flags: [],
|
||||
tables: []
|
||||
)
|
||||
|
||||
alias __MODULE__
|
||||
|
|
@ -30,12 +31,15 @@ defmodule Openflow.Multipart.TableFeatures.Reply do
|
|||
end
|
||||
|
||||
def append_body(%Reply{tables: tables} = message, %Reply{flags: [:more], tables: continue}) do
|
||||
%{message|tables: [continue|tables]}
|
||||
%{message | tables: [continue | tables]}
|
||||
end
|
||||
|
||||
def append_body(%Reply{tables: tables} = message, %Reply{flags: [], tables: continue}) do
|
||||
new_tables = [continue|tables]
|
||||
|> Enum.reverse
|
||||
|> List.flatten
|
||||
%{message|tables: new_tables}
|
||||
new_tables =
|
||||
[continue | tables]
|
||||
|> Enum.reverse()
|
||||
|> List.flatten()
|
||||
|
||||
%{message | tables: new_tables}
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
defmodule Openflow.Multipart.TableFeatures.Request do
|
||||
defstruct(
|
||||
version: 4,
|
||||
xid: 0,
|
||||
datapath_id: nil, # virtual field
|
||||
aux_id: nil,
|
||||
flags: [],
|
||||
tables: []
|
||||
version: 4,
|
||||
xid: 0,
|
||||
# virtual field
|
||||
datapath_id: nil,
|
||||
aux_id: nil,
|
||||
flags: [],
|
||||
tables: []
|
||||
)
|
||||
|
||||
alias __MODULE__
|
||||
|
|
@ -30,12 +31,15 @@ defmodule Openflow.Multipart.TableFeatures.Request do
|
|||
end
|
||||
|
||||
def append_body(%Request{tables: tables} = message, %Request{flags: [:more], tables: continue}) do
|
||||
%{message|tables: [continue|tables]}
|
||||
%{message | tables: [continue | tables]}
|
||||
end
|
||||
|
||||
def append_body(%Request{tables: tables} = message, %Request{flags: [], tables: continue}) do
|
||||
new_tables = [continue|tables]
|
||||
|> Enum.reverse
|
||||
|> List.flatten
|
||||
%{message|tables: new_tables}
|
||||
new_tables =
|
||||
[continue | tables]
|
||||
|> Enum.reverse()
|
||||
|> List.flatten()
|
||||
|
||||
%{message | tables: new_tables}
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue