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 }