我知道如何使用像 eth1.10 这样的 vconfig 在 Linux 中创建标记接口,这使得它可以接收和发送标记数据包。是否可以创建一个接收和发送 vlan 10 未标记数据包的接口?
答案1
未标记的接口已存在:eth1
在本例中,它是父接口。
通过发送数据包eth1.10
会导致这些数据包被标记,而收到带有 VLAN 标记 10 的数据包则通过该接口进入。
通过发送数据包eth1
会导致这些数据包未被标记,而接收到的数据包没有 VLAN 标记则通过该接口进入。
不存在“为 vlan 10 发送未标记的数据包”这样的事情。根据定义,未标记的数据包没有任何 VLAN 标记。
答案2
我发现以下方法有效。
- 使用 TC 在 ingres 上匹配不带 802.1q 的数据包并推送 id 0 的 vlan 标头
- 出口使用TC匹配vlan 0的报文,弹出vlan header
- 创建类型为 vlan 且 id=0 的未标记逻辑接口
这是一个例子:
$ 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
请注意,在出口(上面称为“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
另一种可行的解决方案是在物理接口上的 VLAN 逻辑接口旁边添加一个软件桥。软件桥具有 VLAN 过滤功能,允许使用有限的 VLAN 重新映射(入口处为 pvid->vid,出口处为 vid->pvid,但不能完全重新映射)。这是一个例子:
$ 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
您需要与网桥内部使用的 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 程序的硬件卸载,因此它的性能可能会更高。
答案3
正如评论和另一个答案中提到的,没有专门的方法来发送属于特定 VLAN 的未标记数据包,因为由于缺少标记,未标记数据包无法描述它们属于哪个 VLAN。正如还提到的,父接口(此处为 eth1)将发送未标记的数据包。
然而,这并不意味着从您的 Linux 机器发送的未标记数据包不能属于网络上的特定 VLAN。由交换机将到达给定端口的未标记数据包分配给特定 VLAN。通常,交换机(支持 VLAN)默认情况下会将未标记的数据包分配给“默认 VLAN (1)”。但是,通过更改交换机上的配置,您可以指示它将接收到的未标记数据包放入 VLAN 10 中,并将它们路由到分配了 VLAN 10 的其他位置。
如果 VLAN 10 在不同端口上设置为标记,则这些相同的数据包将在该处标记(如果这是数据包的目的地),而在为 VLAN 10 设置为未标记的不同端口上未标记
答案4
您可以在物理接口 (eth0) 和 vlan 接口 (eth1:10) 之间创建桥接。然后,该网桥将允许来自物理接口 (eth0) 的未标记数据包与 vlan 接口 (eth1:10) 上的标记网络进行通信。
我用的正是这个星座。如果网桥是通过父接口 (eth0) 及其从属 VLAN 接口 (eth0:10) 创建的,这是否有效,我不能说...