关于ip_finish_output2的一点分析
来源:互联网 发布:兴业信用卡淘宝卡年费 编辑:程序博客网 时间:2024/05/17 03:48
分类: LINUX
首先声明,因为刚开始看linux内核协议栈,所以肯定有许多不正确的地方,如果大家发现不对的地方请帮我指正。在此先谢过了。
ip_finish_output2函数在文件“net/ipv4/ip_output.c”中定义,如下:
staticinline int ip_finish_output2(struct sk_buff*skb)
{
struct dst_entry *dst = skb->dst;
struct hh_cache *hh = dst->hh;
struct net_device *dev = dst->dev;
int hh_len = LL_RESERVED_SPACE(dev);
/* Be paranoid, rather than too clever. */
if (unlikely(skb_headroom(skb)< hh_len && dev->hard_header)){
struct sk_buff *skb2;
skb2 = skb_realloc_headroom(skb, LL_RESERVED_SPACE(dev));
if (skb2 ==NULL){
kfree_skb(skb);
return -ENOMEM;
}
if (skb->sk)
skb_set_owner_w(skb2, skb->sk);
kfree_skb(skb);
skb = skb2;
}
if (hh){
int hh_alen;
read_lock_bh(&hh->hh_lock);
hh_alen = HH_DATA_ALIGN(hh->hh_len);
memcpy(skb->data- hh_alen, hh->hh_data, hh_alen);
read_unlock_bh(&hh->hh_lock);
skb_push(skb, hh->hh_len);
return hh->hh_output(skb);
} elseif (dst->neighbour)
return dst->neighbour->output(skb);
if (net_ratelimit())
printk(KERN_DEBUG "ip_finish_output2: No header cache and no neighbour!\n");
kfree_skb(skb);
return -EINVAL;
}
对于“
hh->hh_output(skb);
”,这里hh_output的赋值,在google上没找到,粗略看了一下代码,估计是在函数neigh_hh_init中赋值的(
我也不能确定,还需要以后更熟悉协议栈代码后,如有错再更正
),此
函数在文件“net/core/neighbour.c”中定义,如下
staticvoid neigh_hh_init(struct neighbour*n,struct dst_entry *dst, u16 protocol)
{
struct hh_cache *hh;
struct net_device *dev = dst->dev;
for (hh = n->hh; hh; hh= hh->hh_next)
if (hh->hh_type== protocol)
break;
if (!hh&&(hh = kmalloc(sizeof(*hh), GFP_ATOMIC))!=NULL){
memset(hh, 0,sizeof(struct hh_cache));
rwlock_init(&hh->hh_lock);
hh->hh_type= protocol;
atomic_set(&hh->hh_refcnt, 0);
hh->hh_next= NULL;
if (dev->hard_header_cache(n, hh)){
kfree(hh);
hh = NULL;
} else {
atomic_inc(&hh->hh_refcnt);
hh->hh_next= n->hh;
n->hh = hh;
if (n->nud_state& NUD_CONNECTED)
hh->hh_output= n->ops->hh_output;
else
hh->hh_output= n->ops->output;
}
}
if (hh) {
atomic_inc(&hh->hh_refcnt);
dst->hh= hh;
}
}
我们可以知道赋值为
n->ops->hh_output或n->ops->output, n是结构体struct neighbour指针
. 这里的
n->ops和ip_finish_output2函数中的“
return dst->neighbour->output(skb); ”
里的output函数指针应该是在文件
"net/ipv4/arp.c"中的arp_constructor函数中赋值的,下面是代码:
staticint arp_constructor(struct neighbour*neigh)
{
u32 addr = *(u32*)neigh->primary_key;
struct net_device *dev = neigh->dev;
struct in_device *in_dev;
struct neigh_parms *parms;
neigh->type= inet_addr_type(addr);
rcu_read_lock();
in_dev = __in_dev_get_rcu(dev);
if (in_dev== NULL) {
rcu_read_unlock();
return -EINVAL;
}
parms = in_dev->arp_parms;
__neigh_parms_put(neigh->parms);
neigh->parms= neigh_parms_clone(parms);
rcu_read_unlock();
if (dev->hard_header== NULL) {
neigh->nud_state= NUD_NOARP;
neigh->ops= &arp_direct_ops;
neigh->output= neigh->ops->queue_xmit;
} else {
/* Good devices (checked by reading texts, but only Ethernet is
tested)
ARPHRD_ETHER: (ethernet, apfddi)
ARPHRD_FDDI: (fddi)
ARPHRD_IEEE802: (tr)
ARPHRD_METRICOM: (strip)
ARPHRD_ARCNET:
etc. etc. etc.
ARPHRD_IPDDP will also work, if author repairs it.
I did not it, becausethis driver does not work even
in old paradigm.
*/
#if 1
/* So... these"amateur" devices are hopeless.
The only thing, that I can say now:
It is very sad that we need to keep ugly obsolete
code to make them happy.
They should be moved to more reasonable state, now
they use rebuild_header INSTEAD OF
Besides that, they are sort of out of date
(a lot of redundant clones/copies, uselessin 2.1),
I wonder why people believe that they work.
*/
switch (dev->type) {
default:
break;
case ARPHRD_ROSE:
#if defined(CONFIG_AX25)|| defined(CONFIG_AX25_MODULE)
case ARPHRD_AX25:
#if defined(CONFIG_NETROM)|| defined(CONFIG_NETROM_MODULE)
case ARPHRD_NETROM:
#endif
neigh->ops= &arp_broken_ops;
neigh->output= neigh->ops->output;
return 0;
#endif
;}
#endif
if (neigh->type== RTN_MULTICAST) {
neigh->nud_state= NUD_NOARP;
arp_mc_map(addr, neigh->ha, dev, 1);
} else if (dev->flags&(IFF_NOARP|IFF_LOOPBACK)) {
neigh->nud_state= NUD_NOARP;
memcpy(neigh->ha, dev->dev_addr, dev->addr_len);
} else if (neigh->type== RTN_BROADCAST|| dev->flags&IFF_POINTOPOINT) {
neigh->nud_state= NUD_NOARP;
memcpy(neigh->ha, dev->broadcast, dev->addr_len);
}
if (dev->hard_header_cache)
neigh->ops= &arp_hh_ops;
else
neigh->ops= &arp_generic_ops;
if (neigh->nud_state&NUD_VALID)
neigh->output= neigh->ops->connected_output;
else
neigh->output= neigh->ops->output;
}
return 0;
}
这个netgh->ops赋值为函数
arp_generic_ops
或者
arp_hh_ops或者
arp_broken_ops
或者arp_direct_ops
的地址, 这四个结构体变量的具体定义在“net/ipv4/arp.c”中找到,代码如下:
staticstruct neigh_ops arp_generic_ops = {
.family = AF_INET,
.solicit = arp_solicit,
.error_report = arp_error_report,
.output = neigh_resolve_output,
.connected_output = neigh_connected_output,
.hh_output = dev_queue_xmit,
.queue_xmit = dev_queue_xmit,
};
static struct neigh_ops arp_hh_ops= {
.family = AF_INET,
.solicit = arp_solicit,
.error_report = arp_error_report,
.output = neigh_resolve_output,
.connected_output = neigh_resolve_output,
.hh_output = dev_queue_xmit,
.queue_xmit = dev_queue_xmit,
};
static struct neigh_ops arp_direct_ops= {
.family = AF_INET,
.output = dev_queue_xmit,
.connected_output = dev_queue_xmit,
.hh_output = dev_queue_xmit,
.queue_xmit = dev_queue_xmit,
};
struct neigh_ops arp_broken_ops = {
.family = AF_INET,
.solicit = arp_solicit,
.error_report = arp_error_report,
.output = neigh_compat_output,
.connected_output = neigh_compat_output,
.hh_output = dev_queue_xmit,
.queue_xmit = dev_queue_xmit,
};
一般情况下指向
arp_generic_ops,所以
hh->hh_output对应的函数应该是
dev_queue_xmit,
而
neigh->ops->output对应的就是函数
neigh_resolve_output。
- 关于ip_finish_output2的一点分析
- 关于 include 的一点分析
- 关于vector的一点源码分析
- 关于并行程序分析的一点思考
- 关于REST的一点个人分析
- 关于wince bootloader的一点分析
- 关于数据分析的一点思考
- 关于jsp乱码的一点小分析
- 关于CoordinatorLayout与Behavior的一点分析
- 关于CoordinatorLayout与Behavior的一点分析
- 关于词法分析的一点总结
- 关于CoordinatorLayout与Behavior的一点分析
- 【分析】关于Windows下ShellCode编写的一点思考
- 关于风险分析(Risk Analysis)的一点见解
- 关于C/C++中指针做形参的一点小分析
- 关于程序崩溃后dmp简易分析的一点收获
- 关于软中断和系统调用的一点分析
- 关于国内B2C商城推广的一点分析
- 数据挖掘编程指南_ch1_2
- linkin大话数据结构--Queue
- 浏览器插件屏蔽优酷广告的原理
- 禁止运行两个实例
- eclipse插件开发,调试运行,导出与安装
- 关于ip_finish_output2的一点分析
- iOS 设计模式之抽象工厂
- QT下文件的读写
- UVA 10099 The Tourist Guide
- afx_msg的定义与应用
- 1411102159-ny-背包问题
- Java 1030 接口
- 复制一个图片
- [LeetCode]Best Time to Buy and Sell Stock 系列