admin管理员组文章数量:1642339
在邻居发现协议处理中,对于NA(Neighbour Advertisement)报文,如果其通过的地址已经存在于邻居表中,但是此次通过没有了NTF_ROUTER标志,表明发送NA报文的设备由路由转换为主机模式,其不在转发报文。因此,需要删除其之前通告的路由。
static void ndisc_recv_na(struct sk_buff *skb)
{
neigh = neigh_lookup(&nd_tbl, &msg->target, dev);
if (neigh) {
u8 old_flags = neigh->flags;
...
if ((old_flags & ~neigh->flags) & NTF_ROUTER) {
/*
* Change: router to host
*/
rt6_clean_tohost(dev_net(dev), saddr);
}
如下rt6_clean_tohost,由fib6_clean_all遍历命名空间中的所有路由信息,每个信息项由fib6_clean_tohost处理,参数为发送NA报文的设备地址。
void rt6_clean_tohost(struct net *net, struct in6_addr *gateway)
{
fib6_clean_all(net, fib6_clean_tohost, gateway);
}
由于RA(Router Advertisement)报文通过的路由不会指向nexthop节点,所以,如果当前遍历的路由信息指向nexthop节点,不进行处理。如果路由信息是有RA报文生成,并且路由下一跳网关等于设备地址(此设备由路由转为主机模式),返回-1,删除此路由信息。返回值的处理可参考fib6_clean_node函数。
另外,如果以上不成立,路由信息不符合,需要遍历下一跳的exception,因为重定向生成的exception可能下一跳指向失效的设备地址。
#define RTF_RA_ROUTER (RTF_ADDRCONF | RTF_DEFAULT)
static int fib6_clean_tohost(struct fib6_info *rt, void *arg)
{
struct in6_addr *gateway = (struct in6_addr *)arg;
struct fib6_nh *nh;
/* RA routes do not use nexthops */
if (rt->nh)
return 0;
nh = rt->fib6_nh;
if (((rt->fib6_flags & RTF_RA_ROUTER) == RTF_RA_ROUTER) &&
nh->fib_nh_gw_family && ipv6_addr_equal(gateway, &nh->fib_nh_gw6))
return -1;
/* Further clean up cached routes in exception table.
* This is needed because cached route may have a different
* gateway than its 'parent' in the case of an ip redirect.
*/
fib6_nh_exceptions_clean_tohost(nh, gateway);
return 0;
根据下一跳找到其所属的exception数组,遍历所有的数组,以及每个数组成员表示的链表,取出每个链表元素,如果其网关等于失效的设备地址,将此exception移除。
#define RTF_CACHE_GATEWAY (RTF_GATEWAY | RTF_CACHE)
static void fib6_nh_exceptions_clean_tohost(const struct fib6_nh *nh, const struct in6_addr *gateway)
{
struct rt6_exception_bucket *bucket;
struct rt6_exception *rt6_ex;
struct hlist_node *tmp;
...
bucket = fib6_nh_get_excptn_bucket(nh, &rt6_exception_lock);
if (bucket) {
for (i = 0; i < FIB6_EXCEPTION_BUCKET_SIZE; i++) {
hlist_for_each_entry_safe(rt6_ex, tmp, &bucket->chain, hlist) {
struct rt6_info *entry = rt6_ex->rt6i;
if ((entry->rt6i_flags & RTF_CACHE_GATEWAY) == RTF_CACHE_GATEWAY &&
ipv6_addr_equal(gateway, &entry->rt6i_gateway)) {
rt6_remove_exception(bucket, rt6_ex);
}
}
bucket++;
}
内核版本 5.10
版权声明:本文标题:IPv6下一跳路由器转变为主机 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://www.elefans.com/xitong/1729328417a1196065.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论