linux内核 策略路由之添加
来源:互联网 发布:淘宝不能好评返现了 编辑:程序博客网 时间:2024/06/06 01:34
4.3策略规则的添加
对于策略规则的添加,也可以抽象出通用规则接口函数,然后根据传参进入协议相关的策略规则的接口函数;
4.3.1 通用规则的添加
在规则初始化时,会注册添加函数fib_nl_newrule
rtnl_register(PF_UNSPEC, RTM_NEWRULE, fib_nl_newrule, NULL);
接下来,分析创建规则fib_nl_newrule函数
功能:
(1)根据应用层传递的协议类型,找到相应的fib_rules_ops变量;
(2)解析应用层传入的数据;
(3)针对源IP和目的IP,有效性检查
(4)分配新的fib_rule缓存,并对优先级、接口index、接口名称、mark值、action等赋值;
(5)调用协议对应的configure函数,对fib_rule的源IP、目的IP、掩码、tos进行配置;
(6)将fib_rule添加到rule_lists中,并通过netlink通知其他进程。
4.3.1.1 查找fib_rule对应的ops
功能:
根据协议簇 在链表rules_ops中查找符合要求的fib_rules_ops类型的变量;
对于IPV4,变量为fib4_rules_ops。
4.3.2 协议相关规则的配置
此处以IPV4协议类型为例,
对于策略规则的添加,也可以抽象出通用规则接口函数,然后根据传参进入协议相关的策略规则的接口函数;
4.3.1 通用规则的添加
在规则初始化时,会注册添加函数fib_nl_newrule
rtnl_register(PF_UNSPEC, RTM_NEWRULE, fib_nl_newrule, NULL);
接下来,分析创建规则fib_nl_newrule函数
功能:
(1)根据应用层传递的协议类型,找到相应的fib_rules_ops变量;
(2)解析应用层传入的数据;
(3)针对源IP和目的IP,有效性检查
(4)分配新的fib_rule缓存,并对优先级、接口index、接口名称、mark值、action等赋值;
(5)调用协议对应的configure函数,对fib_rule的源IP、目的IP、掩码、tos进行配置;
(6)将fib_rule添加到rule_lists中,并通过netlink通知其他进程。
static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg){ struct net *net = sock_net(skb->sk); struct fib_rule_hdr *frh = nlmsg_data(nlh); struct fib_rules_ops *ops = NULL; struct fib_rule *rule, *r, *last = NULL; struct nlattr *tb[FRA_MAX+1]; int err = -EINVAL, unresolved = 0; if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh))) goto errout; //根据应用层传递的协议类型,找到相应的fib_rules_ops变量 //ipv4对应的是fib4_rules_ops ops = lookup_rules_ops(net, frh->family); if (ops == NULL) { err = -EAFNOSUPPORT; goto errout; } //解析应用层传入的数据nlh,放入tb中。 err = nlmsg_parse(nlh, sizeof(*frh), tb, FRA_MAX, ops->policy); if (err < 0) goto errout; //有效性检查,针对源IP和目的IP err = validate_rulemsg(frh, tb, ops); if (err < 0) goto errout; //分配新的fib_rule缓存 rule = kzalloc(ops->rule_size, GFP_KERNEL); if (rule == NULL) { err = -ENOMEM; goto errout; } rule->fr_net = hold_net(net);//增加rule->net的引用计数 if (tb[FRA_PRIORITY]) rule->pref = nla_get_u32(tb[FRA_PRIORITY]);//设置优先级 if (tb[FRA_IFNAME]) { struct net_device *dev; rule->ifindex = -1;//接口index nla_strlcpy(rule->ifname, tb[FRA_IFNAME], IFNAMSIZ);//接口名称 dev = __dev_get_by_name(net, rule->ifname);//通过接口名找dev if (dev) rule->ifindex = dev->ifindex;//将dev的index赋值给rule接口index } if (tb[FRA_FWMARK]) { rule->mark = nla_get_u32(tb[FRA_FWMARK]);//mark值 if (rule->mark) /* compatibility: if the mark value is non-zero all bits * are compared unless a mask is explicitly specified. */ rule->mark_mask = 0xFFFFFFFF; } if (tb[FRA_FWMASK]) rule->mark_mask = nla_get_u32(tb[FRA_FWMASK]);//mark掩码值 //设置规则action,table id,实现规则与路由表的关联 rule->action = frh->action; rule->flags = frh->flags; rule->table = frh_get_table(frh, tb); //获取默认优先级为除0外的最高优先级 ??怎么理解 if (!rule->pref && ops->default_pref) rule->pref = ops->default_pref(ops); err = -EINVAL; if (tb[FRA_GOTO]) { if (rule->action != FR_ACT_GOTO) goto errout_free; rule->target = nla_get_u32(tb[FRA_GOTO]); /* Backward jumps are prohibited to avoid endless loops */ if (rule->target <= rule->pref) goto errout_free; list_for_each_entry(r, &ops->rules_list, list) { if (r->pref == rule->target) { rule->ctarget = r; break; } } if (rule->ctarget == NULL) unresolved = 1; } else if (rule->action == FR_ACT_GOTO) goto errout_free; //调用协议对应的configure函数,这里就是协议相关的添加 err = ops->configure(rule, skb, frh, tb); if (err < 0) goto errout_free; //找到第一个pref比新创建的fib_rule的pref值大的 fib_rule //然后将新创建的fib_rule添到该规则之前 //若没有找到,则添加到已有规则链表之后 list_for_each_entry(r, &ops->rules_list, list) { if (r->pref > rule->pref) break; last = r; } fib_rule_get(rule);//增加fib_rule的引用计数 if (ops->unresolved_rules) { /* * There are unresolved goto rules in the list, check if * any of them are pointing to this new rule. */ list_for_each_entry(r, &ops->rules_list, list) { if (r->action == FR_ACT_GOTO && r->target == rule->pref) { BUG_ON(r->ctarget != NULL); rcu_assign_pointer(r->ctarget, rule); if (--ops->unresolved_rules == 0) break; } } } if (rule->action == FR_ACT_GOTO) ops->nr_goto_rules++; if (unresolved) ops->unresolved_rules++; //根据优先级,将fib_rule添到rules_list链表中 if (last) list_add_rcu(&rule->list, &last->list); else list_add_rcu(&rule->list, &ops->rules_list); //通过netlink通知其他进程 notify_rule_change(RTM_NEWRULE, rule, ops, nlh, NETLINK_CB(skb).pid); flush_route_cache(ops);//刷新路由缓存 rules_ops_put(ops);//将一个特定模块module的引用计数减1 return 0;errout_free: release_net(rule->fr_net);//减少rule->net的引用计数 kfree(rule);errout: rules_ops_put(ops); return err;}
4.3.1.1 查找fib_rule对应的ops
功能:
根据协议簇 在链表rules_ops中查找符合要求的fib_rules_ops类型的变量;
对于IPV4,变量为fib4_rules_ops。
static struct fib_rules_ops *lookup_rules_ops(struct net *net, int family){ struct fib_rules_ops *ops; rcu_read_lock(); list_for_each_entry_rcu(ops, &net->rules_ops, list) { if (ops->family == family) { if (!try_module_get(ops->owner)) ops = NULL; rcu_read_unlock(); return ops; } } rcu_read_unlock(); return NULL;}
4.3.2 协议相关规则的配置
此处以IPV4协议类型为例,
功能:
ipv4的配置函数,根据应用层传参,设置fib4_rule变量参数:源IP、目的IP、掩码、路由表ID、tos;
static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb, struct fib_rule_hdr *frh, struct nlattr **tb)// tb 添加策略规则的可选属性{ struct net *net = sock_net(skb->sk); int err = -EINVAL; struct fib4_rule *rule4 = (struct fib4_rule *) rule; if (frh->tos & ~IPTOS_TOS_MASK) goto errout; //若应用层没有设置路由表ID,则创建一个新的,并赋值给rule->table if (rule->table == RT_TABLE_UNSPEC) { if (rule->action == FR_ACT_TO_TBL) { struct fib_table *table; table = fib_empty_table(net); if (table == NULL) { err = -ENOBUFS; goto errout; } rule->table = table->tb_id; } } if (frh->src_len) rule4->src = nla_get_be32(tb[FRA_SRC]); if (frh->dst_len) rule4->dst = nla_get_be32(tb[FRA_DST]);#ifdef CONFIG_NET_CLS_ROUTE if (tb[FRA_FLOW]) rule4->tclassid = nla_get_u32(tb[FRA_FLOW]);#endif rule4->src_len = frh->src_len; rule4->srcmask = inet_make_mask(rule4->src_len); rule4->dst_len = frh->dst_len; rule4->dstmask = inet_make_mask(rule4->dst_len); rule4->tos = frh->tos; err = 0;errout: return err;}
0 0
- linux内核 策略路由之添加
- linux内核 策略路由之基本结构
- linux内核 策略路由之初始化
- linux内核 策略路由之查找
- linux内核 策略路由之删除
- Linux 路由 学习笔记 之六 策略规则的添加
- linux 内核路由添加三种方式
- linux内核 路由fib表之数据结构
- linux内核 路由fib表之初始化
- linux内核 路由fib表之创建
- linux内核 路由fib表之删除
- linux内核 路由缓存表之数据结构
- linux内核 路由缓存表之创建
- linux路由表,策略路由,路由查找
- linux策略路由实例
- linux 策略路由
- Linux 策略路由
- linux 策略路由
- JSPatch 实现原理详解
- extract(c1 from d1)
- dbtimezone
- current_timestamp
- 关于大神--->>>快速集成iOS基于RTMP的视频推流
- linux内核 策略路由之添加
- CF 9B模拟
- UVA 1252 Twenty Questions
- UVA 1627 Team them up!
- UVA 10934 Dropping water balloons
- 简单算法题之 Two Sum
- #ifdef #else #endif #fi #ifndef 的用法
- java IDEA加密/解密 源码
- POJ 3311 Hie with the Pie (Floyd + 暴力全排列 || Floyd + 状态压缩DP (已补充))