我们进入arp协议,我们看看linux中号称邻居子系统是啥样的
static struct
packet_type arp_packet_type __read_mostly = {
.type = cpu_to_be16( ETH_P_ARP),
.func = arp_rcv,
};
.type = cpu_to_be16( ETH_P_ARP),
.func = arp_rcv,
};
还记得那个netif_receive_skb吧,选择三层协议处理的地方,arp通过
dev_add_pack注册了上述的packet_type结构
#define
ETH_P_ARP 0x0806 /* Address Resolution packet */
void __init
arp_init
(void)
{
neigh_table_init(& arp_tbl ); 初始化arp邻居表
dev_add_pack(&arp_packet_type); 注册三层处理协议类型 arp
arp_proc_init(); /proc文件系统相关arp部分创建
#ifdef CONFIG_SYSCTL
neigh_sysctl_register(NULL, &arp_tbl.parms, NET_IPV4,
NET_IPV4_NEIGH, "ipv4", NULL, NULL);
#endif
register_netdevice_notifier(&arp_netdev_notifier); 注册通知链
}
{
neigh_table_init(& arp_tbl ); 初始化arp邻居表
dev_add_pack(&arp_packet_type); 注册三层处理协议类型 arp
arp_proc_init(); /proc文件系统相关arp部分创建
#ifdef CONFIG_SYSCTL
neigh_sysctl_register(NULL, &arp_tbl.parms, NET_IPV4,
NET_IPV4_NEIGH, "ipv4", NULL, NULL);
#endif
register_netdevice_notifier(&arp_netdev_notifier); 注册通知链
}
neigh_table_init(&
arp_tbl); 其实就是把arp_tbl挂在全局的neigh_tables变量上
for (tmp = neigh_tables; tmp; tmp = tmp->next) {
if (tmp->family == tbl->family) 用协议族在区分 arp类型为AF_INET IPV6的ND协议为AF_INET6
break;
}
tbl->next = neigh_tables;
neigh_tables = tbl;
break;
}
tbl->next = neigh_tables;
neigh_tables = tbl;
重要数据结构:
struct neigh_table
{
struct neigh_table *next;
int family; 协议族
int entry_size; 邻居项的大小 为sizeof(struct neighbour) + 4 考虑到有零长数组
{
struct neigh_table *next;
int family; 协议族
int entry_size; 邻居项的大小 为sizeof(struct neighbour) + 4 考虑到有零长数组
int key_len;
hash关键字的长度 为4
__u32 (*hash)(const void *pkey, const struct net_device *); hash函数
int (*constructor)(struct neighbour *);
int (*pconstructor)(struct pneigh_entry *);
void (*pdestructor)(struct pneigh_entry *);
void (*proxy_redo)(struct sk_buff *skb);
char *id;
struct neigh_parms parms;
/* HACK. gc_* shoul follow parms without a gap! */
int gc_interval; 常规的垃圾回收间隔时间 默认30秒
int gc_thresh1; 门限
int gc_thresh2;
int gc_thresh3;
unsigned long last_flush;
struct delayed_work gc_work; 常规的垃圾回收定时器
struct timer_list proxy_timer;
struct sk_buff_head proxy_queue;
atomic_t entries; 整个表中邻居项的个数 当entries大于hash_mask+1,哈希桶增长为原来的两倍
rwlock_t lock;
unsigned long last_rand;
struct kmem_cache *kmem_cachep;
struct neigh_statistics *stats;
struct neighbour **hash_buckets; 存放邻居项的哈希桶
unsigned int hash_mask; hash桶大小的掩码
__u32 hash_rnd;
struct pneigh_entry **phash_buckets; 用于代理arp的邻居哈希表
};
__u32 (*hash)(const void *pkey, const struct net_device *); hash函数
int (*constructor)(struct neighbour *);
int (*pconstructor)(struct pneigh_entry *);
void (*pdestructor)(struct pneigh_entry *);
void (*proxy_redo)(struct sk_buff *skb);
char *id;
struct neigh_parms parms;
/* HACK. gc_* shoul follow parms without a gap! */
int gc_interval; 常规的垃圾回收间隔时间 默认30秒
int gc_thresh1; 门限
int gc_thresh2;
int gc_thresh3;
unsigned long last_flush;
struct delayed_work gc_work; 常规的垃圾回收定时器
struct timer_list proxy_timer;
struct sk_buff_head proxy_queue;
atomic_t entries; 整个表中邻居项的个数 当entries大于hash_mask+1,哈希桶增长为原来的两倍
rwlock_t lock;
unsigned long last_rand;
struct kmem_cache *kmem_cachep;
struct neigh_statistics *stats;
struct neighbour **hash_buckets; 存放邻居项的哈希桶
unsigned int hash_mask; hash桶大小的掩码
__u32 hash_rnd;
struct pneigh_entry **phash_buckets; 用于代理arp的邻居哈希表
};
struct neigh_table arp_tbl = { arp的邻居表项
.family = AF_I
.family = AF_I