注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

Tsecer的回音岛

Tsecer的博客

 
 
 

日志

 
 

内核报文转forward发及neighbour系统  

2011-08-08 22:55:31|  分类: 计算机网络 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

一、说明

这个连个模块总体来首关联性不是很明显,但是这次比较琐碎,所以就放在一起了,大家就将就着看看吧。

二、报文转发

对于ip报文的接受流程

ip_route_input_common--->>>ip_route_input_slow

 /*
  * Now we are ready to route packet.
  */
 err = fib_lookup(net, &fl, &res);首先从路由表中查找这个路由项
 if (err != 0) {
  if (!IN_DEV_FORWARD(in_dev)) 这里判断设备是否使能了报文转发功能
   goto e_hostunreach;
  goto no_route;
 }

……

 if (res.type == RTN_LOCAL) {这里的RTN_LOCAL标志位对于这个转发还是本地上传具有重要的意义
  err = fib_validate_source(saddr, daddr, tos,
       net->loopback_dev->ifindex,
       dev, &spec_dst, &itag, skb->mark);
  if (err < 0)
   goto martian_source_keep_err;
  if (err)
   flags |= RTCF_DIRECTSRC;
  spec_dst = daddr;
  goto local_input;
 }

在local_input中,对于报文的读取执行的操作为

 dev_hold(rth->dst.dev);
 rth->idev = in_dev_get(rth->dst.dev);
 rth->rt_gateway = daddr;
 rth->rt_spec_dst= spec_dst;
 rth->dst.input= ip_local_deliver;

这里判断这个地址是否是本机地址,如果是本机地址,着进入到local_input进行处理,否则继续下面的处理:

err = ip_mkroute_input(skb, &res, &fl, in_dev, daddr, saddr, tos);---》》》__mkroute_input

 rth->dst.input = ip_forward;
 rth->dst.output = ip_output;

这里设置了转发函数

三、RTN_LOCAL的设置

fib_inetaddr_event---》》》

 case NETDEV_UP:
  fib_add_ifaddr(ifa);---》》》

 fib_magic(RTM_NEWROUTE, RTN_LOCAL, addr, 32, prim);这里的addr就是本地网卡设置的网络地址。-------》》》

static void fib_magic(int cmd, int type, __be32 dst, int dst_len, struct in_ifaddr *ifa)
{
 struct net *net = dev_net(ifa->ifa_dev->dev);
 struct fib_table *tb;
 struct fib_config cfg = {
  .fc_protocol = RTPROT_KERNEL,
  .fc_type = type,

---》》》fib_table_insert

 new_fa->fa_type = cfg->fc_type;
当执行fib_lookup的时候,执行的命令为:fib_table_lookup---》》fib_semantic_match

 res->type = fa->fa_type;
从而将刚才设置的RTN_LOCAL传递给了res,进而判断是一个本地地址,执行ip_local_deliver函数进行转发。

转发项的设置为位置位于 /proc/sys/net/ipv4/ip_forward

这个需要使能为1,默认值为零。

四、邻居子系统

1、需要性

对于不同的L2层,都需要一种知道那些和自己相连的科通讯主机,这个可能包括DECnet以及ND(neighbour Discovery)等不同的算法和介质来进行邻居的发现,其中的ARP只是邻居发现的一种协议方法,同时还存在其他的方法。

在路由表中,一个邻居一般式通过dst_entry来实现,这个结构中定义了input和output接口,这些接口的主语都是host,所以是host output to dst或者host input from dst这样的意义。一个dst可以看成一个远端主机在本地的一个成像(IMAGE),也即是这个客观存在在我们主机上的印象或者说倒影

当dst处于不同的状态的时候,对应的发送操作也可以做不同的出来。也就是一个NUD,这个状态可以决定我们可以如何进行L2报文的生成。

在ip_finish_output2函数中:

 if (dst->hh)
  return neigh_hh_output(dst->hh, skb);---》》》

static inline int neigh_hh_output(struct hh_cache *hh, struct sk_buff *skb)
{
 unsigned seq;
 int hh_len;

 do {
  int hh_alen;

  seq = read_seqbegin(&hh->hh_lock);
  hh_len = hh->hh_len;
  hh_alen = HH_DATA_ALIGN(hh_len);
  memcpy(skb->data - hh_alen, hh->hh_data, hh_alen);这里的memcpy就是对所有的HardWare Header的拷贝动作,也就是所谓的cache命中和使用。循环对所有的报文进行报文头添加操作
 } while (read_seqretry(&hh->hh_lock, seq));

 skb_push(skb, hh_len);
 return hh->hh_output(skb);
}
在一个neighbour的初始化过程中会判断一个网络是否支持硬件cache,如果支持则初始化其对应的接口

neigh_hh_init


 if (dev->header_ops->cache(n, hh)) {
  kfree(hh);
  return;
 }
然后进行hh_output的初始化

 if (n->nud_state & NUD_CONNECTED)
  hh->hh_output = n->ops->hh_output;
 else
  hh->hh_output = n->ops->output;

  评论这张
 
阅读(1076)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017