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

An nftables table — the top-level container for chains, sets,
maps, objects, and flowtables, scoped to one family.

## Fields

  * `:family` — `:ip` | `:ip6` | `:inet` | `:arp` | `:bridge` |
    `:netdev`.
  * `:name` — table name (unique within the family in the netns).
  * `:flags` — list. `:owner` enables `NFT_TABLE_F_OWNER` (the
    table auto-destroys when the owning socket closes); `:persist`
    sets `NFT_TABLE_F_PERSIST` (table survives even when
    unreferenced — owner's opt-out, kernel 6.9+); `:dormant`
    sets `NFT_TABLE_F_DORMANT` (table loaded but inactive).
  * `:use_count` — kernel-reported reference count, only set on
    pulled tables; `nil` for authoring-time tables.
  * `:handle` — kernel handle; `nil` until pushed.
  * `:chains` — `%{chain_name => %Linx.Netfilter.Chain{}}`.
  * `:sets` — `%{set_name => %Linx.Netfilter.Set{}}`.
  * `:maps` — `%{map_name => %Linx.Netfilter.Map{}}`.
  * `:objects` — `%{{kind, name} => %Linx.Netfilter.Object{}}` —
    objects are scoped by `(kind, name)` since kinds don't share
    a namespace (a `:counter` and a `:quota` of the same name
    coexist).
  * `:flowtables` — `%{ft_name => %Linx.Netfilter.Flowtable{}}`.

## Construction

    iex> Table.new(:inet, "myapp")
    {:ok, %Linx.Netfilter.Table{family: :inet, name: "myapp", flags: [], ...}}

    iex> Table.new(:inet, "myapp", flags: [:owner])
    {:ok, %Linx.Netfilter.Table{flags: [:owner], ...}}

Errors: `{:error, {:bad_table, reason}}`.

Container mutations (`add_chain/2`, `add_set/2`, …) come with
uniqueness checks and route the entity through its family's
validation. They return the updated table or
`{:error, {:bad_table, …}}` (for uniqueness collisions) /
`{:error, {:bad_chain, …}}` (for entity-shape failures).

## References

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

# `family`

```elixir
@type family() :: :ip | :ip6 | :inet | :arp | :bridge | :netdev
```

# `flag`

```elixir
@type flag() :: :owner | :persist | :dormant
```

# `t`

```elixir
@type t() :: %Linx.Netfilter.Table{
  chains: %{optional(String.t()) =&gt; Linx.Netfilter.Chain.t()},
  family: family(),
  flags: [flag()],
  flowtables: %{optional(String.t()) =&gt; Linx.Netfilter.Flowtable.t()},
  handle: pos_integer() | nil,
  maps: %{optional(String.t()) =&gt; Linx.Netfilter.Map.t()},
  name: String.t(),
  objects: %{
    optional({Linx.Netfilter.Object.kind(), String.t()}) =&gt;
      Linx.Netfilter.Object.t()
  },
  sets: %{optional(String.t()) =&gt; Linx.Netfilter.Set.t()},
  use_count: non_neg_integer() | nil
}
```

# `add_chain`

```elixir
@spec add_chain(t(), Linx.Netfilter.Chain.t()) ::
  {:ok, t()} | {:error, {:bad_table | :bad_chain, term()}}
```

Adds a chain to the table. Validates the chain against the
table's family and that the chain name is unique within the
table.

Sets the chain's `:table` field to this table's name (so
free-standing chains pick up their context when inserted).

# `add_flowtable`

```elixir
@spec add_flowtable(t(), Linx.Netfilter.Flowtable.t()) ::
  {:ok, t()} | {:error, {:bad_table, term()}}
```

Adds a flowtable to the table. Validates name uniqueness.

# `add_map`

```elixir
@spec add_map(t(), Linx.Netfilter.Map.t()) ::
  {:ok, t()} | {:error, {:bad_table, term()}}
```

Adds a map (or vmap) to the table. Validates map name uniqueness
within the table (sets and maps share a namespace at the kernel
level — a set and a map of the same name collide).

# `add_object`

```elixir
@spec add_object(t(), Linx.Netfilter.Object.t()) ::
  {:ok, t()} | {:error, {:bad_table, term()}}
```

Adds an object to the table. Uniqueness is by `(kind, name)` —
objects of different kinds may share a name.

# `add_set`

```elixir
@spec add_set(t(), Linx.Netfilter.Set.t()) ::
  {:ok, t()} | {:error, {:bad_table, term()}}
```

Adds a set to the table. Validates set name uniqueness within
the table.

# `fetch_chain`

```elixir
@spec fetch_chain(t(), String.t()) ::
  {:ok, Linx.Netfilter.Chain.t()} | {:error, :no_such_chain}
```

Looks up a chain by name. Returns `{:ok, chain}` or
`{:error, :no_such_chain}`.

# `new`

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

Builds a table.

# `new!`

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

Bang variant.

# `put_chain`

```elixir
@spec put_chain(t(), Linx.Netfilter.Chain.t()) ::
  {:ok, t()} | {:error, {:bad_table, term()}}
```

Replaces a chain in the table. The chain must already exist by
name (intended for use after mutating one with `Chain.add_rule/2`
or similar).

---

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