__inet_insert_ifa/__inet_del_ifa
两个函数分别完成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的更多相关文章
- ifa_local 和 ifa_address
ifa_local 和 ifa_address区别联系: 1. 在配置了支持广播的接口上,与IFA_LOCAL一样,同样表示本地ip地址: 2. 对于点对点链路,IFA_ADDRESS表示的是对端的地 ...
随机推荐
- day06 小数据池和编码
一. 上次课内容回顾字典:由{}括起来. 每个元素用逗号隔开, key:value的形式存储数据key: 不可变的. 可哈希的.增删改查:1. 增加: 直接用新key来赋值. dict[key] = ...
- [BZOJ3223]文艺平衡树 无旋Treap
3223: Tyvj 1729 文艺平衡树 Time Limit: 10 Sec Memory Limit: 128 MB Description 您需要写一种数据结构(可参考题目标题),来维护一个 ...
- Qt消息机制和事件
Qt消息机制和事件 1 事件 事件(event)是由系统或者 Qt 本身在不同的时刻发出的.当用户按下鼠标.敲下键盘,或者是窗口需要重新绘制的时候,都会发出一个相应的事件.一些事件在对用户操作做出响应 ...
- 【刷题】洛谷 P3676 小清新数据结构题
题目背景 本题时限2s,内存限制256M 题目描述 在很久很久以前,有一棵n个点的树,每个点有一个点权. 现在有q次操作,每次操作是修改一个点的点权或指定一个点,询问以这个点为根时每棵子树点权和的平方 ...
- Glide加载图片并保存到本地返回file,bitmap
有很多朋友都想要知道32位和64位的区别是什么,因为大家都拿不准自己要装32位系统还是64位系统,因此彷徨是必然的.那么到底区别是啥咧?如果大家想要知道的话,下面就让小编给大家带来32位和64位的区别 ...
- 【BZOJ4755】扭动的回文串(Manacher,哈希)
[BZOJ4755]扭动的回文串(Manacher,哈希) 题面 BZOJ 题解 不要真的以为看见了回文串就是\(PAM,Manacher\)一类就可以过. 这题显然不行啊. 我们主要考虑如何解决跨串 ...
- openCV实例:Canny边缘检测
http://blog.sina.com.cn/s/blog_737adf530100z0jk.html 在第一次使用openCV程序成功对图像进行打开后,现在开始试验第二个例程试验:Canny边缘检 ...
- php的错误处理机制
看tp5源码的,补充下 error_reporting(E_ALL); set_error_handler([__CLASS__, 'appError']); set_exception_handle ...
- dmsg命令使用
http://note.youdao.com/noteshare?id=6771284da9f10ac35652907898d63141
- zabbix添加cpu使用率图形监控
zabbix版本: 3.2.5 zabbix 自带的windows模板中没有监控cpu使用率的,可以在模板里自己添加 1. 配置 ---> 模板---> Template OS Windo ...