tres/lib/openflow/actions/nx_flow_spec_load.ex
2017-11-20 13:38:24 +09:00

79 lines
2.7 KiB
Elixir

defmodule Openflow.Action.NxFlowSpecLoad do
defstruct(
src: nil,
dst: nil,
n_bits: 0,
src_offset: 0,
dst_offset: 0
)
@learn_src_field 0
@learn_src_immediate 1
@learn_dst 1
alias __MODULE__
def new(options) do
dst = options[:dst]
n_bits = options[:n_bits] || Openflow.Match.Field.n_bits_of(dst)
%NxFlowSpecLoad{src: options[:src],
dst: dst,
n_bits: n_bits,
src_offset: options[:src_offset] || 0,
dst_offset: options[:dst_offset] || 0}
end
def to_binary(%NxFlowSpecLoad{} = fsm) do
%NxFlowSpecLoad{
dst: dst_field,
n_bits: n_bits,
src_offset: src_ofs,
dst_offset: dst_ofs
} = fsm
{src_code, src_bin} = codec_src(fsm)
dst_bin = Openflow.Match.codec_header(dst_field)
case src_code do
@learn_src_immediate ->
<<0::2, src_code::1, @learn_dst::2, n_bits::11,
src_bin::bytes, dst_bin::4-bytes, dst_ofs::16>>
@learn_src_field ->
<<0::2, src_code::1, @learn_dst::2, n_bits::11,
src_bin::4-bytes, src_ofs::16, dst_bin::4-bytes, dst_ofs::16>>
end
end
def read(<<_::2, @learn_src_field::1, @learn_dst::2, n_bits::11, src_bin::4-bytes,
src_ofs::16, dst_bin::4-bytes, dst_ofs::16, rest::bitstring>>) do
src = Openflow.Match.codec_header(src_bin)
dst = Openflow.Match.codec_header(dst_bin)
flow_spec = %NxFlowSpecLoad{src: src,
dst: dst,
n_bits: n_bits,
src_offset: src_ofs,
dst_offset: dst_ofs}
{flow_spec, rest}
end
def read(<<_::2, @learn_src_immediate::1, @learn_dst::2, n_bits::11, binary::bitstring>>) do
rounded_up_len = Openflow.Utils.pad_length(n_bits, 8)
rounded_up_nbits = n_bits + rounded_up_len
<<src_bin::size(rounded_up_nbits)-bits, dst_bin::4-bytes, dst_ofs::16, rest::bitstring>> = binary
dst = Openflow.Match.codec_header(dst_bin)
src = Openflow.Match.Field.codec(src_bin, dst)
flow_spec = %NxFlowSpecLoad{src: src,
dst: dst,
n_bits: n_bits,
dst_offset: dst_ofs}
{flow_spec, rest}
end
# private functions
defp codec_src(%NxFlowSpecLoad{src: src_field}) when is_atom(src_field) do
src_bin = Openflow.Match.codec_header(src_field)
{@learn_src_field, src_bin}
end
defp codec_src(%NxFlowSpecLoad{src: src, dst: dst_field}) do
src_bin = Openflow.Match.Field.codec(src, dst_field)
{@learn_src_immediate, src_bin}
end
end