- 论坛徽章:
- 0
|
[color="#000000"]首先声明,因为刚开始看linux内核协议栈,所以肯定有许多不正确的地方,如果大家发现不对的地方请帮我指正。在此先谢过了。
[color="#000000"]ip_finish_output2函数在文件“net/ipv4/ip_output.c”[color="#000000"]中定义,如下:
static inline 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);
} else if (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;
}
[color="#000000"]对于“hh->hh_output(skb);[color="#000000"]”,这里hh_output的赋值,在google上没找到,粗略看了一下代码,估计是在函数neigh_hh_init中赋值的([color="#ff0000"]我也不能确定,还需要以后更熟悉协议栈代码后,如有错再更正[color="#000000"]),此[color="#000000"]函数在文件“net/core/neighbour.c”[color="#000000"]中定义,如下[color="#000000"]
static void 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;
}
}
[color="#000000"]我们可以知道赋值为n->ops->hh_output或n->ops->output, n是结构体struct neighbour指针[color="#000000"]. 这里的
[color="#000000"]n->ops和ip_finish_output2函数中的“return dst->neighbour->output(skb); ”[color="#000000"]里的output函数指针应该是在文件"net/ipv4/arp.c" 中的arp_constructor函数中赋值的,下面是代码:
static int 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, because this 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, useless in 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;
}
[color="#000000"]这个netgh->ops赋值为函数arp_generic_ops[color="#0000ff"]或者arp_hh_ops[color="#000000"]或者arp_broken_ops或者arp_direct_ops的地址, 这四个结构体变量的具体定义在“net/ipv4/arp.c”中找到,代码如下:
static struct 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。
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/88019/showart_1903875.html |
|