🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: cn.bbs.comp.unix.programming.kernel
Article #8

Re: arp��ݰ�ķ���

#8
From: ��������
Date: Mon, 11 Mar 2002 14:16
191 lines
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��ݰ�ĺ����������δ�ܲ���˵˵��л�� 
--
�� ��Դ:��UNIX��� apue.dhs.org��[FROM: 211.69.197.81] 
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!APUE

Show 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