浅谈Linux IP路由机制 (linux ip 路由机制)

Linux作为目前更流行的操作系统之一,其网络路由功能也备受青睐。其中,IP路由就是其中之一。本文将从概念、分类、原理等角度来分别介绍Linux IP路由机制。

一、概念

IP路由是指互联网中数据包从一个节点(计算机、路由器等)通过一个或多个中间节点到达目标节点的过程。其主要作用是保证数据能够高效、快速地传输。

Linux IP路由机制是Linux系统中的一种实现路由的机制。在Linux系统中,可以通过配置路由表来实现数据包的转发。

二、分类

根据数据包的路由信息分类,可以将IP路由分为两种:静态路由和动态路由。

静态路由:静态路由是指管理员手动配置的路由。管理员需要手动添加、删除、修改路由表中的路由信息。静态路由的优点是其稳定性高、工作原理简单。但由于需要手动配置,其效率低,不适用于大型企业或数据中心中。

动态路由:动态路由是指路由器通过协议自动学习、交换信息,动态地更新路由表的路由。动态路由技术广泛应用于大型网络中。动态路由协议有多种,包括RIP、OSPF、BGP等。

三、原理

Linux系统中IP路由的实现主要依赖于路由表。路由表是Linux系统中IP路由的核心部分之一,主要用于存储路由器转发数据包的策略。

Linux系统中的路由表主要由四个部分组成:目标IP地址、子网掩码、下一跳IP地址、路由策略。其中,目标IP地址和子网掩码用于匹配数据包的目标IP地址,下一跳IP地址用于指示数据包的下一个路由器或目标主机在网络中的位置,路由策略则用于指示如何转发数据包。

下一跳IP地址是路由表中的重点内容之一。当一个数据包到达路由器时,路由器首先会根据路由表中的目标IP地址和子网掩码来判断其应该往哪里转发。然后,根据路由表中的下一跳IP地址来确定应该往哪一台路由器或主机转发数据包。

路由策略是Linux系统中IP路由机制的另一个重要组成部分。路由策略可以是一些强制性路由,也可以是一些优先级路由。所谓强制性路由,就是指在数据包满足路由表中的最长前缀匹配规则时,强制性地走固定的路径。而优先级路由则是根据不同的路由条目设置不同的优先级,数据包将按优先级更高的路由条目进行转发。

四、

本文从概念、分类、原理等角度介绍了Linux IP路由机制。路由表作为Linux IP路由机制的核心部分之一,其作用是存储路由器转发数据包的策略。路由表中的目标IP地址和子网掩码、下一跳IP地址、路由策略是其组成部分之一。通过深入了解Linux IP路由机制,可以更好地掌握Linux系统的网络路由功能,从而更好地维护和管理网络环境。

相关问题拓展阅读:

从ip addr add和ifconfig的区别看linux网卡ip地址的结构

如果你非常理解网络协议的原理以及网络的分层架构那么我想你就不会有这个问题,实际上,每一个网卡设备都有一个mac地址,但是却可 以有多个网络层地址,比如IP地址,然而这个事实无法很好地像用户提供操作接口,所以就引出了ip别名(IP aliases)和辅助ip(secondary IP addresses)的概念。其实很容易理解简凯这个事实,按照分层的思想,下层总是为上层服务,也就是为上层提供舞台,上层利用下层的服务,而不必让下层知 道自己的情况,如果一个拥有合理mac地址的网卡没有配置网络层地址(比如IP地址)这件事合理的话,那么为这个设备配置多个IP地址也是合理的,正好像 一个ip可以对应多个应用层端口一样,也就是说,下层对上层总是一对多的关系,在分层架构中这种关系是合理的。下面我们就看一下linux的网卡的ip地 址结构。刚才说了在linux中,一个网卡可以有多个IP,那么这多个ip有什么关系呢?其实这些ip组成了一个吊链结构,所谓吊链结构就是一些节点链接 成一条链,然后每个棚兆节点带有自己的一条链

每个节点代表的ip地址标识一个网段,这个节点的ip就是这个网段的 Primary地址,它下面所带的ip就是这个网段的Secondary地址,也就是说一个网卡可以带有各个节点所带链表长度之和个ip地址,而且这些 ip不是线形的,而是上述的吊链结构。我们看一下这么做有什么好处。玩过Cisco路由器的朋友可能都知道有个Secondary IP的概念,这个特性可以创建逻辑子网,也就是说在一个物理网口上连接两个子网,这咋看起来好像不可思议,其实很简单,比如这个网口接到一台交换机上,如 果这个网口没有配置Secondary IP的话,那么这台交换机只能连接一个网段的主机,比如192.168.1.1/24,但是,如果它链咐租配置了Secondary IP,那么就可以连接两个网段的主机,比如192.168.1.1/24和10.0.0.1/24,道理就是这么简单,但是却很有用,该机制可以被路由汇 总策略所使用。注意上面这个例子中的Secondary IP不是这里说的linux的Secondary address,在linux中恰恰相反,只要一个网卡上配置的ip不是一个网段的,那么都是Primary IP,就是吊链结构中上面的那条主链中的IP,linux中的Secondary address是主链结点的子链结点中的IP,这一点一定注意,概念是不能混淆的。前面说的只是吊链中主链的作用,那么子链呢?其实想象一下也很简单,比 如一台机器上运行着一个代理服务器或者负载均衡服务,代理服务器或者负载均衡服务和主服务器要监听相同的端口,那么就可以用secondary address来解决了,只要需要在同一网段监听同一个端口的应用都是吊链中子链存在的原因,因此可以说,主链对外部或者说对下面链路层虚拟了多块网卡, 而子链向上层虚拟了多台机器,配置了吊链结构的linux主机如果说只有一块网卡,那么外部会认为它有多块网卡,对于内部,应用层会认为彼此在不同的主机 上,这就是效果。 

除了上面大体的介绍之外,还有很多细节,吊链在主链上是没有主次的,子链除了之一个节点其它节点也不分主次,都是平行的关系,但是子链中的之一个节点总是 链接在主链中,它们携带的地址就是primary地址,它们下面隶属的子链携带的地址就是这个primary地址的secondary地址,如此看来,一 旦主链上一个节点被删除了,那么它的子链也将不复存在,所谓皮之不存毛将焉附。但是这种策略总是显得不是那么优美,因为父亲犯错,儿子也要受连累,这在现 代社会早就不时行了,那么就需要改变机制了,因此linux中特意有了一个选项,就是当一个primary地址被删除时,如果它有secondary地址 的话,那么它的之一个secondary地址(长子)继承被删除的primary地址的位置成为primary地址,这样就显得很合理了,要不然在删除 primary地址的时候,如果有程序用secondary地址,那么要么延迟删除,要么程序崩溃,采用自动提升策略的话就不会出现问题。 

至于说IP aliases,那是以前版本有的了,就是一个实现问题,解决的问题和现在的secondary IP机制一样,它主要就是在物理网卡名字后面加上后缀从而成为虚拟网络接口,本质上和secondary IP机制没有区别,区别就是IP aliases显得不是那么直观,而secondary IP却是真正让应用看到了一个网卡的多个地址,比如你要是用IP aliases的话,有的时候你总是会问eth0:0是什么?我就曾经在内核里面拼命找eth0:0这个网络设备的注册代码,都要疯掉了也没有找到,其实 我并不是很傻,但是我却因为那个该死的名字作出了傻事。 

下面就可以看看linux内核的实现代码了,首先弄明白一些数据结构,最重要的就是net_device,其次就是in_device,然后就是in_ifaddr,明白了这三个数据结构,一切就明白了,这是真的。 

struct net_device 

… 

     void      *ip_ptr;//指向一个in_device结构,这字段从net_device中分离表明一个网卡可以支持多种网络层协议的 

… 

struct in_device 

struct net_device*dev;//指向它隶属的net_device,也就是网卡 

atomic_t  refcnt;//引用计数 

intdead; 

struct in_ifaddr*ifa_list;      //所有的ip地址链表 

… 

}; 

struct in_ifaddr   //代表一个ip地址 

struct in_ifaddr*ifa_next;//上面的in_device中的ifa_list字段就是靠这个字段连成链的 

struct in_device*ifa_dev;//回指in_device结构 

struct rcu_headrcu_head; 

uifa_local;//ip地址 

uifa_address; 

uifa_mask;//掩码 

uifa_broadcast;   //广播地址 

uifa_anycast; 

unsigned charifa_scope;  

unsigned charifa_flags;//只有IFA_F_SECONDARY标志,因为除了这个就是primary地址了 

unsigned charifa_prefixlen; 

char      ifa_label; //名字,在ip aliases时代,它就可能是ethx:y的形式,在secondary ip时代,它统一就是ethx 

};

注 意,上面的结构并没有将linux网卡的ip地址结构表示为吊链结构,所谓的吊链结构只是逻辑上的,在数据结构上,一个网卡所有的ip地址全部都在 ifa_list中被链接成一个线性的链表,至于是primary地址还是secondary地址就看in_ifaddr的ifa_flags字段了。每 当有新的地址被设置的时候,inet_insert_ifa总是被调用,linux为何没有在代码上将ip地址表示为吊链结构呢?我也不知道,个人感觉一 个net_device带有一个primary ip链表,然后每个primary ip节点带有一个secondary ip链表,这样会更好一些的,我觉得inet_insert_ifa实现的十分拙劣。添加地址可以通过两个用户空间程序搞定,一个是ifconfig,另 一个是ip addr add,ifconfig是基于ioctl进行地址添加的,而ip程序是基于netlink进行地址添加的,不管哪一种方式都可以达到目的,现在就可以看 看另一个问题了:为何用ip addr add添加的ip地址用ifconfig看不到,而ifconfig设置的地址ip addr show却是可以看到。这个问题通过看代码一眼就可以明白,在ifconfig获得ip地址的时候,代码: 

for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; ifap = &ifa->ifa_next) 

    if (!strcmp(ifr.ifr_name, ifa->ifa_label) && sin_orig.sin_addr.s_addr == ifa->ifa_address) 

    { 

break; 

    } 

}

取 的是这个被找到的ifa的ip地址,而我们知道,所有的ifa链接成一个线性链表,那么找到了之一个就不会再往后走了,因此只能得到一个结果,就是链表最 前面的那个,而ip add show就不同了,具体在函数inet_dump_ifaddr中实现,该函数遍历所有的ifa,并且传到用户空间缓冲区。这里可以做一个实验:首先用 ip addr add添加几个不在同一个网段的primary ip地址,然后再ifconfig一个和前面的ip都不在一个网段的ip,然后可以用ifconfig查看一下,发现不是刚刚用ifconfig设置进去 的那个ip,而是用ip addr add添加进去的,这就说明ifconfig永远都是取的ifa链表最前面的那一个,还有一点要注意,就是如果你用ip addr add添加了很多的secondary ip地址,那么恰好你用ifconfig设置的ip地址和那些secondary ip在一个网段,那么所有的secondary ip都将被删除,这些都是sencondary ip的规范决定的,而且在代码中也有体现。另外还要注意,路由表的表项都是基于primary ip的,因为所有的操作都是以primary ip为主的,比如在添加路由的时候: 

void fib_add_ifaddr(struct in_ifaddr *ifa) 

struct in_device *in_dev = ifa->ifa_dev; 

struct net_device *dev = in_dev->dev; 

struct in_ifaddr *prim = ifa; 

… 

if (ifa->ifa_flags&IFA_F_SECONDARY) {   //如果ifa是个sencondary地址,那么就找到它隶属的primary地址后然后以这个primary为主进行设置 

   prim = inet_ifa_byprefix(in_dev, prefix, mask); 

   if (prim == NULL) { 

printk(KERN_DEBUG “fib_add_ifaddr: bug: prim == NULL/n”); 

return; 

   } 

fib_magic(RTM_NEWROUTE, RTN_LOCAL, addr, 32, prim);    //添加进路由表 

… 

}

到 此为止我们知道了不少东西,最重要的就是linux中网卡ip地址的吊链结构以及这么设计的好处,另外就是设置ip地址的方式有ioctl和 netlink。其实网卡拥有多个ip并不会带来什么冲突,本质上ip和网卡没有什么关系,它们唯一的关系就是靠网络分层模型联系在一起的,细节上就是靠 路由联系在一起的,比如我添加路由的时候指定了一个目的地址和下一跳ip地址以及一个网卡出口,那么内核会根据提供的目的地址将路由插在合式的位置,然后 将nh的网络设备设置为你提供的网卡出口,等到传输数据的时候就会查找路由从而找到出口,就是这么简单,你自己手动设置的路由可以随意设置,即使完全错误 内核也会将之加入路由表的,还有一种路由是内核自动生成的,就是在网卡刚刚up的时候,这时通过网卡的net_device找到其in_device然后 找到其ip地址,这样的路由称为链路路由。 

通过secondary IP机制,你可以认为你的机器有很多网卡,对于应用,监听同一端口的应用会认为它们在局域网中不同的机器上,你可以随意使用这些ip地址而不会发生混乱,路由和底层的arp会处理好这一切,当然前提是你将路由设置对。 

附: 用户空间有ifup/ifdown,/in/ip,ifconfig,还有netplugd守护进程,这些有何关系吗?这中间ip程序是最基本的,没 有任何策略,策略就是参数指定,要么就是别的程序调用它,而netplugd就是一个监控守护进程,通过netlink监控网卡状态,然后根据不同的监控 结果调用/etc/netplug.d/netplug脚本,进而可能调用ifup/ifdown脚本,而后者就是脚本,其中会调用ifup-eth脚 本,最终整理好参数后调用ip程序(典型的就是:ip link set eth0 up/down),当然ip程序完全可以自己调用,比如ip addr add以及ip route add等等,而ifconfig没有那么绕圈子,就是通过ioctl进行设置,可以通过strace来观察。这其中奥妙大了去了,说白了就是策略和机制分 离,另外还体现出linux中的很多功能都是很小的程序组合而成的。

linux ip 路由机制的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于linux ip 路由机制,浅谈Linux IP路由机制,从ip addr add和ifconfig的区别看linux网卡ip地址的结构的信息别忘了在本站进行查找喔。


数据运维技术 » 浅谈Linux IP路由机制 (linux ip 路由机制)