Chinaunix首页 | 论坛 | 认证专区 | 博客
  • 博客访问: 167993
  • 博文数量: 23
  • 博客积分: 186
  • 博客等级: 入伍新兵
  • 技术积分: 1051
  • 用 户 组: 普通用户
  • 注册时间: 2012-01-12 19:54
文章存档

2018年(1)

2013年(13)

2012年(9)

微信关注

IT168企业级官微



微信号:IT168qiye



系统架构师大会



微信号:SACC2013

分类: LINUX

[原创文章不易,转载请注明出处链接]


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地址。

点击(此处)折叠或打开

  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. }


管理链表的函数:sctp_assoc_add_peersctp_assoc_rm_peer

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

点击(此处)折叠或打开

  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.        /* If we do not yet have a primary path, set one. */
  15.        if (!asoc->peer.primary_path) {
  16.               sctp_assoc_set_primary(asoc, peer);
  17.               asoc->peer.retran_path = peer;
  18.        }
  19.        if (asoc->peer.active_path == asoc->peer.retran_path &&
  20.            peer->state != SCTP_UNCONFIRMED) {
  21.               asoc->peer.retran_path = peer;
  22.        }

  23.        return peer;
  24. }



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中,需遍历本端绑定地址链表:

点击(此处)折叠或打开

  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
点击(此处)折叠或打开

  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.        }


下一篇继续看看path&assoc的断开和恢复管理。 


阅读(6545) | 评论(6) | 转发(2) |
给主人留下些什么吧!~~

r_luo2014-05-27 22:29:07

yunwu753:博主您好,我最近刚开始研究sctp的内核源码,我之前从未接触过这方面的东西,所以至今还一踏糊涂。不知您在研究的时候,用的工具是什么?如果能推荐一些学习资料的话,那真的是不胜感激!

应用层面有开源项目lksctp提供的library和DEMO,从这里入手可以较快实践。内核层面有一个DEBUG配置开关可以打开,不过log太多,需要分级改造或采用过滤分析;proc fs是一个不错的控制和观察sctp行为的视窗。当然,你还得要一份rfc2960或rfc4960协议文档。希望这些对你有用。

回复 | 举报

yunwu7532014-05-13 15:53:27

博主您好,我最近刚开始研究sctp的内核源码,我之前从未接触过这方面的东西,所以至今还一踏糊涂。不知您在研究的时候,用的工具是什么?如果能推荐一些学习资料的话,那真的是不胜感激!

评论热议
请登录后评论。

登录 注册