# 34.9.链路聚合与故障转移

FreeBSD 提供了 [lagg(4)](https://man.freebsd.org/cgi/man.cgi?query=lagg\&sektion=4\&format=html) 接口，可以将多个网络接口聚合为一个虚拟接口，以提供故障转移和链路聚合。故障转移允许流量继续传输，只要至少一个聚合的网络接口具有有效的链路。链路聚合在支持 LACP 的交换机上效果最佳，因为该协议双向分配流量，并能响应单个链路的故障。

lagg 接口支持的聚合协议决定了哪些端口用于发送流量以及是否允许特定端口接收流量。以下是 [lagg(4)](https://man.freebsd.org/cgi/man.cgi?query=lagg\&sektion=4\&format=html) 支持的协议：

* **failover**\
  此模式仅通过主端口发送和接收流量。如果主端口不可用，则使用下一个活动端口。第一个添加到虚拟接口的接口为主端口，所有后续添加的接口将用作故障转移设备。如果发生故障转移到非主端口，则待原始端口恢复可用，它将重新成为主端口。
* **loadbalance**\
  提供静态设置，不与对端协商聚合或交换帧来监控链路。如果交换机支持 LACP，应该使用 LACP 协议。
* **lacp**\
  IEEE® 802.3ad 链路聚合控制协议（LACP）与对端协商一组可聚合的链路，形成一个或多个链路聚合组（LAG）。每个 LAG 由相同速率、全双工操作的端口组成，并且流量会根据 LAG 的最大总速度在端口之间进行平衡。通常，只有一个 LAG 包含所有端口。在物理连接发生变化时，LACP 会快速收敛到新的配置。

  LACP 基于哈希的协议头信息平衡外发流量，并接受任何活动端口的入站流量。哈希包括以太网源和目标地址，若可用，还包括 VLAN 标签，以及 IPv4 或 IPv6 的源和目标地址。
* **roundrobin**\
  此模式通过所有活动端口使用轮询调度器分配外发流量，并接受任何活动端口的入站流量。由于此模式会违反以太网帧的顺序，因此应谨慎使用。
* **broadcast**\
  此模式将外发流量发送到配置在 lagg 接口上的所有端口，并从任何端口接收帧。

## 34.9.1. 配置示例

本节演示如何配置 Cisco® 交换机和 FreeBSD 系统以进行 LACP 负载平衡。接着，展示了如何将两个以太网接口配置为故障转移模式，以及如何在以太网接口和无线接口之间配置故障转移模式。

**示例 1. 使用 Cisco® 交换机进行 LACP 聚合**

本示例将 FreeBSD 机器上的两个 [fxp(4)](https://man.freebsd.org/cgi/man.cgi?query=fxp\&sektion=4\&format=html) 以太网接口与 Cisco® 交换机上的前两个以太网端口连接，作为一个负载平衡和故障容错链路。可以添加更多接口以增加吞吐量和故障容错性。请将示例中 Cisco® 端口、以太网设备、通道组编号和 IP 地址替换为本地配置。

以太网链路上帧的顺序是强制要求的，在两个站点之间的任何流量始终会通过同一物理链路，这限制了最大速度为一个接口的速率。传输算法会尽可能多地利用信息来区分不同的流量，并将流量均衡分配到可用的接口上。

在 Cisco® 交换机上，将 *FastEthernet0/1* 和 *FastEthernet0/2* 接口添加到通道组 *1* 中：

```sh
interface FastEthernet0/1
 channel-group 1 mode active
 channel-protocol lacp
!
interface FastEthernet0/2
 channel-group 1 mode active
 channel-protocol lacp
```

在 FreeBSD 系统上，使用物理接口 *fxp0* 和 *fxp1* 创建 [lagg(4)](https://man.freebsd.org/cgi/man.cgi?query=lagg\&sektion=4\&format=html) 接口，并为该接口分配 IP 地址 *10.0.0.3/24*：

```sh
# ifconfig fxp0 up
# ifconfig fxp1 up
# ifconfig lagg0 create
# ifconfig lagg0 up laggproto lacp laggport fxp0 laggport fxp1 10.0.0.3/24
```

接下来，验证虚拟接口的状态：

```sh
# ifconfig lagg0
lagg0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
        options=8<VLAN_MTU>
        ether 00:05:5d:71:8d:b8
        inet 10.0.0.3 netmask 0xffffff00 broadcast 10.0.0.255
        media: Ethernet autoselect
        status: active
        laggproto lacp
        laggport: fxp1 flags=1c<ACTIVE,COLLECTING,DISTRIBUTING>
        laggport: fxp0 flags=1c<ACTIVE,COLLECTING,DISTRIBUTING>
```

标记为 `ACTIVE` 的端口是与远程交换机协商的 LAG 部分。流量将通过这些活动端口发送和接收。可以将 `-v` 添加到上述命令中，以查看 LAG 标识符。

要查看 Cisco® 交换机上的端口状态：

```sh
switch# show lacp neighbor
Flags:  S - Device is requesting Slow LACPDUs
        F - Device is requesting Fast LACPDUs
        A - Device is in Active mode       P - Device is in Passive mode

Channel group 1 neighbors

Partner's information:

                  LACP port                        Oper    Port     Port
Port      Flags   Priority  Dev ID         Age     Key     Number   State
Fa0/1     SA      32768     0005.5d71.8db8  29s    0x146   0x3      0x3D
Fa0/2     SA      32768     0005.5d71.8db8  29s    0x146   0x4      0x3D
```

要查看更多详细信息，键入 `show lacp neighbor detail`。

为确保此配置在重启后仍然生效，需在 FreeBSD 系统的 **/etc/rc.conf** 文件中添加以下条目：

```sh
ifconfig_fxp0="up"
ifconfig_fxp1="up"
cloned_interfaces="lagg0"
ifconfig_lagg0="laggproto lacp laggport fxp0 laggport fxp1 10.0.0.3/24"
```

**示例 2. 故障转移模式**

故障转移模式可用于在主接口的链路丢失时切换到备用接口。要配置故障转移，确保底层物理接口已启用，然后创建 [lagg(4)](https://man.freebsd.org/cgi/man.cgi?query=lagg\&sektion=4\&format=html) 接口。在此示例中，*fxp0* 是主接口，*fxp1* 是备用接口，虚拟接口被分配 IP 地址 *10.0.0.15/24*：

```sh
# ifconfig fxp0 up
# ifconfig fxp1 up
# ifconfig lagg0 create
# ifconfig lagg0 up laggproto failover laggport fxp0 laggport fxp1 10.0.0.15/24
```

虚拟接口的状态应如下所示：

```sh
# ifconfig lagg0
lagg0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
        options=8<VLAN_MTU>
        ether 00:05:5d:71:8d:b8
        inet 10.0.0.15 netmask 0xffffff00 broadcast 10.0.0.255
        media: Ethernet autoselect
        status: active
        laggproto failover
        laggport: fxp1 flags=0<>
        laggport: fxp0 flags=5<MASTER,ACTIVE>
```

流量将在 *fxp0* 上发送和接收。如果 *fxp0* 上的链路丢失，*fxp1* 将成为活动链路。如果主接口的链路恢复，它将重新成为活动链路。

为确保此配置在重启后仍然生效，需在 **/etc/rc.conf** 文件中添加以下条目：

```sh
ifconfig_fxp0="up"
ifconfig_fxp1="up"
cloned_interfaces="lagg0"
ifconfig_lagg0="laggproto failover laggport fxp0 laggport fxp1 10.0.0.15/24"
```

**示例 3. 以太网与无线接口之间的故障转移模式**

对于笔记本电脑用户，通常希望将无线设备配置为备用接口，仅在以太网连接不可用时使用。使用 [lagg(4)](https://man.freebsd.org/cgi/man.cgi?query=lagg\&sektion=4\&format=html) 可以配置故障转移模式，优先选择以太网连接，出于性能和安全性考虑，同时保持通过无线连接传输数据的能力。

此配置通过将以太网接口的 MAC 地址覆盖为无线接口的 MAC 地址来实现。

理论上，可以将以太网或无线的 MAC 地址更改为与另一个接口匹配。但是，一些流行的无线接口不支持覆盖 MAC 地址。因此，建议为此目的覆盖以太网 MAC 地址。

如果无线接口的驱动程序未在 `GENERIC` 或自定义内核中加载，且计算机运行 FreeBSD 12.1，请在 **/boot/loader.conf** 中加载相应的 **.ko** 文件，通过添加 `driver_load="YES"` 到该文件并重启。另一种更好的方法是通过将其添加到 **/etc/rc.conf** 的 `kld_list` 中加载驱动程序（请参见 [rc.conf(5)](https://man.freebsd.org/cgi/man.cgi?query=rc.conf\&sektion=5\&format=html) 以获取详细信息），然后重启。因为如果不这样做，驱动程序在设置 [lagg(4)](https://man.freebsd.org/cgi/man.cgi?query=lagg\&sektion=4\&format=html) 接口时尚未加载。

在此示例中，*re0* 是主接口，*wlan0* 是故障转移接口。*wlan0* 接口是由 *ath0* 物理无线接口创建的，并且以太网接口将配置为无线接口的 MAC 地址。首先，启用无线接口（将 *FR* 替换为你的国家/地区的两位字母代码），但不设置 IP 地址。将 *wlan0* 替换为系统的无线接口名称：

```sh
# ifconfig wlan0 create wlandev ath0 country FR ssid my_router up
```

现在可以确定无线接口的 MAC 地址：

```sh
# ifconfig wlan0
wlan0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
	ether b8:ee:65:5b:32:59
	groups: wlan
	ssid Bbox-A3BD2403 channel 6 (2437 MHz 11g ht/20) bssid 00:37:b7:56:4b:60
	regdomain ETSI country FR indoor ecm authmode WPA2/802.11i privacy ON
	deftxkey UNDEF AES-CCM 2:128-bit txpower 30 bmiss 7 scanvalid 60
	protmode CTS ampdulimit 64k ampdudensity 8 shortgi -stbctx stbcrx
	-ldpc wme burst roaming MANUAL
	media: IEEE 802.11 Wireless Ethernet MCS mode 11ng
	status: associated
	nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
```

`ether` 行将显示指定接口的 MAC 地址。现在，将以太网接口的 MAC 地址更改为匹配：

```sh
# ifconfig re0 ether b8:ee:65:5b:32:59
```

确保 *re0* 接口已启用，然后创建 [lagg(4)](https://man.freebsd.org/cgi/man.cgi?query=lagg\&sektion=4\&format=html) 接口，以 *re0* 作为主接口并故障转移到 *wlan0*：

```sh
# ifconfig re0 up
# ifconfig lagg0 create
# ifconfig lagg0 up laggproto failover laggport re0 laggport wlan0
```

虚拟接口的状态应如下所示：

```sh
# ifconfig lagg0
lagg0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
        options=8<VLAN_MTU>
        ether b8:ee:65:5b:32:59
        laggproto failover lagghash l2,l3,l4
        laggport: re0 flags=5<MASTER,ACTIVE>
        laggport: wlan0 flags=0<>
        groups: lagg
        media: Ethernet autoselect
        status: active
```

然后，启动 DHCP 客户端以获取 IP 地址：

```sh
# dhclient lagg0
```

为确保此配置在重启后仍然生效，需在 **/etc/rc.conf** 文件中添加以下条目：

```sh
ifconfig_re0="ether b8:ee:65:5b:32:59"
wlans_ath0="wlan0"
ifconfig_wlan0="WPA"
create_args_wlan0="country FR"
cloned_interfaces="lagg0"
ifconfig_lagg0="up laggproto failover laggport re0 laggport wlan0 DHCP"
```
