# `Linx.Netlink.Rtnl.Link`
[🔗](https://github.com/oshlabs/linx/blob/v0.2.0/lib/linx/netlink/rtnl/link.ex#L1)

rtnetlink network links (interfaces) — the `RTM_*LINK` messages.

A `%Link{}` is a decoded interface: its index, name, link-layer type, flags,
MTU, MAC address, parent, master and kind-specific information. Read verbs
`list/1` / `get/2` retrieve interfaces; mutating verbs create, delete and
configure them.

## Example

    {:ok, sock} = Rtnl.open()

    {:ok, links} = Link.list(sock)
    # => [#Linx.Netlink.Rtnl.Link<"lo" (1) UP MTU=65536>,
    #     #Linx.Netlink.Rtnl.Link<"eth0" (2) UP MTU=1500>]

    # A veth pair: bring one end up, hand the peer to a container's netns.
    :ok = Link.create_veth(sock, "ct0a", "ct0b")
    :ok = Link.set_up(sock, "ct0a")
    :ok = Link.move_to_netns(sock, "ct0b", container_pid)

## Creating

Several kinds of virtual link are supported, each by its own constructor:

    Link.create_macvlan(socket, name, parent, mode \\ :bridge)
    Link.create_ipvlan (socket, name, parent, mode \\ :l3)
    Link.create_veth   (socket, name, peer_name)
    Link.create_vlan   (socket, name, parent, vlan_id)
    Link.create_bridge (socket, name)
    Link.create_dummy  (socket, name)

## Configuring

`set_up/2` / `set_down/2` toggle `IFF_UP`; `set_mtu/3`, `set_name/3`,
`set_address/3` and `set_master/3` change the MTU, name, MAC and bridge /
bond master respectively; `move_to_netns/3` hands the link to another
network namespace.

## Wire format

`struct ifinfomsg` (`include/uapi/linux/rtnetlink.h`) and the `IFLA_*`
attributes (`include/uapi/linux/if_link.h`) — declared with the
`Linx.Netlink.Codec` DSL. `IFLA_LINKINFO` is itself a sub-codec
(`Linx.Netlink.Rtnl.LinkInfo`) whose `IFLA_INFO_DATA` is dispatched on the
kind value, picking the right per-kind module (`LinkInfo.Macvlan`,
`LinkInfo.Veth`, …).

# `t`

```elixir
@type t() :: %Linx.Netlink.Rtnl.Link{
  address: term(),
  change: term(),
  family: term(),
  flags: term(),
  index: term(),
  link: term(),
  linkinfo: term(),
  master: term(),
  mtu: term(),
  name: term(),
  net_ns_pid: term(),
  type: term()
}
```

# `create_bridge`

```elixir
@spec create_bridge(Linx.Netlink.Socket.t(), binary()) :: :ok | {:error, term()}
```

Creates an empty Linux bridge named `name`.

# `create_dummy`

```elixir
@spec create_dummy(Linx.Netlink.Socket.t(), binary()) :: :ok | {:error, term()}
```

Creates a `dummy` interface named `name` — a loopback-like virtual link
with no real packet path, useful as a stable address holder or a test
fixture.

# `create_ipvlan`

```elixir
@spec create_ipvlan(Linx.Netlink.Socket.t(), binary(), binary(), :l2 | :l3) ::
  :ok | {:error, term()}
```

Creates an `ipvlan` link named `name` on parent interface `parent`.

`mode` is `:l3` (default) or `:l2`.

# `create_macvlan`

```elixir
@spec create_macvlan(Linx.Netlink.Socket.t(), binary(), binary(), :bridge | :private) ::
  :ok | {:error, term()}
```

Creates a `macvlan` link named `name` on parent interface `parent`.

`mode` is `:bridge` (default) or `:private`.

# `create_veth`

```elixir
@spec create_veth(Linx.Netlink.Socket.t(), binary(), binary()) ::
  :ok | {:error, term()}
```

Creates a `veth` pair — two interfaces named `name` and `peer_name`,
connected back-to-back.

# `create_vlan`

```elixir
@spec create_vlan(Linx.Netlink.Socket.t(), binary(), binary(), 1..4094) ::
  :ok | {:error, term()}
```

Creates an `vlan` sub-interface named `name` on parent `parent` carrying
802.1Q VLAN tag `vlan_id` (1..4094).

# `decode`

```elixir
@spec decode(binary()) :: t()
```

Decodes a netlink message body into a `t:t/0`.

# `delete`

```elixir
@spec delete(Linx.Netlink.Socket.t(), binary()) :: :ok | {:error, term()}
```

Deletes the link named `name`.

# `encode`

```elixir
@spec encode(t()) :: binary()
```

Encodes a `t:t/0` into its netlink message body.

# `get`

```elixir
@spec get(Linx.Netlink.Socket.t(), binary()) :: {:ok, t()} | {:error, term()}
```

Gets the link named `name`.

Returns `{:error, %Linx.Netlink.Error{errno: :enodev}}` if there is no such
interface.

# `list`

```elixir
@spec list(Linx.Netlink.Socket.t()) :: {:ok, [t()]} | {:error, term()}
```

Lists every link in the socket's network namespace.

# `move_to_netns`

```elixir
@spec move_to_netns(Linx.Netlink.Socket.t(), binary(), pos_integer()) ::
  :ok | {:error, term()}
```

Moves link `name` into the network namespace of process `pid`.

# `set_address`

```elixir
@spec set_address(Linx.Netlink.Socket.t(), binary(), binary() | Linx.MAC.t()) ::
  :ok | {:error, term()}
```

Sets link `name`'s MAC address to `mac` — a colon-separated hex string,
e.g. `"aa:bb:cc:dd:ee:ff"`, or a `Linx.MAC`.

# `set_down`

```elixir
@spec set_down(Linx.Netlink.Socket.t(), binary()) :: :ok | {:error, term()}
```

Brings link `name` administratively down (clears `IFF_UP`).

# `set_master`

```elixir
@spec set_master(Linx.Netlink.Socket.t(), binary(), binary()) ::
  :ok | {:error, term()}
```

Enslaves link `name` to `master_name` — typically a bridge or bond.

# `set_mtu`

```elixir
@spec set_mtu(Linx.Netlink.Socket.t(), binary(), pos_integer()) ::
  :ok | {:error, term()}
```

Sets link `name`'s MTU to `mtu`.

# `set_name`

```elixir
@spec set_name(Linx.Netlink.Socket.t(), binary(), binary()) :: :ok | {:error, term()}
```

Renames link `name` to `new_name`.

# `set_up`

```elixir
@spec set_up(Linx.Netlink.Socket.t(), binary()) :: :ok | {:error, term()}
```

Brings link `name` administratively up (sets `IFF_UP`).

# `up?`

```elixir
@spec up?(t()) :: boolean()
```

Returns whether `link` is administratively up (has `IFF_UP` set).

---

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