__inet_insert_ifa/__inet_del_ifa

Kernel: 4.12.6

添加ip地址:主从ip的判断,并且插入到合适的位置中;

static int __inet_insert_ifa(struct in_ifaddr *ifa, struct nlmsghdr *nlh,
                 u32 portid)
{
    struct in_device *in_dev = ifa->ifa_dev;
    struct in_ifaddr *ifa1, **ifap, **last_primary;

    ASSERT_RTNL();

    //ifa_local地址不存在
    if (!ifa->ifa_local) {
        inet_free_ifa(ifa);
        return 0;
    }

    //去除从地址标志
    ifa->ifa_flags &= ~IFA_F_SECONDARY;

    //获取地址列表
    last_primary = &in_dev->ifa_list;

    //遍历地址列表
    for (ifap = &in_dev->ifa_list; (ifa1 = *ifap) != NULL;
         ifap = &ifa1->ifa_next) {

        //查找合适插入主地址的位置
        if (!(ifa1->ifa_flags & IFA_F_SECONDARY) && //主地址
            ifa->ifa_scope <= ifa1->ifa_scope) //ifa范围小于主地址范围
            last_primary = &ifa1->ifa_next; //记录插入位置

        //掩码相同并且在同一子网
        if (ifa1->ifa_mask == ifa->ifa_mask &&
            inet_ifa_match(ifa1->ifa_address, ifa)) {


            //地址也相同,则地址已存在
            if (ifa1->ifa_local == ifa->ifa_local) {
                inet_free_ifa(ifa);
                return -EEXIST;
            }

             //范围不同,非法地址
            if (ifa1->ifa_scope != ifa->ifa_scope) {
                inet_free_ifa(ifa);
                return -EINVAL;
            }

            //在同一子网,ip地址不同,范围相同,则为从地址

            //地址打从地址标志
            ifa->ifa_flags |= IFA_F_SECONDARY;
        }
    }

    //为主地址
    if (!(ifa->ifa_flags & IFA_F_SECONDARY)) {
        prandom_seed((__force u32) ifa->ifa_local);
        ifap = last_primary;
    }

    //将ifa节点添加到ifa_list链表的合适位置
    //主地址添加符合范围的最后一个primary之后
    //从地址添加到链表尾
    ifa->ifa_next = *ifap;
    *ifap = ifa;

    //加入hash表
    inet_hash_insert(dev_net(in_dev->dev), ifa);

    //取消并重新提交检查生命周期任务
    cancel_delayed_work(&check_lifetime_work);
    queue_delayed_work(system_power_efficient_wq, &check_lifetime_work, 0);

    /* Send message first, then call notifier.
       Notifier will trigger FIB update, so that
       listeners of netlink will know about new ifaddr */

    //发送netlink消息
    rtmsg_ifa(RTM_NEWADDR, ifa, nlh, portid);

    //inetaddr_chain通知ip地址加入
    blocking_notifier_call_chain(&inetaddr_chain, NETDEV_UP, ifa);

    return 0;
}

static int inet_insert

删除ip地址:主ip删除,若配置能够提升成主ip,则从ip提升成主ip,否则全部删除;

static void __inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
             int destroy, struct nlmsghdr *nlh, u32 portid)
{
    struct in_ifaddr *promote = NULL;
    struct in_ifaddr *ifa, *ifa1 = *ifap;
    struct in_ifaddr *last_prim = in_dev->ifa_list;
    struct in_ifaddr *prev_prom = NULL;
    int do_promote = IN_DEV_PROMOTE_SECONDARIES(in_dev);

    ASSERT_RTNL();

    //ip配置块需要被释放
    if (in_dev->dead)
        goto no_promotions;

    /* 1. Deleting primary ifaddr forces deletion all secondaries
     * unless alias promotion is set
     **/

    //要删除的地址为主地址
    if (!(ifa1->ifa_flags & IFA_F_SECONDARY)) {
        struct in_ifaddr **ifap1 = &ifa1->ifa_next;

        //遍历链表
        while ((ifa = *ifap1) != NULL) {

            //找到范围内最后的主地址
            if (!(ifa->ifa_flags & IFA_F_SECONDARY) &&
                ifa1->ifa_scope <= ifa->ifa_scope)
                last_prim = ifa;

            //如果是主地址
            //掩码不同
            //不在同一子网
            //记录这个从地址,继续查找
            if (!(ifa->ifa_flags & IFA_F_SECONDARY) ||
                ifa1->ifa_mask != ifa->ifa_mask ||
                !inet_ifa_match(ifa1->ifa_address, ifa)) {
                ifap1 = &ifa->ifa_next;
                prev_prom = ifa;
                continue;
            }

            //与ip在同一子网的从地址
            

            //如果没有从地址提升,则删除之
            if (!do_promote) {
                inet_hash_remove(ifa);
                *ifap1 = ifa->ifa_next;

                //通知删除地址
                rtmsg_ifa(RTM_DELADDR, ifa, nlh, portid);
                blocking_notifier_call_chain(&inetaddr_chain,
                        NETDEV_DOWN, ifa);
                inet_free_ifa(ifa);
            } else { //有从地址提升,则记录从地址,跳出
                promote = ifa;
                break;
            }
        }
    }

    /* On promotion all secondaries from subnet are changing
     * the primary IP, we must remove all their routes silently
     * and later to add them back with new prefsrc. Do this
     * while all addresses are on the device list.
     */
    //遍历从地址,相同子网的清除fib表项
    for (ifa = promote; ifa; ifa = ifa->ifa_next) {
        if (ifa1->ifa_mask == ifa->ifa_mask &&
            inet_ifa_match(ifa1->ifa_address, ifa))
            fib_del_ifaddr(ifa, ifa1);
    }

no_promotions:
    /* 2. Unlink it */

    //从链表和hash表中删除目标地址
    *ifap = ifa1->ifa_next;
    inet_hash_remove(ifa1);

    /* 3. Announce address deletion */

    /* Send message first, then call notifier.
       At first sight, FIB update triggered by notifier
       will refer to already deleted ifaddr, that could confuse
       netlink listeners. It is not true: look, gated sees
       that route deleted and if it still thinks that ifaddr
       is valid, it will try to restore deleted routes... Grr.
       So that, this order is correct.
     */

    //通知地址删除
    rtmsg_ifa(RTM_DELADDR, ifa1, nlh, portid);
    blocking_notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa1);

    //进行地址提升
    if (promote) {
        struct in_ifaddr *next_sec = promote->ifa_next;

        //将地址插入到主地址后面
        if (prev_prom) {
            prev_prom->ifa_next = promote->ifa_next;
            promote->ifa_next = last_prim->ifa_next;
            last_prim->ifa_next = promote;
        }

        //去掉从地址标记
        promote->ifa_flags &= ~IFA_F_SECONDARY;

        //通知ip设置消息
        rtmsg_ifa(RTM_NEWADDR, promote, nlh, portid);
        blocking_notifier_call_chain(&inetaddr_chain,
                NETDEV_UP, promote);

        //继续遍历从地址
        for (ifa = next_sec; ifa; ifa = ifa->ifa_next) {
            if (ifa1->ifa_mask != ifa->ifa_mask ||
                !inet_ifa_match(ifa1->ifa_address, ifa))
                    continue;

            //与删除地址在同一子网的地址添加fib表项
            
            fib_add_ifaddr(ifa);
        }

    }

    //如果有释放标记,则释放内存
    if (destroy)
        inet_free_ifa(ifa1);
}
原文地址:https://www.cnblogs.com/wanpengcoder/p/7392637.html