Implement an Open_vSwitch configuration module
This commit is contained in:
parent
82b24f5411
commit
ae00e7b76d
3 changed files with 169 additions and 1 deletions
22
lib/ovsdb.ex
Normal file
22
lib/ovsdb.ex
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
defmodule OVSDB do
|
||||||
|
@moduledoc false
|
||||||
|
|
||||||
|
@behaviour :supervisor
|
||||||
|
|
||||||
|
def start_link do
|
||||||
|
:supervisor.start_link({:local, __MODULE__}, __MODULE__, [])
|
||||||
|
end
|
||||||
|
|
||||||
|
def init([]) do
|
||||||
|
child = OVSDB.OpenvSwitch
|
||||||
|
strategy = :simple_one_for_one
|
||||||
|
max_r = 1000
|
||||||
|
intensity = 3600
|
||||||
|
sup_flags = {strategy, max_r, intensity}
|
||||||
|
{:ok, {sup_flags, [{child, {child, :start_link, []}, :temporary, 1000, :worker, [child]}]}}
|
||||||
|
end
|
||||||
|
|
||||||
|
def start_child(server) do
|
||||||
|
:supervisor.start_child(__MODULE__, [server])
|
||||||
|
end
|
||||||
|
end
|
||||||
145
lib/ovsdb/open_vswitch.ex
Normal file
145
lib/ovsdb/open_vswitch.ex
Normal file
|
|
@ -0,0 +1,145 @@
|
||||||
|
defmodule OVSDB.OpenvSwitch do
|
||||||
|
use GenServer
|
||||||
|
|
||||||
|
defmodule State do
|
||||||
|
defstruct [
|
||||||
|
server: nil,
|
||||||
|
client_pid: nil,
|
||||||
|
monitor_pid: nil,
|
||||||
|
ovs_uuid: nil
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
@database "Open_vSwitch"
|
||||||
|
|
||||||
|
@open_vswitch "Open_vSwitch"
|
||||||
|
@interface "Interface"
|
||||||
|
@port "Port"
|
||||||
|
@controller "Controller"
|
||||||
|
@bridge "Bridge"
|
||||||
|
|
||||||
|
def start_link(server) do
|
||||||
|
GenServer.start_link(__MODULE__, [server])
|
||||||
|
end
|
||||||
|
|
||||||
|
def find_by_name(pid, table, name) do
|
||||||
|
GenServer.call(pid, {:find_by_name, table, name})
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_br(pid, bridge, options \\ []) do
|
||||||
|
br_uuids = GenServer.call(pid, {:sync_get, @open_vswitch, "bridges"})
|
||||||
|
add_br_options = [
|
||||||
|
bridge: bridge,
|
||||||
|
controller: options[:controller] || "tcp:127.0.0.1:6653",
|
||||||
|
protocol: options[:protocol] || "OpenFlow13",
|
||||||
|
fail_mode: options[:fail_mode] || "standalone",
|
||||||
|
br_uuids: br_uuids
|
||||||
|
]
|
||||||
|
GenServer.call(pid, {:add_br, add_br_options})
|
||||||
|
end
|
||||||
|
|
||||||
|
def del_br(pid, bridge) do
|
||||||
|
case find_by_name(pid, @bridge, bridge) do
|
||||||
|
%{"_uuid" => uuid} ->
|
||||||
|
new_bridges =
|
||||||
|
case GenServer.call(pid, {:sync_get, @open_vswitch, "bridges"}) do
|
||||||
|
["set", bridges] -> %{"bridges" => ["set", bridges -- [uuid]]}
|
||||||
|
^uuid -> %{"bridges" => ["set", []]}
|
||||||
|
curr_bridges -> %{"bridges" => curr_bridges}
|
||||||
|
end
|
||||||
|
GenServer.call(pid, {:del_br, new_bridges})
|
||||||
|
:not_found ->
|
||||||
|
{:error, :not_found}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def init([server]) do
|
||||||
|
state = server
|
||||||
|
|> String.to_charlist
|
||||||
|
|> init_client
|
||||||
|
{:ok, state}
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle_call({:sync_get, table, col_name}, _from, state) do
|
||||||
|
[%{"rows" => [%{^col_name => values}|_]}] =
|
||||||
|
[col_name]
|
||||||
|
|> :eovsdb_op.select(table, [])
|
||||||
|
|> xact(state.client_pid)
|
||||||
|
{:reply, values, state}
|
||||||
|
end
|
||||||
|
def handle_call({:add_br, options}, _from, state) do
|
||||||
|
%State{client_pid: pid, ovs_uuid: ovs} = state
|
||||||
|
br_iface = %{name: options[:bridge], type: :internal}
|
||||||
|
br_port = %{name: options[:bridge], interfaces: ["named-uuid", "brinterface"]}
|
||||||
|
controller = %{target: options[:controller]}
|
||||||
|
new_bridge = %{
|
||||||
|
name: options[:bridge],
|
||||||
|
ports: ["named-uuid", "brport"],
|
||||||
|
controller: ["named-uuid", "brcontroller"],
|
||||||
|
fail_mode: options[:fail_mode],
|
||||||
|
protocols: options[:protocol]
|
||||||
|
}
|
||||||
|
named_uuid = ["named-uuid", "bridge"]
|
||||||
|
new_bridges =
|
||||||
|
case options[:br_uuids] do
|
||||||
|
["set", []] -> %{bridges: named_uuid}
|
||||||
|
["set", bridges] -> %{bridges: ["set", bridges ++ [named_uuid]]}
|
||||||
|
["uuid", _] = bridge -> %{bridges: ["set", [bridge] ++ [named_uuid]]}
|
||||||
|
end
|
||||||
|
next_config = [{"next_cfg", "+=", 1}]
|
||||||
|
eq_ovs_uuid = [{"_uuid", "==", ovs}]
|
||||||
|
replies = xact([
|
||||||
|
:eovsdb_op.insert(@interface, br_iface, "brinterface"),
|
||||||
|
:eovsdb_op.insert(@port, br_port, "brport"),
|
||||||
|
:eovsdb_op.insert(@controller, controller, "brcontroller"),
|
||||||
|
:eovsdb_op.insert(@bridge, new_bridge, "bridge"),
|
||||||
|
:eovsdb_op.update(@open_vswitch, eq_ovs_uuid, new_bridges),
|
||||||
|
:eovsdb_op.mutate(@open_vswitch, eq_ovs_uuid, next_config)
|
||||||
|
], pid)
|
||||||
|
{:reply, replies, state}
|
||||||
|
end
|
||||||
|
def handle_call({:del_br, new_bridges}, _from, state) do
|
||||||
|
%State{client_pid: pid, ovs_uuid: ovs} = state
|
||||||
|
eq_ovs_uuid = [{"_uuid", "==", ovs}]
|
||||||
|
next_config = [{"next_cfg", "+=", 1}]
|
||||||
|
replies = xact([
|
||||||
|
:eovsdb_op.update(@open_vswitch, eq_ovs_uuid, new_bridges),
|
||||||
|
:eovsdb_op.mutate(@open_vswitch, eq_ovs_uuid, next_config)
|
||||||
|
], pid)
|
||||||
|
{:reply, replies, state}
|
||||||
|
end
|
||||||
|
def handle_call({:find_by_name, table, name}, _from, state) do
|
||||||
|
%State{client_pid: pid} = state
|
||||||
|
query = :eovsdb_op.select('*', table, [{"name", "==", name}])
|
||||||
|
reply = case xact(query, pid) do
|
||||||
|
[%{"rows" => []}] -> :not_found
|
||||||
|
[%{"rows" => [row]}] -> row
|
||||||
|
end
|
||||||
|
{:reply, reply, state}
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle_cast({:async_get, "_uuid"}, state) do
|
||||||
|
[%{"rows" => [%{"_uuid" => values}|_]}] =
|
||||||
|
["_uuid"]
|
||||||
|
|> :eovsdb_op.select(@open_vswitch, [])
|
||||||
|
|> xact(state.client_pid)
|
||||||
|
{:noreply, %{state|ovs_uuid: values}}
|
||||||
|
end
|
||||||
|
|
||||||
|
# private functions
|
||||||
|
|
||||||
|
defp init_client(server) do
|
||||||
|
{:ok, pid} = :eovsdb_client.connect(server, [database: @database])
|
||||||
|
:eovsdb_client.regist_schema(pid)
|
||||||
|
:ok = GenServer.cast(self(), {:async_get, "_uuid"})
|
||||||
|
%State{server: server, client_pid: pid}
|
||||||
|
end
|
||||||
|
|
||||||
|
defp xact(query, pid) when is_list(query) do
|
||||||
|
{:ok, res} = :eovsdb_client.transaction(pid, query)
|
||||||
|
res
|
||||||
|
end
|
||||||
|
defp xact(query, pid) when is_map(query) do
|
||||||
|
xact([query], pid)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -10,7 +10,8 @@ defmodule Tres.Application do
|
||||||
|
|
||||||
{cb_mod, _cb_args} = Tres.Utils.get_callback_module
|
{cb_mod, _cb_args} = Tres.Utils.get_callback_module
|
||||||
children = [worker(Registry, [[keys: :unique, name: SwitchRegistry]], id: SwitchRegistry),
|
children = [worker(Registry, [[keys: :unique, name: SwitchRegistry]], id: SwitchRegistry),
|
||||||
supervisor(Tres.MessageHandlerSup, [cb_mod], id: MessageHandlerSup)]
|
supervisor(Tres.MessageHandlerSup, [cb_mod], id: MessageHandlerSup),
|
||||||
|
supervisor(OVSDB, [], id: OVSDB)]
|
||||||
opts = [strategy: :one_for_one, name: Tres.Supervisor]
|
opts = [strategy: :one_for_one, name: Tres.Supervisor]
|
||||||
{:ok, _connection_pid} = Tres.Utils.start_openflow_listener
|
{:ok, _connection_pid} = Tres.Utils.start_openflow_listener
|
||||||
Supervisor.start_link(children, opts)
|
Supervisor.start_link(children, opts)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue