SCTP协议源码分析--多归属特性multi-homed(一)

来源:互联网 发布:cnc模拟仿真软件 编辑:程序博客网 时间:2024/06/01 10:13

SCTP协议有一个重要的特点,即Multi-homed(多归属),这是与TCP协议不同的显著地方之一,是对TCP协议的重大改进,充分利用了多条路由皆可承载数据流的特点,保证了物理网络级的冗余

Multi-homed SCTP的直接表现就是有多个transport(即通路path),即到对端多个IP地址的path(通路)。一般来说有一条primary transport(主通路),其它的就是alternate transport(备用通路)。

SCTP的每条path实际上就是一条路由,而SCTP查找路由是根据destination address(目标地址)来决定,所以path的管理依赖于OSI L3IP层)的路由缓存。而且,每条pathsource address(源端地址)由路由决定,所以多条pathsource address可能是本端的同一个IP address,尽管本端也许绑定了多个IP address

先来看看与多path密切相关的IP地址列表的管理。 


.    Manage address list


主要管理两个链表,即对端的peer_addr列表(实际上是path链表)和本地的bind_addr列表,都采用了内核的数据结构双向链表list_head。同时加上counter便于管理。这些地址表用双向链表list_head保存,而多个association却用哈希表,此处不详述。

1. 到对端的path链表

链表:asoc->peer.transport_addr_list

数量:asoc->peer.transport_count

path的对端IPassoc->peer.primary_addr

比如在函数sctp_seq_dump_remote_addrs中要打印对端的所有IP地址。

[cpp] view plain copy
  1.     list_for_each_entry(transport, &assoc->peer.transport_addr_list,  
  2.             transports) {  
  3.         addr = &transport->ipaddr;  
  4.         af = sctp_get_af_specific(addr->sa.sa_family);  
  5.         af->seq_dump_addr(seq, addr);  
  6.     }<span style="font-size: 18px;">  
  7. </span>  

管理链表的函数:sctp_assoc_add_peersctp_assoc_rm_peer

比如添加一个新的path到偶联的path链表:

[cpp] view plain copy
  1.     /* Add a transport address to an association.  */  
  2.     struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,  
  3.                        const union sctp_addr *addr,  
  4.                        const gfp_t gfp,  
  5.                        const int peer_state)  
  6.     {  
  7.     struct sctp_transport *peer;  
  8.     //。。。(略)  
  9.     peer = sctp_transport_new(net, addr, gfp);  
  10.     //。。。(略)  
  11.     /* Attach the remote transport to our asoc.  */  
  12.     list_add_tail(&peer->transports, &asoc->peer.transport_addr_list);  
  13.     asoc->peer.transport_count++;  
  14.   
  15.     /* If we do not yet have a primary path, set one.  */  
  16.     if (!asoc->peer.primary_path) {  
  17.         sctp_assoc_set_primary(asoc, peer);  
  18.         asoc->peer.retran_path = peer;  
  19.     }  
  20.     if (asoc->peer.active_path == asoc->peer.retran_path &&  
  21.         peer->state != SCTP_UNCONFIRMED) {  
  22.         asoc->peer.retran_path = peer;  
  23.     }  
  24.   
  25.     return peer;  
  26.     }<span style="font-size: 18px;">  
  27. </span>  

2. 本端绑定的addr_entry链表

链表:asoc->base.bind_addr.address_list

数量:asoc->base.bind_addr.address_count          //目前没有,可以考虑增加

path的本端IPasoc->peer.primary_path.saddr

比如,在获取路由函数sctp_v4_get_dst中,需遍历本端绑定地址链表:

[cpp] view plain copy
  1. bp = &asoc->base.bind_addr;  
  2. if (dst) {  
  3.     /* Walk through the bind address list and look for a bind 
  4.      * address that matches the source address of the returned dst. 
  5.      */  
  6.     sctp_v4_dst_saddr(&dst_saddr, fl4, htons(bp->port));  
  7.     rcu_read_lock();  
  8.     list_for_each_entry_rcu(laddr, &bp->address_list, list) {  
  9.         if (!laddr->valid || (laddr->state == SCTP_ADDR_DEL) ||  
  10.             (laddr->state != SCTP_ADDR_SRC &&  
  11.             !asoc->src_out_of_asoc_ok))  
  12.             continue;  
  13.         if (sctp_v4_cmp_addr(&dst_saddr, &laddr->a))  
  14.             goto out_unlock;  
  15.     }  
  16.     rcu_read_unlock();  
  17.        //。。。(略)  
  18. }  


再比如sctp_seq_dump_local_addrs中要打印本端地址列表,而且会标明primary path

[cpp] view plain copy
  1. if (epb->type == SCTP_EP_TYPE_ASSOCIATION) {  
  2.     asoc = sctp_assoc(epb);  
  3.     peer = asoc->peer.primary_path;  
  4.     primary = &peer->saddr;  
  5. }  
  6. list_for_each_entry(laddr, &epb->bind_addr.address_list, list) {  
  7.     addr = &laddr->a;  
  8.     af = sctp_get_af_specific(addr->sa.sa_family);  
  9.     if (primary && af->cmp_addr(addr, primary)) {  
  10.         seq_printf(seq, "*");  
  11.     }  
  12.     af->seq_dump_addr(seq, addr);           //printk  
  13. }  
原创粉丝点击