IPv6全局定义了一个blackhole路由缓存项的模板ip6_blk_hole_entry_template,每个网络命名空间将据此生成一个路由缓存项ip6_blk_hole_entry。

static const struct rt6_info ip6_blk_hole_entry_template = {.dst = {.__refcnt   = ATOMIC_INIT(1),.__use      = 1,.obsolete   = DST_OBSOLETE_FORCE_CHK,.error      = -EINVAL,.input      = dst_discard,.output     = dst_discard_out,},.rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP),
};

如下ip6_route_net_init函数,复制模板ip6_blk_hole_entry_template生成本命名空间中的ip6_blk_hole_entry项。

static int __net_init ip6_route_net_init(struct net *net)
{...net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template,sizeof(*net->ipv6.ip6_blk_hole_entry),GFP_KERNEL);if (!net->ipv6.ip6_blk_hole_entry)goto out_ip6_prohibit_entry;net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops;dst_init_metrics(&net->ipv6.ip6_blk_hole_entry->dst,ip6_template_metrics, true);INIT_LIST_HEAD(&net->ipv6.ip6_blk_hole_entry->rt6i_uncached);

Blackhole缓存设备

在IPv6路由系统初始化时,注册通知处理函数ip6_route_dev_notify。

static struct notifier_block ip6_route_dev_notifier = {.notifier_call = ip6_route_dev_notify,.priority = ADDRCONF_NOTIFY_PRIORITY - 10,
};int __init ip6_route_init(void)
{...ret = register_netdevice_notifier(&ip6_route_dev_notifier);if (ret)goto out_register_late_subsys;

对于命名空间中新注册的环回网络设备(NETDEV_REGISTER事件),将其以及其所对应的inet6_dev结构,赋值到ip6_blk_hole_entry中。

static int ip6_route_dev_notify(struct notifier_block *this,unsigned long event, void *ptr)
{struct net_device *dev = netdev_notifier_info_to_dev(ptr);struct net *net = dev_net(dev);if (!(dev->flags & IFF_LOOPBACK))return NOTIFY_OK;if (event == NETDEV_REGISTER) {...
#ifdef CONFIG_IPV6_MULTIPLE_TABLESnet->ipv6.ip6_blk_hole_entry->dst.dev = dev;net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev);...
#endif} else if (event == NETDEV_UNREGISTER &&dev->reg_state != NETREG_UNREGISTERED) {/* NETDEV_UNREGISTER could be fired for multiple times by* netdev_wait_allrefs(). Make sure we only call this once.*/in6_dev_put_clear(&net->ipv6.ip6_null_entry->rt6i_idev);
#ifdef CONFIG_IPV6_MULTIPLE_TABLESin6_dev_put_clear(&net->ipv6.ip6_blk_hole_entry->rt6i_idev);

默认命名空间中的blackhole路由缓存项,由初始化函数ip6_route_init_special_entries赋值回环接口以及其所对应的inet6_dev结构。

void __init ip6_route_init_special_entries(void)
{/* Registering of the loopback is done before this portion of code,* the loopback reference in rt6_info will not be taken, do it* manually for init_net */...#ifdef CONFIG_IPV6_MULTIPLE_TABLESinit_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev;init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);

由函数addrconf_init可知,在调用ip6_route_init_special_entries之前,已经将默认命名空间init_net中的环回接口进行了初始化。

int __init addrconf_init(void)
{struct inet6_dev *idev;int i, err;...rtnl_lock();idev = ipv6_add_dev(init_net.loopback_dev);rtnl_unlock();if (IS_ERR(idev)) {err = PTR_ERR(idev);goto errlo;}ip6_route_init_special_entries();

blackhole策略路由

如下策略路由,对于目的地址属于3ffe::/64的报文,禁止报文进行路由。

# ip -6 rule add from 3ffe::/64 type blackhole
#
$ ip -6 rule
0:      from all lookup local
32764:  from 3ffe::/64 blackhole

策略路由查找函数fib_rules_lookup,如果action不等于FR_ACT_GOTO或者FR_ACT_NOP,对于IPv6协议,执行fib6_rule_action。

int fib_rules_lookup(struct fib_rules_ops *ops, struct flowi *fl,int flags, struct fib_lookup_arg *arg)
{struct fib_rule *rule;list_for_each_entry_rcu(rule, &ops->rules_list, list) {
jumped:if (!fib_rule_match(rule, ops, fl, flags, arg))continue;if (rule->action == FR_ACT_GOTO) {struct fib_rule *target;target = rcu_dereference(rule->ctarget);if (target == NULL) {continue;} else {rule = target;goto jumped;}} else if (rule->action == FR_ACT_NOP)continue;elseerr = INDIRECT_CALL_MT(ops->action,fib6_rule_action,fib4_rule_action,rule, fl, flags, arg);

对于action类型等于FR_ACT_BLACKHOLE的策略路由,直接使用命名空间中的ip6_blk_hole_entry路由缓存项。

static int __fib6_rule_action(struct fib_rule *rule, struct flowi *flp,int flags, struct fib_lookup_arg *arg)
{struct fib6_result *res = arg->result;struct rt6_info *rt = NULL;struct net *net = rule->fr_net;switch (rule->action) {default:case FR_ACT_BLACKHOLE:err = -EINVAL;rt = net->ipv6.ip6_blk_hole_entry;goto discard_pkt;...}discard_pkt:if (!(flags & RT6_LOOKUP_F_DST_NOREF))dst_hold(&rt->dst);
out:res->rt6 = rt;return err;

blackhole路由缓存处理函数

在ip6_blk_hole_entry_template中,将input和output函数分别赋值为dst_discard和dst_discard_out,对于接收到的外部报文,或者本机发出的报文,都执行丢弃,释放skb。

static inline int dst_discard(struct sk_buff *skb)
{return dst_discard_out(&init_net, skb->sk, skb);
}int dst_discard_out(struct net *net, struct sock *sk, struct sk_buff *skb)
{kfree_skb(skb);return 0;
}

内核版本 5.10

IPv6 Blackhole策略路由相关推荐

  1. IPv6 Blackhole路由

    如下添加IPv6路由,对于目的地址属于3301::/64的报文,将报文丢弃. # ip -6 route add blackhole 3301::/64 # # ip -6 route ::1 dev ...

  2. Linux 添加IPv6策略路由,基于策略的路由通过IPv6配置示例

    基于策略的路由为表示和实现转发提供一机制/根据策略的路由数据包定义由网络管理员.基于策略的路由应用到流入数据包并且使用路由映射定义策略.基于在路由映射定义的标准,数据包转发/路由对适当的下一跳.本文为 ...

  3. Android网络框架(二)——策略路由与常用命令

    目录 一. 策略路由 1.1 默认路由表 1.2 默认规则 1.3 路由 二. 命令 2.1 ip route 2.2 ip rule 一. 策略路由 传统路由:在Android4.4之前是使用的传统 ...

  4. android+ip+rule+策略路由,策略路由以及使用 ip route , ip rule , iptables 配置策略路由实例...

    route 命令 使用 Route 命令行工具查看并编辑计算机的 IP 路由表.Route 命令和语法如下所示: route [-f] [-p] [Command [Destination] [mas ...

  5. tcp/ip 协议栈Linux内核源码分析七 路由子系统分析二 策略路由

    内核版本:3.4.39 策略路由就是根据配置策略查找路由表,早期的Linux版本是不支持策略路由的,默认的查找策略就是先查找local路由表,找不到再继续查找main表,当支持策略路由功能时,内核最多 ...

  6. hosts 文件与 ipv6

    ipv6 的项目地址:ipv6-hosts 正如文档中所说,用于在大陆地区加快 Google.YouTube.Facebook.Wikipedia 等的访问:(twitter 不支持) 使用说明(wi ...

  7. 路由总结之静态、RIP、OSPF、IS-IS、BGP和策略路由

    路由无疑是当今网络的核心,看到浩如烟海的网络资料,可以让人皓首穷经啊,而且都是浩浩荡荡几百页,所以想搞简单点. 静态路由 静态路由无疑是最简单,也是最基本的. Ip route-static(指定是静 ...

  8. 华为交换机静态路由配置案例_快速了解配置三层交换机策略路由配置

    交换机策略路由功能简介 交换机的策略路由(PBR:Policy-Based Routing)提供了一种比基于目的地址进行路由转发更加灵活的数据包路由转发机制.策略路由可以根据 IP/IPv6 报文源地 ...

  9. 华为策略路由原理与实验

    概述: 策略路由PBR是一种依据用户制定的策略进行路由选择的机制,分为本地策略路由.接口策略路由和智能策略路由SPR.本课程仅讨论本地策略路由. IP单播策略路由具有如下优点: 可以根据用户实际需求制 ...

最新文章

  1. android开发检测用户是否使用了虚拟定位
  2. ZeroC Ice启用SSL通讯的配置
  3. webform数据导出
  4. 向MFC应用程序添加控制台窗口
  5. c# image转换为bitmap,C# - 转换WPF Image.source到System.Drawing.Bitmap
  6. 让PHP查询mysql时不区分大小写
  7. 第一期:一款简单好用的屏幕画笔工具
  8. 粒子群优化算法(PSO)附代码
  9. 企业如何选择固定资产管理系统?
  10. MAXScript入门
  11. Hexo添加Icarus主题
  12. BI相关的内容---BI是什么,主要工作的内容有哪些?
  13. php仿maka,iH5和MAKA哪个好?
  14. android手机固件升级原理,为什么常说Android手机千万别频繁的系统升级,背后的真实原因?...
  15. Clipboard -- 剪贴板操作
  16. 在Spring中的过滤器
  17. babel-预设和插件
  18. [转]中国为什么培育不出自己的跨国公司(搜藏)
  19. python怎样使用各个日期赤纬_科学网—PyEphem基本功能介绍 - 张金龙的博文
  20. openEuler上一键部署opengauss数据库

热门文章

  1. 关于毕业生就业方向有什么规划
  2. crestline cpv 相关知识
  3. ssh隧道(跳板机)
  4. 【CentOS】Spark 运行环境(Local、Standalone)
  5. Zookeeper Watcher 机制
  6. FlyAI资讯:收藏!深度学习必读10篇经典算法论文总结!
  7. opencascade 获取鼠标选中对象
  8. Solidity优化 - 减少智能合约gas消耗
  9. MongoDB安全认证
  10. 豆瓣石岩谈豆瓣阅读前端排版工作的感受