现在的位置: 首页 > 综合 > 正文

linux socket 绑定机制的研究

2013年02月03日 ⁄ 综合 ⁄ 共 1696字 ⁄ 字号 评论关闭

linux socket 绑定机制的研究

 

 

 

1.    概述:

在多 link 环境中,如何保证数据在正确的 link 上传输是一个棘手的问题。

本文主要分析 linux socket 绑定机制的实现,从而帮助开发人员更好的了解 socket 绑定的本质。

2.    linux kernel 提供给 user space 的接口

linux 提供一个新的 setsockopt() 选项 SO_BINDTODEVICE 作为 user space 的接口。

 

源码:net/core/sock.c:

在编译内核的时候,必须打开 CONFIG_NETDEVICES 选项,否则 SO_BINDTODEVICE 不起作用;

struct sock 结构中,专门有一个域 bound_dev_if;在调用 setsockopt() 后,bound_dev_if 被设置为所绑定的 interface index bound_dev_if 将会影响后续的数据包的发送和接收。

sk->bound_dev_if = dev->ifindex;

 

socket 绑定之所以能保证数据在所绑定的 interface 上传输,是因为 linux 在路由选择的时候,需要考虑 socket 所绑定的interface(也就是 sock->bound_dev_if)。下面从发送和接收数据两个方面来分析这种影响:

 

3.    socket 绑定对发送数据包的影响

源码:include/net/route.h

              net/ipv4/route.c

 

影响1

任何传输层协议,最终都要走到 ip_route_output() 进行路由选择,linux 是根据 socket 的源地址、目的地址、TOS值以及所绑定的 interface(如果有)作为关键字进行路由查找的。因此,在 socket 绑定情况下,如果一个路由项的源地址、目的地址、TOS 都和 socket 匹配,但是 out interface socket 所绑定的 interface 不一致,那么该路由项也不会被选中。

这也正是绑定的意义所在:必须保证数据包被路由到所绑定的 interface 上。

影响2

socket 绑定对发送数据的路由选择的另一个重要影响是:即使在 route cache route table 中都查不到路由,该数据包仍然会被送到所绑定的 interface 上。具体代码在ip_route_output_slow() 中。

 

4.    socket 绑定对接收数据包的影响

源码:net/ipv4/ip_input.c

       Net/ipv4/tcp_ipv4.c

       Net/ipv4/udp.c

 

接收数据包需要在 ip_route_input() 中进行路由选择,socket 绑定对此阶段没有影响。

路由以后,到本地的包走到ip_local_deliver()ip_local_deliver_finish(),此后,根据传输层协议的不同,分别走到tcp_v4_rcv() udp_rcv()

这两个函数都首先需要找到该数据包所对应的 struct sock 结构:

       tcp_v4_rcv()  在查找sock 时,会严格检查 sock bound_dev_if 与数据包进来的 interface 是否一致,如果两者不一致,则该 sock 不会被匹配。

udp_rcv() 在查找 sock 时,也检查这两个值是否匹配(具体代码在udp_v4_lookup_longway()中),但是就算不匹配,也可能接收这个包,原因是 UDP 相对于 TCP 来说,在一致性检查上没有那么严格。它的策略是:在源地址、目的地址、目的端口、绑定的 interface 四项检查中,寻找匹配程度最高的那个 sock

 

5.    socket 绑定使用时候的注意事项

不要将一个 socket 绑定到多个不同的 interface 上,这样会导致不可预料的后果。因为当你第一次绑定到一个interface 上发送数据后,在 route cache 中将会保存一个路由项,如果此时将该 socket 绑定到另一个 interface,那么从前一个 interface 上回来的数据包在路由的时候,就可能查不到对应的 socket ,从而被丢弃。

 

 

抱歉!评论已关闭.