use*_*571 6 linux vlan network-interface
我知道如何使用 eth1.10 之类的 vconfig 在 linux 中创建标记接口,这使它接收和发送标记数据包。是否可以创建一个接口来接收和发送 vlan 10 的未标记数据包?
一个未标记的接口已经存在:eth1在这种情况下,它是父接口。
发送数据包会eth1.10导致这些数据包被标记,而接收到的带有 VLAN 标记 10 的数据包则通过该接口进入。
通过发送数据包会eth1导致这些数据包没有标记,而没有 VLAN 标记的数据包则通过该接口进入。
没有“为 vlan 10 发送未标记的数据包”这样的东西。根据定义,未标记的数据包没有任何 vlan 标记。
小智 6
我发现以下方法有效。
下面是一个例子:
$ tc qdisc del dev eth0 root
$ tc qdisc add dev eth0 handle 1: root prio
$ tc filter add dev eth0 parent 1: protocol 802.1q basic match 'meta(vlan eq 0)' action vlan pop
$ tc qdisc del dev eth0 ingress
$ tc qdisc add dev eth0 handle ffff: ingress
$ tc filter add dev eth0 parent ffff: protocol all basic match 'not meta(protocol eq 0x8100)' action vlan push id 0
$ ip link add eth0-vlan0 type vlan id 0
$ ip link set eth0-vlan0 up
$ ip addr add 192.168.10.253/24 dev eth0-vlan0
peer$ ping 192.168.10.253
PING 192.168.10.253 (192.168.10.253) 56(84) bytes of data.
64 bytes from 192.168.10.253: icmp_seq=1 ttl=64 time=0.209 ms
64 bytes from 192.168.10.253: icmp_seq=2 ttl=64 time=0.188 ms
^C
Run Code Online (Sandbox Code Playgroud)
请注意,在出口(上面称为“root”)上添加 prio qdisc 会禁用默认的 mq 规则,该规则根据 NIC 上的传输队列数量划分数据包,以允许多个 CPU 线程将数据包推送到不同的 TX 队列。要恢复默认行为,请按如下方式使用 mqprio:
$ tx_q_count=$(ls -d /sys/class/net/eth0/queues/tx-* | wc -l)
$ tc qdisc del dev eth0 root
$ tc qdisc add dev eth0 handle 1: root prio bands $tx_q_count multiqueue
$ tc filter add dev eth0 parent 1: protocol 802.1q basic match 'meta(vlan eq 0)' action vlan pop
$ for i in $(seq 1 $tx_q_count); do tc qdisc add dev eth0 parent 1:$i pfifo_fast; done
$ tc qdisc del dev eth0 ingress
$ tc qdisc add dev eth0 handle ffff: ingress
$ tc filter add dev eth0 parent ffff: protocol all basic match 'not meta(protocol eq 0x8100)' action vlan push id 0
$ ip link add eth0-vlan0 type vlan id 0
$ ip link set eth0-vlan0 up
$ ip addr add 192.168.10.253/24 dev eth0-vlan0
peer$ ping 192.168.10.253
PING 192.168.10.253 (192.168.10.253) 56(84) bytes of data.
64 bytes from 192.168.10.253: icmp_seq=1 ttl=64 time=0.230 ms
64 bytes from 192.168.10.253: icmp_seq=2 ttl=64 time=0.198 ms
^C
Run Code Online (Sandbox Code Playgroud)
另一种同样有效的解决方案是在物理接口上的 vlan 逻辑接口旁边添加一个软件桥接器。软件桥有一个 vlan 过滤功能,允许使用有限的 vlan 重映射(pvid->vid on ingre 和 vid->pvid on egress,但不是完全重映射)。下面是一个例子:
$ ip link add eth0-vlan0 type bridge
$ echo 0 > /sys/class/net/eth0-vlan0/bridge/default_pvid
$ echo 1 > /sys/class/net/eth0-vlan0/bridge/vlan_filtering
$ ip link set dev eth0 master eth0-vlan0
$ bridge vlan add vid 4094 dev eth0 pvid untagged
$ bridge vlan add vid 4094 dev eth0-vlan0 untagged pvid self
$ ip link add eth0-vlan4094 link eth0 type vlan id 4094
# ... BEGIN: only if you intend to use vlan 4094 ...
$ ip link set eth0-vlan4094 up
$ ip addr add 10.10.40.253/24 dev eth0-vlan4094
# ... END ...
$ ip link set eth0-vlan0 up
$ ip addr add 192.168.10.253/24 dev eth0-vlan0
peer$ ping 192.168.10.253
PING 192.168.10.253 (192.168.10.253) 56(84) bytes of data.
64 bytes from 192.168.10.253: icmp_seq=1 ttl=64 time=0.238 ms
64 bytes from 192.168.10.253: icmp_seq=2 ttl=64 time=0.215 ms
^C
Run Code Online (Sandbox Code Playgroud)
您需要与网桥内部使用的 VID 号匹配的 VLAN 接口,因为 VLAN 过滤功能有点马马虎虎。它使用 pvid->vid 映射接受两个未标记的帧,但它也接受与重新映射的 vid 匹配的线路上带有 VLAN 标记的帧。VLAN 接口反而会吃掉这些帧。如果您不需要该特定 VLAN,请将其保留在关闭状态。
软件桥最近获得了“default_pvid”功能,使其像廉价的硬件交换机一样工作:它可以识别 vlan,但默认情况下会执行 pvid->vid 映射到 vid 1,并允许所有端口上的 vid 1,以便您可以插入交换机并开始将端口用于未标记的流量,而无需单个配置指令。
最后,更现代的解决方案是使用 tc_clsact 并编写一个小的 BPF 程序来推送/弹出 PVID 的标签。就像上面的 TC 示例一样工作,除了一些 NIC 允许 BPF 程序的硬件卸载,因此它可以更高效。
小智 5
正如评论和另一个答案中提到的,没有专门的方法来发送属于特定 VLAN 的未标记数据包,因为由于缺少标记,未标记数据包无法描述它们属于哪个 VLAN。正如还提到的,父接口(此处为 eth1)将发送未标记的数据包。
然而,这并不意味着从您的 Linux 机器发送的未标记数据包不能属于网络上的特定 VLAN。由交换机将到达给定端口的未标记数据包分配给特定 VLAN。通常,交换机(支持 VLAN)默认情况下会将未标记的数据包分配给“默认 VLAN (1)”。但是,通过更改交换机上的配置,您可以指示它将收到的未标记数据包放入 VLAN 10 中,并将它们路由到分配了 VLAN 10 的其他位置。
如果 VLAN 10 在不同端口上设置为标记,则这些相同的数据包将在该处标记(如果这是数据包的目的地),而在为 VLAN 10 设置为未标记的不同端口上未标记