SCTP在LINUX中的实现:代码结构

来源:互联网 发布:linux shell 变量 编辑:程序博客网 时间:2024/05/22 20:29

Linux中,SCTP是作为一个kernel模块编译加载的,代码主要是在net/sctp目录下。

1. 主要数据结构

1.1 endpoint

struct sctp_endpoint{

  struct list_head asocs;

……

}

在应用程序调用listen()之后,会创建一个endpoint结构。收到INIT CHUNK的时候,如果没有找到相应的endpoint,则association的建立请求会被拒绝。

1.2 association

struct sctp_association {

  struct sctp_ep_commonbase;

  ...

    struct {

  ...

  struct list_head transport_addr_list;

  ...

  }peer;

...

}

association结构保存了一条SCTP连接(association)的各种参数,以及对端(peer/path)的地址列表。

1.3 path

struct sctp_transport {

}

保存了peer/path的参数信息,即association结构中transport_addr_list链表中的各个节点。

2. SCTP状态机

linux中SCTP协议的实现是采用状态机的方式,状态机定义了各种“状态”下对各种“事件”的处理方法。

SCTP定义了以下状态:

•CLOSED
•COOKIE_WAIT
•COOKIE_ECHOED
•ESTABLISHED
•SHUTDOWN_PENDING
•SHUTDOWN_SENT
•SHUTDOWN_RECEIVED
•SHUTDOWN_ACK_SENT

事件有以下几类:

•SCTPuser primitive calls, e.g., [ASSOCIATE], [SHUTDOWN], [ABORT]
•Receptionof INIT, COOKIE ECHO, ABORT, SHUTDOWN, etc., control Chunks
•Sometimeout events

sm_statetable.c中,定义了以下状态机:

3. SCTP收包处理

在收到一个SCTP包之后,以CHUNK为单位,一个一个的处理。大致流程如下:

association建立起来之后,会加到一个hash表。在收到一个SCTP包的时候,通过关键字(源IP地址、目的IP地址、源SCTP端口号、目的SCTP端口号)匹配来查找对应的association。然后sctp_do_sm()函数会根据当前ASSOCIATION的状态以及CHUNK类型找到处理函数。

4. SCTP发包

发包流程如下:

5. SCTP查表的性能问题

在LINUX 4.5之前,是用association来组织hash表。由于同一条association的两端都可以用多个IP地址,因此只能用两端的端口号作为关键字来组织association的hash表。此时,在所有association的两端端口号都相同的情况下,所有association都会被加入到hash表的同一条链表上。这种情况下,在查表的时候,有可能要遍历比较所有的association。在收到INIT处理建立请求的时候尤其严重,必须得遍历所有association,判断是否已经存在相同的association。

在LINUX 4.5,不是把association加入hash表,而是把struct sctp_transport加入hash表。通过查transport来得到SCTP包所属的association。由于是以transport来组织hash表,因此对端IP地址(association中,每个对端IP地址有一个唯一的transport)、端口号都可以用来计算hash表的key(即hash数组的下标)。即使所有association的端口号都相同,由于对端IP地址不相同,也可以分散到hash表,基本上满足各种场景下的性能需求。