概述 ip层在构造好ip头,检查完分片之后,会调用邻居子系统的输出函数neigh_output进行输出,输出分为有二层头缓存和没有两种情况,有缓存时调用neigh_hh_output进行快速输出,没有缓存时,则调用邻居子系统的输出回调函数进行慢速输出: 源码分析 static inline int neigh_output(struct neighbour *n, struct sk_buff *skb) { const struct hh_cache *hh = &n->hh; /* 连接…
概述 neigh_update函数用来更新指定的邻居项,更新内容是硬件地址和状态,更新之后,会根据新状态设置其输出函数,CONNECTED状态则使用快速输出,否则使用慢速输出:如果是由原来的无效状态变为现在的有效状态,则需要将数据包缓存队列中的数据包发送出去: 该函数在邻居子系统中被频繁调用:arp模块再收到邻居应答,收到邻居的情况,转发单播代理请求后,会调用该函数更新地址和状态:netlink或者ioctl模块添加或者删除邻居项,也会调用该函数更新地址和状态: 源码分析 /* 更新指定的邻居项…
概述 在分配邻居子系统之后,会设置定时器来处理那些需要定时器处理的状态,定时器回调函数为neigh_timer_handler:函数会根据状态机变换规则对状态进行切换,切换状态后,如果需要更新输出函数则更新,并更新定时器下一次超时时间:其中NUD_INCOMPLETE | NUD_PROBE状态需要发送邻居请求,如果超过最大次数,则释放缓存中的数据包: 源码分析 /* 邻居项各个状态的定时器处理回调 */ static void neigh_timer_handler(unsigned long…
概述 邻居子系统支持多种实现,例如ARP,ND等,这些实现需要在其初始化的时候,调用neigh_table_init将邻居表项添加到全局邻居子系统数组中,并对实例中的字段(如hash,定时器等)进行相关初始化: 源码分析 分析过程以ARP为例,引出邻居表的初始化,在arp_init初始化中,调用neigh_table_init来进行邻居表的初始化:其中NEIGH_ARP_TABLE为ARP在全局邻居表数组中的索引值,arp_table则是邻居表的一个实例,里面包含了部分字段的初始化: void…
1.5.1 当邻居项不处于NUD_CONNECTD状态时,不允许快速路径发送报文,函数neigh_resolve_output 用于慢而安全的输出,通常用初始化neigh_ops结构 来实例output函数,当邻居从NUD_CONNECT转到非NUD_CONNECT的时候,使用neigh_suspect 将output设置为neigh_resolve_output () /* Neighbour state is suspicious;   disable fast path.   Called…
1.封包从L3至L2的传送过程如下所示: 本地主机的路由子系统选择L3目的地址(下一个跃点). 根据路由表,如果下一个跃点在同一个网络中,邻居层就把目的L3地址解析为跃点的L2地址.这个关联会被放入缓存中以便再次使用. 最后,调用一个函数,例如dev_queue_xmit负责完成发送,将封包传递给流量控制或者Qos层. 2.当收到solicitation请求的主机启动桥接功能时,该主机对其不进行处理,而是按照网桥配置,将其从合适的接口转发出去,桥接功能在邻居协议之前起作用. 3.从邻居的角度来说…
概述 IP层输出数据包会根据路由的下一跳查询邻居项,如果不存在则会调用__neigh_create创建邻居项,然后调用邻居项的output函数进行输出: __neigh_create完成邻居项的创建,进行初始化之后,加入到邻居项hash表,然后返回,其中,如果hash表中有与新建邻居项相同的项会复用该项,新建项会被释放: neigh_alloc完成邻居项的分配,分配成功后会设定定时器来检查和更新邻居项的状态: 源码分析 struct neighbour *__neigh_create(struc…
概述 邻居项查找是通过neigh_lookup相关函数来进行的: ___neigh_lookup_noref,该函数根据输出设备和主键值(IPv4为下一跳ip地址)在邻居项hash表中查找,找到则返回该项: neigh_lookup,该函数调用了___neigh_lookup_noref函数,并且在找到邻居项之后,进行引用计数的递增,然后返回该项: 源码分析 struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *p…
概述 ip_output-设置输出设备和协议,然后经过POST_ROUTING钩子点,最后调用ip_finish_output: ip_finish_output-对skb进行分片判断,需要分片,则分片后输出,不需要分片则知直接输出: ip_finish_output2-对skb的头部空间进行检查,看是否能够容纳下二层头部,若空间不足,则需要重新申请skb:然后,获取邻居子系统,并通过邻居子系统输出: 源码分析 int ip_output(struct net *net, struct sock…