linux内核 策略路由之初始化

4.2 路由策略初始化
        路由策略的初始化,主要分为通用策略规则初始化和协议相关的策略规则初始化。
4.2.1 通用策略规则初始化
        功能:注册通知链,包括设备注册和注销时的通知。

static int __init fib_rules_init(void)
{
    int err;
    rtnl_register(PF_UNSPEC, RTM_NEWRULE, fib_nl_newrule, NULL);
    rtnl_register(PF_UNSPEC, RTM_DELRULE, fib_nl_delrule, NULL);
    rtnl_register(PF_UNSPEC, RTM_GETRULE, NULL, fib_nl_dumprule);

    err = register_pernet_subsys(&fib_rules_net_ops);
    if (err < 0)
        goto fail;

    //该通知链只处理NETDEV_REGISTER、NETDEV_UNREGISTER两个事件。
    //(1)设备注册时,遍历策略规则,对于匹配的规则,将该策略规则的index赋值;
    //(2)设备注销时,对于匹配的规则,将策略规则的index值设为-1。
    err = register_netdevice_notifier(&fib_rules_notifier);
    if (err < 0)
        goto fail_unregister;

    return 0;

fail_unregister:
    unregister_pernet_subsys(&fib_rules_net_ops);
fail:
    rtnl_unregister(PF_UNSPEC, RTM_NEWRULE);
    rtnl_unregister(PF_UNSPEC, RTM_DELRULE);
    rtnl_unregister(PF_UNSPEC, RTM_GETRULE);
    return err;
}

4.2.2 协议相关的策略规则初始化
这里主要讲IPV4协议相关初始化fib4_rules_init
功能:(1)注册fib4_rules_ops
(2)创建local、main、default规则表,添到rules_list
(3)将fib4_rules_ops添到rules_ops中。
int __net_init fib4_rules_init(struct net *net)
{
    int err;
    struct fib_rules_ops *ops;

    //分配空间,初始化
    ops = kmemdup(&fib4_rules_ops_template, sizeof(*ops), GFP_KERNEL);
    if (ops == NULL)
        return -ENOMEM;
    INIT_LIST_HEAD(&ops->rules_list);
    ops->fro_net = net;
    
    //将fib4_rules_ops注册到系统,添加到链表fib4_rules_ops.fro_net.rules_ops中
    fib_rules_register(ops);

    //创建local、main、default规则表,并添到fib4_rules_ops.rules_list中
    err = fib_default_rules_init(ops);
    if (err < 0)
        goto fail;

    //将fib4_rules_ops添到fib4_rules_ops.fro_net.ipv4.rules_ops中
    net->ipv4.rules_ops = ops;
    return 0;

fail:
    /* also cleans all rules already added */
    fib_rules_unregister(ops);
    kfree(ops);
    return err;
}

4.2.2.1 初始化IPV4操作集
        初始化Ipv4对应的操作集fib_rules_ops,并规定ipv4的规则为fib4_rule。

static struct fib_rules_ops fib4_rules_ops_template = {
    .family     = AF_INET,
    .rule_size  = sizeof(struct fib4_rule),
    .addr_size  = sizeof(u32),
    .action     = fib4_rule_action,
    .match      = fib4_rule_match,
    .configure  = fib4_rule_configure,//配置协议相关的fib_rule参数
    .compare    = fib4_rule_compare,
    .fill       = fib4_rule_fill,
    .default_pref   = fib4_rule_default_pref,//获取默认优先级
    .nlmsg_payload  = fib4_rule_nlmsg_payload,
    .flush_cache    = fib4_rule_flush_cache,
    .nlgroup    = RTNLGRP_IPV4_RULE,
    .policy     = fib4_rule_policy,
    .owner      = THIS_MODULE,
};

4.2.2.2 注册策略规则函数

功能:

        (1)对fib_rules_ops进行合理性检查,操作函数是否为空

        (2)将传入的fib_rules_ops添加到rules_ops中。
int fib_rules_register(struct fib_rules_ops *ops)
{
    int err = -EEXIST;
    struct fib_rules_ops *o;
    struct net *net;

    net = ops->fro_net;

    if (ops->rule_size < sizeof(struct fib_rule))
        return -EINVAL;

    if (ops->match == NULL || ops->configure == NULL ||
        ops->compare == NULL || ops->fill == NULL ||
        ops->action == NULL)//操作函数是否为空
        return -EINVAL;

    spin_lock(&net->rules_mod_lock);
    list_for_each_entry(o, &net->rules_ops, list)
        if (ops->family == o->family)
            goto errout;

    hold_net(net);
    list_add_tail_rcu(&ops->list, &net->rules_ops);//添到rules_ops
    err = 0;
errout:
    spin_unlock(&net->rules_mod_lock);

    return err;
}

4.2.2.3 增加local/main/default策略规则

功能:

        (1)增加local/main/default,并添到rules_list链表中。

static int fib_default_rules_init(struct fib_rules_ops *ops)
{
    int err;
    err = fib_default_rule_add(ops, 0, RT_TABLE_LOCAL, FIB_RULE_PERMANENT);
    if (err < 0)
        return err;
    err = fib_default_rule_add(ops, 0x7FFE, RT_TABLE_MAIN, 0);
    if (err < 0)
        return err;
    err = fib_default_rule_add(ops, 0x7FFF, RT_TABLE_DEFAULT, 0);
    if (err < 0)
        return err;
    return 0;
}

        添加默认规则,将新分配的fib_rule,挂到rules_list链表

int fib_default_rule_add(struct fib_rules_ops *ops,
             u32 pref, u32 table, u32 flags)
{
    struct fib_rule *r;

    r = kzalloc(ops->rule_size, GFP_KERNEL);
    if (r == NULL)
        return -ENOMEM;

    atomic_set(&r->refcnt, 1);
    r->action = FR_ACT_TO_TBL;
    r->pref = pref;
    r->table = table;
    r->flags = flags;
    r->fr_net = hold_net(ops->fro_net);

    /* The lock is not required here, the list in unreacheable
     * at the moment this function is called */
    list_add_tail(&r->list, &ops->rules_list);
    return 0;
}

你可能感兴趣的:(linux,网络协议)