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 <> = 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