From ec1cdb6effc735d95af00dec17b45fb1a9f79fd4 Mon Sep 17 00:00:00 2001 From: Eishun Kondoh Date: Mon, 4 Mar 2019 04:03:25 +0900 Subject: [PATCH] Feature/bundle support (#15) * openflow: Add bundle support * openflow: Add bundle message generator and parser * openflow: Add bundle API --- .../lib/learning_switch/ofctl.ex | 6 +- examples/learning_switch/mix.lock | 4 +- lib/openflow/enum_gen.ex | 14 ++ lib/openflow/enums.ex | 190 ++++++++++++++++++ lib/openflow/onf_bundle_add.ex | 50 +++++ lib/openflow/onf_bundle_control.ex | 44 ++++ lib/tres/message_helper.ex | 89 +++++++- lib/tres/secure_channel_state.ex | 2 +- test/packet_data/onf_bundle_control.raw | Bin 0 -> 24 bytes 9 files changed, 388 insertions(+), 11 deletions(-) create mode 100644 lib/openflow/onf_bundle_add.ex create mode 100644 lib/openflow/onf_bundle_control.ex create mode 100644 test/packet_data/onf_bundle_control.raw diff --git a/examples/learning_switch/lib/learning_switch/ofctl.ex b/examples/learning_switch/lib/learning_switch/ofctl.ex index 0abaef1..8c42401 100644 --- a/examples/learning_switch/lib/learning_switch/ofctl.ex +++ b/examples/learning_switch/lib/learning_switch/ofctl.ex @@ -63,14 +63,18 @@ defmodule LearningSwitch.Ofctl do end defp init_flow_tables(datapath_id) do + :ok = onf_bundle_open(datapath_id, bundle_id: 1, flags: [:atomic, :ordered]) + for flow_options <- [ add_default_broadcast_flow_entry(), add_default_flooding_flow_entry(), add_multicast_mac_drop_flow_entry(), add_ipv6_multicast_mac_drop_flow_entry(), add_default_forwarding_flow_entry()] do - send_flow_mod_add(datapath_id, flow_options) + send_flow_mod_add(datapath_id, Keyword.merge(flow_options, [bundle_id: 1, bundle_flags: [:atomic, :ordered]])) end + + :ok = onf_bundle_commit(datapath_id, bundle_id: 1, flags: [:atomic, :ordered]) end defp add_forwarding_flow_and_packet_out(packet_in, state) do diff --git a/examples/learning_switch/mix.lock b/examples/learning_switch/mix.lock index cbc80d1..d1071b3 100644 --- a/examples/learning_switch/mix.lock +++ b/examples/learning_switch/mix.lock @@ -1,7 +1,7 @@ %{ "binpp": {:git, "https://github.com/jtendo/binpp.git", "64bd68d215d1a6cd35871e7c134d7fe2e46214ea", [branch: "master"]}, "eovsdb": {:git, "https://github.com/shun159/eovsdb.git", "1ff1572708d72fd25631c681f2102407903252a3", [branch: "master"]}, - "jsone": {:git, "https://github.com/sile/jsone.git", "eecc9666c7165e1870b78a7a762549ae8d1c391b", [tag: "1.2.1"]}, - "ranch": {:hex, :ranch, "1.4.0", "10272f95da79340fa7e8774ba7930b901713d272905d0012b06ca6d994f8826b", [], [], "hexpm"}, + "jsone": {:git, "https://github.com/sile/jsone.git", "b23d312a5ed051ea7ad0989a9f2cb1a9c3f9a502", [tag: "1.4.6"]}, + "ranch": {:hex, :ranch, "1.7.1", "6b1fab51b49196860b733a49c07604465a47bdb78aa10c1c16a3d199f7f8c881", [:rebar3], [], "hexpm"}, "uuid": {:git, "https://github.com/avtobiff/erlang-uuid.git", "585c2474afb4a597ae8c8bf6d21e5a9c73f18e0b", [tag: "v0.5.0"]}, } diff --git a/lib/openflow/enum_gen.ex b/lib/openflow/enum_gen.ex index 51e0a3d..c4c7b57 100644 --- a/lib/openflow/enum_gen.ex +++ b/lib/openflow/enum_gen.ex @@ -990,6 +990,20 @@ defmodule Openflow.EnumGen do apply_setfield_miss: 15, experimenter: 0xFFFE, experimenter_miss: 0xFFFF + ], + bundle_ctrl_type: [ + open_request: 0, + open_reply: 1, + close_request: 2, + close_reply: 3, + commit_request: 4, + commit_reply: 5, + discard_request: 6, + discard_reply: 7 + ], + bundle_flags: [ + atomic: 1 <<< 0, + ordered: 1 <<< 1 ] ] diff --git a/lib/openflow/enums.ex b/lib/openflow/enums.ex index d462319..51426c7 100644 --- a/lib/openflow/enums.ex +++ b/lib/openflow/enums.ex @@ -5101,6 +5101,74 @@ defmodule Openflow.Enums do throw(:bad_enum) end + def to_int(:open_request, :bundle_ctrl_type) do + bundle_ctrl_type_to_int(:open_request) + catch + _class, _reason -> :open_request + end + + def to_int(:open_reply, :bundle_ctrl_type) do + bundle_ctrl_type_to_int(:open_reply) + catch + _class, _reason -> :open_reply + end + + def to_int(:close_request, :bundle_ctrl_type) do + bundle_ctrl_type_to_int(:close_request) + catch + _class, _reason -> :close_request + end + + def to_int(:close_reply, :bundle_ctrl_type) do + bundle_ctrl_type_to_int(:close_reply) + catch + _class, _reason -> :close_reply + end + + def to_int(:commit_request, :bundle_ctrl_type) do + bundle_ctrl_type_to_int(:commit_request) + catch + _class, _reason -> :commit_request + end + + def to_int(:commit_reply, :bundle_ctrl_type) do + bundle_ctrl_type_to_int(:commit_reply) + catch + _class, _reason -> :commit_reply + end + + def to_int(:discard_request, :bundle_ctrl_type) do + bundle_ctrl_type_to_int(:discard_request) + catch + _class, _reason -> :discard_request + end + + def to_int(:discard_reply, :bundle_ctrl_type) do + bundle_ctrl_type_to_int(:discard_reply) + catch + _class, _reason -> :discard_reply + end + + def to_int(_int, :bundle_ctrl_type) do + throw(:bad_enum) + end + + def to_int(:atomic, :bundle_flags) do + bundle_flags_to_int(:atomic) + catch + _class, _reason -> :atomic + end + + def to_int(:ordered, :bundle_flags) do + bundle_flags_to_int(:ordered) + catch + _class, _reason -> :ordered + end + + def to_int(_int, :bundle_flags) do + throw(:bad_enum) + end + def to_atom(0x0, :openflow_codec) do openflow_codec_to_atom(0x0) catch @@ -10201,6 +10269,74 @@ defmodule Openflow.Enums do throw(:bad_enum) end + def to_atom(0x0, :bundle_ctrl_type) do + bundle_ctrl_type_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :bundle_ctrl_type) do + bundle_ctrl_type_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :bundle_ctrl_type) do + bundle_ctrl_type_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x3, :bundle_ctrl_type) do + bundle_ctrl_type_to_atom(0x3) + catch + _class, _reason -> 3 + end + + def to_atom(0x4, :bundle_ctrl_type) do + bundle_ctrl_type_to_atom(0x4) + catch + _class, _reason -> 4 + end + + def to_atom(0x5, :bundle_ctrl_type) do + bundle_ctrl_type_to_atom(0x5) + catch + _class, _reason -> 5 + end + + def to_atom(0x6, :bundle_ctrl_type) do + bundle_ctrl_type_to_atom(0x6) + catch + _class, _reason -> 6 + end + + def to_atom(0x7, :bundle_ctrl_type) do + bundle_ctrl_type_to_atom(0x7) + catch + _class, _reason -> 7 + end + + def to_atom(_, :bundle_ctrl_type) do + throw(:bad_enum) + end + + def to_atom(0x1, :bundle_flags) do + bundle_flags_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :bundle_flags) do + bundle_flags_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(_, :bundle_flags) do + throw(:bad_enum) + end + def openflow_codec_to_int(Openflow.Hello), do: 0x0 def openflow_codec_to_int(Openflow.ErrorMsg), do: 0x1 def openflow_codec_to_int(Openflow.Echo.Request), do: 0x2 @@ -11961,6 +12097,30 @@ defmodule Openflow.Enums do def table_feature_prop_type_to_atom(0xFFFE), do: :experimenter def table_feature_prop_type_to_atom(0xFFFF), do: :experimenter_miss def table_feature_prop_type_to_atom(_), do: throw(:bad_enum) + def bundle_ctrl_type_to_int(:open_request), do: 0x0 + def bundle_ctrl_type_to_int(:open_reply), do: 0x1 + def bundle_ctrl_type_to_int(:close_request), do: 0x2 + def bundle_ctrl_type_to_int(:close_reply), do: 0x3 + def bundle_ctrl_type_to_int(:commit_request), do: 0x4 + def bundle_ctrl_type_to_int(:commit_reply), do: 0x5 + def bundle_ctrl_type_to_int(:discard_request), do: 0x6 + def bundle_ctrl_type_to_int(:discard_reply), do: 0x7 + def bundle_ctrl_type_to_int(_), do: throw(:bad_enum) + def bundle_ctrl_type_to_atom(0x0), do: :open_request + def bundle_ctrl_type_to_atom(0x1), do: :open_reply + def bundle_ctrl_type_to_atom(0x2), do: :close_request + def bundle_ctrl_type_to_atom(0x3), do: :close_reply + def bundle_ctrl_type_to_atom(0x4), do: :commit_request + def bundle_ctrl_type_to_atom(0x5), do: :commit_reply + def bundle_ctrl_type_to_atom(0x6), do: :discard_request + def bundle_ctrl_type_to_atom(0x7), do: :discard_reply + def bundle_ctrl_type_to_atom(_), do: throw(:bad_enum) + def bundle_flags_to_int(:atomic), do: 0x1 + def bundle_flags_to_int(:ordered), do: 0x2 + def bundle_flags_to_int(_), do: throw(:bad_enum) + def bundle_flags_to_atom(0x1), do: :atomic + def bundle_flags_to_atom(0x2), do: :ordered + def bundle_flags_to_atom(_), do: throw(:bad_enum) def int_to_flags(int, :openflow_codec) do Openflow.Utils.int_to_flags([], int, enum_of(:openflow_codec)) @@ -12322,6 +12482,14 @@ defmodule Openflow.Enums do Openflow.Utils.int_to_flags([], int, enum_of(:table_feature_prop_type)) end + def int_to_flags(int, :bundle_ctrl_type) do + Openflow.Utils.int_to_flags([], int, enum_of(:bundle_ctrl_type)) + end + + def int_to_flags(int, :bundle_flags) do + Openflow.Utils.int_to_flags([], int, enum_of(:bundle_flags)) + end + def flags_to_int(flags, :openflow_codec) do Openflow.Utils.flags_to_int(0, flags, enum_of(:openflow_codec)) end @@ -12682,6 +12850,14 @@ defmodule Openflow.Enums do Openflow.Utils.flags_to_int(0, flags, enum_of(:table_feature_prop_type)) end + def flags_to_int(flags, :bundle_ctrl_type) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:bundle_ctrl_type)) + end + + def flags_to_int(flags, :bundle_flags) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:bundle_flags)) + end + defp enum_of(:openflow_codec), do: [ {Openflow.Hello, 0}, @@ -13555,4 +13731,18 @@ defmodule Openflow.Enums do experimenter: 65534, experimenter_miss: 65535 ] + + defp enum_of(:bundle_ctrl_type), + do: [ + open_request: 0, + open_reply: 1, + close_request: 2, + close_reply: 3, + commit_request: 4, + commit_reply: 5, + discard_request: 6, + discard_reply: 7 + ] + + defp enum_of(:bundle_flags), do: [atomic: 1, ordered: 2] end diff --git a/lib/openflow/onf_bundle_add.ex b/lib/openflow/onf_bundle_add.ex new file mode 100644 index 0000000..7b87c55 --- /dev/null +++ b/lib/openflow/onf_bundle_add.ex @@ -0,0 +1,50 @@ +defmodule Openflow.OnfBundleAdd do + defstruct( + version: 4, + xid: 0, + datapath_id: "", + aux_id: 0, + # bundle header + bundle_id: 0, + flags: [], + message: nil + ) + + alias __MODULE__ + + # ONF Experimenter + @experimenter 0x4F4E4600 + # BUNDLE_ADD + @onf_type 2301 + + @onf_bundle_add_message_size 24 + + # experimenter + def ofp_type, do: 4 + + def new(options \\ []) do + %OnfBundleAdd{ + xid: options[:xid] || 0, + bundle_id: options[:bundle_id] || 0, + flags: options[:flags] || [], + message: options[:message] + } + end + + def to_binary(%OnfBundleAdd{} = bundle_add) do + bundle_id = bundle_add.bundle_id + message_bin = Openflow.to_binary(%{bundle_add.message | xid: bundle_add.xid}) + length = @onf_bundle_add_message_size + byte_size(message_bin) + pad_length = Openflow.Utils.pad_length(length, 8) + flags_int = Openflow.Enums.flags_to_int(bundle_add.flags, :bundle_flags) + + <<@experimenter::32, @onf_type::32, bundle_id::32, 0::2-unit(8), + flags_int::16, message_bin::bytes, 0::size(pad_length)-unit(8)>> + end + + def read(<<@experimenter::32, @onf_type::32, bundle_id::32, _pad::16, flags_int::16, message_bin::bytes>>) do + message = Openflow.read(message_bin) + flags = Openflow.Enums.int_to_flags(flags_int, :bundle_flags) + %OnfBundleAdd{bundle_id: bundle_id, flags: flags, message: message} + end +end diff --git a/lib/openflow/onf_bundle_control.ex b/lib/openflow/onf_bundle_control.ex new file mode 100644 index 0000000..8f32987 --- /dev/null +++ b/lib/openflow/onf_bundle_control.ex @@ -0,0 +1,44 @@ +defmodule Openflow.OnfBundleControl do + defstruct( + version: 4, + xid: 0, + datapath_id: "", + aux_id: 0, + # bundle header + bundle_id: 0, + type: :open_request, + flags: [] + ) + + alias __MODULE__ + + # ONF Experimenter + @experimenter 0x4F4E4600 + # BUNDLE_CONTROL + @onf_type 2300 + + # experimenter + def ofp_type, do: 4 + + def new(options \\ []) do + %OnfBundleControl{ + xid: options[:xid] || 0, + bundle_id: options[:bundle_id] || 0, + type: options[:type] || :open_request, + flags: options[:flags] || [] + } + end + + def to_binary(%OnfBundleControl{} = ctrl) do + bundle_id = ctrl.bundle_id + type_int = Openflow.Utils.get_enum(ctrl.type, :bundle_ctrl_type) + flags_int = Openflow.Enums.flags_to_int(ctrl.flags, :bundle_flags) + <<@experimenter::32, @onf_type::32, bundle_id::32, type_int::16, flags_int::16>> + end + + def read(<<@experimenter::32, @onf_type::32, bundle_id::32, type_int::16, flags_int::16>>) do + type = Openflow.Utils.get_enum(type_int, :bundle_ctrl_type) + flags = Openflow.Enums.int_to_flags(flags_int, :bundle_flags) + %OnfBundleControl{bundle_id: bundle_id, type: type, flags: flags} + end +end diff --git a/lib/tres/message_helper.ex b/lib/tres/message_helper.ex index e91e088..136fe04 100644 --- a/lib/tres/message_helper.ex +++ b/lib/tres/message_helper.ex @@ -17,7 +17,14 @@ defmodule Tres.MessageHelper do instructions: options[:instructions] || [] } - send_message(flow_mod, datapath_id, Keyword.get(options, :blocking, false)) + case options[:bundle_id] do + nil -> + send_message(flow_mod, datapath_id, Keyword.get(options, :blocking, false)) + + bundle_id when is_integer(bundle_id) -> + bundle = Openflow.OnfBundleAdd.new(bundle_id: bundle_id, flags: options[:bundle_flags] || [], message: flow_mod) + send_message(bundle, datapath_id, Keyword.get(options, :blocking, false)) + end end defp send_flow_mod_modify(datapath_id, options \\ []) do @@ -36,7 +43,14 @@ defmodule Tres.MessageHelper do instructions: options[:instructions] || [] } - send_message(flow_mod, datapath_id, Keyword.get(options, :blocking, false)) + case options[:bundle_id] do + nil -> + send_message(flow_mod, datapath_id, Keyword.get(options, :blocking, false)) + + bundle_id when is_integer(bundle_id) -> + bundle = Openflow.OnfBundleAdd.new(bundle_id: bundle_id, flags: options[:bundle_flags] || [], message: flow_mod) + send_message(bundle, datapath_id, Keyword.get(options, :blocking, false)) + end end defp send_flow_mod_delete(datapath_id, options \\ []) do @@ -53,7 +67,14 @@ defmodule Tres.MessageHelper do match: options[:match] || Openflow.Match.new() } - send_message(flow_mod, datapath_id, Keyword.get(options, :blocking, false)) + case options[:bundle_id] do + nil -> + send_message(flow_mod, datapath_id, Keyword.get(options, :blocking, false)) + + bundle_id when is_integer(bundle_id) -> + bundle = Openflow.OnfBundleAdd.new(bundle_id: bundle_id, flags: options[:bundle_flags] || [], message: flow_mod) + send_message(bundle, datapath_id, Keyword.get(options, :blocking, false)) + end end defp send_packet_out(options \\ []) do @@ -101,7 +122,14 @@ defmodule Tres.MessageHelper do data: options[:data] || "" } - send_message(packet_out, datapath_id, Keyword.get(options, :blocking, false)) + case options[:bundle_id] do + nil -> + send_message(packet_out, datapath_id, Keyword.get(options, :blocking, false)) + + bundle_id when is_integer(bundle_id) -> + bundle = Openflow.OnfBundleAdd.new(bundle_id: bundle_id, flags: options[:bundle_flags], message: packet_out) + send_message(bundle, datapath_id, Keyword.get(options, :blocking, false)) + end end defp send_group_mod_add(datapath_id, options \\ []) do @@ -114,7 +142,14 @@ defmodule Tres.MessageHelper do buckets: options[:buckets] || [] ) - send_message(group_mod, datapath_id, Keyword.get(options, :blocking, false)) + case options[:bundle_id] do + nil -> + send_message(group_mod, datapath_id, Keyword.get(options, :blocking, false)) + + bundle_id when is_integer(bundle_id) -> + bundle = Openflow.OnfBundleAdd.new(bundle_id: bundle_id, flags: options[:bundle_flags] || [], message: group_mod) + send_message(bundle, datapath_id, Keyword.get(options, :blocking, false)) + end end defp send_group_mod_delete(datapath_id, options \\ []) do @@ -125,7 +160,14 @@ defmodule Tres.MessageHelper do group_id: options[:group_id] || :all ) - send_message(group_mod, datapath_id, Keyword.get(options, :blocking, false)) + case options[:bundle_id] do + nil -> + send_message(group_mod, datapath_id, Keyword.get(options, :blocking, false)) + + bundle_id when is_integer(bundle_id) -> + bundle = Openflow.OnfBundleAdd.new(bundle_id: bundle_id, flags: options[:bundle_flags] || [], message: group_mod) + send_message(bundle, datapath_id, Keyword.get(options, :blocking, false)) + end end defp send_group_mod_modify(datapath_id, options \\ []) do @@ -138,7 +180,14 @@ defmodule Tres.MessageHelper do buckets: options[:buckets] || [] ) - send_message(group_mod, datapath_id, Keyword.get(options, :blocking, false)) + case options[:bundle_id] do + nil -> + send_message(group_mod, datapath_id, Keyword.get(options, :blocking, false)) + + bundle_id when is_integer(bundle_id) -> + bundle = Openflow.OnfBundleAdd.new(bundle_id: bundle_id, flags: options[:bundle_flags] || [], message: group_mod) + send_message(bundle, datapath_id, Keyword.get(options, :blocking, false)) + end end defp send_role_request(datapath_id, options) do @@ -193,6 +242,32 @@ defmodule Tres.MessageHelper do resume = Openflow.NxResume.new(options) send_message(resume, datapath_id, options[:blocking] || false) end + + # ONF Bundle Control + + defp onf_bundle_open(datapath_id, options \\ []) do + options2 = Keyword.merge(options, [type: :open_request]) + bundle = Openflow.OnfBundleControl.new(options2) + send_message(bundle, datapath_id) + end + + defp onf_bundle_close(datapath_id, options) do + options2 = Keyword.merge(options, [type: :close_request]) + bundle = Openflow.OnfBundleControl.new(options2) + send_message(bundle, datapath_id) + end + + defp onf_bundle_commit(datapath_id, options) do + options2 = Keyword.merge(options, [type: :commit_request]) + bundle = Openflow.OnfBundleControl.new(options2) + send_message(bundle, datapath_id) + end + + defp onf_bundle_discard(datapath_id, options) do + options2 = Keyword.merge(options, [type: :discard_request]) + bundle = Openflow.OnfBundleControl.new(options2) + send_message(bundle, datapath_id) + end end end end diff --git a/lib/tres/secure_channel_state.ex b/lib/tres/secure_channel_state.ex index e5312c0..483b5cd 100644 --- a/lib/tres/secure_channel_state.ex +++ b/lib/tres/secure_channel_state.ex @@ -59,7 +59,7 @@ defmodule Tres.SecureChannelState do @spec get_transaction_id(:counters.counters_ref()) :: integer() def get_transaction_id(counter_ref) do - :counters.get(counter_ref, 1) &&& 0xffffffff + :counters.get(counter_ref, 1) &&& 0xFFFFFFFF end # private functions diff --git a/test/packet_data/onf_bundle_control.raw b/test/packet_data/onf_bundle_control.raw new file mode 100644 index 0000000000000000000000000000000000000000..1d9717859d0906bdc1599d0e90d3b579231ea889 GIT binary patch literal 24 fcmZQ!VUS>8VBqrib7Np&;P}J9z`)4Bz`z6m8UF$m literal 0 HcmV?d00001