网络子系统69_路由表辅助程序

简介:
//	关闭设备上的ip协议
//	函数主要任务:
//		1.删除与设备相关的路由信息
//		2.刷新路由缓存
//		3.通知邻居子系统,与该设备有关的邻居项失效
1.1 static void fib_disable_ip(struct net_device *dev, int force)
{
	if (fib_sync_down(0, dev, force))
		fib_flush();
	rt_cache_flush(0);
	arp_ifdown(dev);
}


//	设备状态改变/删除ip,标记失效路由信息
//	参数:
//		local,被删除的ip地址
//		dev,被关闭的设备
//		force:
//			0, local有效,表示ip地址被删除
//			1, dev有效,表示dev被关闭
//			2, dev有效,表示dev被注销

//	返回值:返回标记为dead的fib_info的数量

//	函数主要任务:
//		1.ip地址被删除
//			1.1 遍历fib_info_laddrhash,标记所有使用该地址作为首选源地址的fib_info->fib_flags|=RTNH_F_DEAD
//		2.设备状态发生改变
//			2.1 遍历fib_info_devhash,标记所有使用该设备的fib_nh->nh_flags|=RTNF_F_DEAD,如果fib_info的所有下一跳均失效,
//				或者设备注销,则标记fib_info->fib_flags|=RTNH_F_DEAD
//		3.返回失效fib_info个数

//	注:
//		1.
//			fib_info_hash 所有fib_info结构被插入到这个hash表
//			fib_info_laddrhash 路由表项有一个首选源地址时,插入到这个表
//		2.
//			fib_create_info 添加新fib_info到fib_info_hash, fib_info_laddrhash,fib_info_cnt统计实例个数,当超过
//			fib_hash_size时,fib_info_hash, fib_info_laddrhash容量同时增加一倍。
//		3.
//			fib_info_devhash 索引与设备相关的所有下一跳的hash表
//		4.
//			fib_info_devhash 静态分配256个bucket
2.1 int fib_sync_down(u32 local, struct net_device *dev, int force)
{
	int ret = 0;
	int scope = RT_SCOPE_NOWHERE;
	//表示设备状态发生改变
	if (force)
		scope = -1;
	//1.处理ip地址被删除
	if (local && fib_info_laddrhash) {
		unsigned int hash = fib_laddr_hashfn(local);
		struct hlist_head *head = &fib_info_laddrhash[hash];
		struct hlist_node *node;
		struct fib_info *fi;
		//遍历fib_info_laddr的bucket
		hlist_for_each_entry(fi, node, head, fib_lhash) {
			//凡是与该首选源地址相关的路由信息,均标识为失效
			if (fi->fib_prefsrc == local) {
				fi->fib_flags |= RTNH_F_DEAD;
				ret++;//统计标识为失效的节点个数
			}
		}
	}
	//2.处理设备状态改变
	if (dev) {
		struct fib_info *prev_fi = NULL;
		//对设备index hash
		unsigned int hash = fib_devindex_hashfn(dev->ifindex);
		struct hlist_head *head = &fib_info_devhash[hash];
		struct hlist_node *node;
		struct fib_nh *nh;
		//遍历使用该设备的下一跳
		hlist_for_each_entry(nh, node, head, nh_hash) {
			struct fib_info *fi = nh->nh_parent;
			int dead;
			
			if (nh->nh_dev != dev || fi == prev_fi)
				continue;
			prev_fi = fi;
			dead = 0;
			//遍历路由信息的所有下一跳
			change_nexthops(fi) {
				//统计失效的下一跳个数
				if (nh->nh_flags&RTNH_F_DEAD)
					dead++;
				else if (nh->nh_dev == dev &&
					 nh->nh_scope != scope) {
					nh->nh_flags |= RTNH_F_DEAD;
					//多路径路由
#ifdef CONFIG_IP_ROUTE_MULTIPATH
					//下一跳失效,调整路由权重
					spin_lock_bh(&fib_multipath_lock);
					fi->fib_power -= nh->nh_power;
					nh->nh_power = 0;
					spin_unlock_bh(&fib_multipath_lock);
#endif
					dead++;
				}
#ifdef CONFIG_IP_ROUTE_MULTIPATH
				//设备注销,与该设备相关的路由信息均失效
				if (force > 1 && nh->nh_dev == dev) {
					dead = fi->fib_nhs;
					break;
				}
#endif
			} endfor_nexthops(fi)
			//所有下一跳均失效,则标记该路由信息失效
			if (dead == fi->fib_nhs) {
				fi->fib_flags |= RTNH_F_DEAD;
				ret++;
			}
		}
	}

	return ret;
}
//	删除失效路由信息
//	函数主要任务:
//		1.由路由表刷新路由表
//		2.刷新路由缓存
3.1 static void fib_flush(void)
{
	int flushed = 0;
	// 编译支持多路由表
#ifdef CONFIG_IP_MULTIPLE_TABLES
	struct fib_table *tb;
	int id;
	//遍历255个路由表
	for (id = RT_TABLE_MAX; id>0; id--) {
		if ((tb = fib_get_table(id))==NULL)
			continue;
		//特定于路由表的刷新操作
		flushed += tb->tb_flush(tb);
	}
#else /* CONFIG_IP_MULTIPLE_TABLES */
	flushed += ip_fib_main_table->tb_flush(ip_fib_main_table);
	flushed += ip_fib_local_table->tb_flush(ip_fib_local_table);
#endif /* CONFIG_IP_MULTIPLE_TABLES */
	//删除的路由个数>0,刷新路由缓存
	if (flushed)
		rt_cache_flush(-1);
}
//	设备开启,激活使用该设备的下一跳
//		在路由的某些下一跳为alive时,更新fib_info结构内该路由的一些参数。

//	返回值:RTNH_F_DEAD标识被清除的fib_info结构的个数

//	函数主要任务:
//		1.1 遍历与设备相关的下一跳信息
//		1.2 清除下一跳的RTNH_F_DEAD标志
//		1.3 清除该下一跳相关的路由信息的RTNH_F_DEAD标志
//		1.4 返回清除RTNH_F_DEAD标志的fib_info个数

//	注:只有内核支持多路径路由时才使用该函数
4.1 int fib_sync_up(struct net_device *dev)
{
	struct fib_info *prev_fi;
	unsigned int hash;
	struct hlist_head *head;
	struct hlist_node *node;
	struct fib_nh *nh;
	int ret;
	//设备需要开启状态
	if (!(dev->flags&IFF_UP))
		return 0;

	prev_fi = NULL;
	hash = fib_devindex_hashfn(dev->ifindex);
	head = &fib_info_devhash[hash];
	ret = 0;
	//与设备相关的所有下一跳
	hlist_for_each_entry(nh, node, head, nh_hash) {
		struct fib_info *fi = nh->nh_parent;
		int alive;

		if (nh->nh_dev != dev || fi == prev_fi)
			continue;

		prev_fi = fi;
		alive = 0;
		//遍历路由信息的下一跳,统计有效下一跳的个数
		change_nexthops(fi) {
			if (!(nh->nh_flags&RTNH_F_DEAD)) {
				alive++;
				continue;
			}
			if (nh->nh_dev == NULL || !(nh->nh_dev->flags&IFF_UP))
				continue;
			if (nh->nh_dev != dev || __in_dev_get(dev) == NULL)
				continue;
			alive++;
			//设备开启,清除之前由于设备关闭而设置的RTNH_F_DEAD标志
			spin_lock_bh(&fib_multipath_lock);
			nh->nh_power = 0;
			nh->nh_flags &= ~RTNH_F_DEAD;
			spin_unlock_bh(&fib_multipath_lock);
		} endfor_nexthops(fi)
		//只要路由信息有一个有效的下一跳,则该路由信息有效
		if (alive > 0) {
			fi->fib_flags &= ~RTNH_F_DEAD;
			ret++;
		}
	}

	return ret;
}

//	绑定路由缓存到邻居子系统
5.1 int arp_bind_neighbour(struct dst_entry *dst)
{
	struct net_device *dev = dst->dev;
	struct neighbour *n = dst->neighbour;

	if (dev == NULL)
		return -EINVAL;
	//此路由缓存还没有绑定邻居项
	if (n == NULL) {
		u32 nexthop = ((struct rtable*)dst)->rt_gateway;
		//回环设备,点到点设备不需要绑定到邻居子系统
		if (dev->flags&(IFF_LOOPBACK|IFF_POINTOPOINT))
			nexthop = 0;
		//根据出口设备,下一跳地址,寻找邻居项
		n = __neigh_lookup_errno(
		    &arp_tbl, &nexthop, dev);
		//绑定到路由缓存
		dst->neighbour = n;
	}
	return 0;
}

目录
相关文章
|
3月前
|
缓存 网络协议 Python
Python网络编程(二)编写TCP协议程序
Python网络编程(二)编写TCP协议程序
118 0
|
7月前
|
网络协议 API 数据处理
【网络编程】第2章(2) 应用程序接口(API)
【网络编程】第2章(2) 应用程序接口(API)
|
4月前
|
网络协议 Java API
基于UDP/TCP实现客户端服务器的网络通信程序
基于UDP/TCP实现客户端服务器的网络通信程序
|
27天前
|
监控 网络协议 Linux
【Shell 命令集合 网络通讯 】Linux 显示网络 连接、路由表和网络接口信息 netstat命令 使用指南
【Shell 命令集合 网络通讯 】Linux 显示网络 连接、路由表和网络接口信息 netstat命令 使用指南
54 1
|
8月前
|
Python
【从零学习python 】73. UDP网络程序-发送数据
【从零学习python 】73. UDP网络程序-发送数据
45 0
|
4月前
|
存储 网络协议 安全
网络编程『socket套接字 ‖ 简易UDP网络程序』
网络编程『socket套接字 ‖ 简易UDP网络程序』
75 0
|
4月前
|
缓存 算法 网络架构
【网络层】IP组播(多播)、硬件组播、IGMP、组播路由选择协议、移动IP、路由器详解、路由表和路由转发
【网络层】IP组播(多播)、硬件组播、IGMP、组播路由选择协议、移动IP、路由器详解、路由表和路由转发
57 0
|
4月前
|
移动开发 开发工具
解决微信H5获取SDK授权报错提示errMsg: “config:fail,Error: 系统错误,错误码:63002,invalid signature [20200908 22:17:17][]“
解决微信H5获取SDK授权报错提示errMsg: “config:fail,Error: 系统错误,错误码:63002,invalid signature [20200908 22:17:17][]“
解决微信H5获取SDK授权报错提示errMsg: “config:fail,Error: 系统错误,错误码:63002,invalid signature [20200908 22:17:17][]“
|
5月前
|
设计模式 存储 API
游戏服务器架构:网络服务器端程序线程划分
游戏服务器架构:网络服务器端程序线程划分
|
7月前
|
弹性计算 Java 数据安全/隐私保护
使用Java面向对象编写网络通信程序应用
本实验将提供一台 Windows Server 2012 64位的 ECS 实例。首先进行Java环境的搭建与配置,然后进行Python开发环境的搭建与配置,最后使用Java与Python语言分别编写与运行简单程序,并进行验证。
40 0

热门文章

最新文章