分类: 系统运维
2009-05-09 14:01:25
Sockets over infiniband devices
(By 宋贤广,欢迎转载,
出处 http://sxg.cublog.cn, http://blog.chinaunix.net/u/8754/showart_1923014.html)
当前有三种方法在infiniband device上跑socket应用:IPoIB、WSD、SDP。
一、IPoIB
(适用于linux和windows平台)
IPoIB驱动程序将InfiniBand设备模拟成普通网卡,走传统的TCP/IP协议栈:
app -> socket api -> TCP/IP stack -> IPoIB -> Infiniband hardware
二、WSD
(适用于windows平台)
WSD架构是MS OS提供的一种利用硬件RDMA特性的机制,用于衔接socket应用和RDMA硬件,如下:
app -> Winsock -> Winsock Direct Socket Switch -> WSD Provider -> User access layer -> infiniband core -> infiniband hardware
使用WSD的方法很简单,安装WSD provider之后,运行socket应用即可。
三、SDP
(适用于linux和windows平台,以下为linux平台描述)
什么是SDP
Socket Direct Protocol,SDP enables existing socket based application to transparently utilize the InfiniBand capabilities and achieve superior performance。SDP是InfiniBand内核协议栈中的一个上层协议,它对上接socket系统调用,提供socket stream semantics,对下接IB逻辑,可充分利用InfiniBand的RDMA特性。
app -> socket api -> SDP -> RDMA -> Infiniband hardware
目前在linux平台,OpenFabircs出品的OFED中包含了SDP驱动,但是尚不支持IPv6,linux内核中的InfiniBand协议栈暂未将该协议包含在内。
SDP协议实现原理
SDP协议的实现跟IPv4、IPv6类似,走的基本上是一个路子。
以IPv6为例(net/ipv6/af_inet6.c):
首先是协议簇的定义:
static struct net_proto_family inet6_family_ops = {
.family = PF_INET6,
.create = inet6_create,
.owner = THIS_MODULE,
};
err = sock_register(&inet6_family_ops); ß 注册协议簇
当用户建立socket的时候,sfd = socket(AF_INET6, SOCK_STREAM, 0);就指示内核要用到IPv6协议簇了,
Socket调用的时候,inet6_create将用来创建内核sock数据结构。
然后是协议簇中的各种协议:
err = proto_register(&tcpv6_prot, 1); ß TCPv6
err = proto_register(&udpv6_prot, 1); ß UDPv6
err = proto_register(&udplitev6_prot, 1); ß UDPlite
err = proto_register(&rawv6_prot, 1); ß RAWv6
与各种协议相关联的是针对socket的各种操作,以TCPv6为例:
struct proto tcpv6_prot = {
.name = "TCPv6",
.close = tcp_close,
.connect = tcp_v6_connect,
.disconnect = tcp_disconnect,
.accept = inet_csk_accept,
.ioctl = tcp_ioctl,
.shutdown = tcp_shutdown,
.setsockopt = tcp_setsockopt,
.getsockopt = tcp_getsockopt,
.recvmsg = tcp_recvmsg,
……
};
用户空间的各种socket操作将都会映射到上述的协议关联函数。
在linux/include/socket.h中定义了协议簇号:
#define AF_INET 2 /* Internet IP Protocol */
#define AF_INET6 10 /* IP version 6 */
其中并未有SDP协议簇号,SDP协议簇号27,如下样子:
#define AF_INET_SDP 27
如下是SDP实现部分,可跟IPv6参考:
SDP协议簇定义:
static struct net_proto_family sdp_net_proto = {
.family = AF_INET_SDP,
.create = sdp_create_socket,
.owner = THIS_MODULE,
};
rc = sock_register(&sdp_net_proto);
SDP协议:
rc = proto_register(&sdp_proto, 1);
SDP协议关联的socket操作:
struct proto sdp_proto = {
.close = sdp_close,
.connect = sdp_connect,
.disconnect = sdp_disconnect,
.accept = sdp_accept,
.ioctl = sdp_ioctl,
.init = sdp_init_sock,
.shutdown = sdp_shutdown,
.setsockopt = sdp_setsockopt,
.getsockopt = sdp_getsockopt,
.sendmsg = sdp_sendmsg,
.recvmsg = sdp_recvmsg,
.name = "SDP",
…………
};
不同于IP协议上的这些操作是针对网卡,IB协议上的这些操作则是针对HCA设备,这些操作屏蔽了底层设备的差别,向用户展现统一的socket接口。
基于对SDP实现机制的了解,我们可以乐观的断定,为InfiniBand测试模块加上SDP的高速引擎将是一件很简单的事情,这一切都要得益于卓越的LINUX架构!
采用SDP编程
首先定义SDP协议簇号:
#define AF_INET_SDP 27
在创建socket的时候,将该协议簇号传入:
skfd = socket(AF_INET_SDP, SOCK_STREAM, IPPROTO_IP);
通过查看SDP驱动代码可以发现,第三个参数可以写IPPROTO_TCP或者IPPROTO_IP,二者无差别;另外两个参数必须是AF_INET_SDP和SOCK_STREAM。
接下来send、recv等等socket上的招数尽管使出来吧。
Windows平台上的SDP
OpenFabrics出品的WinOF中没有SDP协议,该协议的实现依赖于IB Verder。
如下是Mellanox公司的SDP示意图: