IPVlan 详解

这篇具有很好参考价值的文章主要介绍了IPVlan 详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


主要探讨使用 ipvlan 为 cni 通过虚拟网卡的实现。

简介

ipvlan 和 macvlan 类似,都是从一个主机接口虚拟出多个虚拟网络接口。唯一比较大的区别就是 ipvlan 虚拟出的子接口都有相同的 mac地址(与物理接口共用同个 mac 地址),但可配置不同的 ip 地址。由于所有的虚拟接口共享同个mac地址,因此有些地方需要注意:当使用 DHCP 协议分配 ip 时,一般会用 mac 地址作为机器的标识,因此需要配置唯一的 ClientID 字段作为机器的标识, DHCP server 配置 ip 时需使用该字段作为机器标识,而不是使用 mac 地址。

两种工作模式
ipvlan 有两种不同的工作模式:L2 和 L3。一个父接口只能选择其中一种模式(不能采用混用模式),依附于它的所有虚拟接口都会运行在这个模式下。
1、L2 模式
Ipvlan 的 L2 模式和 macvlan 的 bridge 模式工作原理很相似,父接口作为交换机来转发子接口的数据。同一个网络的子接口可以通过父接口来转发数据,而如果想发送到其他网络,报文则会通过父接口的路由转发出去。
2、L3 模式
L3 模式下,ipvlan 有点像路由器的功能,它在各个虚拟网络和主机网络之间进行不同网络报文的路由转发工作。只要父接口相同,即使虚拟机/容器不在同一个网络,也可以互相 ping 通对方,因为 ipvlan 会在中间做报文的转发工作。该模式把宿主接口当成一个路由器,完全不支持广播,这个模式下的接口也比l2模式下的ipvlan接口多了一个 NOARP属性,也不会发送广播报文

Ipvlan2

同节点 Ns 互通

ipvlan,Linux 网络,网络,网络协议

// 创建 netns, 创建 ipvlan,netns 内配置 ip,link up,配置路由
ip netns add node1ns
ip link add ipvl_10_1 link ens10 type ipvlan mode l2
ip link set ipvl_10_1 netns node1ns
ip netns exec node1ns ip link set ipvl_10_1 name eth0
ip netns exec node1ns ip a a 192.168.100.101/24 dev eth0
ip netns exec node1ns ip link set lo up
ip netns exec node1ns ip link set eth0 up


ip netns add node1ns2
ip link add ipvl_10_1 link ens10 type ipvlan mode l2
ip link set ipvl_10_1 netns node1ns2
ip netns exec node1ns2 ip link set ipvl_10_1 name eth0
ip netns exec node1ns2 ip a a 192.168.100.102/24 dev eth0
ip netns exec node1ns2 ip link set lo up
ip netns exec node1ns2 ip link set eth0 up


// 到此两个 ns 的 ip 是互通的
192.168.100.101 <--> 192.168.100.102   OK

Ns 内与宿主机 通信

因为要跟其他网段通信,配置 ns 内的路由

//配置 ns 内部下一跳 192.168.100.1,将 192.168.100.1/24 配置在 ens10 网卡上
ip netns exec node1ns ip r add default via 192.168.100.1
ip netns exec node1ns2 ip r add default via 192.168.100.1

第一种方法
ipvlan,Linux 网络,网络,网络协议

将 192.168.100.1/24 配置在 ens10 网卡上

//在 宿主机上配置到 ns ip 的 路由
ip link add ipvl_10 link ens10 type ipvlan mode l2
ip link set ipvl_10 up
ip a a 192.168.100.1/32 dev ipvl_10
ip route add 192.168.100.101/32 dev ipvl_10
ip route add 192.168.100.102/32 dev ipvl_10

第二种方法

ipvlan,Linux 网络,网络,网络协议

// 在 ns 中配置宿主机 ip 的路由
ip netns exec node1ns ip r add 172.18.22.0/24 dev eth0
ip netns exec node1ns2 ip r add 172.18.22.0/24 dev eth0

ens10 不配置 ip,在 ipvl_10 配置 宿主机的 ip
ip a a 172.18.22.114/32 dev ipvl_10

Ns 到节点外部

ns 内部下一跳 ip 在宿主机外部的情况,会直接从 ens10 出。

结论

保证业务流量走业务网卡,使用第三种方法实现 host 到 ns 的通信,将 需要通信的 host IP 配置到 业务网卡上,其他流量默认从业务网卡出。

Ipvlan3

1. 同节点 Ns 互通

ipvlan,Linux 网络,网络,网络协议

// 创建 netns, 创建 ipvlan,netns 内配置 ip,link up,配置路由
ip netns add node2ns
ip link add ipvl_10_1 link ens10 type ipvlan mode l3
ip link set ipvl_10_1 netns node2ns
ip netns exec node2ns ip link set ipvl_10_1 name eth0
ip netns exec node2ns ip a a 192.168.100.201/24 dev eth0
ip netns exec node2ns ip link set lo up
ip netns exec node2ns ip link set eth0 up
ip netns exec node2ns ip r add default dev eth0


ip netns add node2ns2
ip link add ipvl_10_1 link ens10 type ipvlan mode l3
ip link set ipvl_10_1 netns node2ns2
ip netns exec node2ns2 ip link set ipvl_10_1 name eth0
ip netns exec node2ns2 ip a a 192.168.200.201/24 dev eth0
ip netns exec node2ns2 ip link set lo up
ip netns exec node2ns2 ip link set eth0 up
ip netns exec node2ns2 ip r add default dev eth0

// 到此两个 ns 的 ip 是互通的
192.168.100.201 <--> 192.168.200.201    OK

Ns 内与宿主机 通信

ipvlan,Linux 网络,网络,网络协议

// 宿主机起 ipvl_10,配置需要访问的宿主机 ip,设置到 ns 的路由
ip link add ipvl_10 link ens10 type ipvlan mode l3
ip a a 172.18.22.115/32 dev ipvl_10
ip r add 192.168.100.201 dev ipvl_10
ip r add 192.168.200.201 dev ipvl_10

192.168.100.201 <--> 172.18.22.115

Ns 内到外部网络

发包时,通过宿主机路由选择对应网卡
ipvlan,Linux 网络,网络,网络协议

总结

l3 mode 的 ipvlan 网卡 NOARP,不回复 arp 报文,如果外部流量访问 ipvlan 上的 ip,需要在 ens10 配置 ip,然后外部配置到 ipvlan ip 的流量下一跳到 ens10 的 ip。

源码分析

ipvlan 收包流程

ipvlan_netdev_ops 中 收包函数 ipvlan_start_xmit

int ipvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev)
{
	struct ipvl_dev *ipvlan = netdev_priv(dev);
	struct ipvl_port *port = ipvlan_port_get_rcu_bh(ipvlan->phy_dev);

	if (!port)
		goto out;
...
// 获取 端口模式,L2,L3 或 L3S;进行对应处理
	switch(port->mode) {
	case IPVLAN_MODE_L2:
		return ipvlan_xmit_mode_l2(skb, dev);
	case IPVLAN_MODE_L3:
#ifdef CONFIG_IPVLAN_L3S
	case IPVLAN_MODE_L3S:
#endif
		return ipvlan_xmit_mode_l3(skb, dev);
	}
...
}

L2 mode 收包

static int ipvlan_xmit_mode_l2(struct sk_buff *skb, struct net_device *dev)
{
	const struct ipvl_dev *ipvlan = netdev_priv(dev);
	struct ethhdr *eth = skb_eth_hdr(skb);
	struct ipvl_addr *addr;
	void *lyr3h;
	int addr_type;

// 非 vepa 且源 mac 目的 mac 相等,获取三层头指针,和类型(ipv4,arp)
	if (!ipvlan_is_vepa(ipvlan->port) &&
	    ether_addr_equal(eth->h_dest, eth->h_source)) {
		lyr3h = ipvlan_get_L3_hdr(ipvlan->port, skb, &addr_type);
		if (lyr3h) {
			// 找到目的地址
			addr = ipvlan_addr_lookup(ipvlan->port, lyr3h, addr_type, true);
			if (addr) {
				// ipvlan 如果是 private 则 drop。
				if (ipvlan_is_private(ipvlan->port)) {
					consume_skb(skb);
					return NET_XMIT_DROP;
				}
				// ipvlan 虚拟接口收包,改 skb type 为 local,使用该目的地址的接口收包。如 1 中 netns 互通和 2 中 第三种方法。
				return ipvlan_rcv_frame(addr, &skb, true);
			}
		}
...
		/* Packet definitely does not belong to any of the
		 * virtual devices, but the dest is local. So forward
		 * the skb for the main-dev. At the RX side we just return
		 * RX_PASS for it to be processed further on the stack.
		 */
		 // 目的地址不是虚拟接口里的,直接物理口收包,接下来会进协议栈。如 2 中 netns 到 host 的第一,二种方法。
		return dev_forward_skb(ipvlan->phy_dev, skb);
	// 多播包,虚拟接口处理
	} else if (is_multicast_ether_addr(eth->h_dest)) {
		skb_reset_mac_header(skb);
		ipvlan_skb_crossing_ns(skb, NULL);
		ipvlan_multicast_enqueue(ipvlan->port, skb, true);
		return NET_XMIT_SUCCESS;
	}
	// 源目的 mac 不同,且不是多播包,直接物理网卡发出。
	skb->dev = ipvlan->phy_dev;
	return dev_queue_xmit(skb);
}

L3 mode 收包,L3 和 L3S 相同,和 L2 Mode 很像

static int ipvlan_xmit_mode_l3(struct sk_buff *skb, struct net_device *dev)
{
	const struct ipvl_dev *ipvlan = netdev_priv(dev);
	void *lyr3h;
	struct ipvl_addr *addr;
	int addr_type;

	lyr3h = ipvlan_get_L3_hdr(ipvlan->port, skb, &addr_type);
	if (!lyr3h)
		goto out;

	if (!ipvlan_is_vepa(ipvlan->port)) {
		addr = ipvlan_addr_lookup(ipvlan->port, lyr3h, addr_type, true);
		if (addr) {
			// ip 或 arp 三层包,且目的地址是虚拟接口的,目的地址的虚拟接口收包、
			if (ipvlan_is_private(ipvlan->port)) {
				consume_skb(skb);
				return NET_XMIT_DROP;
			}
			return ipvlan_rcv_frame(addr, &skb, true);
		}
	}
out:
	// 目的地址不是本网卡接口,交给物理口,ip_route_output_flow查找路由表,走三层转发。
	ipvlan_skb_crossing_ns(skb, ipvlan->phy_dev);
	return ipvlan_process_outbound(skb);
}

收包流程

ipvlan 收包流程
物理卡收包后的处理,分配区分 L2,L3,L3S mode

rx_handler_result_t ipvlan_handle_frame(struct sk_buff **pskb)
{
    struct sk_buff *skb = *pskb;
    struct ipvl_port *port = ipvlan_port_get_rcu(skb->dev);

    if (!port)
        return RX_HANDLER_PASS;

    switch (port->mode) {
    case IPVLAN_MODE_L2:
        return ipvlan_handle_mode_l2(pskb, port);
    case IPVLAN_MODE_L3:
        return ipvlan_handle_mode_l3(pskb, port);
#ifdef CONFIG_IPVLAN_L3S
    case IPVLAN_MODE_L3S:
        return RX_HANDLER_PASS;
#endif
    }

    /* Should not reach here */
    WARN_ONCE(true, "%s called for mode = [%x]\n", __func__, port->mode);
    kfree_skb(skb);
    return RX_HANDLER_CONSUMED;
}

L2 mode 收包

static rx_handler_result_t ipvlan_handle_mode_l2(struct sk_buff **pskb,
                         struct ipvl_port *port)
{
    struct sk_buff *skb = *pskb;
    struct ethhdr *eth = eth_hdr(skb);
    rx_handler_result_t ret = RX_HANDLER_PASS;

    // 多播包,ipvlan_external_frame 判断如果是本地子接口发的包,且目的 ip 不是本物理网卡和子接口的 ip,复制一份,直接物理网卡的多播队列处理。
    if (is_multicast_ether_addr(eth->h_dest)) {
        if (ipvlan_external_frame(skb, port)) {
            struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC);

            /* External frames are queued for device local
             * distribution, but a copy is given to master
             * straight away to avoid sending duplicates later
             * when work-queue processes this frame. This is
             * achieved by returning RX_HANDLER_PASS.
             */
            if (nskb) {
                ipvlan_skb_crossing_ns(nskb, NULL);
                ipvlan_multicast_enqueue(port, nskb, false);
            }
        }
    } else {
        // 单播报文,和 l3 mode 处理方法一致
        /* Perform like l3 mode for non-multicast packet */
        ret = ipvlan_handle_mode_l3(pskb, port);
    }

    return ret;
}

L3 mode 收包,该模式同样适合 l2 mode 的单播包

static rx_handler_result_t ipvlan_handle_mode_l3(struct sk_buff **pskb,
                         struct ipvl_port *port)
{
    void *lyr3h;
    int addr_type;
    struct ipvl_addr *addr;
    struct sk_buff *skb = *pskb;
    rx_handler_result_t ret = RX_HANDLER_PASS;

    lyr3h = ipvlan_get_L3_hdr(port, skb, &addr_type);
    if (!lyr3h)
        goto out;

    addr = ipvlan_addr_lookup(port, lyr3h, addr_type, true);
    if (addr)
        // arp 或 ip 包,且目的地址是本网卡和子接口的,对应接口收包
        ret = ipvlan_rcv_frame(addr, pskb, false);

out:
    // 其他报文走物理网卡路由
    return ret;
}

L3S mode

    case IPVLAN_MODE_L3S:
        return RX_HANDLER_PASS;

直接走物理卡主机路由文章来源地址https://www.toymoban.com/news/detail-643093.html

到了这里,关于IPVlan 详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 网络协议 - UDP 协议详解

    基于TCP和UDP的协议非常广泛,所以也有必要对UDP协议进行详解。 UDP(User Datagram Protocol)即用户数据报协议,在网络中它与TCP协议一样用于处理数据包,是一种无连接的协议。在OSI模型中,在第四层——传输层,处于IP协议的上一层。UDP用来支持那些需要在计算机之间传输数据的

    2024年02月22日
    浏览(43)
  • 网络协议 - HTTP 协议详解

    HTTP 协议详解,web开发必备。 URI 包含 URL 和 URN,目前 WEB 只有 URL 比较流行,所以见到的基本都是 URL。 URI(Uniform Resource Identifier,统一资源标识符) URL(Uniform Resource Locator,统一资源定位符) URN(Uniform Resource Name,统一资源名称) 1. 请求报文 2. 响应报文 客户端发送的 请求报文 第

    2024年02月04日
    浏览(53)
  • 网络协议 - TCP 协议详解

    TCP是一个巨复杂的协议,关于TCP这个协议的细节,我还是推荐你去看W.Richard Stevens的《TCP/IP 详解 卷1:协议》。全网上讲TCP/IP的文章众多,多数是皮毛;本文梳理自 左耳朵耗子的文章《TCP 的那些事儿》,来帮助大家理解TCP/IP, 其中引用的图片在这里。 **提示** 本文有深度,请

    2024年02月03日
    浏览(31)
  • 【网络协议详解】——OSPF协议(学习笔记)

    开放最短路径优先 OSPF (Open Shortest Path First),是为克服RIP的缺点在1989年开发出来的。 “开放”表明OSPF协议不是受某一家厂商控制,而是 公开发表 的。 \\\"最短路径优先”是因为使用了Dijkstra提出的 最短路径算法 SPF。 OSPF是一种基于 链路状态选路算法 的路由协议。 链路状态

    2024年02月03日
    浏览(36)
  • 【网络协议详解】——PPP协议(学习笔记)

    用户计算机与ISP进行通信时,所使用的数据链路层协议通常就是点对点协议PPP(Point-to-Point Protocol)。PPP协议是目前使用最广泛的 点对点 数据链路层协议,也广泛应用于 广域网路由器 之间的专用线路。 在1999年公布的在 以太网 上运行的 PPPoE 协议,它使得lSP可以通过ADSL、电

    2024年02月08日
    浏览(35)
  • 【网络协议详解】——BGP协议(学习笔记)

    BGP(Border Gateway Protocol),边界网关协议。 一种自治系统间的选路协议, 在 AS 之间交换网络的可达性信息 。 根据可达性信息,路由器能够构造 AS 之间的连接关系图,从而计算出到达目的网络的路由。 在计算路由时,管理员可以在 AS 层面上应用一些 路由控制 策略。 例如,

    2024年02月05日
    浏览(46)
  • NAT协议(网络地址转换协议)详解

    NAT协议是将IP数据报头中的IP地址转换为另外一个IP地址的过程,主要用于实现私有网络访问公有网络的功能 。这种通过使用少量的IP地址代表较多的私有IP地址的方式,将有助于减少IP地址空间的枯竭。 IPv4地址随着用户的增多压力不断增大,但是每一个路由器的IP地址下面都

    2024年02月14日
    浏览(42)
  • 【网络协议详解】——RIP协议(学习笔记)

    路由器接收到一个 IP 分组后: 从分组首部提取目的 IP 地址,检测目的地址是否属于某个直连网络,若属于则直接发送; 否则,在路由表中查找是否存在主机路由(静态或动态); 否则,在路由表中查找匹配的路由; 否则,在路由表中查找默认路由; 否则,丢弃分组,向源

    2024年02月04日
    浏览(38)
  • 【网络协议详解】——FTP系统协议(学习笔记)

    将某台计算机中的文件通过网络传送到可能相距很远的另一台计算机中,是一项基本的网络应用,即 文件传送 。 文件传送协议FTP (File Transfer Protocol)是因特网上使用得最广泛的文件传送协议。 FTP 提供交互式的访问 ,允许客户 指明文件的类型与格式 (如指明是否使用AS

    2024年02月07日
    浏览(44)
  • 【Linux 网络】网络层协议之IP协议

    IP指网际互连协议,Internet Protocol的缩写,是TCP/IP体系中的网络层协议。 网络层是夹在传输层和数据链路层的中间,传输层里最具有代表性的协议是TCP协议,而TCP协议作为传输层控制协议,其保证的是数据传输的可靠性和传输效率,但TCP提供的仅仅是数据传输的策略,真正负

    2024年02月14日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包