如何通过 Linux 中的特定接口发送多播数据包
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6798165/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to send multicast packets via a specfic interface in Linux
提问by Sumit
Having tried all possible ways couldn't find a work around for this problem. I have a machine with two interfaces eth0 and eth2. I want all ff38:40:2001:dead:beef:cafe::/96 packets to go on eth2. I tried all the following but when I do ping6 ff38:40:2001:dead:beef:cafe::1 the packets always goes on eth0. Things I have tried and have not worked (i.e., packet still goes out on eth0).
尝试了所有可能的方法后找不到解决此问题的方法。我有一台机器有两个接口 eth0 和 eth2。我希望所有 ff38:40:2001:dead:beef:cafe::/96 数据包都在 eth2 上。我尝试了以下所有方法,但是当我执行 ping6 ff38:40:2001:dead:beef:cafe::1 时,数据包总是在 eth0 上。我尝试过但没有奏效的事情(即,数据包仍然在 eth0 上发出)。
$> route add --inet6 ff38:40:2001:dead:beef:cafe::/96 gw 2003::100 dev eth2
$> route add --inet6 ff38:40:2001:dead:beef:cafe::/96 dev eth2
$> route add --inet6 ff38:40:2001:dead:beef:cafe::/96 metric 1 gw 2003::100 dev eth2
My routing table is
我的路由表是
[root@dev ~]# route --inet6 |grep eth0
fe80::/64 * U 256 0 0 eth0
ff00::/8 * U 256 0 0 eth0
[root@dev ~]# route --inet6 |grep eth2
2003::/64 * U 256 68 0 eth2
fe80::/64 * U 256 0 0 eth2
ff38:40:2001:dead:beef:cafe::/96 2003::100 UG 1 0 0 eth2
*/0 fe80::c671:feff:fe14:e482 UGDA 1024 0 0 eth2
ff00::/8 * U 256 0 0 eth2
However, ping6 ff38:40:2001:dead:beef:cafe::1 -I eth2 work just fine. Moreover, I see this problem only on Linux machines (MAC is fine).
但是, ping6 ff38:40:2001:dead:beef:cafe::1 -I eth2 工作得很好。此外,我只在 Linux 机器上看到这个问题(MAC 很好)。
[root@dev ~]# ping6 ff38:40:2001:dead:beef:cafe::1 -I eth2
PING ff38:40:2001:dead:beef:cafe::1(ff38:40:2001:dead:beef:cafe:0:1) from cal eth2: 56 data bytes
64 bytes from 2012::1: icmp_seq=0 ttl=253 time=19.1 ms
64 bytes from 2012::1: icmp_seq=1 ttl=253 time=2.16 ms
64 bytes from 2012::1: icmp_seq=2 ttl=253 time=2.14 ms
64 bytes from 2012::1: icmp_seq=3 ttl=253 time=2.26 ms
64 bytes from 2012::1: icmp_seq=4 ttl=253 time=2.08 ms
64 bytes from 2012::1: icmp_seq=5 ttl=253 time=2.15 ms
root@dev ~]# uname -a
Linux 2.6.18-194.el5 #1 SMP Tue Mar 16 21:52:39 EDT 2010 x86_64 x86_64 x86_64 GNU/Linux
Perhaps the problem has to do with the fact that there is a ff00::/8 for eth0. How do I overrule that route. I am not able to delete ff00::/8 route as well.
也许问题与 eth0 有一个 ff00::/8 的事实有关。我如何推翻这条路线。我也无法删除 ff00::/8 路由。
采纳答案by Jander
I'm not entirely convinced my solution is correct, but I can at least shed a little more light on what is going on.
我并不完全相信我的解决方案是正确的,但我至少可以更清楚地了解正在发生的事情。
Background
背景
Linux actually has multiple routing tables, and they are searched one at a time in a specific priority order until a table with a matching route is found. You can optionally search some of the routing tables based on source address or protocol; see the ip-rule(8)
man page.
Linux 实际上有多个路由表,它们会按照特定的优先级顺序一次搜索一个,直到找到具有匹配路由的表。您可以根据源地址或协议选择性地搜索一些路由表;请参阅ip-rule(8)
手册页。
The trouble is the "local" routing table, which has priority 0, the highest possible. The "local" table is populated automatically by the kernel and holds "obvious" interface and broadcast routes. For IPv6 under Linux, this apparently includes the entire multicast block.
麻烦的是“本地”路由表,它的优先级为 0,可能是最高的。“本地”表由内核自动填充并保存“明显”接口和广播路由。对于 Linux 下的 IPv6,这显然包括整个多播块。
The Problem
问题
I'm going to be using the iproute2tool rather than the more traditional route
, because it will show me everything I need to know.
我将使用iproute2工具而不是更传统的工具route
,因为它会显示我需要知道的一切。
On my Linux box:
在我的 Linux 机器上:
$ ip -6 route show table local
local ::1 via :: dev lo proto none metric 0
local fe80::213:a9ff:fe91:5bcb via :: dev lo proto none metric 0
local fe80::250:b6ff:fe44:37d1 via :: dev lo proto none metric 0
ff00::/8 dev eth0 metric 256
ff00::/8 dev eth1 metric 256
$ ip -6 route show table main
fe80::/64 dev eth0 proto kernel metric 256
fe80::/64 dev eth1 proto kernel metric 256
ff15::/16 dev eth1 metric 1024
ff00::/8 dev eth1 metric 1024
$ ip -6 rule show
0: from all lookup local
32766: from all lookup main
...And my multicast packets for ff15::1 (5==site-local, >link-local) end up on eth0, because the "local" routing table matches first and overrides the "main" table, even though the "main" table has a more specific route. This overriding behavior is correct in the greater scheme of policy routing, but the choice of auto-adding ff00::/8 to the local table is questionable to me.
...我的 ff15::1 (5==site-local, >link-local) 的多播数据包最终在 eth0 上,因为“本地”路由表首先匹配并覆盖“主”表,即使“主”表有一个更具体的路线。这种覆盖行为在更大的策略路由方案中是正确的,但是将 ff00::/8 自动添加到本地表的选择对我来说是有问题的。
My Solution
我的解决方案
I don't have enough experience to know if this is a good idea, but:
我没有足够的经验来知道这是否是一个好主意,但是:
# ip -6 route add ff15::/16 dev eth1 table local
and now my ff15::1 packets are routed through eth1.
现在我的 ff15::1 数据包通过 eth1 路由。
This agrees somewhat with the semantics of the local table, in that it's routed directly through a device. It doesn't feel exactly right (considering automatic management and "you shouldn't have to look at this table"), but it's the best solution I've found.
这与本地表的语义有些一致,因为它直接通过设备路由。感觉不太对劲(考虑到自动管理和“你不应该看这张表”),但这是我找到的最好的解决方案。
回答by ardje
Multicast is inherently a local link "broadcast". As such you mustalways indicate the zone or network interface it is sent to. There is no routing. If you have multiple interfaces, you should send it out to multiple interfaces. The way to do it is: ping(6) ip%zone . Now on that same network might be a router that receives the packets and might forward it to another zone, iff some node on the other zone has subscribed to that address, and the TTL of the packet is > 1. There are no routing tables involved in multicast routing, except on multicast routers.
多播本质上是本地链接“广播”。因此,您必须始终指明它被发送到的区域或网络接口。没有路由。如果您有多个接口,则应将其发送到多个接口。这样做的方法是: ping(6) ip%zone 。现在在同一个网络上可能有一个路由器接收数据包并将其转发到另一个区域,如果另一个区域上的某个节点订阅了该地址,并且数据包的 TTL > 1。没有涉及路由表在多播路由中,除了在多播路由器上。
Since this original question was from 2012, around that time user kernel space was fixed to make it illegal to send a multicast packet without a zone identifier. So the ping6 in the original question would not even work.
由于这个最初的问题是从 2012 年开始的,大约在那个时候,用户内核空间被修复,使得发送没有区域标识符的多播数据包是非法的。所以原始问题中的 ping6 甚至不起作用。
The situation for IPv4 is dire, since it is hard to bind to a specific interface for the outgoing multicast, unless the software used was correctly implemented.
IPv4 的情况很糟糕,因为除非所使用的软件得到正确实施,否则很难绑定到特定接口以用于传出多播。