至少在2.6的里面,arp是归于邻居系统的,跟路由相关。在1.2.13 好像是独立的<只看过这两个版本的kernel>
一.ARP函数的调用过程
(1) 当系统初始化时,调用arp_init来初始化ARP缓存(arp_tbl),并且注册ARP协议的接收函数
(2)当网卡驱动程序收到一个网络包(packet)的时候,会分配一个sk_buff(skb),将数据拷贝进这个缓冲区,然后调用netif_rx把skb放入等待队列(input_pkt_queue)中,并且产生一个软中断。当系统处理这个软中断的时候,会调用net_rx_action,它根据网络包的类型,调用相应的接收函数来处理。如果是ARP包,则调用arp_rcv。
(3) arp_rcv判断这个arp请求是不是询问本机或者本机代理的硬件地址,如果是的话,调用arp_send发回arp应答。另外arp_rcv还尽量保留对方机器的mac addres。
(4) arp_send分配一个sk_buff(skb),填好arp包的类型,源硬件地址,源IP地址,目的硬件地址,目的IP地址,然后调用dev_queue_xmit这个arp包发送出去。
二.ARP结构体
http://www.oschina.net/code/explore/linux-2.6.36/include/net/neighbour.h line142
/**neigh_table是一个用来描述物理上互相连接的机器的信息的哈希表,ARP缓存arp_tbl 就是这样的一个neigh_table。*/
struct neigh_table {
struct neigh_table *next;/**Used to link into a list of neighbour tables*/
int family;
int entry_size;/**Size of the struct neighbour + 4*/
int key_len;/**Length of key used by hash function.长度为4*/
__u32 (*hash)(const void *pkey, const struct net_device *);
int (*constructor)(struct neighbour *);/**Initalizes new instances of 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_* should follow parms without a gap! */
int gc_interval;
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;
rwlock_t lock;
unsigned long last_rand;
struct kmem_cache *kmem_cachep;
struct neigh_statistics __percpu *stats;
struct neighbour **hash_buckets;/**存放着所有物理邻居的信息,共32个,每一个bucket存放着一条neighbor链表*/
unsigned int hash_mask;
__u32 hash_rnd;
/**存放着所有proxy arp的entry,每一个entry由网卡设备和ip地址组成,指明由哪个网卡设备代理哪个ip的mac地址*/
struct pneigh_entry **phash_buckets;/*共16个*/
};
三.ARP初始化
http://www.oschina.net/code/explore/linux-2.6.36/net/ipv4/arp.c line1287
void __init arp_init(void)
{
neigh_table_init(&arp_tbl);/**net/core/neighbour.c*/
dev_add_pack(&arp_packet_type);/**register the ARP packet type with the link layer*/
arp_proc_init();
#ifdef CONFIG_SYSCTL
neigh_sysctl_register(NULL, &arp_tbl.parms, "ipv4", NULL);
#endif
register_netdevice_notifier(&arp_netdev_notifier);
}
四.传输和接收ARP封包
PS:很大程度上自己对这一部分也不是很熟悉,以前零星看过,现在只是整理,如果有问题轻拍,欢迎交流
网上临时找到的【周末花整段时间整理下,目前只整理自己原有的】:
http://www.cnitblog.com/flutist1225/articles/19996.html