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); }
时间: 2024-11-03 22:31:21