9. Broadcasting 和 Loacl Multicasting (IGMP 和 MLD)
9.1 介绍
我们在第二章中提到有 4 种类型的 IP 地址:unicast,anycast,multicast,broadcast。IPv4 能使用所有类型的地址,IPv6 能使用除 broadcast 外其他所有类型的地址。本章我们讨论 broadcast 和 multicast 更多的细节,包括链接层寻址如何被用于高效地发送从一个计算机到其他几个的 multicast 或 broadcast 流量。我们也探查 Internet Group Management Protocol (IGMP)[RFC3376] 和 IPv6 Multicast Listener Discovery (MLD)[RFC3810] 协议,它被用于通知 IPv4 和 IPv6 多播路由器在子网上哪个多播地址正在被使用。
Broadcasting 和 multicasting 为应用提供两种服务:向多个目的地的 packet 的递交,客户端请求/发现服务器。
- 向多个目的地递交
有很多应用向多个接收方递交信息:例如,互动式会议,和向多个接收方发送的邮件或新闻。在没有 broadcast 或 multicast 的情况下,这些类型的服务如今倾向于使用 TCP (向每个目的地递交单独的副本,这可能十分低效)。 - 客户端对服务的请求
使用 broadcasting 或 multicasting,应用可以在不知道服务器的 IP 地址的情况下向服务器发送请求。当在配置期间不知道本地网络环境时,该能力十分有用。例如,笔记本电脑可能需要使用 DHCP 获取它的初始 IP 地址并找到距它最近的路由器。
虽然 broadcast 和 multicast 都能提供这些重要的功能,但通常更偏向于使用 multicast,因为 multicast 仅涉及支持或使用特定服务或协议的那些系统,但是 broadcast 不是这样。因此,broadcast 请求影响所有广播域内可抵达的主机,而 multicast 仅影响对请求感兴趣的主机。broadcast 更简单但是开销更大,multicast 更复杂但是效率上有所提升。
Broadcast 在 IPv4 问世时就已经被支持了,multicast 随着 [RFC1112] 的发布被添加到 IPv4。IPv6 支持多播但是不支持广播。通常,只有使用 UDP 传输协议 (第 10 章) 的用户应用才会利用广播和多播,此时向多个接收方发送单条消息的意义才存在。TCP 是面向连接的协议,两个主机(由 IP 地址指定)的一个进程 (由端口号指定) 之间存在一条连接。TCP 能使用 unicast 和 anycast 地址 (anycast 的行为如同 unicast),但是不能使用广播和多播。
Note
广播和多播也被重要的系统进程使用,例如路由协议,ARP,IPv6 中的 ND,和其他。
9.2 Broadcasting
Broadcasting 指的是向所有网络中可能的接收方发送消息。理论上,这很简单:路由器简单的转发任何它从每个接口上收到的消息的拷贝,除了消息到达的那一个。当多个主机关联当同一个局域网时,情况变得稍微有些复杂。在这种情况下,可能使用链接层的特性来使广播更加效率。
考虑网络上,比如在链接层上支持广播的 Ethernet,有一系列的主机。每个 Ethernet frame 包含源和目的 MAC 地址 (48-bit 值)。通常,每个 IP packet 的目的地都是单个主机,所以使用单播地址,目的地的唯一 MAC 地址使用 ARP 或 IPv6 的 ND 确认。当一个 frame 以这种方式被发往一个单播目的地,在两个主机之间的通讯不会打扰任何网络上的其他主机。对于交换的 Ethernet 网络,这些类型的地址能在交换机或网桥的栈缓存中找到 (见第 3 章)。然而,有时主机想要向网络中 (或 VLAN) 的所有其他主机发送一个 frame,这被称为 broadcast。我们在第 4 章的 ARP 中看到过这一行为。
9.2.1 使用 Broadcast 地址
在 Ethernet 或类似的网络上,多播 MAC 地址高序字节的低序位被打开。以 16 进制表示时看起来像这样 01:00:00:00:00:00。我们可以认为 Ethernet 广播地址 ff:ff:ff:ff:ff:ff 是 Ethernet 多播地址的一个特例。回顾第 2 章,在 IPv4 中,每个子网都有一个本地 subnet-directed 广播地址,该地址的主机部分全部为 1,特殊的地址 255.255.255.255 对应于本地网络 (也被称为 “有限制的”) 的广播。
9.2.1.1 示例
在 Linux 中,关联每个接口的 IPv4 subnet-directed 广播地址能使用 ifconfig 命令找到。期显示如下:
这里,地址 10.0.0.127 是 eth0 设备关联的网络上使用的 (subnet-directed) 广播地址。该地址通过取出网络前缀 (10.0.0.0/25) 并使用 32 - 25 = 7 位的 1 与地址的主机部分结合形成:10.0.0.0 OR 0.0.0.127 = 10.0.0.127。一些系统提供一个简单的工具 ipcalc 来执行该计算。
为了了解广播的工作如何简单,我们可以使用 ping 程序向广播地址 10.0.0.127 发送一个 ICMPv4 Echo Request 消息:
我们在第 8 章提到这种类型的广播,所有在本地 LAN (或 VLAN) 上的主机都会受到影响。这里我们收到 3 个来自网站上其他主机的回复,且 ping 程序提示较发出的请求数量收到了更多的响应 (DUP! 指示)。
Echo Request 消息被发往地址 10.0.0.127。IPv4 实现通过咨询本地路由表中的信息确定它是一个 subnet-directed 广播地址,它使用链接层广播地址 ff:ff:ff:ff:ff:ff 发送该消息,所以不需要 ARP 请求来位每个目的地确认 MAC 地址。事实上,发送方在主机响应前并不知道什么主机会响应。它仅知道 10.0.0.127 是一个广播地址,因此它在发送时应当使用链接层广播地址。源地址在链接层和 IP 层完全为常规的单播;多播地址仅用于目的地址。
在这个特殊的例子中,每个生成的响应都被定向到 10.0.0.13,源发送方的单播地址,且每个响应都包含响应方的 IPv4 地址:10.0.0.6,10.0.0.113,和 10.0.0.120。这是一个简单的例子,但其包含的原理很普遍:广播寻址 (和多播寻址) 能被用于发现还不知道的系统和服务。在这个例子中,广播 ping 请求发现了 3 个愿意响应广播 Echo Request 消息的主机。
9.2.2 发送广播数据报
通常来说,使用广播的应用使用 UDP 协议 (或 ICMPv4 协议) 并调用一系列普通的 API 调用来发送流量。唯一的例外是何时进行 APIs 调用,一些操作系统使用一个特殊的 flag (SO_BROADCAST) 来表示应用真的打算发送广播数据报。例如,在 Linux 中,在尝试执行广播 ping 时不使用 -b flag 会导致下述输出:
造成该错误的原因是仅当使用 -b 选项时才会向 API 提供 SO_BROADCAST flag。这帮助避免意外的产生广播流量,可能会暂时拥塞网络。
为了确定使用哪个接口进行广播,IPv4 转发表 (这里称其为 “路由表”) 被咨询。下述例子是一个 Windows Vista 路由表,展示了接口列表和广播相关的路由信息。
输出的第一部分展示了 7 个不同的网络接口,可能被用于携带网络流量。第一个是虚拟环回接口,下一个是 Wi-Fi 无线接口,第三个是有线 Ethernet 接口 (连接被断开),第四个是另一个环回接口,接下来的三个被用作非标准的 Intra-Site Automatic Tunnel Addressing Protocol (ISATAP) [RFC5214] [RFC5579]。ISATAP 被用于支持被 IPv4 网络分离的 IPv6 主机。
移动到路由表,我们可以看到有 7 个条目能被用于确定广播流量应当被发送到哪。第一个条目是默认路由 (掩码为 0.0.0.0),所以它匹配任何目的地。它能被执行本地网络之外的广播使用,如果这样的设施启用的话。这种类型的定向广播,会传输到本地网络之外,通常被路由器禁用以避免一些安全问题,如 [RFC2644] 所述。
接下来的三个条目是定向的子网广播地址,关联的三个接口的 IPv4 地址分别是 10.0.0.57,127.0.0.1,和 169.254.57.240,后两个是软件环回地址。这些条目展示了 Windows 如何表达一个定向的子网广播路由,将网络前缀与主机部分所有位全为 1 相结合作为目的地址,一个 /32 或 255.255.255.255 子网掩码。Gateway 列表示 On-link,则流量使用在 Interface 列标识的接口上直接递交的方式递交 (见第 5 章)。在这些场景中,对于每一个定向子网广播地址而言不会有一个以上的匹配,所以 Metric 不被参考。
最后三个条目是用于有限制的广播地址,255.255.255.255,的路由条目。某种程度上来说,这一地址与多播地址表现类似。因此,应当使用哪个接口来发送目的地为有限广播地址的流量并不是显然的。
总之,对有限广播地址的外出流量的方式由操作系统指定。大部分操作系统选择一个能广播的接口用于发送这样的流量。Linux 和 FreeBSD 就是这样。FreeBSD 实际上将有限广播地址转换为 “主要的” (第一个配置的) subnet-directed 广播地址,虽然应用可以使用 IP_ONESBCAST API 选项。例如,Windows 的不同版本行为不同。直到 Windows 2000,有限广播都在多个接口上转发。Windows XP 和之后的版本,默认行为是发送到单个接口上。在本例中,对该流量可能有多个匹配的路由,因此使用度量值最低的条目 (接口 10.0.0.57)。
9.3 Multicast
为了减少广播中涉及的开销,考虑仅向感兴趣的接收方发送流量。这被称为 multicasting。基本上,这可以通过让发送方指定接收方或让接收方单独指定它们的兴趣点来实现。网络负责仅向有意向/感兴趣的接收方发送流量。实现多播较广播更具挑战性,因为 multicast state (信息) 必须由主机或路由器维护,以知晓某个用户对哪些流量感兴趣。在多播的 TCP/IP 模型中,接收方通过指定多播地址和可选的源列表来指定它们期望接收的感兴趣的流量。该信息作为路由器或主机内的 soft state (见第 4 章),意味着它们必须被频繁更新,或它们将超时并被删除。当这种情况发生时,多播流量的递交要么停止,要么恢复为广播。
广播的低效率不仅仅发生在广域网,也发生在局域网和企业网,只是广域网上尤为严重。每个能到达相同的 LAN 或 VLAN 的主机必须处理相同的广播包。IP 多播提供一种更有效率的方法来执行相同的任务类型。如果能合适的使用 IP 多播,只有通讯中涉及的主机才需要处理相同的包,流量只在那些需要使用它的链接上携带,在任何这样的链接上的任何多播数据报都只有一个拷贝。为了使多播工作,通讯中涉及的应用需要一种机制来通知它们的协议实现它们的期望。主机软件能安排接收匹配应用标准的包。
IP 多播起初使用的设计基于在链接层网络 (例如 Ethernet) 中使用的组寻址的工作方式。在该方法中,每个站选择它愿意接受流量的组地址,与发送者无关。该方法有时也被称为 any-source multicast (ASM) 因为它对发送方的身份不敏感。随着 IP 多播的发展,一个可选的对发送方身份敏感的方式被称为 source-specific multicast (SSM) [RFC4607],允许 end station 显式地包含或不包含从一组特定的发送方集合发送到一个多播组的流量。SSM 服务模型较 ASM 更易实现,主要因为在广域多播中确定单个源的位置较确定多个源的位置更简单。然而,在局域网中,设计支持 ASM 或 SSM 的大部分机制是相同的,所以我们将它们放到一起看待,并且解释几个重要的不同点。我们从研究 IP 多播流量如何在支持多播的 IEEE LAN 技术上使用 MAC 层多播地址开始。
9.3.1 转换 IP 多播地址为 802 MAC/Ethernet 地址
当在 Ethernet-like 网络中使用单播地址时,ARP (见第 4 章) 通常用于确定所给 IP 地址的本地目的地的 MAC 地址。在 IPv6 中,ND 扮演类似的角色 (见第 8 章)。当我们早先研究广播时,我们注意到有一个熟知的广播地址能被用于到达所有在 LAN 或 VLAN 上的站。当我们期望发送发送多播流量时,什么链接层地址应该被放到链接层 frame 上的目的 MAC 地址上?理论上,我们不应该使用协议消息来确定合适的 MAC 地址,而应该简单地直接映射 IP 多播地址到对应地 MAC 地址上。为了明白这种映射是如何完成的,我们将专注于 IEEE 802 网络,特别是 Ethernet 和 Wi-Fi。这些网络是使用 IP 多播的最常见的网络类型。我们首先讨论在 IPv4 中映射如何工作,然后转移到 IPv6 中稍有些不同的方法。
为了高效的在链接层网络中携带 IP 多播,IP 层的包和地址与链接层的 frame 之间应当有一个一对一映射。IANA 拥有 IEEE Organizationally Unique Identifier (简写为 OUI,或更加非正式的 Ethernet 地址前缀) 00:00:5e。有了它,IANA 被授予使用起始于 01:00:5e 组(多播) MAC 地址和起始于 00:00:5e 的单播地址。这一前缀被用作 Ethernet 地址的高序 24 位,意味着该地址块包含从 00:00:5e:00:00:00 到 00:00:5e:ff:ff:ff 的单播地址,和从 01:00:5e:00:00:00 到 01:00:5e:ff:ff:ff 的组地址。除 IANA 外,其他组织也拥有地址块,但只用 IANA 将其部分地址空间用作 IP 多播。IANA 分配一半的组块用于识别 在 IEEE 802 LANs 上的 IPv4 多播流量。这意味着对应于 IPv4 多播的 Ethernet 地址的范围从 01:00:5e:00:00:00 到 01:00:5e:7f:ff:ff。
注意
我们这里使用的符号使用 Internet 标准位序作为出现在内存中的位序。大部分程序员和系统管理员也是这样处理的。IEEE 文档使用位的传输顺序。
IPv4 地址到对应的 IEEE 802 风格的链接层地址的映射如图 9-2 所示:
回顾第二章,所有的 IPv4 多播地址都包含在地址空间 224.0.0.0 到 239.255.255.255 (被称为 D 类网址)。所有的这些地址在高序位共享相同的 4 位序列 1110。因此有 32 - 4 = 28 位能用于编码 2^28 = 268,435,456 个多播 IPv4 地址 (也被称为组 IDs) 的整个地址空间。对于 IPv4,IANA 分配它的组地址的一半用于支持 IPv4 多播意味着所有 268,435,456 个 IPv4 多播组 IDs 需要被映射到仅包含 2^23 = 8,388,608 个唯一条目的链接层地址空间。映射因此是 nonunique 的。即,超过一个 IPv4 组 ID 被映射到相同的 MAC 层组地址。尤其是, 2^28/2^23 = 2^5 = 32 个不同的 IPv4 多播组 IDs 被映射到一个组地址。例如,多播地址 224.128.64.32 (16 进制表示为 e0.80.40.20) 和 224.0.64.32 (16 进制表示为 e0.00.40.20) 被映射到相同的 Ethernet 地址 01:00:5e:00:40:20。
对 IPv6,16 位 OUI 16 进制表示的前缀是 33:33。这意味着 IPv6 地址至少有 32 位能被用于形成链接层地址。因此,任何以相同的 32 位结尾的地址都被映射到相同的 MAC 地址 (见图 9-3)。鉴于所有的 IPv6 多播地址都以 ff 开始,随后的 8 位被用于 flag 和 scope 信息,还剩下 128 - 16 = 112 位来表示 2^112 个组。因此,用于编码这些组的 32 位的 MAC 层地址,有 2^112/2^32 = 2^80 个组被映射到相同的 MAC 地址。
9.3.2 示例
在早先的例子中,我们使用子网广播地址确定所有响应广播 ICMPv4 Echo Request 消息的本地局域网中的主机。这里,因为我们能使用多播地址来确定提供特定服务的主机,我们能向响应 Multicast DNS (mDNS) 地址 224.0.0.251 的主机发送一个 ICMPv4 echo request。
这里主机 10.0.0.2,10.0.0.11,10.0.0.120 都进行响应,表示它们都订阅了 mDNS 组。
对于 IPv6,我们能使用 ICMPv6 Echo Request 消息执行类似的操作:
注意这个例子中,我们提供一个外出接口作为 ping6 程序的输入。这允许程序在 Windows XP 中选择合适的外出 IPv6 地址。正如我们在图 9-4 中所见到的,选择的地址是关联 eth0 设备的本地链接地址。
包被标识为 ICMPv6 Echo Request/Reply 消息,其 Identifier 字段被设置为 0x1d47,Sequence Number 字段被设置为 1。源 IPv6 地址在所有情况下都是本地链接的。请求的目的地址是多播地址 ff02::fb,它被映射到 MAC 地址 33:33:00:00:00:fb。Echo Reply 消息被直接发送到本地链接的 IPv6 单播地址,fe80:217:f2ff:fee7:6d91。注意 Echo Reply 消息的发送方安排使用相同域的源 IPv6 地址 (见第 5 章关于源地址选择的讨论,比较图 9-4 和图 5-16)。
9.3.3 发送多播数据报
当发送任何 IP 包时,必须决定使用哪个源地址和接口。对 IPv6 来说尤是如此,每个接口有多个地址十分正常。为了确定源地址和接口,我们可以查看主机中的转发表。无论在 Windows 还是 Linux 上,netstat 命令都能使用。下述是 Windows Vista 上的 IPv4 和 IPv6 路由表的输出:
从该表中我们能看到 IPv4 流量的默认流量使用接口 10.0.0.57 流向 10.0.0.1。虽然这确实匹配多播流量,但是还有其他更具体的条目。224.0.0.0/4 条目 (子网掩码为 240:0:0:0) 表示有三个不同的接口能携带外出的多播流量。有最低 metric 的接口 (10.0.0.57, metric 为 281) 是最偏向使用的,所以使用它除非应用指定了其他接口。对于 IPv6 来说,所有的多播地址起始于 ff,没有广播地址,所以接口 1,9,和 10 都能被使用。接口 9 (恰巧与 IPv4 使用的接口相同,也是 IPv6 单播流量的默认接口) 有最低的 metric。表明接口持有哪个 IP 地址额外的信息能使用 Windows 命令 ipconfig /all 确定。
Linux 上的输出不同的协议族 (例如 IPv4 和 IPv6) 有所区别。对 netstat 使用不同的参数来表示对哪个版本的 IP 协议感兴趣。对 IPv4 来说,没有什么好展示的,因为没有特殊的用于多播的条目;传统的默认路由处理多播流量。对于 IPv6,我们看到下述内容:
在这种情况下,没有直接的"下一跳",所以未指定的地址 :: 在表中被列出,但是我们可以看到外出的接口是 eth0。Flags 列仅包含 U,表示改路由是可用的,但是缺少 G flag 表示它是一个链接上的路由,不需要转发到一个路由器上。
9.3.4 接收多播数据报
多播的基本概念是进程在主机的某接口上 joining 或 leaving 一个或多个多播地址。(我们使用术语 process 表示正在由操作系统执行的程序,通常代表用户。) 所给接口上的多播组中的成员是动态的,它随着进程加入或离开多播组动态变化。除了加入和离开多播组,如果进程期望指定它关心或不关心的源,则需要提供额外的接口。这些是任何支持多播的主机需要的部分 API。我们使用限定符 “接口” 因为组中的成员与一个接口向关联。进程可以在多个接口上加入同一个组,也可以使用同一个接口加入多个组,或其任何组合。
9.3.4.1 示例
可以使用操作系统特定的命令确定每个接口上使用的多播组。Windows 中,命令是 netsh 包的一部分。对于 IPv6 来说,如下 (对于 IPv4,使用 ip 替换 ipv6):
这里我们能看到 IPv6 的每个接口使用几个多播地址。第一个接口是环回,本地接口。在它上面使用的唯一的多播组是 link-local scoped 的 Simple Service Discovery Protocol (SSDP) 多播地址,我们在第 7 章中见到了它。
Note
SSDP 在一个 (过期的) Internet 草案中描述。SSDP 也运行在 IPv4 上,使用地址 239.255.255.250 和 UDP 端口 1900。
在另一个网络接口中,地址 ff01::1 (node-local All Nodes address) 和 ff02::1 (link-local All Nodes address) 显示所有节点的连接,ff02::c 显示 SSDP 的使用。下一个地址, ff02::1::3 用于支持 LLMNR,一个早先提过的本地多播名解析系统,我们在第 11 章讨论关于它的更多细节。最终,地址 ff02::1:ffdc:fc85 是本节点的 Solicited-Node 多播地址,用于 IPv6 ND。回顾 IPv6,使用 ICMPv6 ND 消息确定邻居的 MAC 地址,而 IPv4 中使用 ARP 机制。
在 Linux 中,netstat 命令显示 IP 组成员:
该命令的输出信息包括多个接口的 join 信息,包括 IPv4 和 IPv6 的。在本例中,我们看到 224.0.0.1 (All Hosts) 在 Ethernet 接口 (eth1) 和本地环回接口 (lo) 上都有。我们也看到 link-local scope All Nodes 绑定每个接口。最后,Solicited-Node address 是 ff02::1:ff2a:1988
Note
使用 IP 多播时,进程可能在没有加入该多播组的情况下向其发送消息。更常见的是,进程在一个或多个接口上加入同一个多播组。在 socket API 中有一个特殊的选项 (IP_MULTICAST_LOOP),用于改变多播流量在处于相同主机,是相同的多播组的成员,且使用相同的接口加入多播组的进程中处理的方式。在 UNIX 中,该选项应用于发送路径,意味着如果该选项启用,其他在相同主机的进程接收多播数据报,即使它们禁用该选项。相反,在 Windows 上,改选项应用于接收路径,意味着任何启用该选项的进程接收来自相同主机上其他应用的多播流量,即使发送流量的应用禁用该选项。
9.3.5 主机地址过滤
为了理解操作系统进程如何处理从程序加入的多播数据组中接收到的多播数据报,回顾第三章发生在每个主机的网络接口卡 (NIC) 上的 filtering,每一次一个 frame 因为可能被接受而呈现给它 (e.g.,通过一个 bridge 或 switch)。图 9-5 展示了这是如何发生的。
在一个典型的交换 Ethernet 环境中,广播和多播 frame 在 VLAN 中的所有网段复制,沿着交换机之间形成的生成树。这样的 frame 被递交到每个主机的 NIC 上,NIC 检查 frame 的正确性 (通过 CRC),并决定是否接收该 frame 并递交它到设备驱动和网络栈上。通常,NIC 仅接收哪些目的地址是其接口的硬件地址或广播地址的 frame。然而,当设计多播 frame 时,情况则变得有些复杂。
NICs 通常有两种类型。一种类型执行基于其主机软件感兴趣的多播硬件地址的 hash 值得过滤,这意味着因为哈希碰撞,一些不想要的 frame 总是能通过 NIC。另一种类型监听一个多播地址的有限表,意味着如果主机需要接收目的地为比表中满足的多播地址更多的 frame,NIC 进入 “multicast-promiscuous” 模式,在这种情况下所有的多播流量都会给到主机软件。因此,两种类型的接口需要设备驱动或更高层的软件执行对接收到的 frame 的检查。即使接口执行完美的多播过滤 (基于 48 位硬件地址),因为从多播 IPv4 和多播 IPv6 地址映射到 48 位的硬件地址并不是唯一的,依然需要过滤。尽管有不完美的地址映射和硬件过滤,多播依然比广播效率更高。
对于支持多条目地址表的 NICs 来说,每个接收的 frame 的目的地址与该表比较,如果地址在表中找到,该 frame 由设备驱动接收并处理。该表的条目由设备驱动软件结合其他层的协议栈 (比如 IPv4 和 IPv6 实现) 管理。这种过滤类型的另一种实现是对目的地址应用 hash 函数,形成一个二进制 index 到一个 (更小的) 二进制数组。当数组种索引条目包含一个 1 位,对应的地址被认为是可接受的,frame 被进一步处理。这种方法能节省 NIC 中的内存,但是因为 hash 函数的冲突,一些帧可能被认为是可接受的,但事实上它们不应该被接受。这不是一个致命的问题,因为更高层的栈也执行过滤,在不应该丢弃时,没有一个 frame 会被丢弃 (i.e.,没有 false negatives,有 false positives)。
Node
NIC 的不同功能因厂商而异。例如,Intel 82583V Ethernet controller 包含一个 16-entry exact match table (unicast 或 multicast),一个用于多播目的地址的 4096 位的 hash 过滤器,除了基于至多 4096 VLAN tags 的过滤,还支持混杂接收和混杂多播接收。
一旦 NIC 硬件证实 frame 能接受 (i.e.,CRC 是正确的,VLAN tags 匹配,目的 MAC 地址匹配一个或多个 NIC 表中的地址条目),frame 被传递到设备驱动器,在那里执行额外的过滤。首先,frame 类型必须指定一个支持的协议类型 (e.g.,IPv4,IPv6,ARP,等)。其次,额外的多播过滤器必须可能被执行,用于检查是否主机属于寻址多播组 (由目的 IP 地址指示)。对于 NICs 来说,能生成一个 false positives 是必要的。
设备驱动器随后将 frame 传递给下一层,例如 IP,如果 frame 类型指定一个 IP datagram。IP 执行进一步过滤,基于源地址和目的 IP 地址,如果一起正常将数据报传递给下一层 (例如,TCP 或 UDP)。每一次 UDP 从 IP 接收到一个数据报,它基于目的端口号执行过滤,有时也使用源端口号。如果当前没有进程使用该目的端口号,数据报被丢弃且通常生成一个 ICMPv4 或 ICMPv6 Port Unreachable 消息。(TCP 基于它的端口号执行类似的过滤。) 如果 UDP 数据报发现有 checksum 错误,UDP 静默地丢弃它。
开发多播寻址特性背后最主要的动机是避免广播的开销。假设有一个应用被设计使用 UDP 广播。如果在网络上 (或 VLAN 上) 有 50 个主机,但是仅有 20 参与应用,每次 20 个主机的其中之一发送一个 UDP 广播,其他 30 个非参与方的主机必须处理广播,直到 UDP 层的所有路径,直到 UDP 数据报被丢弃。UDP 数据报因为目的端口号未被使用而被这 30 个主机丢弃。多播的目的就是减少对该应用不感兴趣的主机上的这种负载。使用多播,主机加入一个或多个多播组。如果可能的话,NIC 会被告知主机属于哪个多播组,只有那些关联 IP 层多播组的多播 frames 被允许通过 NIC 的过滤器。所有的这些机制减少了主机上的开销,但是带来了管理多播地址和组成员的额外的复杂度。
9.4 Internet Group Management Protocol (IGMP) 和 Multicast Listener Discovery Protocol (MLD)
到目前为止,我们已经讨论了从主机视角来看多播数据报如何传输,过滤,和接收。当多播数据报在广域网或跨公司的多个子网转发时,我们需要一个多多个多播路由器启用 multicast routing。这使情况相当复杂,因为多播路由器需要知道哪个主机对哪个多播组感兴趣,以安排多播流量进行合适的递交。它们也执行一个特殊的过程,被称为 Reverse Path Forwarding (RPF) 检查。这一过程执行对到达的多播数据报的源地址的路由查找。只有当路由的外出接口匹配数据报到达的接口时,数据报才会被转发。PRF 对于避免多播循环十分重要。多播路由在很大程度上独立于 IP 路由器提供的普通的单播路由。然而,IPv6 ND 协议 (见第 8 章) 需要一些多播路由的功能才能正常运行。
被用于允许多播路由器知道附近的主机对哪个组感兴趣的两个主要的协议是:Internet Group Management Protocol (IGMP),被 IPv4 使用,和 Multicast Listener Discovery(MLD) 协议,被 IPv4 使用。两种协议都被用于支持多播的路由器和主机,且它们十分相似。这些协议使在 LAN (VLAN) 上的多播路由器知道某个主机当前属于哪个多播组。这一信息被路由器所需要,这样它们就知道某个多播数据报应当被转发给哪个接口。在大部分情况下,多播路由器仅需要知道至少一个监听的主机通过特定的接口是可达的,因为链接层路由寻址 (假设它支持) 允许多播路由器发送链接层多播 frame,该 frame 将被所有感兴趣的监听者接收。这允许多播路由器不需要对每个单独的主机上的接口保持追踪,该接口可能某特定组的多播流量感兴趣。
IGMP 随着时间的推移而发展,[RFC3376] 定义了版本 3。MLD 也在并行发展,它的当前版本 (2) 定义于 [RFC3810]。IGMPv3 和/或 MLDv2 需要用来支持 SSM。当每个多播组仅使用一个源时,如何限制这些协议的更多相关细节见[RFC4604]。
IGMP 的版本 1 是第一个常用的 IGMP 版本。版本 2 添加了更快的离开组的能力 (MLDv1 也支持)。IGMPv3 和 MLDv2 添加了选择多播流量的源的能力,它们在部署 SSM 时需要。IGMP 是用于 IPv4 的单独的协议,MLD 是 ICMPv6 的一部分 (见第 8 章)。
图 9-6 展示 IGMP(MLD) 如何在 IPv4(IPv6) 多播支持的路由器中被使用。这些路由器感兴趣的是查明哪个多播组对每个它附加的接口感兴趣。这些路由器需要这一信息以简单地在每个接口上广播出所有流量。
在图 9-6 中,我们能看到 IGMP(MLD) 查询如何通过多播路由器发送。它们被发送到 All Hosts 多播地址,224.0.0.1 (IGMP),或 All Nodes link-scope 多播地址,ff02::1(MLD),由每个实现 IP 多播的主机处理 (见 9.4.2 节中对 “特殊” 查询的例外情况)。成员报告的信息由组成员 (主机) 发送以响应该查询,但是也有可能以未经请求的方式从主机发送,期望通知多播路由器它们的组成员和/或感兴趣的特定源已经发生改变了。IGMPv3 报告被发送到 IGMPv3 支持的多播路由器地址 224.0.0.22。MLDv2 报告被发送到对应的 MLDv2 Listeners IPv6 多播地址 ff02::16。注意当多播路由器加入多播组时,多播路由器本身可能也是成员之一。
Note
在 IGMPv1 和 IGMPv2 中,在接收到一个查询后,主机不立刻响应,而是等待一个很短的随机数量的时间来看对相同的组是否有其他的主机响应。如果是这样,主机的响应被抑制 (不发送)。通过向请求中的组的多播地址发送报告完成这一工作。[RFC3376] 的附录 A 指出为何这一行为在 IGMPv3 中被移除。简而言之,多播路由器可能希望追踪单独的主机订阅,抑制在使用 IGMP snooping (见 9.4.7 节) 的桥接的 LANs 中工作的不是很好,处理抑制使协议的实现复杂化,IGMPv3 报告包含多个组的信息,使成功地抑制更不可能。注意 IGMPv3 和 MLDv2 都需要向后兼容早期版本,恢复为使用同一子网中检测到的旧的主机或路由器的旧版本协议消息。
IGMP 和 MLD 的封装见图 9-7。与 ICMP 类似,IGMP 被认为是 IP 层的一部分,IGMP 以 IPv4 数据报的形式发送。不像其他我们看过的协议那样,IGMP 使用固定的 TTL 1,所以包被限制于本地子网。IGMP 包也使用 IPv4 Router Alert 选项,且在 DS Field 使用 6-bit 的值 0x30 表示 Internetwork Control (CS6,见第 5 章)。在 IPv6 中,MLD 是 ICMPv6 的一部分,但是功能上 MLD 几乎与 IGMP 相同,所以我们在这里描述它 (我们在第 8 章描述 ICMPv6 时简单的描述了它的消息格式)。它的封装使用 IPv6 Hop-by-Hop 拓展 header 来告知 Router Alert 选项。在很多情况下,源列表为空。
IGMP 和 MLD 定义了两种协议处理规则:由组成员主机执行的规则和由多播路由器执行的规则。通常来说,成员主机的工作 (我们将其称之为 “组成员”) 为自动地报告多播组和源感兴趣内容的改变,以及响应周期性的查询。多播路由器发送查询,以确定在每个组所关联的链接上是否有任何感兴趣的内容存在。路由器也与广域网多播协议进行交互 (例如 PIM-SM 和 BIDIR-PIM) 以携带流量到感兴趣的主机或禁止流量流向不感兴趣的主机。关于更多关于这些协议的细节,见 [RFC4601] 和 [RFC 5015]。