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

 /*
添加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(); /* 地址不存在 */
if (!ifa->ifa_local) {
inet_free_ifa(ifa);
return ;
} /* 清除从地址标记 */
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)
/* 记录主地址的next指针 */
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指向最后一个主地址的next指针 */
ifap = last_primary;
} /* ifa的next赋值为ifap保存的值,也就是待插入位置的下一个节点地址 */
ifa->ifa_next = *ifap; /* 而前面保存下一个节点的next指针指向新的ifa */
*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, ); /* Send message first, then call notifier.
Notifier will trigger FIB update, so that
listeners of netlink will know about new ifaddr */ /* 发送添加新地址消息 */
rtmsg_ifa(RTM_NEWADDR, ifa, nlh, portid); /* 通知设备启动 */
blocking_notifier_call_chain(&inetaddr_chain, NETDEV_UP, ifa); return ;
}
 /* 删除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.
*/
/* 因为允许提升从地址,需要 删除从地址的路由 */
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 */ /* 删除地址 */
*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); /* 允许提升从ip为主ip */
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;
} /* 修改该ip为主地址 */
promote->ifa_flags &= ~IFA_F_SECONDARY; /* 发送新地址消息 */
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_add_ifaddr(ifa);
} } /* 需要释放则释放内存 */
if (destroy)
inet_free_ifa(ifa1);
}

__inet_insert_ifa/__inet_del_ifa的更多相关文章

  1. ifa_local 和 ifa_address

    ifa_local 和 ifa_address区别联系: 1. 在配置了支持广播的接口上,与IFA_LOCAL一样,同样表示本地ip地址: 2. 对于点对点链路,IFA_ADDRESS表示的是对端的地 ...

随机推荐

  1. mysql 、慢查询、到底如何玩

    在项目开发中,那些开发大佬经常会写出一些SQL语句,一条糟糕的SQL语句可能让你测试的整个程序都非常慢,超过10秒的话,我觉得一般用户就会选择关闭网页,如何优化SQL语句将那些运行时间 比较长的SQL ...

  2. angularjs 常用功能练习

    <!DOCTYPE html> <html ng-app="app"> <head> <meta charset="utf-8& ...

  3. HDU4055_Number String

    题目告诉你在一个排列中,相邻两个数的大小关系.问你排列可能有多少种情况. DP. f[i][j]表示将i个数按照前面i-1个大小关系排列且最后一个数位j的排列数有多少个. 这样对于新加入的一个数i+1 ...

  4. HDU4747——2013 ACM/ICPC Asia Regional Hangzhou Online

    啦啦啦. 这是杭州网赛的一个题目,当时没做出来,当然这个想法确实比较难想到. 题目质量很高,这个题目也很特别,以前都没做过类似的题目.让我又一次体验了线段树的强大力量. 题目的意思是给你n个数a1-a ...

  5. Python中int()函数的用法浅析

      int()是Python的一个内部函数 Python系统帮助里面是这么说的 >>> help(int)  Help on class int in module __builti ...

  6. 【题解】APIO2014回文串

    哇哦~想不到我有生之年竟然能够做出字符串的题目ヾ(✿゚▽゚)ノ虽然这题比较裸但依然灰常开心! 首先有一个棒棒的性质:本质不同的回文串最多有 O(n) 个.首先 manacher 把它们都找出来,然后问 ...

  7. bzoj2089&2090: [Poi2010]Monotonicity

    双倍经验一眼题... f[i][1/2]表示以i结尾,当前符号应该是</>的最长上升子序列, 用BIT优化转移就好 =的话就不用说了吧= = #include<iostream> ...

  8. 图像PNG格式介绍

    1 图像png格式简介 PNG是20世纪90年代中期开始开发的图像文件存储格式,其目的是企图替代GIF和TIFF文件格式,同时增加一些GIF文件格式所不具备的特性.流式网络图形格式(PortableN ...

  9. laravel 添加自定义 Provider 配置之后不生效的问题

    有可能是配置缓存导致的, 运行: php artisan config:clear 可清除配置缓存,配置缓存保存在 bootstrap/cache/config.php,可以直接去那文件夹看看是不是缓 ...

  10. codeforces 691F 暴力

    传送门:https://codeforces.com/contest/691/problem/F 题意:给你n个数和q次询问,每次询问问你有多少对ai,aj满足ai*aj>=q[i],注意 a* ...