ovsdb: Add functions that I often use
This commit is contained in:
parent
927241b3f4
commit
d555cd8e09
2 changed files with 256 additions and 28 deletions
BIN
bin/enum_gen
BIN
bin/enum_gen
Binary file not shown.
|
|
@ -16,28 +16,43 @@ defmodule OVSDB.OpenvSwitch do
|
||||||
@controller "Controller"
|
@controller "Controller"
|
||||||
@bridge "Bridge"
|
@bridge "Bridge"
|
||||||
|
|
||||||
def start_link(server) do
|
|
||||||
GenServer.start_link(__MODULE__, [server])
|
|
||||||
end
|
|
||||||
|
|
||||||
def find_by_name(pid, table, name) do
|
def find_by_name(pid, table, name) do
|
||||||
GenServer.call(pid, {:find_by_name, table, name})
|
GenServer.call(pid, {:find_by_name, table, name})
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_br(pid, bridge, options \\ []) do
|
# API functions
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Create a bridge:
|
||||||
|
|
||||||
|
## options:
|
||||||
|
iex> OpenvSwitch.add_br(
|
||||||
|
client_pid,
|
||||||
|
name: "br0",
|
||||||
|
fail_mode: "standalone",
|
||||||
|
datapath_id: "0000000000000001",
|
||||||
|
disable_in_band: "true"
|
||||||
|
)
|
||||||
|
"""
|
||||||
|
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: bridge,
|
bridge: options[:name],
|
||||||
controller: options[:controller] || "tcp:127.0.0.1:6653",
|
fail_mode: options[:fail_mode] || "standalone",
|
||||||
protocol: options[:protocol] || "OpenFlow13",
|
datapath_id: options[:datapath_id],
|
||||||
fail_mode: options[:fail_mode] || "standalone",
|
disable_in_band: options[:disable_in_band],
|
||||||
br_uuids: br_uuids
|
br_uuids: br_uuids
|
||||||
]
|
]
|
||||||
|
|
||||||
GenServer.call(pid, {:add_br, add_br_options})
|
GenServer.call(pid, {:add_br, add_br_options})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Delete a bridge
|
||||||
|
|
||||||
|
iex> OpenvSwitch.del_br(client_pid, "br0")
|
||||||
|
"""
|
||||||
def del_br(pid, bridge) do
|
def del_br(pid, bridge) do
|
||||||
case find_by_name(pid, @bridge, bridge) do
|
case find_by_name(pid, @bridge, bridge) do
|
||||||
%{"_uuid" => uuid} ->
|
%{"_uuid" => uuid} ->
|
||||||
|
|
@ -55,6 +70,109 @@ defmodule OVSDB.OpenvSwitch do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Set a controller to the switch
|
||||||
|
|
||||||
|
iex> OpenvSwitch.set_controller(
|
||||||
|
client_pid,
|
||||||
|
bridge: "br0",
|
||||||
|
target: "tcp:127.0.0.1:6653",
|
||||||
|
connection_mode: "out-of-band",
|
||||||
|
controller_rate_limit: 100,
|
||||||
|
controller_burst_limit: 25,
|
||||||
|
protocol: "OpenFlow13"
|
||||||
|
)
|
||||||
|
"""
|
||||||
|
def set_controller(pid, [_|_] = options) do
|
||||||
|
case find_by_name(pid, @bridge, options[:bridge]) do
|
||||||
|
:not_found ->
|
||||||
|
{:error, :not_found}
|
||||||
|
%{"_uuid" => _uuid} ->
|
||||||
|
set_ctl_opts = [
|
||||||
|
bridge: options[:bridge],
|
||||||
|
target: options[:target] || "tcp:127.0.0.1:6653",
|
||||||
|
connection_mode: options[:connection_mode] || "out-of-band",
|
||||||
|
controller_rate_limit: options[:controller_rate_limit] || 1000,
|
||||||
|
controller_burst_limit: options[:controller_burst_limit] || 100,
|
||||||
|
protocol: options[:protocol] || "OpenFlow13",
|
||||||
|
]
|
||||||
|
|
||||||
|
GenServer.call(pid, {:set_controller, set_ctl_opts})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
iex> OpenvSwitch.add_port(
|
||||||
|
client_pid,
|
||||||
|
bridge: "br0",
|
||||||
|
name: "vxlan5",
|
||||||
|
type: "vxlan",
|
||||||
|
remote_ip: "flow",
|
||||||
|
ofport_request: 99
|
||||||
|
)
|
||||||
|
"""
|
||||||
|
def add_port(pid, [_|_] = options) do
|
||||||
|
case find_by_name(pid, @bridge, options[:bridge]) do
|
||||||
|
:not_found ->
|
||||||
|
{:error, :not_found}
|
||||||
|
%{"_uuid" => _uuid, "ports" => ports} ->
|
||||||
|
port_opts = [
|
||||||
|
bridge: options[:bridge],
|
||||||
|
name: options[:name],
|
||||||
|
type: options[:type] || "system",
|
||||||
|
ofport_request: options[:ofport_request],
|
||||||
|
remote_ip: options[:remote_ip],
|
||||||
|
local_ip: options[:local_ip],
|
||||||
|
in_key: options[:in_key],
|
||||||
|
out_key: options[:out_key],
|
||||||
|
key: options[:key],
|
||||||
|
tos: options[:tos],
|
||||||
|
ttl: options[:ttl],
|
||||||
|
df_default: options[:df_default],
|
||||||
|
csum: options[:csum],
|
||||||
|
peer_cert: options[:peer_cert],
|
||||||
|
certificate: options[:certificate],
|
||||||
|
private_key: options[:private_key],
|
||||||
|
psk: options[:psk],
|
||||||
|
ingress_policing_rate: options[:ingress_policing_rate] || 0,
|
||||||
|
ingress_policing_burst: options[:ingress_policing_burst] || 0,
|
||||||
|
ports: ports
|
||||||
|
]
|
||||||
|
|
||||||
|
GenServer.call(pid, {:add_port, port_opts})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
iex> OpenvSwitch.del_port(client_pid, bridge: "br0", port: "vxlan5")
|
||||||
|
"""
|
||||||
|
def del_port(pid, [_|_] = options) do
|
||||||
|
case find_by_name(pid, @bridge, options[:bridge]) do
|
||||||
|
:not_found ->
|
||||||
|
{:error, :not_found}
|
||||||
|
%{"_uuid" => _uuid, "ports" => ports} ->
|
||||||
|
case find_by_name(pid, @port, options[:port]) do
|
||||||
|
:not_found ->
|
||||||
|
{:error, :not_found}
|
||||||
|
%{"_uuid" => port_uuid} ->
|
||||||
|
new_ports = del_elem_from_set(ports, port_uuid)
|
||||||
|
|
||||||
|
port_opts = [
|
||||||
|
bridge: options[:bridge],
|
||||||
|
ports: new_ports
|
||||||
|
]
|
||||||
|
|
||||||
|
GenServer.call(pid, {:del_port, port_opts})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# GenServer callback functions
|
||||||
|
|
||||||
|
def start_link(server) do
|
||||||
|
GenServer.start_link(__MODULE__, [server])
|
||||||
|
end
|
||||||
|
|
||||||
def init([server]) do
|
def init([server]) do
|
||||||
state =
|
state =
|
||||||
server
|
server
|
||||||
|
|
@ -77,25 +195,24 @@ defmodule OVSDB.OpenvSwitch do
|
||||||
%State{client_pid: pid, ovs_uuid: ovs} = state
|
%State{client_pid: pid, ovs_uuid: ovs} = state
|
||||||
br_iface = %{name: options[:bridge], type: :internal}
|
br_iface = %{name: options[:bridge], type: :internal}
|
||||||
br_port = %{name: options[:bridge], interfaces: ["named-uuid", "brinterface"]}
|
br_port = %{name: options[:bridge], interfaces: ["named-uuid", "brinterface"]}
|
||||||
controller = %{target: options[:controller]}
|
|
||||||
|
other_config = [
|
||||||
|
["datapath-id", options[:datapath_id]],
|
||||||
|
["dp-desc", options[:dp_desc]],
|
||||||
|
["disable-in-band", options[:disable_in_band]],
|
||||||
|
["in-band-queue", options[:in_band_queue]]
|
||||||
|
]
|
||||||
|
|
||||||
new_bridge = %{
|
new_bridge = %{
|
||||||
name: options[:bridge],
|
name: options[:bridge],
|
||||||
ports: ["named-uuid", "brport"],
|
ports: ["named-uuid", "brport"],
|
||||||
controller: ["named-uuid", "brcontroller"],
|
|
||||||
fail_mode: options[:fail_mode],
|
fail_mode: options[:fail_mode],
|
||||||
protocols: options[:protocol]
|
other_config: make_ovsdb_map(other_config)
|
||||||
}
|
}
|
||||||
|
|
||||||
named_uuid = ["named-uuid", "bridge"]
|
named_uuid = ["named-uuid", "bridge"]
|
||||||
|
|
||||||
new_bridges =
|
new_bridges = add_elem_to_set(options[:br_uuids], named_uuid)
|
||||||
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}]
|
next_config = [{"next_cfg", "+=", 1}]
|
||||||
eq_ovs_uuid = [{"_uuid", "==", ovs}]
|
eq_ovs_uuid = [{"_uuid", "==", ovs}]
|
||||||
|
|
||||||
|
|
@ -104,7 +221,6 @@ defmodule OVSDB.OpenvSwitch do
|
||||||
[
|
[
|
||||||
:eovsdb_op.insert(@interface, br_iface, "brinterface"),
|
:eovsdb_op.insert(@interface, br_iface, "brinterface"),
|
||||||
:eovsdb_op.insert(@port, br_port, "brport"),
|
:eovsdb_op.insert(@port, br_port, "brport"),
|
||||||
:eovsdb_op.insert(@controller, controller, "brcontroller"),
|
|
||||||
:eovsdb_op.insert(@bridge, new_bridge, "bridge"),
|
:eovsdb_op.insert(@bridge, new_bridge, "bridge"),
|
||||||
:eovsdb_op.update(@open_vswitch, eq_ovs_uuid, new_bridges),
|
:eovsdb_op.update(@open_vswitch, eq_ovs_uuid, new_bridges),
|
||||||
:eovsdb_op.mutate(@open_vswitch, eq_ovs_uuid, next_config)
|
:eovsdb_op.mutate(@open_vswitch, eq_ovs_uuid, next_config)
|
||||||
|
|
@ -132,16 +248,103 @@ defmodule OVSDB.OpenvSwitch do
|
||||||
{:reply, replies, state}
|
{:reply, replies, state}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def handle_call({:del_port, options}, _from, state) do
|
||||||
|
%State{client_pid: pid, ovs_uuid: ovs} = state
|
||||||
|
eq_br_name = [{"name", "==", options[:bridge]}]
|
||||||
|
eq_ovs_uuid = [{"_uuid", "==", ovs}]
|
||||||
|
next_config = [{"next_cfg", "+=", 1}]
|
||||||
|
|
||||||
|
bridge = %{ports: options[:ports]}
|
||||||
|
|
||||||
|
replies =
|
||||||
|
xact([
|
||||||
|
:eovsdb_op.update(@bridge, eq_br_name, bridge),
|
||||||
|
:eovsdb_op.mutate(@open_vswitch, eq_ovs_uuid, next_config)
|
||||||
|
], pid)
|
||||||
|
|
||||||
|
{:reply, replies, state}
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle_call({:set_controller, options}, _from, state) do
|
||||||
|
%State{client_pid: pid, ovs_uuid: ovs} = state
|
||||||
|
controller = %{
|
||||||
|
target: options[:target],
|
||||||
|
connection_mode: options[:connection_mode],
|
||||||
|
controller_rate_limit: options[:controller_rate_limit],
|
||||||
|
controller_burst_limit: options[:controller_burst_limit],
|
||||||
|
}
|
||||||
|
|
||||||
|
bridge = %{
|
||||||
|
protocols: options[:protocol],
|
||||||
|
controller: ["named-uuid", "controller"],
|
||||||
|
}
|
||||||
|
|
||||||
|
replies =
|
||||||
|
xact([
|
||||||
|
:eovsdb_op.insert(@controller, controller, "controller"),
|
||||||
|
:eovsdb_op.update(@bridge, [{"name", "==", options[:bridge]}], bridge),
|
||||||
|
:eovsdb_op.mutate(@open_vswitch, [{"_uuid", "==", ovs}], [{"next_cfg", "+=", 1}])
|
||||||
|
], pid)
|
||||||
|
|
||||||
|
{:reply, replies, state}
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle_call({:add_port, options}, _from, state) do
|
||||||
|
%State{client_pid: pid, ovs_uuid: ovs} = state
|
||||||
|
|
||||||
|
port = %{
|
||||||
|
name: options[:name],
|
||||||
|
interfaces: ["named-uuid", "interface"],
|
||||||
|
}
|
||||||
|
|
||||||
|
iface_options = [
|
||||||
|
["remote_ip", options[:remote_ip]],
|
||||||
|
["local_ip", options[:local_ip]],
|
||||||
|
["in_key", options[:in_key]],
|
||||||
|
["out_key", options[:out_key]],
|
||||||
|
["key", options[:key]],
|
||||||
|
["tos", options[:tos]],
|
||||||
|
["ttl", options[:ttl]],
|
||||||
|
["df_default", options[:df_default]],
|
||||||
|
["csum", options[:csum]],
|
||||||
|
["peer_cert", options[:peer_cert]],
|
||||||
|
["certificate", options[:certificate]],
|
||||||
|
["private_key", options[:private_key]],
|
||||||
|
["psk", options[:psk]]
|
||||||
|
]
|
||||||
|
|
||||||
|
interface = %{
|
||||||
|
name: options[:name],
|
||||||
|
type: options[:type],
|
||||||
|
ingress_policing_rate: options[:ingress_policing_rate],
|
||||||
|
ingress_policing_burst: options[:ingress_policing_burst],
|
||||||
|
ofport_request: make_ovsdb_set(options[:ofport_request]),
|
||||||
|
options: make_ovsdb_map(iface_options)
|
||||||
|
}
|
||||||
|
|
||||||
|
bridge = %{ports: add_elem_to_set(options[:ports], ["named-uuid", "port"])}
|
||||||
|
|
||||||
|
next_config = [{"next_cfg", "+=", 1}]
|
||||||
|
eq_br_name = [{"name", "==", options[:bridge]}]
|
||||||
|
eq_ovs_uuid = [{"_uuid", "==", ovs}]
|
||||||
|
|
||||||
|
replies =
|
||||||
|
xact(
|
||||||
|
[
|
||||||
|
:eovsdb_op.insert(@interface, interface, "interface"),
|
||||||
|
:eovsdb_op.insert(@port, port, "port"),
|
||||||
|
:eovsdb_op.update(@bridge, eq_br_name, bridge),
|
||||||
|
: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
|
def handle_call({:find_by_name, table, name}, _from, state) do
|
||||||
%State{client_pid: pid} = state
|
%State{client_pid: pid} = state
|
||||||
query = :eovsdb_op.select('*', table, [{"name", "==", name}])
|
reply = do_find_by_name(pid, table, name)
|
||||||
|
|
||||||
reply =
|
|
||||||
case xact(query, pid) do
|
|
||||||
[%{"rows" => []}] -> :not_found
|
|
||||||
[%{"rows" => [row]}] -> row
|
|
||||||
end
|
|
||||||
|
|
||||||
{:reply, reply, state}
|
{:reply, reply, state}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -171,4 +374,29 @@ defmodule OVSDB.OpenvSwitch do
|
||||||
defp xact(query, pid) when is_map(query) do
|
defp xact(query, pid) when is_map(query) do
|
||||||
xact([query], pid)
|
xact([query], pid)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp do_find_by_name(pid, table, name) do
|
||||||
|
query = :eovsdb_op.select('*', table, [{"name", "==", name}])
|
||||||
|
case xact(query, pid) do
|
||||||
|
[%{"rows" => []}] -> :not_found
|
||||||
|
[%{"rows" => [row]}] -> row
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
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, [[_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_set(nil), do: ["set", []]
|
||||||
|
defp make_ovsdb_set([_|_] = list), do: ["set", list]
|
||||||
|
defp make_ovsdb_set(value), do: value
|
||||||
|
|
||||||
|
defp add_elem_to_set(["set", []], value), do: value
|
||||||
|
defp add_elem_to_set(["set", values], value), do: ["set", values ++ value]
|
||||||
|
defp add_elem_to_set(["uuid", _] = uuid, value), do: ["set", [uuid] ++ [value]]
|
||||||
|
|
||||||
|
defp del_elem_from_set(["set", values], value), do: ["set", values -- [value]]
|
||||||
|
defp del_elem_from_set(["uuid", _], _value), do: ["set", []]
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue