zoukankan      html  css  js  c++  java
  • IP结构与操作之__inet_insert_ifa/__inet_del_ifa

    两个函数分别完成ip地址的添加和删除工作,具体见下面源码分析;

     1 /* 
     2     添加ip地址 
     3     主地址添加到最后一个满足范围的主地址后面
     4     从地址添加到整个列表后面
     5     若列表中存在与插入地址在同一子网的地址,则
     6     要求ip地址不同且范围相同,并且插入地址认为是从地址
     7 */
     8 static int __inet_insert_ifa(struct in_ifaddr *ifa, struct nlmsghdr *nlh,
     9                  u32 portid)
    10 {
    11     struct in_device *in_dev = ifa->ifa_dev;
    12     struct in_ifaddr *ifa1, **ifap, **last_primary;
    13 
    14     ASSERT_RTNL();
    15 
    16     /* 地址不存在 */
    17     if (!ifa->ifa_local) {
    18         inet_free_ifa(ifa);
    19         return 0;
    20     }
    21 
    22     /* 清除从地址标记 */
    23     ifa->ifa_flags &= ~IFA_F_SECONDARY;
    24 
    25     /* 记录最后一个满足范围的主地址位置,用于插入 */
    26     last_primary = &in_dev->ifa_list;
    27 
    28     /* 遍历地址列表 */
    29     for (ifap = &in_dev->ifa_list; (ifa1 = *ifap) != NULL;
    30          ifap = &ifa1->ifa_next) {
    31          /* 不是从地址&& 范围值小于当前地址 */
    32         if (!(ifa1->ifa_flags & IFA_F_SECONDARY) &&
    33             ifa->ifa_scope <= ifa1->ifa_scope)
    34             /* 记录主地址的next指针 */
    35             last_primary = &ifa1->ifa_next;
    36 
    37         /* 同一子网 */
    38         if (ifa1->ifa_mask == ifa->ifa_mask &&
    39             inet_ifa_match(ifa1->ifa_address, ifa)) {
    40             /* 地址相同 */
    41             if (ifa1->ifa_local == ifa->ifa_local) {
    42                 /* 地址已存在 */
    43                 inet_free_ifa(ifa);
    44                 return -EEXIST;
    45             }
    46 
    47             /* 范围不同 */
    48             if (ifa1->ifa_scope != ifa->ifa_scope) {
    49                 /* 非法地址 */
    50                 inet_free_ifa(ifa);
    51                 return -EINVAL;
    52             }
    53 
    54             /* 同子网范围相同的不同ip地址为从地址 */
    55             ifa->ifa_flags |= IFA_F_SECONDARY;
    56         }
    57     }
    58 
    59 
    60     /* 下面添加地址规则 */
    61     /* 主地址放在最后一个满足范围的主地址的后面 */
    62     /* 从地址放在最后一个(从)地址的后面 */
    63 
    64 
    65     /* 地址为主地址 */
    66     if (!(ifa->ifa_flags & IFA_F_SECONDARY)) {
    67         prandom_seed((__force u32) ifa->ifa_local);
    68         /*  ifap指向最后一个主地址的next指针 */
    69         ifap = last_primary;
    70     }
    71 
    72     /* ifa的next赋值为ifap保存的值,也就是待插入位置的下一个节点地址 */
    73     ifa->ifa_next = *ifap;
    74 
    75     /* 而前面保存下一个节点的next指针指向新的ifa */
    76     *ifap = ifa;
    77 
    78     /* 插入hash表 */
    79     inet_hash_insert(dev_net(in_dev->dev), ifa);
    80 
    81     /* 重新开启检查生命周期任务 */
    82     cancel_delayed_work(&check_lifetime_work);
    83     queue_delayed_work(system_power_efficient_wq, &check_lifetime_work, 0);
    84 
    85     /* Send message first, then call notifier.
    86        Notifier will trigger FIB update, so that
    87        listeners of netlink will know about new ifaddr */
    88 
    89     /* 发送添加新地址消息 */
    90     rtmsg_ifa(RTM_NEWADDR, ifa, nlh, portid);
    91 
    92     /* 通知设备启动 */
    93     blocking_notifier_call_chain(&inetaddr_chain, NETDEV_UP, ifa);
    94 
    95     return 0;
    96 }
      1 /* 删除ip地址,如果从地址允许提升为主地址,则提升 */
      2 static void __inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
      3              int destroy, struct nlmsghdr *nlh, u32 portid)
      4 {
      5     struct in_ifaddr *promote = NULL;
      6     struct in_ifaddr *ifa, *ifa1 = *ifap;
      7     struct in_ifaddr *last_prim = in_dev->ifa_list;
      8     struct in_ifaddr *prev_prom = NULL;
      9 
     10     /* 从地址是否允许提升为主地址 */
     11     int do_promote = IN_DEV_PROMOTE_SECONDARIES(in_dev);
     12 
     13     ASSERT_RTNL();
     14 
     15     /* ip控制块正在被销毁 */
     16     if (in_dev->dead)
     17         goto no_promotions;
     18 
     19     /* 1. Deleting primary ifaddr forces deletion all secondaries
     20      * unless alias promotion is set
     21      **/
     22 
     23     /* 如果是主地址 */
     24     if (!(ifa1->ifa_flags & IFA_F_SECONDARY)) {
     25         struct in_ifaddr **ifap1 = &ifa1->ifa_next;
     26 
     27         /* 遍历链表 */
     28         while ((ifa = *ifap1) != NULL) {
     29 
     30             /* 最后一个满足范围的主地址 */
     31             if (!(ifa->ifa_flags & IFA_F_SECONDARY) &&
     32                 ifa1->ifa_scope <= ifa->ifa_scope)
     33                 last_prim = ifa;
     34 
     35             /* 主地址|| 子网掩码不同 || 网络前缀不同 */
     36             if (!(ifa->ifa_flags & IFA_F_SECONDARY) ||
     37                 ifa1->ifa_mask != ifa->ifa_mask ||
     38                 !inet_ifa_match(ifa1->ifa_address, ifa)) {
     39                 ifap1 = &ifa->ifa_next;
     40                 prev_prom = ifa;
     41                 continue;
     42             }
     43 
     44             /* 找到在同一子网的从地址 */
     45 
     46             /* 不允许提升ip地址 */
     47             if (!do_promote) {
     48                 /* 删除地址 */
     49                 inet_hash_remove(ifa);
     50                 *ifap1 = ifa->ifa_next;
     51 
     52                 /* 发送删除地址消息 */
     53                 rtmsg_ifa(RTM_DELADDR, ifa, nlh, portid);
     54                 /* 通知设备关闭 */
     55                 blocking_notifier_call_chain(&inetaddr_chain,
     56                         NETDEV_DOWN, ifa);
     57                 inet_free_ifa(ifa);
     58             } else {
     59                 /* 需要提升的从地址为找到的地址 */
     60                 promote = ifa;
     61                 break;
     62             }
     63         }
     64     }
     65 
     66     /* On promotion all secondaries from subnet are changing
     67      * the primary IP, we must remove all their routes silently
     68      * and later to add them back with new prefsrc. Do this
     69      * while all addresses are on the device list.
     70      */
     71     /* 因为允许提升从地址,需要 删除从地址的路由 */
     72     for (ifa = promote; ifa; ifa = ifa->ifa_next) {
     73         if (ifa1->ifa_mask == ifa->ifa_mask &&
     74             inet_ifa_match(ifa1->ifa_address, ifa))
     75             fib_del_ifaddr(ifa, ifa1);
     76     }
     77 
     78 no_promotions:
     79     /* 2. Unlink it */
     80 
     81     /* 删除地址 */
     82     *ifap = ifa1->ifa_next;
     83     inet_hash_remove(ifa1);
     84 
     85     /* 3. Announce address deletion */
     86 
     87     /* Send message first, then call notifier.
     88        At first sight, FIB update triggered by notifier
     89        will refer to already deleted ifaddr, that could confuse
     90        netlink listeners. It is not true: look, gated sees
     91        that route deleted and if it still thinks that ifaddr
     92        is valid, it will try to restore deleted routes... Grr.
     93        So that, this order is correct.
     94      */
     95     /* 发送删除地址消息 */
     96     rtmsg_ifa(RTM_DELADDR, ifa1, nlh, portid);
     97     /* 通知设备关闭 */
     98     blocking_notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa1);
     99 
    100     /* 允许提升从ip为主ip */
    101     if (promote) {
    102         struct in_ifaddr *next_sec = promote->ifa_next;
    103 
    104         /* 插入该从地址到主地址位置 */
    105         if (prev_prom) {
    106             prev_prom->ifa_next = promote->ifa_next;
    107             promote->ifa_next = last_prim->ifa_next;
    108             last_prim->ifa_next = promote;
    109         }
    110 
    111         /* 修改该ip为主地址 */
    112         promote->ifa_flags &= ~IFA_F_SECONDARY;
    113 
    114         /* 发送新地址消息 */
    115         rtmsg_ifa(RTM_NEWADDR, promote, nlh, portid);
    116         /* 通知设备启动 */
    117         blocking_notifier_call_chain(&inetaddr_chain,
    118                 NETDEV_UP, promote);
    119 
    120         /* 重新添加路由表 */
    121         for (ifa = next_sec; ifa; ifa = ifa->ifa_next) {
    122             if (ifa1->ifa_mask != ifa->ifa_mask ||
    123                 !inet_ifa_match(ifa1->ifa_address, ifa))
    124                     continue;
    125             fib_add_ifaddr(ifa);
    126         }
    127 
    128     }
    129 
    130     /* 需要释放则释放内存 */
    131     if (destroy)
    132         inet_free_ifa(ifa1);
    133 }
  • 相关阅读:
    如何发布自定义的UI 组件库到 npmjs.com 并且编写 UI组件说明文档
    Go 包导入备忘
    Incorrect column count: expected 1, actual 5,JdbcTemplate queryForList 出错
    SpringJdbc持久层封装,Spring jdbcTemplate封装,springJdbc泛型Dao,Spring baseDao封装
    Java最快的maven仓库地址,国内Maven地址,超快的Maven地址
    SQLyog-12.4.2版下载,SQLyog最新版下载,SQLyog官网下载,SQLyog Download
    easyui datebox定位到某一个日期, easyui datebox直接定位到具体的日期, easyui datebox MoveTo方法使用
    Echarts调整图表上下左右的间距,Echarts调整柱状图左右的间距
    Spring整合Quartz定时任务执行2次,Spring定时任务执行2次
    Linux关闭Tomcat为什么要用Kill,而不是shutdown.sh
  • 原文地址:https://www.cnblogs.com/wanpengcoder/p/7538366.html
Copyright © 2011-2022 走看看