两个函数分别完成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. RGB555转RGB565

    做tft彩屏显示图片的时候,显示16位位图,显示屏的显示模式为RGB565.使用img2lcd转换后的16位bmp,显示出来后,颜色有偏差:转换为565格式的bin文件,显示完全正常,可以确定转换为b ...

  2. bzoj4484[JSOI2015]最小表示

    题意 给出一张DAG,要求删除尽量多的边使得连通性不变.(即:若删边前u到v有路径,则删边后仍有路径).点数30000,边数100000. 分析 如果从u到v有(u,v)这条边,且从u到v只有这一条路 ...

  3. 黑客帝国雨效果JS

    黑客帝国雨效果JS. <!DOCTYPE html> <html lang="en"> <head> <meta charset=&quo ...

  4. 【JavaScript】table显示问题

    table有时显示出问题,解决办法如下: 添加<thead></thead>和<tbody></tbody>在table的外面添加<div> ...

  5. Spring Boot系列教程十:Spring boot集成Sentinel Redis

    前言 上一篇文章介绍了spring boot集成单点的redis,然而实际生产环境使用单点的redis风险很高,一旦宕机整个服务将无法使用,这篇文章介绍如何使用基于sentinel的redis高可用方 ...

  6. 最长上升子序列nlogn算法

    LIS问题是经典的动态规划问题,它的状态转移相信大家都很熟悉: f[i] = f[k] + 1  (k < i 且 A[k] < A[i]) 显然这样做复杂度是O(n^2) 有没有更快的算 ...

  7. NOIP2016天天爱跑步 题解报告【lca+树上统计(桶)】

    题目描述 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.«天天爱跑步»是一个养成类游戏,需要玩家每天按时上线,完成打卡任务. 这个游戏的地图可以看作一一棵包含 nn个 ...

  8. python 常用 time, datetime处理

    python 中 time 有三种格式: float, struct tuple(time.struct_time 或 datetime.datetime), str 常用的: float --> ...

  9. poj3648 Wedding

    Wedding Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10975   Accepted: 3355   Specia ...

  10. javascript和bigint

    http://note.youdao.com/noteshare?id=91e21eb1d8c20025d72d7ee6f401e34d