# `Linx.Netfilter.Set`
[🔗](https://github.com/oshlabs/linx/blob/v0.2.0/lib/linx/netfilter/set.ex#L1)

An nftables set — a named collection of elements with a uniform
key type, used for O(1) lookups in rules.

Sets are the kernel's high-performance match primitive: a rule
saying "if source IP is in @blocklist drop" hashes once into the
set rather than scanning a hundred individual rules.
Concatenations, dynamic sets, and intervals are not yet
implemented (see `docs/netfilter/DESIGN.md`).

## Fields

  * `:name` — set name (unique within the table).
  * `:table` — owning table's name; `nil` for free-standing sets.
  * `:key_type` — element-type atom. The basic atomic types are
    accepted: `:ipv4_addr`, `:ipv6_addr`, `:ether_addr`,
    `:inet_proto`, `:inet_service`, `:mark`, `:ifname`.
    Concatenations (`{:concat, [type1, type2, ...]}`) are not yet
    implemented.
  * `:flags` — list. Currently accepted: `:constant`,
    `:interval`, `:timeout`, `:dynamic`, `:auto_merge`,
    `:anonymous`. The timeout / dynamic / interval flags are not
    yet fully implemented; the value-type slot is here today.
  * `:elements` — list of element values matching `:key_type`.
    Element-type validation is a basic check; strict validation
    is not yet implemented.
  * `:timeout` — default element lifetime in ms; `nil` for no
    timeout (default).
  * `:gc_interval` — kernel's gc cadence in ms; `nil` to let the
    kernel choose.
  * `:size` — maximum element count; `nil` for unbounded.
  * `:handle` — kernel-assigned handle; `nil` until pushed.
  * `:comment` — round-trips via set userdata.

## Construction

    iex> Set.new("blocklist", key_type: :ipv4_addr)
    {:ok, %Linx.Netfilter.Set{name: "blocklist", key_type: :ipv4_addr, ...}}

    iex> Set.new("ssh_clients", key_type: :ipv4_addr,
    ...>          flags: [:timeout], timeout: 60_000)
    {:ok, %Linx.Netfilter.Set{...}}

Errors come back as `{:error, {:bad_set, reason}}`.
Element-shape errors as `{:error, {:bad_set_element, reason}}`.

## References

  * [wiki.nftables.org — Sets](https://wiki.nftables.org/wiki-nftables/index.php/Sets)

# `flag`

```elixir
@type flag() :: :constant | :interval | :timeout | :dynamic | :auto_merge | :anonymous
```

# `key_type`

```elixir
@type key_type() ::
  :ipv4_addr
  | :ipv6_addr
  | :ether_addr
  | :inet_proto
  | :inet_service
  | :mark
  | :ifname
```

# `t`

```elixir
@type t() :: %Linx.Netfilter.Set{
  comment: String.t() | nil,
  elements: [term()],
  flags: [flag()],
  gc_interval: pos_integer() | nil,
  handle: pos_integer() | nil,
  key_type: key_type(),
  name: String.t(),
  size: pos_integer() | nil,
  table: String.t() | nil,
  timeout: pos_integer() | nil
}
```

# `add_elements`

```elixir
@spec add_elements(t(), [term()]) :: {:ok, t()} | {:error, {:bad_set_element, term()}}
```

Adds elements to a set, validating each against the set's
`:key_type`. Returns the updated set or
`{:error, {:bad_set_element, reason}}`.

# `delete_elements`

```elixir
@spec delete_elements(t(), [term()]) :: {:ok, t()}
```

Removes elements from a set. No validation — removes whichever
elements match by equality.

# `new`

```elixir
@spec new(
  String.t(),
  keyword()
) :: {:ok, t()} | {:error, {:bad_set, term()}}
```

Builds a set.

# `new!`

```elixir
@spec new!(
  String.t(),
  keyword()
) :: t()
```

Bang variant of `new/2`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
