parent
2c4d247a2f
commit
95d2f2e87c
15 changed files with 735 additions and 71 deletions
BIN
bin/enum_gen
BIN
bin/enum_gen
Binary file not shown.
|
|
@ -4,7 +4,7 @@ use Mix.Config
|
||||||
|
|
||||||
config :tres,
|
config :tres,
|
||||||
protocol: :tcp,
|
protocol: :tcp,
|
||||||
port: 6653,
|
port: 6633,
|
||||||
max_connections: 10,
|
max_connections: 10,
|
||||||
num_acceptors: 10,
|
num_acceptors: 10,
|
||||||
callback_module: Tres.ExampleHandler,
|
callback_module: Tres.ExampleHandler,
|
||||||
|
|
|
||||||
|
|
@ -15,22 +15,23 @@ defmodule Openflow do
|
||||||
end
|
end
|
||||||
|
|
||||||
def read(<<ver::8, type::8, len::16, xid::32, binary2::bytes>>) do
|
def read(<<ver::8, type::8, len::16, xid::32, binary2::bytes>>) do
|
||||||
try do
|
try do
|
||||||
body_len = len - @ofp_header_size
|
body_len = len - @ofp_header_size
|
||||||
<<body_bin::bytes-size(body_len), rest::bytes>> = binary2
|
<<body_bin::bytes-size(body_len), rest::bytes>> = binary2
|
||||||
|
|
||||||
result = type
|
result =
|
||||||
|
type
|
||||||
|> Openflow.Enums.to_atom(:openflow_codec)
|
|> Openflow.Enums.to_atom(:openflow_codec)
|
||||||
|> do_read(body_bin)
|
|> do_read(body_bin)
|
||||||
|
|
||||||
case result do
|
case result do
|
||||||
{:ok, struct} -> {:ok, %{struct | version: ver, xid: xid}, rest}
|
{:ok, struct} -> {:ok, %{struct | version: ver, xid: xid}, rest}
|
||||||
{:error, reason} -> {:error, reason}
|
{:error, reason} -> {:error, reason}
|
||||||
end
|
|
||||||
catch
|
|
||||||
_c, _e ->
|
|
||||||
{:error, :malformed_packet}
|
|
||||||
end
|
end
|
||||||
|
catch
|
||||||
|
_c, reason ->
|
||||||
|
{:error, {:malformed_packet, {reason, __STACKTRACE__}}}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_binary(messages) when is_list(messages) do
|
def to_binary(messages) when is_list(messages) do
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,8 @@ defmodule Openflow.Hello do
|
||||||
|
|
||||||
def supported_version?(%Hello{elements: elements}) do
|
def supported_version?(%Hello{elements: elements}) do
|
||||||
elements
|
elements
|
||||||
|> Enum.reduce([], fn({:versionbitmap, versions}, acc) -> acc ++ versions end)
|
|> Enum.reduce([], fn {:versionbitmap, versions}, acc -> acc ++ versions end)
|
||||||
|> Enum.any?(fn(version) -> version == 4 end)
|
|> Enum.any?(fn version -> version == 4 end)
|
||||||
end
|
end
|
||||||
|
|
||||||
def read(binary), do: %Hello{elements: decode([], binary)}
|
def read(binary), do: %Hello{elements: decode([], binary)}
|
||||||
|
|
|
||||||
|
|
@ -14,17 +14,40 @@ defmodule Openflow.NxPacketIn2 do
|
||||||
metadata: nil,
|
metadata: nil,
|
||||||
userdata: nil,
|
userdata: nil,
|
||||||
# continuation properties:
|
# continuation properties:
|
||||||
continuation_bridge: "",
|
continuation_bridge: nil,
|
||||||
continuation_stack: [],
|
continuation_stack: nil,
|
||||||
continuation_conntracked: false,
|
continuation_conntracked: nil,
|
||||||
|
continuation_mirrors: nil,
|
||||||
continuation_table_id: nil,
|
continuation_table_id: nil,
|
||||||
continuation_cookie: nil,
|
continuation_cookie: nil,
|
||||||
continuation_actions: [],
|
continuation_actions: nil,
|
||||||
continuation_action_set: nil
|
continuation_action_set: nil
|
||||||
)
|
)
|
||||||
|
|
||||||
alias __MODULE__
|
alias __MODULE__
|
||||||
|
|
||||||
|
@encode_keys ~w(
|
||||||
|
packet
|
||||||
|
full_len
|
||||||
|
buffer_id
|
||||||
|
table_id
|
||||||
|
cookie
|
||||||
|
reason
|
||||||
|
metadata
|
||||||
|
userdata
|
||||||
|
)a
|
||||||
|
|
||||||
|
@continuation_keys ~w(
|
||||||
|
continuation_bridge
|
||||||
|
continuation_stack
|
||||||
|
continuation_conntracked
|
||||||
|
continuation_table_id
|
||||||
|
continuation_cookie
|
||||||
|
continuation_actions
|
||||||
|
continuation_mirrors
|
||||||
|
continuation_action_set
|
||||||
|
)a
|
||||||
|
|
||||||
@experimenter 0x00002320
|
@experimenter 0x00002320
|
||||||
@nx_type 30
|
@nx_type 30
|
||||||
|
|
||||||
|
|
@ -51,6 +74,12 @@ defmodule Openflow.NxPacketIn2 do
|
||||||
|
|
||||||
def ofp_type, do: 4
|
def ofp_type, do: 4
|
||||||
|
|
||||||
|
def to_binary(%NxPacketIn2{} = pin) do
|
||||||
|
props_bin = encode_props("", pin, @encode_keys)
|
||||||
|
continuations_bin = encode_continuations("", pin, @continuation_keys)
|
||||||
|
<<@experimenter::32, @nx_type::32, props_bin::bytes, continuations_bin::bytes>>
|
||||||
|
end
|
||||||
|
|
||||||
def read(<<@experimenter::32, @nx_type::32, props_bin::bytes>>) do
|
def read(<<@experimenter::32, @nx_type::32, props_bin::bytes>>) do
|
||||||
%NxPacketIn2{}
|
%NxPacketIn2{}
|
||||||
|> decode_props(props_bin)
|
|> decode_props(props_bin)
|
||||||
|
|
@ -58,6 +87,189 @@ defmodule Openflow.NxPacketIn2 do
|
||||||
|
|
||||||
## private functions
|
## private functions
|
||||||
|
|
||||||
|
defp encode_props(acc, _pin, []), do: acc
|
||||||
|
|
||||||
|
defp encode_props(acc, %NxPacketIn2{packet: packet} = pin, [:packet | rest])
|
||||||
|
when not is_nil(packet) and is_binary(packet) do
|
||||||
|
length = @prop_header_length + byte_size(packet)
|
||||||
|
pad_length = Openflow.Utils.pad_length(length, 8)
|
||||||
|
binary = <<@packet::16, length::16, packet::bytes, 0::size(pad_length)-unit(8)>>
|
||||||
|
encode_props(<<acc::bytes, binary::bytes>>, pin, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp encode_props(acc, %NxPacketIn2{full_len: full_len} = pin, [:full_len | rest])
|
||||||
|
when not is_nil(full_len) and is_integer(full_len) do
|
||||||
|
length = @prop_header_length + 4
|
||||||
|
binary = <<@full_len::16, length::16, full_len::32>>
|
||||||
|
encode_props(<<acc::bytes, binary::bytes>>, pin, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp encode_props(acc, %NxPacketIn2{buffer_id: buffer_id} = pin, [:buffer_id | rest])
|
||||||
|
when not is_nil(buffer_id) and is_integer(buffer_id) do
|
||||||
|
length = @prop_header_length + 4
|
||||||
|
binary = <<@buffer_id::16, length::16, buffer_id::32>>
|
||||||
|
encode_props(<<acc::bytes, binary::bytes>>, pin, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp encode_props(acc, %NxPacketIn2{table_id: table_id} = pin, [:table_id | rest])
|
||||||
|
when not is_nil(table_id) and is_integer(table_id) do
|
||||||
|
length = @prop_header_length + 4
|
||||||
|
binary = <<@table_id::16, length::16, table_id::8, 0::24>>
|
||||||
|
encode_props(<<acc::bytes, binary::bytes>>, pin, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp encode_props(acc, %NxPacketIn2{cookie: cookie} = pin, [:cookie | rest])
|
||||||
|
when not is_nil(cookie) and is_integer(cookie) do
|
||||||
|
length = @prop_header_length + 4
|
||||||
|
binary = <<@cookie::16, length::16, 0::32, cookie::64>>
|
||||||
|
encode_props(<<acc::bytes, binary::bytes>>, pin, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp encode_props(acc, %NxPacketIn2{metadata: metadata} = pin, [:metadata | rest])
|
||||||
|
when not is_nil(metadata) and is_list(metadata) do
|
||||||
|
pad_match_bin =
|
||||||
|
metadata
|
||||||
|
|> Openflow.Match.new()
|
||||||
|
|> Openflow.Match.to_binary()
|
||||||
|
|
||||||
|
<<1::16, match_len_with_header::16, padded_match_bin::bytes>> = pad_match_bin
|
||||||
|
match_len = match_len_with_header - 4
|
||||||
|
<<match_bin::size(match_len)-bytes, _pad::bytes>> = padded_match_bin
|
||||||
|
length = @prop_header_length + match_len
|
||||||
|
pad_length = Openflow.Utils.pad_length(length, 8)
|
||||||
|
binary = <<@metadata::16, length::16, match_bin::bytes, 0::size(pad_length)-unit(8)>>
|
||||||
|
encode_props(<<acc::bytes, binary::bytes>>, pin, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp encode_props(acc, %NxPacketIn2{userdata: userdata} = pin, [:userdata | rest])
|
||||||
|
when not is_nil(userdata) and is_binary(userdata) do
|
||||||
|
length = @prop_header_length + byte_size(userdata)
|
||||||
|
pad_length = Openflow.Utils.pad_length(length, 8)
|
||||||
|
binary = <<@userdata::16, length::16, userdata::bytes, 0::size(pad_length)-unit(8)>>
|
||||||
|
encode_props(<<acc::bytes, binary::bytes>>, pin, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp encode_props(acc, pin, [_ | rest]) do
|
||||||
|
encode_props(acc, pin, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp encode_continuations(acc, _pin, []) do
|
||||||
|
if byte_size(acc) > 0 do
|
||||||
|
length = @prop_header_length + byte_size(acc)
|
||||||
|
pad_length = Openflow.Utils.pad_length(length, 8)
|
||||||
|
<<@continuation::16, acc::bytes, 0::size(pad_length)-unit(8)>>
|
||||||
|
else
|
||||||
|
<<>>
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp encode_continuations(
|
||||||
|
acc,
|
||||||
|
%NxPacketIn2{continuation_bridge: br} = pin,
|
||||||
|
[:continuation_bridge | rest]
|
||||||
|
)
|
||||||
|
when not is_nil(br) do
|
||||||
|
length = @prop_header_length + byte_size(br)
|
||||||
|
pad_length = Openflow.Utils.pad_length(length, 8)
|
||||||
|
bridge_bin = <<br::bytes, 0::size(pad_length)-unit(8), acc::bytes>>
|
||||||
|
binary = <<@nxcpt_bridge::16, length::16, bridge_bin::bytes, acc::bytes>>
|
||||||
|
encode_continuations(binary, pin, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp encode_continuations(
|
||||||
|
acc,
|
||||||
|
%NxPacketIn2{continuation_stack: stack} = pin,
|
||||||
|
[:continuation_stack | rest]
|
||||||
|
)
|
||||||
|
when not is_nil(stack) do
|
||||||
|
length = @prop_header_length + byte_size(stack)
|
||||||
|
pad_length = Openflow.Utils.pad_length(length, 8)
|
||||||
|
stack_bin = <<stack::bytes, 0::size(pad_length)-unit(8), acc::bytes>>
|
||||||
|
binary = <<@nxcpt_stack::16, length::16, stack_bin::bytes, acc::bytes>>
|
||||||
|
encode_continuations(binary, pin, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp encode_continuations(
|
||||||
|
acc,
|
||||||
|
%NxPacketIn2{continuation_mirrors: mirrors} = pin,
|
||||||
|
[:continuation_mirrors | rest]
|
||||||
|
)
|
||||||
|
when not is_nil(mirrors) do
|
||||||
|
length = @prop_header_length + byte_size(mirrors)
|
||||||
|
pad_length = Openflow.Utils.pad_length(length, 8)
|
||||||
|
mirrors_bin = <<mirrors::bytes, 0::size(pad_length)-unit(8), acc::bytes>>
|
||||||
|
binary = <<@nxcpt_mirrors::16, length::16, mirrors_bin::bytes, acc::bytes>>
|
||||||
|
encode_continuations(binary, pin, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp encode_continuations(
|
||||||
|
acc,
|
||||||
|
%NxPacketIn2{continuation_conntracked: true} = pin,
|
||||||
|
[:continuation_conntracked | rest]
|
||||||
|
) do
|
||||||
|
length = @prop_header_length + 1
|
||||||
|
pad_length = Openflow.Utils.pad_length(length, 8)
|
||||||
|
conntracked_bin = <<1::size(1)-unit(8), 0::size(pad_length)-unit(8), acc::bytes>>
|
||||||
|
binary = <<@nxcpt_conntracked::16, length::16, conntracked_bin::bytes, acc::bytes>>
|
||||||
|
encode_continuations(binary, pin, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp encode_continuations(
|
||||||
|
acc,
|
||||||
|
%NxPacketIn2{continuation_table_id: table_id} = pin,
|
||||||
|
[:continuation_table_id | rest]
|
||||||
|
)
|
||||||
|
when not is_nil(table_id) do
|
||||||
|
length = @prop_header_length + 1
|
||||||
|
pad_length = Openflow.Utils.pad_length(length, 8)
|
||||||
|
table_id_bin = <<table_id::8, 0::size(pad_length)-unit(8), acc::bytes>>
|
||||||
|
binary = <<@nxcpt_table_id::16, length::16, table_id_bin::bytes, acc::bytes>>
|
||||||
|
encode_continuations(binary, pin, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp encode_continuations(
|
||||||
|
acc,
|
||||||
|
%NxPacketIn2{continuation_cookie: cookie} = pin,
|
||||||
|
[:continuation_cookie | rest]
|
||||||
|
)
|
||||||
|
when not is_nil(cookie) do
|
||||||
|
length = @prop_header_length + 8
|
||||||
|
pad_length = Openflow.Utils.pad_length(length, 8)
|
||||||
|
cookie_bin = <<cookie::64, 0::size(pad_length)-unit(8), acc::bytes>>
|
||||||
|
binary = <<@nxcpt_cookie::16, length::16, cookie_bin::bytes, acc::bytes>>
|
||||||
|
encode_continuations(binary, pin, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp encode_continuations(
|
||||||
|
acc,
|
||||||
|
%NxPacketIn2{continuation_actions: actions} = pin,
|
||||||
|
[:continuation_actions | rest]
|
||||||
|
) do
|
||||||
|
actions_bin = Openflow.Action.to_binary(actions)
|
||||||
|
length = @prop_header_length + byte_size(actions_bin)
|
||||||
|
pad_length = Openflow.Utils.pad_length(length, 8)
|
||||||
|
actions_bin = <<actions_bin::bytes, 0::size(pad_length)-unit(8), acc::bytes>>
|
||||||
|
binary = <<@nxcpt_actions::16, length::16, actions_bin::bytes, acc::bytes>>
|
||||||
|
encode_continuations(binary, pin, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp encode_continuations(
|
||||||
|
acc,
|
||||||
|
%NxPacketIn2{continuation_action_set: action_set} = pin,
|
||||||
|
[:continuation_action_set | rest]
|
||||||
|
)
|
||||||
|
when not is_nil(action_set) do
|
||||||
|
length = @prop_header_length + byte_size(action_set)
|
||||||
|
pad_length = Openflow.Utils.pad_length(length, 8)
|
||||||
|
action_set_bin = <<action_set::bytes, 0::size(pad_length)-unit(8), acc::bytes>>
|
||||||
|
binary = <<@nxcpt_action_set::16, length::16, action_set_bin::bytes, acc::bytes>>
|
||||||
|
encode_continuations(binary, pin, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp encode_continuations(acc, pin, [_ | rest]) do
|
||||||
|
encode_continuations(acc, pin, rest)
|
||||||
|
end
|
||||||
|
|
||||||
defp decode_props(pktin, ""), do: pktin
|
defp decode_props(pktin, ""), do: pktin
|
||||||
|
|
||||||
defp decode_props(pktin, <<@packet::16, length::16, tail::bytes>>) do
|
defp decode_props(pktin, <<@packet::16, length::16, tail::bytes>>) do
|
||||||
|
|
|
||||||
436
lib/openflow/nx_resume.ex
Normal file
436
lib/openflow/nx_resume.ex
Normal file
|
|
@ -0,0 +1,436 @@
|
||||||
|
defmodule Openflow.NxResume do
|
||||||
|
defstruct(
|
||||||
|
version: 4,
|
||||||
|
xid: 0,
|
||||||
|
datapath_id: "",
|
||||||
|
aux_id: 0,
|
||||||
|
# packet_in properties:
|
||||||
|
packet: nil,
|
||||||
|
full_len: nil,
|
||||||
|
buffer_id: nil,
|
||||||
|
table_id: nil,
|
||||||
|
cookie: nil,
|
||||||
|
reason: nil,
|
||||||
|
metadata: nil,
|
||||||
|
userdata: nil,
|
||||||
|
# continuation properties:
|
||||||
|
continuation_bridge: nil,
|
||||||
|
continuation_stack: nil,
|
||||||
|
continuation_conntracked: nil,
|
||||||
|
continuation_mirrors: nil,
|
||||||
|
continuation_table_id: nil,
|
||||||
|
continuation_cookie: nil,
|
||||||
|
continuation_actions: nil,
|
||||||
|
continuation_action_set: nil
|
||||||
|
)
|
||||||
|
|
||||||
|
alias __MODULE__
|
||||||
|
|
||||||
|
@encode_keys ~w(
|
||||||
|
packet
|
||||||
|
full_len
|
||||||
|
buffer_id
|
||||||
|
table_id
|
||||||
|
cookie
|
||||||
|
reason
|
||||||
|
metadata
|
||||||
|
userdata
|
||||||
|
)a
|
||||||
|
|
||||||
|
@continuation_keys ~w(
|
||||||
|
continuation_bridge
|
||||||
|
continuation_stack
|
||||||
|
continuation_conntracked
|
||||||
|
continuation_table_id
|
||||||
|
continuation_cookie
|
||||||
|
continuation_actions
|
||||||
|
continuation_mirrors
|
||||||
|
continuation_action_set
|
||||||
|
)a
|
||||||
|
|
||||||
|
@experimenter 0x00002320
|
||||||
|
@nx_type 28
|
||||||
|
|
||||||
|
@packet 0
|
||||||
|
@full_len 1
|
||||||
|
@buffer_id 2
|
||||||
|
@table_id 3
|
||||||
|
@cookie 4
|
||||||
|
@reason 5
|
||||||
|
@metadata 6
|
||||||
|
@userdata 7
|
||||||
|
@continuation 8
|
||||||
|
|
||||||
|
@nxcpt_bridge 0x8000
|
||||||
|
@nxcpt_stack 0x8001
|
||||||
|
@nxcpt_mirrors 0x8002
|
||||||
|
@nxcpt_conntracked 0x8003
|
||||||
|
@nxcpt_table_id 0x8004
|
||||||
|
@nxcpt_cookie 0x8005
|
||||||
|
@nxcpt_actions 0x8006
|
||||||
|
@nxcpt_action_set 0x8007
|
||||||
|
|
||||||
|
@prop_header_length 4
|
||||||
|
|
||||||
|
def ofp_type, do: 4
|
||||||
|
|
||||||
|
def new(options \\ []) do
|
||||||
|
packet_in = options[:packet_in]
|
||||||
|
packet = options[:packet] || packet_in.packet
|
||||||
|
|
||||||
|
%NxResume{
|
||||||
|
packet: options[:packet] || packet_in.packet,
|
||||||
|
full_len: byte_size(packet),
|
||||||
|
buffer_id: packet_in.buffer_id || :no_buffer,
|
||||||
|
table_id: packet_in.table_id,
|
||||||
|
cookie: packet_in.cookie,
|
||||||
|
reason: packet_in.reason,
|
||||||
|
metadata: packet_in.metadata,
|
||||||
|
userdata: packet_in.userdata,
|
||||||
|
continuation_bridge: packet_in.continuation_bridge,
|
||||||
|
continuation_stack: packet_in.continuation_stack,
|
||||||
|
continuation_conntracked: packet_in.continuation_conntracked,
|
||||||
|
continuation_table_id: packet_in.continuation_table_id,
|
||||||
|
continuation_cookie: packet_in.continuation_cookie,
|
||||||
|
continuation_actions: packet_in.continuation_actions,
|
||||||
|
continuation_action_set: packet_in.continuation_action_set,
|
||||||
|
continuation_mirrors: packet_in.continuation_mirrors
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_binary(%NxResume{} = pin) do
|
||||||
|
props_bin = encode_props("", pin, @encode_keys)
|
||||||
|
continuations_bin = encode_continuations("", pin, @continuation_keys)
|
||||||
|
bin0 = <<@experimenter::32, @nx_type::32, props_bin::bytes, continuations_bin::bytes>>
|
||||||
|
pad_length = Openflow.Utils.pad_length(byte_size(bin0) + 8, 8)
|
||||||
|
<<bin0::bytes, 0::size(pad_length)-unit(8)>>
|
||||||
|
end
|
||||||
|
|
||||||
|
def read(<<@experimenter::32, @nx_type::32, props_bin::bytes>>) do
|
||||||
|
%NxResume{}
|
||||||
|
|> decode_props(props_bin)
|
||||||
|
end
|
||||||
|
|
||||||
|
## private functions
|
||||||
|
|
||||||
|
defp encode_props(acc, _pin, []), do: acc
|
||||||
|
|
||||||
|
defp encode_props(acc, %NxResume{packet: packet} = pin, [:packet | rest])
|
||||||
|
when not is_nil(packet) and is_binary(packet) do
|
||||||
|
length = @prop_header_length + byte_size(packet)
|
||||||
|
pad_length = Openflow.Utils.pad_length(length, 8)
|
||||||
|
binary = <<@packet::16, length::16, packet::bytes, 0::size(pad_length)-unit(8)>>
|
||||||
|
encode_props(<<acc::bytes, binary::bytes>>, pin, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp encode_props(acc, %NxResume{full_len: full_len} = pin, [:full_len | rest])
|
||||||
|
when not is_nil(full_len) and is_integer(full_len) do
|
||||||
|
length = @prop_header_length + 4
|
||||||
|
binary = <<@full_len::16, length::16, full_len::32>>
|
||||||
|
encode_props(<<acc::bytes, binary::bytes>>, pin, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp encode_props(acc, %NxResume{buffer_id: buffer_id} = pin, [:buffer_id | rest])
|
||||||
|
when not is_nil(buffer_id) do
|
||||||
|
length = @prop_header_length + 4
|
||||||
|
buffer_id_int = Openflow.Utils.get_enum(buffer_id, :buffer_id)
|
||||||
|
binary = <<@buffer_id::16, length::16, buffer_id_int::32>>
|
||||||
|
encode_props(<<acc::bytes, binary::bytes>>, pin, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp encode_props(acc, %NxResume{table_id: table_id} = pin, [:table_id | rest])
|
||||||
|
when not is_nil(table_id) and is_integer(table_id) do
|
||||||
|
length = @prop_header_length + 4
|
||||||
|
binary = <<@table_id::16, length::16, table_id::8, 0::24>>
|
||||||
|
encode_props(<<acc::bytes, binary::bytes>>, pin, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp encode_props(acc, %NxResume{cookie: cookie} = pin, [:cookie | rest])
|
||||||
|
when not is_nil(cookie) and is_integer(cookie) do
|
||||||
|
length = @prop_header_length + 4
|
||||||
|
binary = <<@cookie::16, length::16, 0::32, cookie::64>>
|
||||||
|
encode_props(<<acc::bytes, binary::bytes>>, pin, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp encode_props(acc, %NxResume{metadata: metadata} = pin, [:metadata | rest])
|
||||||
|
when not is_nil(metadata) and is_list(metadata) do
|
||||||
|
pad_match_bin =
|
||||||
|
metadata
|
||||||
|
|> Openflow.Match.new()
|
||||||
|
|> Openflow.Match.to_binary()
|
||||||
|
|
||||||
|
<<1::16, match_len_with_header::16, padded_match_bin::bytes>> = pad_match_bin
|
||||||
|
match_len = match_len_with_header - 4
|
||||||
|
<<match_bin::size(match_len)-bytes, _pad::bytes>> = padded_match_bin
|
||||||
|
length = @prop_header_length + match_len
|
||||||
|
pad_length = Openflow.Utils.pad_length(length, 8)
|
||||||
|
binary = <<@metadata::16, length::16, match_bin::bytes, 0::size(pad_length)-unit(8)>>
|
||||||
|
encode_props(<<acc::bytes, binary::bytes>>, pin, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp encode_props(acc, %NxResume{userdata: userdata} = pin, [:userdata | rest])
|
||||||
|
when not is_nil(userdata) and is_binary(userdata) do
|
||||||
|
length = @prop_header_length + byte_size(userdata)
|
||||||
|
pad_length = Openflow.Utils.pad_length(length, 8)
|
||||||
|
binary = <<@userdata::16, length::16, userdata::bytes, 0::size(pad_length)-unit(8)>>
|
||||||
|
encode_props(<<acc::bytes, binary::bytes>>, pin, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp encode_props(acc, pin, [_ | rest]) do
|
||||||
|
encode_props(acc, pin, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp encode_continuations(acc, _pin, []) do
|
||||||
|
if byte_size(acc) > 0 do
|
||||||
|
length = @prop_header_length + byte_size(acc)
|
||||||
|
pad_length = Openflow.Utils.pad_length(length, 8)
|
||||||
|
binary = <<@continuation::16, length::16, acc::bytes, 0::size(pad_length)-unit(8)>>
|
||||||
|
binary
|
||||||
|
else
|
||||||
|
<<>>
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp encode_continuations(
|
||||||
|
acc,
|
||||||
|
%NxResume{continuation_bridge: br} = pin,
|
||||||
|
[:continuation_bridge | rest]
|
||||||
|
)
|
||||||
|
when not is_nil(br) do
|
||||||
|
length = @prop_header_length + byte_size(br)
|
||||||
|
bridge_bin = <<br::16-bytes, acc::bytes>>
|
||||||
|
binary = <<@nxcpt_bridge::16, length::16, bridge_bin::bytes, 0::size(4)-unit(8), acc::bytes>>
|
||||||
|
|
||||||
|
encode_continuations(binary, pin, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp encode_continuations(
|
||||||
|
acc,
|
||||||
|
%NxResume{continuation_stack: stack} = pin,
|
||||||
|
[:continuation_stack | rest]
|
||||||
|
)
|
||||||
|
when not is_nil(stack) do
|
||||||
|
length = @prop_header_length + byte_size(stack)
|
||||||
|
pad_length = Openflow.Utils.pad_length(length, 8)
|
||||||
|
stack_bin = <<stack::bytes, 0::size(pad_length)-unit(8), acc::bytes>>
|
||||||
|
binary = <<@nxcpt_stack::16, length::16, stack_bin::bytes, acc::bytes>>
|
||||||
|
encode_continuations(binary, pin, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp encode_continuations(
|
||||||
|
acc,
|
||||||
|
%NxResume{continuation_mirrors: mirrors} = pin,
|
||||||
|
[:continuation_mirrors | rest]
|
||||||
|
)
|
||||||
|
when not is_nil(mirrors) do
|
||||||
|
length = @prop_header_length + byte_size(mirrors)
|
||||||
|
pad_length = Openflow.Utils.pad_length(length, 8)
|
||||||
|
mirrors_bin = <<mirrors::bytes, 0::size(pad_length)-unit(8), acc::bytes>>
|
||||||
|
binary = <<@nxcpt_mirrors::16, length::16, mirrors_bin::bytes, acc::bytes>>
|
||||||
|
|
||||||
|
encode_continuations(binary, pin, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp encode_continuations(
|
||||||
|
acc,
|
||||||
|
%NxResume{continuation_conntracked: true} = pin,
|
||||||
|
[:continuation_conntracked | rest]
|
||||||
|
) do
|
||||||
|
length = @prop_header_length + 1
|
||||||
|
pad_length = Openflow.Utils.pad_length(length, 8)
|
||||||
|
conntracked_bin = <<1::size(1)-unit(8), 0::size(pad_length)-unit(8), acc::bytes>>
|
||||||
|
binary = <<@nxcpt_conntracked::16, length::16, conntracked_bin::bytes, acc::bytes>>
|
||||||
|
|
||||||
|
encode_continuations(binary, pin, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp encode_continuations(
|
||||||
|
acc,
|
||||||
|
%NxResume{continuation_table_id: table_id} = pin,
|
||||||
|
[:continuation_table_id | rest]
|
||||||
|
)
|
||||||
|
when not is_nil(table_id) do
|
||||||
|
length = @prop_header_length + 1
|
||||||
|
pad_length = Openflow.Utils.pad_length(length, 8)
|
||||||
|
table_id_bin = <<table_id::8, 0::size(pad_length)-unit(8), acc::bytes>>
|
||||||
|
binary = <<@nxcpt_table_id::16, length::16, table_id_bin::bytes, acc::bytes>>
|
||||||
|
|
||||||
|
encode_continuations(binary, pin, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp encode_continuations(
|
||||||
|
acc,
|
||||||
|
%NxResume{continuation_cookie: cookie} = pin,
|
||||||
|
[:continuation_cookie | rest]
|
||||||
|
)
|
||||||
|
when not is_nil(cookie) do
|
||||||
|
length = @prop_header_length + 8
|
||||||
|
pad_length = Openflow.Utils.pad_length(length, 8)
|
||||||
|
cookie_bin = <<cookie::64, 0::size(pad_length)-unit(8), acc::bytes>>
|
||||||
|
binary = <<@nxcpt_cookie::16, length::16, cookie_bin::bytes, acc::bytes>>
|
||||||
|
|
||||||
|
encode_continuations(binary, pin, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp encode_continuations(
|
||||||
|
acc,
|
||||||
|
%NxResume{continuation_actions: actions} = pin,
|
||||||
|
[:continuation_actions | rest]
|
||||||
|
)
|
||||||
|
when not is_nil(actions) do
|
||||||
|
actions_bin = Openflow.Action.to_binary(actions)
|
||||||
|
length = @prop_header_length + byte_size(actions_bin)
|
||||||
|
pad_length = Openflow.Utils.pad_length(length, 8)
|
||||||
|
actions_bin = <<actions_bin::bytes, 0::size(pad_length)-unit(8), acc::bytes>>
|
||||||
|
binary = <<@nxcpt_actions::16, length::16, actions_bin::bytes, acc::bytes>>
|
||||||
|
encode_continuations(binary, pin, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp encode_continuations(
|
||||||
|
acc,
|
||||||
|
%NxResume{continuation_action_set: action_set} = pin,
|
||||||
|
[:continuation_action_set | rest]
|
||||||
|
)
|
||||||
|
when not is_nil(action_set) do
|
||||||
|
length = @prop_header_length + byte_size(action_set)
|
||||||
|
pad_length = Openflow.Utils.pad_length(length, 8)
|
||||||
|
action_set_bin = <<action_set::bytes, 0::size(pad_length)-unit(8), acc::bytes>>
|
||||||
|
binary = <<@nxcpt_action_set::16, length::16, action_set_bin::bytes, acc::bytes>>
|
||||||
|
encode_continuations(binary, pin, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp encode_continuations(acc, pin, [other | rest]) do
|
||||||
|
encode_continuations(acc, pin, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp decode_props(pktin, ""), do: pktin
|
||||||
|
|
||||||
|
defp decode_props(pktin, <<@packet::16, length::16, tail::bytes>>) do
|
||||||
|
pad_length = Openflow.Utils.pad_length(length, 8)
|
||||||
|
packet_length = length - @prop_header_length
|
||||||
|
<<packet::size(packet_length)-bytes, _::size(pad_length)-unit(8), rest::bytes>> = tail
|
||||||
|
decode_props(%{pktin | packet: packet}, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp decode_props(pktin, <<@full_len::16, _length::16, full_len::32, rest::bytes>>) do
|
||||||
|
decode_props(%{pktin | full_len: full_len}, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp decode_props(pktin, <<@buffer_id::16, _length::16, buffer_id::32, rest::bytes>>) do
|
||||||
|
decode_props(%{pktin | buffer_id: buffer_id}, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp decode_props(pktin, <<@table_id::16, _length::16, table_id::8, _::24, rest::bytes>>) do
|
||||||
|
decode_props(%{pktin | table_id: table_id}, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp decode_props(pktin, <<@cookie::16, _length::16, _::32, cookie::64, rest::bytes>>) do
|
||||||
|
decode_props(%{pktin | cookie: cookie}, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp decode_props(pktin, <<@reason::16, _length::16, reason_int::8, _::24, rest::bytes>>) do
|
||||||
|
reason = Openflow.Enums.to_atom(reason_int, :packet_in_reason)
|
||||||
|
decode_props(%{pktin | reason: reason}, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp decode_props(pktin, <<@metadata::16, length::16, tail::bytes>>) do
|
||||||
|
pad_length = Openflow.Utils.pad_length(length, 8)
|
||||||
|
match_field_length = length - @prop_header_length
|
||||||
|
|
||||||
|
<<match_fields_bin::size(match_field_length)-bytes, _::size(pad_length)-unit(8), rest::bytes>> =
|
||||||
|
tail
|
||||||
|
|
||||||
|
match_len = 4 + byte_size(match_fields_bin)
|
||||||
|
padding = Openflow.Utils.pad_length(match_len, 8)
|
||||||
|
match_bin = <<1::16, match_len::16, match_fields_bin::bytes, 0::size(padding)-unit(8)>>
|
||||||
|
{fields, _rest} = Openflow.Match.read(match_bin)
|
||||||
|
decode_props(%{pktin | metadata: fields}, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp decode_props(pktin, <<@userdata::16, length::16, tail::bytes>>) do
|
||||||
|
pad_length = Openflow.Utils.pad_length(length, 8)
|
||||||
|
userdata_length = length - @prop_header_length
|
||||||
|
<<userdata::size(userdata_length)-bytes, _::size(pad_length)-unit(8), rest::bytes>> = tail
|
||||||
|
decode_props(%{pktin | userdata: userdata}, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp decode_props(pktin, <<@continuation::16, length::16, tail::bytes>>) do
|
||||||
|
pad_length = Openflow.Utils.pad_length(length, 8)
|
||||||
|
data_length = length - @prop_header_length - 4
|
||||||
|
<<_pad::32, data::size(data_length)-bytes, _::size(pad_length)-unit(8), rest::bytes>> = tail
|
||||||
|
|
||||||
|
pktin
|
||||||
|
|> decode_continuations(data)
|
||||||
|
|> decode_props(rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp decode_props(pktin, <<_::16, length::16, tail::bytes>>) do
|
||||||
|
pad_length = Openflow.Utils.pad_length(length, 8)
|
||||||
|
data_length = length - @prop_header_length
|
||||||
|
<<_data::size(data_length)-bytes, _::size(pad_length)-unit(8), rest::bytes>> = tail
|
||||||
|
decode_props(pktin, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp decode_continuations(pktin, ""), do: pktin
|
||||||
|
|
||||||
|
defp decode_continuations(pktin, <<@nxcpt_bridge::16, length::16, tail::bytes>>) do
|
||||||
|
pad_length = Openflow.Utils.pad_length(length, 8)
|
||||||
|
data_length = length - @prop_header_length
|
||||||
|
<<bridge::size(data_length)-bytes, _::size(pad_length)-unit(8), rest::bytes>> = tail
|
||||||
|
decode_continuations(%{pktin | continuation_bridge: bridge}, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp decode_continuations(pktin, <<@nxcpt_stack::16, length::16, tail::bytes>>) do
|
||||||
|
pad_length = Openflow.Utils.pad_length(length, 8)
|
||||||
|
data_length = (length - @prop_header_length) * 8
|
||||||
|
<<stack::size(data_length), _::size(pad_length)-unit(8), rest::bytes>> = tail
|
||||||
|
decode_continuations(%{pktin | continuation_stack: pktin.continuation_stack ++ [stack]}, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp decode_continuations(pktin, <<@nxcpt_mirrors::16, length::16, tail::bytes>>) do
|
||||||
|
pad_length = Openflow.Utils.pad_length(length, 8)
|
||||||
|
data_length = length - @prop_header_length
|
||||||
|
<<mirrors::size(data_length)-bytes, _::size(pad_length)-unit(8), rest::bytes>> = tail
|
||||||
|
decode_continuations(%{pktin | continuation_mirrors: mirrors}, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp decode_continuations(pktin, <<@nxcpt_conntracked::16, length::16, tail::bytes>>) do
|
||||||
|
pad_length = Openflow.Utils.pad_length(length, 8)
|
||||||
|
data_length = length - @prop_header_length
|
||||||
|
<<_::size(data_length)-bytes, _::size(pad_length)-unit(8), rest::bytes>> = tail
|
||||||
|
decode_continuations(%{pktin | continuation_conntracked: true}, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp decode_continuations(pktin, <<@nxcpt_table_id::16, length::16, tail::bytes>>) do
|
||||||
|
pad_length = Openflow.Utils.pad_length(length, 8)
|
||||||
|
<<table_id::8, _::size(pad_length)-unit(8), rest::bytes>> = tail
|
||||||
|
decode_continuations(%{pktin | continuation_table_id: table_id}, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp decode_continuations(pktin, <<@nxcpt_cookie::16, length::16, tail::bytes>>) do
|
||||||
|
pad_length = Openflow.Utils.pad_length(length, 8)
|
||||||
|
<<cookie::64, _::size(pad_length)-unit(8), rest::bytes>> = tail
|
||||||
|
decode_continuations(%{pktin | continuation_cookie: cookie}, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp decode_continuations(pktin, <<@nxcpt_actions::16, length::16, tail::bytes>>) do
|
||||||
|
pad_length = Openflow.Utils.pad_length(length, 8)
|
||||||
|
data_length = length - @prop_header_length - 4
|
||||||
|
|
||||||
|
<<_pad::32, actions::size(data_length)-bytes, _::size(pad_length)-unit(8), rest::bytes>> =
|
||||||
|
tail
|
||||||
|
|
||||||
|
decode_continuations(%{pktin | continuation_actions: Openflow.Action.read(actions)}, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp decode_continuations(pktin, <<@nxcpt_action_set::16, length::16, tail::bytes>>) do
|
||||||
|
pad_length = Openflow.Utils.pad_length(length, 8)
|
||||||
|
data_length = length - @prop_header_length
|
||||||
|
<<action_set::size(data_length)-bytes, _::size(pad_length)-unit(8), rest::bytes>> = tail
|
||||||
|
decode_continuations(%{pktin | continuation_action_set: action_set}, rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp decode_continuations(pktin, _) do
|
||||||
|
decode_continuations(pktin, "")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -34,12 +34,12 @@ defmodule OVSDB.OpenvSwitch do
|
||||||
disable_in_band: "true"
|
disable_in_band: "true"
|
||||||
)
|
)
|
||||||
"""
|
"""
|
||||||
def add_br(pid, [_|_] = options) do
|
def add_br(pid, [_ | _] = options) do
|
||||||
br_uuids = GenServer.call(pid, {:sync_get, @open_vswitch, "bridges"})
|
br_uuids = GenServer.call(pid, {:sync_get, @open_vswitch, "bridges"})
|
||||||
|
|
||||||
add_br_options = [
|
add_br_options = [
|
||||||
bridge: options[:name],
|
bridge: options[:name],
|
||||||
fail_mode: options[:fail_mode] || "standalone",
|
fail_mode: options[:fail_mode] || "standalone",
|
||||||
datapath_id: options[:datapath_id],
|
datapath_id: options[:datapath_id],
|
||||||
disable_in_band: options[:disable_in_band],
|
disable_in_band: options[:disable_in_band],
|
||||||
br_uuids: br_uuids
|
br_uuids: br_uuids
|
||||||
|
|
@ -83,10 +83,11 @@ defmodule OVSDB.OpenvSwitch do
|
||||||
protocol: "OpenFlow13"
|
protocol: "OpenFlow13"
|
||||||
)
|
)
|
||||||
"""
|
"""
|
||||||
def set_controller(pid, [_|_] = options) do
|
def set_controller(pid, [_ | _] = options) do
|
||||||
case find_by_name(pid, @bridge, options[:bridge]) do
|
case find_by_name(pid, @bridge, options[:bridge]) do
|
||||||
:not_found ->
|
:not_found ->
|
||||||
{:error, :not_found}
|
{:error, :not_found}
|
||||||
|
|
||||||
%{"_uuid" => _uuid} ->
|
%{"_uuid" => _uuid} ->
|
||||||
set_ctl_opts = [
|
set_ctl_opts = [
|
||||||
bridge: options[:bridge],
|
bridge: options[:bridge],
|
||||||
|
|
@ -94,7 +95,7 @@ defmodule OVSDB.OpenvSwitch do
|
||||||
connection_mode: options[:connection_mode] || "out-of-band",
|
connection_mode: options[:connection_mode] || "out-of-band",
|
||||||
controller_rate_limit: options[:controller_rate_limit] || 1000,
|
controller_rate_limit: options[:controller_rate_limit] || 1000,
|
||||||
controller_burst_limit: options[:controller_burst_limit] || 100,
|
controller_burst_limit: options[:controller_burst_limit] || 100,
|
||||||
protocol: options[:protocol] || "OpenFlow13",
|
protocol: options[:protocol] || "OpenFlow13"
|
||||||
]
|
]
|
||||||
|
|
||||||
GenServer.call(pid, {:set_controller, set_ctl_opts})
|
GenServer.call(pid, {:set_controller, set_ctl_opts})
|
||||||
|
|
@ -111,10 +112,11 @@ defmodule OVSDB.OpenvSwitch do
|
||||||
ofport_request: 99
|
ofport_request: 99
|
||||||
)
|
)
|
||||||
"""
|
"""
|
||||||
def add_port(pid, [_|_] = options) do
|
def add_port(pid, [_ | _] = options) do
|
||||||
case find_by_name(pid, @bridge, options[:bridge]) do
|
case find_by_name(pid, @bridge, options[:bridge]) do
|
||||||
:not_found ->
|
:not_found ->
|
||||||
{:error, :not_found}
|
{:error, :not_found}
|
||||||
|
|
||||||
%{"_uuid" => _uuid, "ports" => ports} ->
|
%{"_uuid" => _uuid, "ports" => ports} ->
|
||||||
port_opts = [
|
port_opts = [
|
||||||
bridge: options[:bridge],
|
bridge: options[:bridge],
|
||||||
|
|
@ -146,14 +148,16 @@ defmodule OVSDB.OpenvSwitch do
|
||||||
@doc """
|
@doc """
|
||||||
iex> OpenvSwitch.del_port(client_pid, bridge: "br0", port: "vxlan5")
|
iex> OpenvSwitch.del_port(client_pid, bridge: "br0", port: "vxlan5")
|
||||||
"""
|
"""
|
||||||
def del_port(pid, [_|_] = options) do
|
def del_port(pid, [_ | _] = options) do
|
||||||
case find_by_name(pid, @bridge, options[:bridge]) do
|
case find_by_name(pid, @bridge, options[:bridge]) do
|
||||||
:not_found ->
|
:not_found ->
|
||||||
{:error, :not_found}
|
{:error, :not_found}
|
||||||
|
|
||||||
%{"_uuid" => _uuid, "ports" => ports} ->
|
%{"_uuid" => _uuid, "ports" => ports} ->
|
||||||
case find_by_name(pid, @port, options[:port]) do
|
case find_by_name(pid, @port, options[:port]) do
|
||||||
:not_found ->
|
:not_found ->
|
||||||
{:error, :not_found}
|
{:error, :not_found}
|
||||||
|
|
||||||
%{"_uuid" => port_uuid} ->
|
%{"_uuid" => port_uuid} ->
|
||||||
new_ports = del_elem_from_set(ports, port_uuid)
|
new_ports = del_elem_from_set(ports, port_uuid)
|
||||||
|
|
||||||
|
|
@ -257,34 +261,41 @@ defmodule OVSDB.OpenvSwitch do
|
||||||
bridge = %{ports: options[:ports]}
|
bridge = %{ports: options[:ports]}
|
||||||
|
|
||||||
replies =
|
replies =
|
||||||
xact([
|
xact(
|
||||||
:eovsdb_op.update(@bridge, eq_br_name, bridge),
|
[
|
||||||
:eovsdb_op.mutate(@open_vswitch, eq_ovs_uuid, next_config)
|
:eovsdb_op.update(@bridge, eq_br_name, bridge),
|
||||||
], pid)
|
:eovsdb_op.mutate(@open_vswitch, eq_ovs_uuid, next_config)
|
||||||
|
],
|
||||||
|
pid
|
||||||
|
)
|
||||||
|
|
||||||
{:reply, replies, state}
|
{:reply, replies, state}
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_call({:set_controller, options}, _from, state) do
|
def handle_call({:set_controller, options}, _from, state) do
|
||||||
%State{client_pid: pid, ovs_uuid: ovs} = state
|
%State{client_pid: pid, ovs_uuid: ovs} = state
|
||||||
|
|
||||||
controller = %{
|
controller = %{
|
||||||
target: options[:target],
|
target: options[:target],
|
||||||
connection_mode: options[:connection_mode],
|
connection_mode: options[:connection_mode],
|
||||||
controller_rate_limit: options[:controller_rate_limit],
|
controller_rate_limit: options[:controller_rate_limit],
|
||||||
controller_burst_limit: options[:controller_burst_limit],
|
controller_burst_limit: options[:controller_burst_limit]
|
||||||
}
|
}
|
||||||
|
|
||||||
bridge = %{
|
bridge = %{
|
||||||
protocols: options[:protocol],
|
protocols: options[:protocol],
|
||||||
controller: ["named-uuid", "controller"],
|
controller: ["named-uuid", "controller"]
|
||||||
}
|
}
|
||||||
|
|
||||||
replies =
|
replies =
|
||||||
xact([
|
xact(
|
||||||
:eovsdb_op.insert(@controller, controller, "controller"),
|
[
|
||||||
:eovsdb_op.update(@bridge, [{"name", "==", options[:bridge]}], bridge),
|
:eovsdb_op.insert(@controller, controller, "controller"),
|
||||||
:eovsdb_op.mutate(@open_vswitch, [{"_uuid", "==", ovs}], [{"next_cfg", "+=", 1}])
|
:eovsdb_op.update(@bridge, [{"name", "==", options[:bridge]}], bridge),
|
||||||
], pid)
|
:eovsdb_op.mutate(@open_vswitch, [{"_uuid", "==", ovs}], [{"next_cfg", "+=", 1}])
|
||||||
|
],
|
||||||
|
pid
|
||||||
|
)
|
||||||
|
|
||||||
{:reply, replies, state}
|
{:reply, replies, state}
|
||||||
end
|
end
|
||||||
|
|
@ -294,7 +305,7 @@ defmodule OVSDB.OpenvSwitch do
|
||||||
|
|
||||||
port = %{
|
port = %{
|
||||||
name: options[:name],
|
name: options[:name],
|
||||||
interfaces: ["named-uuid", "interface"],
|
interfaces: ["named-uuid", "interface"]
|
||||||
}
|
}
|
||||||
|
|
||||||
iface_options = [
|
iface_options = [
|
||||||
|
|
@ -377,6 +388,7 @@ defmodule OVSDB.OpenvSwitch do
|
||||||
|
|
||||||
defp do_find_by_name(pid, table, name) do
|
defp do_find_by_name(pid, table, name) do
|
||||||
query = :eovsdb_op.select('*', table, [{"name", "==", name}])
|
query = :eovsdb_op.select('*', table, [{"name", "==", name}])
|
||||||
|
|
||||||
case xact(query, pid) do
|
case xact(query, pid) do
|
||||||
[%{"rows" => []}] -> :not_found
|
[%{"rows" => []}] -> :not_found
|
||||||
[%{"rows" => [row]}] -> row
|
[%{"rows" => [row]}] -> row
|
||||||
|
|
@ -386,11 +398,11 @@ defmodule OVSDB.OpenvSwitch do
|
||||||
defp make_ovsdb_map(map), do: make_ovsdb_map([], map)
|
defp make_ovsdb_map(map), do: make_ovsdb_map([], map)
|
||||||
|
|
||||||
defp make_ovsdb_map(acc, []), do: ["map", Enum.reverse(acc)]
|
defp make_ovsdb_map(acc, []), do: ["map", Enum.reverse(acc)]
|
||||||
defp make_ovsdb_map(acc, [[_key, nil]|rest]), do: make_ovsdb_map(acc, rest)
|
defp make_ovsdb_map(acc, [[_key, nil] | rest]), do: make_ovsdb_map(acc, rest)
|
||||||
defp make_ovsdb_map(acc, [attr|rest]), do: make_ovsdb_map([attr|acc], rest)
|
defp make_ovsdb_map(acc, [attr | rest]), do: make_ovsdb_map([attr | acc], rest)
|
||||||
|
|
||||||
defp make_ovsdb_set(nil), do: ["set", []]
|
defp make_ovsdb_set(nil), do: ["set", []]
|
||||||
defp make_ovsdb_set([_|_] = list), do: ["set", list]
|
defp make_ovsdb_set([_ | _] = list), do: ["set", list]
|
||||||
defp make_ovsdb_set(value), do: value
|
defp make_ovsdb_set(value), do: value
|
||||||
|
|
||||||
defp add_elem_to_set(["set", []], value), do: value
|
defp add_elem_to_set(["set", []], value), do: value
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ defmodule Tres.Controller do
|
||||||
|
|
||||||
def handler_spec(dpid) do
|
def handler_spec(dpid) do
|
||||||
{cb_mod, cb_args} = Tres.Utils.get_callback_module()
|
{cb_mod, cb_args} = Tres.Utils.get_callback_module()
|
||||||
|
|
||||||
%{
|
%{
|
||||||
id: {__MODULE__, dpid},
|
id: {__MODULE__, dpid},
|
||||||
start: {cb_mod, :start_link, [[dpid, cb_args]]},
|
start: {cb_mod, :start_link, [[dpid, cb_args]]},
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ defmodule Tres.MessageHandlerSup do
|
||||||
|
|
||||||
def init(_init_args) do
|
def init(_init_args) do
|
||||||
children = []
|
children = []
|
||||||
|
|
||||||
Supervisor.init(
|
Supervisor.init(
|
||||||
children,
|
children,
|
||||||
strategy: :one_for_one,
|
strategy: :one_for_one,
|
||||||
|
|
|
||||||
|
|
@ -147,11 +147,16 @@ defmodule Tres.MessageHelper do
|
||||||
Openflow.MeterMod.new(
|
Openflow.MeterMod.new(
|
||||||
xid: options[:xid] || 0,
|
xid: options[:xid] || 0,
|
||||||
command: :delete,
|
command: :delete,
|
||||||
meter_id: options[:meter_id] || 0,
|
meter_id: options[:meter_id] || 0
|
||||||
)
|
)
|
||||||
|
|
||||||
send_message(meter_mod, datapath_id, options[:blocking] || false)
|
send_message(meter_mod, datapath_id, options[:blocking] || false)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp send_resume(datapath_id, options) do
|
||||||
|
resume = Openflow.NxResume.new(options)
|
||||||
|
send_message(resume, datapath_id, options[:blocking] || false)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ defmodule Tres.SecureChannel do
|
||||||
{:tcp, socket, packet},
|
{:tcp, socket, packet},
|
||||||
state,
|
state,
|
||||||
%State{socket: socket, transport: transport} = state_data
|
%State{socket: socket, transport: transport} = state_data
|
||||||
) do
|
) do
|
||||||
transport.setopts(socket, active: :once)
|
transport.setopts(socket, active: :once)
|
||||||
handle_packet(packet, state_data, state, [])
|
handle_packet(packet, state_data, state, [])
|
||||||
end
|
end
|
||||||
|
|
@ -137,9 +137,7 @@ defmodule Tres.SecureChannel do
|
||||||
|
|
||||||
# INIT state
|
# INIT state
|
||||||
defp handle_INIT(:enter, _old_state, state_data) do
|
defp handle_INIT(:enter, _old_state, state_data) do
|
||||||
debug(
|
debug("Initiate HELLO handshake: " <> "#{state_data.ip_addr}:#{state_data.port}")
|
||||||
"Initiate HELLO handshake: " <> "#{state_data.ip_addr}:#{state_data.port}"
|
|
||||||
)
|
|
||||||
|
|
||||||
initiate_hello_handshake(state_data)
|
initiate_hello_handshake(state_data)
|
||||||
end
|
end
|
||||||
|
|
@ -153,19 +151,14 @@ defmodule Tres.SecureChannel do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp handle_INIT(:internal, message, _state_data) do
|
defp handle_INIT(:internal, message, _state_data) do
|
||||||
debug(
|
debug("Hello handshake in progress, " <> "dropping message: #{inspect(message)}")
|
||||||
"Hello handshake in progress, " <> "dropping message: #{inspect(message)}"
|
|
||||||
)
|
|
||||||
|
|
||||||
:keep_state_and_data
|
:keep_state_and_data
|
||||||
end
|
end
|
||||||
|
|
||||||
# CONNECTING state
|
# CONNECTING state
|
||||||
defp handle_CONNECTING(:enter, :INIT, state_data) do
|
defp handle_CONNECTING(:enter, :INIT, state_data) do
|
||||||
debug(
|
debug("Initiate FEATURES handshake:" <> " #{state_data.ip_addr}:#{state_data.port}")
|
||||||
"Initiate FEATURES handshake:" <>
|
|
||||||
" #{state_data.ip_addr}:#{state_data.port}"
|
|
||||||
)
|
|
||||||
|
|
||||||
initiate_features_handshake(state_data)
|
initiate_features_handshake(state_data)
|
||||||
end
|
end
|
||||||
|
|
@ -195,8 +188,7 @@ defmodule Tres.SecureChannel do
|
||||||
|
|
||||||
defp handle_CONNECTING(:internal, {:openflow, message}, _state_data) do
|
defp handle_CONNECTING(:internal, {:openflow, message}, _state_data) do
|
||||||
debug(
|
debug(
|
||||||
"Features handshake in progress," <>
|
"Features handshake in progress," <> " dropping message: #{inspect(message.__struct__)}"
|
||||||
" dropping message: #{inspect(message.__struct__)}"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
:keep_state_and_data
|
:keep_state_and_data
|
||||||
|
|
@ -209,6 +201,7 @@ defmodule Tres.SecureChannel do
|
||||||
# CONNECTED state
|
# CONNECTED state
|
||||||
defp handle_CONNECTED(:enter, :CONNECTING, state_data) do
|
defp handle_CONNECTED(:enter, :CONNECTING, state_data) do
|
||||||
_tref = schedule_xactdb_ageout()
|
_tref = schedule_xactdb_ageout()
|
||||||
|
|
||||||
case init_handler(state_data) do
|
case init_handler(state_data) do
|
||||||
%State{} = new_state_data ->
|
%State{} = new_state_data ->
|
||||||
start_periodic_idle_check()
|
start_periodic_idle_check()
|
||||||
|
|
@ -340,10 +333,12 @@ defmodule Tres.SecureChannel do
|
||||||
action = {:next_event, :internal, {:openflow, message}}
|
action = {:next_event, :internal, {:openflow, message}}
|
||||||
new_state_data = %{state_data | buffer: "", last_received: :os.timestamp()}
|
new_state_data = %{state_data | buffer: "", last_received: :os.timestamp()}
|
||||||
handle_packet(leftovers, new_state_data, state, [action | actions])
|
handle_packet(leftovers, new_state_data, state, [action | actions])
|
||||||
|
|
||||||
{:error, :binary_too_small} ->
|
{:error, :binary_too_small} ->
|
||||||
handle_packet("", %{state_data | buffer: binary}, state, actions)
|
handle_packet("", %{state_data | buffer: binary}, state, actions)
|
||||||
{:error, :malformed_packet} ->
|
|
||||||
:ok = debug("malformed packet received from #{state_data.datapath_id}")
|
{:error, {:malformed_packet, {_reason, st}}} ->
|
||||||
|
:ok = debug("malformed packet received from #{state_data.datapath_id} stack_trace: #{st}")
|
||||||
handle_packet("", %{state_data | buffer: ""}, state, actions)
|
handle_packet("", %{state_data | buffer: ""}, state, actions)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -375,8 +370,9 @@ defmodule Tres.SecureChannel do
|
||||||
unless is_nil(message), do: send(state_data.handler_pid, message)
|
unless is_nil(message), do: send(state_data.handler_pid, message)
|
||||||
XACT_KV.delete(state_data.xact_kv_ref, xid)
|
XACT_KV.delete(state_data.xact_kv_ref, xid)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp process_xact_entry({:xact_entry, xid, message, _orig, from, _inserted_at}, state_data)
|
defp process_xact_entry({:xact_entry, xid, message, _orig, from, _inserted_at}, state_data)
|
||||||
when is_tuple(from) do
|
when is_tuple(from) do
|
||||||
reply = if is_nil(message), do: :noreply, else: message
|
reply = if is_nil(message), do: :noreply, else: message
|
||||||
:ok = :gen_statem.reply(from, {:ok, reply})
|
:ok = :gen_statem.reply(from, {:ok, reply})
|
||||||
XACT_KV.delete(state_data.xact_kv_ref, xid)
|
XACT_KV.delete(state_data.xact_kv_ref, xid)
|
||||||
|
|
@ -558,8 +554,7 @@ defmodule Tres.SecureChannel do
|
||||||
defp send_message(message, %State{socket: socket, transport: transport}) do
|
defp send_message(message, %State{socket: socket, transport: transport}) do
|
||||||
if is_list(message) do
|
if is_list(message) do
|
||||||
for message <- message,
|
for message <- message,
|
||||||
do:
|
do: debug("Sending: #{inspect(message.__struct__)}(xid: #{message.xid})")
|
||||||
debug("Sending: #{inspect(message.__struct__)}(xid: #{message.xid})")
|
|
||||||
else
|
else
|
||||||
debug("Sending: #{inspect(message.__struct__)}(xid: #{message.xid})")
|
debug("Sending: #{inspect(message.__struct__)}(xid: #{message.xid})")
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ defmodule Tres.SwitchRegistry do
|
||||||
def send_message(message, dpid, _blocking = true) do
|
def send_message(message, dpid, _blocking = true) do
|
||||||
blocking_send_message(message, dpid)
|
blocking_send_message(message, dpid)
|
||||||
end
|
end
|
||||||
|
|
||||||
def send_message(message, dpid, _blocking) do
|
def send_message(message, dpid, _blocking) do
|
||||||
send_message(message, dpid)
|
send_message(message, dpid)
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -14,11 +14,11 @@ defmodule Tres.Utils do
|
||||||
|
|
||||||
def start_openflow_listener do
|
def start_openflow_listener do
|
||||||
:ranch.start_listener(
|
:ranch.start_listener(
|
||||||
_ref = Tres,
|
_ref = Tres,
|
||||||
_trasport = :ranch_tcp,
|
_trasport = :ranch_tcp,
|
||||||
_transport_opts = transport_options(),
|
_transport_opts = transport_options(),
|
||||||
_protocol = @connection_manager,
|
_protocol = @connection_manager,
|
||||||
_protocol_opts = []
|
_protocol_opts = []
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -631,14 +631,14 @@ defmodule OfpActionTest do
|
||||||
test_file = "test/packet_data/nx_clone.raw"
|
test_file = "test/packet_data/nx_clone.raw"
|
||||||
packet = File.read!(test_file)
|
packet = File.read!(test_file)
|
||||||
actions = Openflow.Action.read(packet)
|
actions = Openflow.Action.read(packet)
|
||||||
|
|
||||||
clone =
|
clone =
|
||||||
Openflow.Action.NxClone.new(
|
Openflow.Action.NxClone.new([
|
||||||
[
|
Openflow.Action.PushVlan.new(),
|
||||||
Openflow.Action.PushVlan.new(),
|
Openflow.Action.SetField.new({:vlan_vid, 5}),
|
||||||
Openflow.Action.SetField.new({:vlan_vid, 5}),
|
Openflow.Action.Output.new(10)
|
||||||
Openflow.Action.Output.new(10)
|
])
|
||||||
]
|
|
||||||
)
|
|
||||||
actions_bin = Openflow.Action.to_binary(clone)
|
actions_bin = Openflow.Action.to_binary(clone)
|
||||||
assert actions_bin == packet
|
assert actions_bin == packet
|
||||||
assert actions == [clone]
|
assert actions == [clone]
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,9 @@ defmodule OfpPacketIn2Test do
|
||||||
assert pktin.full_len == 64
|
assert pktin.full_len == 64
|
||||||
assert pktin.table_id == 7
|
assert pktin.table_id == 7
|
||||||
assert pktin.buffer_id == 0x114
|
assert pktin.buffer_id == 0x114
|
||||||
assert pktin.cookie == 0xfedcba9876543210
|
assert pktin.cookie == 0xFEDCBA9876543210
|
||||||
assert pktin.reason == :action
|
assert pktin.reason == :action
|
||||||
assert pktin.metadata == [metadata: 0x5a5a5a5a5a5a5a5a]
|
assert pktin.metadata == [metadata: 0x5A5A5A5A5A5A5A5A]
|
||||||
assert pktin.userdata == <<1, 2, 3, 4, 5>>
|
assert pktin.userdata == <<1, 2, 3, 4, 5>>
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue