ARP - 内核设计与实现

 

参考资料:

http://www.saminiir.com/lets-code-tcp-ip-stack-1-ethernet-arp/

rfc 826

 

ARP 分成三个部分:

* 输出模块

* 输入模块

* 高速缓存管理程序: 轮循表项,删除已经过期的表项。

 

设计原则:

* 单一的ARP高速缓存

* 全局替换策略

* 高速缓存中的超时与删除

* 分组多队列的形式等待与发送

* 互斥访问

 

数据结构 neighbor   include/net/neighbour.h

struct neighbour {
    struct neighbour __rcu    *next;   // 邻居表散列表中下一个
    struct neigh_table    *tbl;        // 邻居表
    struct neigh_parms    *parms;      // 邻居对象
    unsigned long        confirmed;    // 确认时间
    unsigned long        updated;      // 
    rwlock_t        lock;
    refcount_t        refcnt;          // 引用计数器 neigh_hold() 会增1,neigh_release()减1, 当为0时,neigh_release会调用neigh_destroy()释放
    struct sk_buff_head    arp_queue;  
    unsigned int        arp_queue_len_bytes;
    struct timer_list    timer;        // 时间定时器
    unsigned long        used;         // 
    atomic_t        probes;
    __u8            flags;
    __u8            nud_state;         // 邻居NUD状态
    __u8            type;
    __u8            dead;              // 活动状态时设置
    seqlock_t        ha_lock;         // 对邻居硬件地址进行保护
    unsigned char        ha[ALIGN(MAX_ADDR_LEN, sizeof(unsigned long))];   // 邻居mac地址
    struct hh_cache        hh;        // L2报头的硬件报头缓存
    int            (*output)(struct neighbour *, struct sk_buff *);   // 一个指向传输方法 neigh_resolv_output()  neigh_direct_output()
    const struct neigh_ops    *ops;
    struct rcu_head        rcu;
    struct net_device    *dev;
    u8            primary_key[0];     // 邻居IP地址
} __randomize_layout;

 

数据结构ARP表  neigh_table  include/net/neighbour.h

struct neigh_table {
    int            family;        // 协议 AF_INET 或者 AF_INET6
    int            entry_size;        // neigh_alloc() 分配邻居条目,分配的空间tbl->entry_size + dev->neigh_priv_len
    int            key_len;           // 查找键长度
    __be16            protocol;
    __u32            (*hash)(const void *pkey,
                    const struct net_device *dev,
                    __u32 *hash_rnd);
    bool            (*key_eq)(const struct neighbour *, const void *pkey);
    int            (*constructor)(struct neighbour *);
    int            (*pconstructor)(struct pneigh_entry *);
    void            (*pdestructor)(struct pneigh_entry *);
    void            (*proxy_redo)(struct sk_buff *skb);
    char            *id;              // arp 表的名称
    struct neigh_parms    parms;
    struct list_head    parms_list;
    int            gc_interval;
    int            gc_thresh1;
    int            gc_thresh2;
    int            gc_thresh3;
    unsigned long        last_flush;  // 最近一次运行方法neigh_forced_gc 时间
    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 neigh_statistics    __percpu *stats;
    struct neigh_hash_table __rcu *nht;        // 邻居散列表
    struct pneigh_entry    **phash_buckets;
};

 

 

ARP表初始化

void neigh_table_init(int index, struct neigh_table *tbl);

 

创建与释放邻居

struct neighbour *__neigh_create(struct neigh_table *tbl, const void *pkey,
                 struct net_device *dev, bool want_ref);


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

 

用户空间与邻接子系统交互

iproute2/ip neigh 模块

 

删除arp表项中的项
int
arpdelete(const char *, const char *);


搜索ARP表
int arpsearch(FILE *, char *, in_addr_t addr, void (*action)(FILE *, char *, struct sockaddr_dl *sdl, struct sockaddr_inarp *sin, struct rt_msghdr *rtm));

打印entry
void print_entry(FILE *, char *, struct sockaddr_dl *sdl, struct sockaddr_inarp *sin, struct rt_msghdr *rtm);

// 配置arp表项 void conf_arp_entry(FILE *, char *, struct sockaddr_dl *, struct sockaddr_inarp *, struct rt_msghdr *);


获取 邻居地址
int getinetaddr(const char *, struct in_addr *);

发送arp消息
int rtmsg_arp(int, int, int, int);

 

posted @ 2017-12-26 16:45  elewei  阅读(646)  评论(0)    收藏  举报