Article View: cn.bbs.comp.unix.programming.kernel
Article #8Re: arp��ݰ�ķ���
From: ��������
Date: Mon, 11 Mar 2002 14:16
Date: Mon, 11 Mar 2002 14:16
191 lines
7910 bytes
7910 bytes
����·�ɻ����в���·��ʧ�ܵ�ʱ����ip_route(output)_slow��fib�в��ң�
ip_route_input(output)_slow
{ rth=dst_alloc;
rth->u.dst.output=ip_output;
rt_set_nexthop(rth,&res,0);
rt_intern_hash(hash,rth,rp);
} |
|
--------|
|
|
V
rt_intern_hash
{
arp_bind_neighbour(&rt->u.dst)
} |
|
|
|-------|
|
|
V
arp_bind_neighbour(struct dst_entry *dst)
{
n = neigh_lookup(arp_tbl,pkey,dev)
:��arp_tbl->hash_buckets�������ƥ��
if ( !n ) n=neigh_alloc(arp_tbl)
dst->neighbour = n; |
} |
|
----------------------------|
|
|
V
neigh_create(arp_tbl) |--->n->output=neigh_blackhole;
{ |
n=neigh_alloc(arp_tbl)--|--->n->parms=&arp_tbl->parms
|
|--->n->tbl=arp_tbl;
--- arp_tbl->constructor(n);
| //����arp_constructor
| n->parms->neigh_setup(n);
| n->next=arp_tbl->hash_buckets[hash_val];
| arp_tbl->hash_buckets[hash_val]=n;
} |
V
arp_constructor(struct neighbour *neigh)
{
//����ҪӲ��ͷ��ֱ��Ͷ��
if (dev->hard_header == NULL)
{
neigh->nud_state = NUD_NOARP;
neigh->ops = &arp_direct_ops;
neigh->output = neigh->ops->queue_xmit;
} else
{
if (dev->hard_header_cache)
:��̫�����ΪNULL
neigh->ops = &arp_hh_ops;----------------------|
else |
neigh->ops = &arp_generic_ops; |
:��outpub��ֵ����һ�μ��ָ�� |
if (neigh->nud_state&NUD_VALID) |
neigh->output = neigh->ops->connected_output; |
else |
neigh->output = neigh->ops->output; |
} |
} |
|
|-------------------------------------------------|
|
V
static struct neigh_ops arp_hh_ops =
{
AF_INET,
NULL,
arp_solicit,
arp_error_report,
neigh_resolve_output,
neigh_resolve_output,
dev_queue_xmit,
dev_queue_xmit
};
<------------------------------------------------------------->
�����ʱ��
static inline int ip_finish_output2(struct sk_buff *skb)
{
struct dst_entry *dst = skb->dst;
struct hh_cache *hh = dst->hh;
if (hh) {
read_lock_bh(&hh->hh_lock);
memcpy(skb->data - 16, hh->hh_data, 16);
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);
printk(KERN_DEBUG "khm\n");
kfree_skb(skb);
return -EINVAL;
}
���֡ͷ����hh��û�и�ֵ,�����neigh_resolve_output��
/* Slow and careful. */
int neigh_resolve_output(struct sk_buff *skb)
{
struct dst_entry *dst = skb->dst;
struct neighbour *neigh;
__skb_pull(skb, skb->nh.raw - skb->data);
/*neigh_event_send,����Ҫ����Ҫ����neigh->ops->solicit,
��arp_solicit,����arp�����Ӳ����ַ*/
if (neigh_event_send(neigh, skb) == 0) {
int err;
struct net_device *dev = neigh->dev;
if (dev->hard_header_cache && dst->hh == NULL) {
write_lock_bh(&neigh->lock);
if (dst->hh == NULL)
/*����֡ͷ���壨�ṹstruct hh_cache��,������������*/
neigh_hh_init(neigh, dst, dst->ops->protocol);
/*�������hard_header����,��̫Ϊeth_header�������ݱ���Ӳ��֡
ͷ,
/*����saddrΪNULL�����dev->dev_addrΪԴmac��ַ*/
err = dev->hard_header(skb, dev, ntohs(skb->protocol), neigh->ha
, NU
LL, s
kb->len);
write_unlock_bh(&neigh->lock);
} else {
read_lock_bh(&neigh->lock);
err = dev->hard_header(skb, dev, ntohs(skb->protocol), neigh->ha
, NU
LL, s
kb->len);
read_unlock_bh(&neigh->lock);
}
if (err >= 0)
/*hard_header����Ӳ����ַ�ij���,�����ֵ���dev_queue_xmit*/
return neigh->ops->queue_xmit(skb);
kfree_skb(skb);
return -EINVAL;
}
return 0;
}
static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst, u16 pr
otocol)
{
struct hh_cache *hh = NULL;
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));
hh->hh_lock = RW_LOCK_UNLOCKED;
hh->hh_type = protocol;
atomic_set(&hh->hh_refcnt, 0);
hh->hh_next = NULL;
/*����eth_header_cache����dev->dev_addr��Դmac����neigh->ha��Ŀ��mac
��
������hh->hh_data*/
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;
/*��̫��֡ͷ���巢������ȻΪneigh_resolve_output*/
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;
}
}
�� �� algous.bbs@smth.org ( ������) �Ĵ������ᵽ: ��
: linux��̽�������ھ�neighbour��ͨ����ܱ������������arp��ݰ��Dz�֪
: ���ں��з���arp��ݰ�ĺ����������δ�ܲ���˵˵��л��
--
[m[1;34m�� ��Դ:��UNIX��� apue.dhs.org��[FROM: 211.69.197.81][m
Technical Details
Message-ID:
<3lHTcP$11k@apue.dhs.org>Path:
arc1-ca.pugleaf.net!archiver1.google.com!news1.google.com!sn-xit-02!sn-xit-04!supernews.com!telocity-west!TELOCITY!hub1.nntpserver.com!news-out.spamkiller.net!propagator-la!news-in-la.newsfeeds.com!news-in.superfeed.net!news.cn99.com!news.tiaozhan.com!APUEShow Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII X-Google-Thread: 10e809,c1901edb475b084b,start X-Google-Attributes: gid10e809,public X-Google-ArrivalTime: 2002-03-11 06:28:20 PST Path: arc1-ca.pugleaf.net!archiver1.google.com!news1.google.com!sn-xit-02!sn-xit-04!supernews.com!telocity-west!TELOCITY!hub1.nntpserver.com!news-out.spamkiller.net!propagator-la!news-in-la.newsfeeds.com!news-in.superfeed.net!news.cn99.com!news.tiaozhan.com!APUE From: ysqcn.bbs@apue.dhs.org (��������) Newsgroups: cn.bbs.comp.unix.programming.kernel Subject: Re: arp��ݰ�ķ��� Date: 11 Mar 2002 14:16:39 GMT Organization: APUE Message-ID: <3lHTcP$11k@apue.dhs.org> X-Filename: UKP/M.1015856185.A Lines: 191