Chinaunix首页 | 论坛 | 博客
  • 博客访问: 419883
  • 博文数量: 124
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 872
  • 用 户 组: 普通用户
  • 注册时间: 2018-03-29 14:38
个人简介

默默的一块石头

文章分类

全部博文(124)

文章存档

2022年(26)

2021年(10)

2020年(28)

2019年(60)

我的朋友

分类: LINUX

2019-10-14 16:30:04

1.arp_tbl
struct neigh_table arp_tbl = {
.family = AF_INET,
.key_len = 4,
.hash = arp_hash,
.constructor = arp_constructor,
.proxy_redo = parp_redo,
.id = "arp_cache",
.parms = {
.tbl = &arp_tbl,
......
},
......
};

2.arp_generic_ops
static const 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,
};

3.arp_constructor()
static int arp_constructor(struct neighbour *neigh)
{
__be32 addr = *(__be32 *)neigh->primary_key;
struct net_device *dev = neigh->dev;
struct in_device *in_dev;
struct neigh_parms *parms;

rcu_read_lock();
in_dev = __in_dev_get_rcu(dev);
if (in_dev == NULL) {
rcu_read_unlock();
return -EINVAL;
}

neigh->type = inet_addr_type(dev_net(dev), addr);

parms = in_dev->arp_parms;
__neigh_parms_put(neigh->parms);
neigh->parms = neigh_parms_clone(parms);
rcu_read_unlock();

if (!dev->header_ops) {
neigh->nud_state = NUD_NOARP;
neigh->ops = &arp_direct_ops;
neigh->output = neigh_direct_output;
} else {
/* Good devices (checked by reading texts, but only Ethernet is */

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->header_ops->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;
}


4.neigh_create()
static inline struct neighbour *neigh_create(struct neigh_table *tbl,
     const void *pkey,struct net_device *dev)
{
return __neigh_create(tbl, pkey, dev, true);
}

5.__neigh_create()
struct neighbour *__neigh_create(struct neigh_table *tbl, const void *pkey,
struct net_device *dev, bool want_ref)
{
u32 hash_val;
int key_len = tbl->key_len;
int error;
struct neighbour *n1, *rc, *n = neigh_alloc(tbl, dev);
struct neigh_hash_table *nht;

if (!n) {
rc = ERR_PTR(-ENOBUFS);
goto out;
}

memcpy(n->primary_key, pkey, key_len);
n->dev = dev;
dev_hold(dev);

/* Protocol specific setup. */
if (tbl->constructor && (error = tbl->constructor(n)) < 0) {
rc = ERR_PTR(error);
goto out_neigh_release;
}

if (dev->netdev_ops->ndo_neigh_construct) {
error = dev->netdev_ops->ndo_neigh_construct(n);
if (error < 0) {
rc = ERR_PTR(error);
goto out_neigh_release;
}
}

/* Device specific setup. */
if (n->parms->neigh_setup &&
    (error = n->parms->neigh_setup(n)) < 0) {
rc = ERR_PTR(error);
goto out_neigh_release;
}

n->confirmed = jiffies - (n->parms->base_reachable_time << 1);

write_lock_bh(&tbl->lock);
nht = rcu_dereference_protected(tbl->nht,
lockdep_is_held(&tbl->lock));

if (atomic_read(&tbl->entries) > (1 << nht->hash_shift))
nht = neigh_hash_grow(tbl, nht->hash_shift + 1);

hash_val = tbl->hash(pkey, dev, nht->hash_rnd) >> (32 - nht->hash_shift);

if (n->parms->dead) {
rc = ERR_PTR(-EINVAL);
goto out_tbl_unlock;
}

for (n1 = rcu_dereference_protected(nht->hash_buckets[hash_val],
    lockdep_is_held(&tbl->lock));
     n1 != NULL;
     n1 = rcu_dereference_protected(n1->next,
lockdep_is_held(&tbl->lock))) {
if (dev == n1->dev && !memcmp(n1->primary_key, pkey, key_len)) {
if (want_ref)
neigh_hold(n1);
rc = n1;
goto out_tbl_unlock;
}
}

n->dead = 0;
if (want_ref)
neigh_hold(n);
rcu_assign_pointer(n->next,
   rcu_dereference_protected(nht->hash_buckets[hash_val],
     lockdep_is_held(&tbl->lock)));
rcu_assign_pointer(nht->hash_buckets[hash_val], n);
write_unlock_bh(&tbl->lock);
neigh_dbg(2, "neigh %p is created\n", n);
rc = n;
out:
return rc;
out_tbl_unlock:
write_unlock_bh(&tbl->lock);
out_neigh_release:
neigh_release(n);
goto out;
}

6.neigh_alloc()
static struct neighbour *neigh_alloc(struct neigh_table *tbl, struct net_device *dev)
{
struct neighbour *n = NULL;
unsigned long now = jiffies;
int entries;

entries = atomic_inc_return(&tbl->entries) - 1;
if (entries >= tbl->gc_thresh3 ||
    (entries >= tbl->gc_thresh2 &&
     time_after(now, tbl->last_flush + 5 * HZ))) {
if (!neigh_forced_gc(tbl) &&
    entries >= tbl->gc_thresh3)
goto out_entries;
}

n = kzalloc(tbl->entry_size + dev->neigh_priv_len, GFP_ATOMIC);
if (!n)
goto out_entries;

__skb_queue_head_init(&n->arp_queue);
rwlock_init(&n->lock);
seqlock_init(&n->ha_lock);
n->updated   = n->used = now;
n->nud_state   = NUD_NONE;
n->output   = neigh_blackhole;
seqlock_init(&n->hh.hh_lock);
n->parms   = neigh_parms_clone(&tbl->parms);
setup_timer(&n->timer, neigh_timer_handler, (unsigned long)n);

NEIGH_CACHE_STAT_INC(tbl, allocs);
n->tbl   = tbl;
atomic_set(&n->refcnt, 1);
n->dead   = 1;
out:
return n;

out_entries:
atomic_dec(&tbl->entries);
goto out;
}

7.neigh_timer_handler
/* Called when a timer expires for a neighbour entry. */
static void neigh_timer_handler(unsigned long arg)
{
unsigned long now, next;
struct neighbour *neigh = (struct neighbour *)arg;
unsigned int state;
int notify = 0;

printk("neigh_timer_handler() 890!\n");
write_lock(&neigh->lock);

state = neigh->nud_state;
now = jiffies;
next = now + HZ;

if(){
......
} else {
/* NUD_PROBE|NUD_INCOMPLETE */ //也不知道这里是怎么算的,注释和debug在创建的时候走的这边
next = now + neigh->parms->retrans_time;
}

......
if (neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) {
neigh_probe(neigh);
} else {
out:
write_unlock(&neigh->lock);
}

if (notify)
neigh_update_notify(neigh);

neigh_release(neigh);
}

8.neigh_probe()
static void neigh_probe(struct neighbour *neigh)
__releases(neigh->lock)
{
struct sk_buff *skb = skb_peek_tail(&neigh->arp_queue);
/* keep skb alive even if arp_queue overflows */
if (skb)
skb = skb_copy(skb, GFP_ATOMIC);
write_unlock(&neigh->lock);
neigh->ops->solicit(neigh, skb);
atomic_inc(&neigh->probes);
kfree_skb(skb);
}

阅读(5710) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~