热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

IPVlan详解

文章目录简介Ipvlan2同节点Ns互通Ns内与宿主机通信第三种方法Ns到节点外部结论Ipvlan31.同节点Ns互通Ns内与宿主机通信Ns内到外部网络总结源码分析ipvlan收包

文章目录


  • 简介
  • Ipvlan2
    • 同节点 Ns 互通
    • Ns 内与宿主机 通信
    • 第三种方法
    • Ns 到节点外部
    • 结论

  • Ipvlan3
    • 1. 同节点 Ns 互通
    • Ns 内与宿主机 通信
    • Ns 内到外部网络
    • 总结

  • 源码分析
    • 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 互通

在这里插入图片描述

// 创建 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 内与宿主机 通信

因为要跟其他网段通信&#xff0c;配置 ns 内的路由

//配置 ns 内部下一跳 192.168.100.1&#xff0c;将 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

第一种方法
在这里插入图片描述

将 192.168.100.1/24 配置在 ens10 网卡上
ip a a 192.168.100.1/24 dev ens10
192.168.100.101 <--> 172.18.22.114 OK

第二种方法
在这里插入图片描述

将 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

第三种方法

在这里插入图片描述

// 在 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&#xff0c;在 ipvl_10 配置 宿主机的 ip
ip a a 172.18.22.114/32 dev ipvl_10

Ns 到节点外部


  • 上面第一种和第二种&#xff0c;将 ns 内部下一跳 ip 放到网卡上的情况&#xff0c;会匹配宿主机路由&#xff0c;从 ens3 出&#xff0c;需要配置 snat。

$ iptables -t nat -A POSTROUTING -s 192.168.100.101/24 -j SNAT --to 172.18.22.114

  • 上面第三种&#xff0c;ns 内部下一跳 ip 在宿主机外部的情况&#xff0c;会直接从 ens10 出。

结论

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

Ipvlan3

1. 同节点 Ns 互通

在这里插入图片描述

// 创建 netns, 创建 ipvlan&#xff0c;netns 内配置 ip&#xff0c;link up&#xff0c;配置路由
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 l2
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 内与宿主机 通信

在这里插入图片描述

// 宿主机起 ipvl_10&#xff0c;配置需要访问的宿主机 ip&#xff0c;设置到 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 内到外部网络

需要为 ens10 配置 ip&#xff0c;默认从 ens10 发出
默认从 ens10 发出
外部回包时&#xff0c;需要内部网络的路由

总结

l3 mode 的 ipvlan 网卡 NOARP&#xff0c;不回复 arp 报文&#xff0c;如果外部流量访问 ipvlan 上的 ip&#xff0c;需要在 ens10 配置 ip&#xff0c;然后外部配置到 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 &#61; netdev_priv(dev);
struct ipvl_port *port &#61; ipvlan_port_get_rcu_bh(ipvlan->phy_dev);
if (!port)
goto out;
...
// 获取 端口模式&#xff0c;L2&#xff0c;L3 或 L3S&#xff1b;进行对应处理
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 &#61; netdev_priv(dev);
struct ethhdr *eth &#61; skb_eth_hdr(skb);
struct ipvl_addr *addr;
void *lyr3h;
int addr_type;
// 非 vepa 且源 mac 目的 mac 相等&#xff0c;获取三层头指针&#xff0c;和类型&#xff08;ipv4&#xff0c;arp&#xff09;
if (!ipvlan_is_vepa(ipvlan->port) &&
ether_addr_equal(eth->h_dest, eth->h_source)) {
lyr3h &#61; ipvlan_get_L3_hdr(ipvlan->port, skb, &addr_type);
if (lyr3h) {
// 找到目的地址
addr &#61; 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 虚拟接口收包&#xff0c;改 skb type 为 local&#xff0c;使用该目的地址的接口收包。如 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.
*/
// 目的地址不是虚拟接口里的&#xff0c;直接物理口收包&#xff0c;接下来会进协议栈。如 2 中 netns 到 host 的第一&#xff0c;二种方法。
return dev_forward_skb(ipvlan->phy_dev, skb);
// 多播包&#xff0c;虚拟接口处理
} 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 不同&#xff0c;且不是多播包&#xff0c;直接物理网卡发出。
skb->dev &#61; ipvlan->phy_dev;
return dev_queue_xmit(skb);
}

L3 mode 收包&#xff0c;L3 和 L3S 相同&#xff0c;和 L2 Mode 很像

static int ipvlan_xmit_mode_l3(struct sk_buff *skb, struct net_device *dev)
{
const struct ipvl_dev *ipvlan &#61; netdev_priv(dev);
void *lyr3h;
struct ipvl_addr *addr;
int addr_type;
lyr3h &#61; ipvlan_get_L3_hdr(ipvlan->port, skb, &addr_type);
if (!lyr3h)
goto out;
if (!ipvlan_is_vepa(ipvlan->port)) {
addr &#61; ipvlan_addr_lookup(ipvlan->port, lyr3h, addr_type, true);
if (addr) {
// ip 或 arp 三层包&#xff0c;且目的地址是虚拟接口的&#xff0c;目的地址的虚拟接口收包、
if (ipvlan_is_private(ipvlan->port)) {
consume_skb(skb);
return NET_XMIT_DROP;
}
return ipvlan_rcv_frame(addr, &skb, true);
}
}
out:
// 目的地址不是本网卡接口&#xff0c;交给物理口&#xff0c;ip_route_output_flow查找路由表&#xff0c;走三层转发。
ipvlan_skb_crossing_ns(skb, ipvlan->phy_dev);
return ipvlan_process_outbound(skb);
}

收包流程

ipvlan 收包流程
物理卡收包后的处理&#xff0c;分配区分 L2&#xff0c;L3&#xff0c;L3S mode

rx_handler_result_t ipvlan_handle_frame(struct sk_buff **pskb)
{
struct sk_buff *skb &#61; *pskb;
struct ipvl_port *port &#61; 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 &#61; [%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 &#61; *pskb;
struct ethhdr *eth &#61; eth_hdr(skb);
rx_handler_result_t ret &#61; RX_HANDLER_PASS;
// 多播包&#xff0c;ipvlan_external_frame 判断如果是本地子接口发的包&#xff0c;且目的 ip 不是本物理网卡和子接口的 ip&#xff0c;复制一份&#xff0c;直接物理网卡的多播队列处理。
if (is_multicast_ether_addr(eth->h_dest)) {
if (ipvlan_external_frame(skb, port)) {
struct sk_buff *nskb &#61; 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 {
// 单播报文&#xff0c;和 l3 mode 处理方法一致
/* Perform like l3 mode for non-multicast packet */
ret &#61; ipvlan_handle_mode_l3(pskb, port);
}
return ret;
}

L3 mode 收包&#xff0c;该模式同样适合 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 &#61; *pskb;
rx_handler_result_t ret &#61; RX_HANDLER_PASS;
lyr3h &#61; ipvlan_get_L3_hdr(port, skb, &addr_type);
if (!lyr3h)
goto out;
addr &#61; ipvlan_addr_lookup(port, lyr3h, addr_type, true);
if (addr)
// arp 或 ip 包&#xff0c;且目的地址是本网卡和子接口的&#xff0c;对应接口收包
ret &#61; ipvlan_rcv_frame(addr, pskb, false);
out:
// 其他报文走物理网卡路由
return ret;
}

L3S mode

case IPVLAN_MODE_L3S:
return RX_HANDLER_PASS;

直接走物理卡主机路由






推荐阅读
  • 毕业设计:基于机器学习与深度学习的垃圾邮件(短信)分类算法实现
    本文详细介绍了如何使用机器学习和深度学习技术对垃圾邮件和短信进行分类。内容涵盖从数据集介绍、预处理、特征提取到模型训练与评估的完整流程,并提供了具体的代码示例和实验结果。 ... [详细]
  • 在多线程编程环境中,线程之间共享全局变量可能导致数据竞争和不一致性。为了解决这一问题,Linux提供了线程局部存储(TLS),使每个线程可以拥有独立的变量副本,确保线程间的数据隔离与安全。 ... [详细]
  • 本文详细介绍了 org.apache.commons.io.IOCase 类中的 checkCompareTo() 方法,通过多个代码示例展示其在不同场景下的使用方法。 ... [详细]
  • Python处理Word文档的高效技巧
    本文详细介绍了如何使用Python处理Word文档,涵盖从基础操作到高级功能的各种技巧。我们将探讨如何生成文档、定义样式、提取表格数据以及处理超链接和图片等内容。 ... [详细]
  • 深入解析ESFramework中的AgileTcp组件
    本文详细介绍了ESFramework框架中AgileTcp组件的设计与实现。AgileTcp是ESFramework提供的ITcp接口的高效实现,旨在优化TCP通信的性能和结构清晰度。 ... [详细]
  • 在编译BSP包过程中,遇到了一个与 'gets' 函数相关的编译错误。该问题通常发生在较新的编译环境中,由于 'gets' 函数已被弃用并视为安全漏洞。本文将详细介绍如何通过修改源代码和配置文件来解决这一问题。 ... [详细]
  • 深入解析 Android IPC 中的 Messenger 机制
    本文详细介绍了 Android 中基于消息传递的进程间通信(IPC)机制——Messenger。通过实例和源码分析,帮助开发者更好地理解和使用这一高效的通信工具。 ... [详细]
  • Python自动化测试入门:Selenium环境搭建
    本文详细介绍如何在Python环境中安装和配置Selenium,包括开发工具PyCharm的安装、Python环境的设置以及Selenium包的安装方法。此外,还提供了编写和运行第一个自动化测试脚本的步骤。 ... [详细]
  • 深入探讨CPU虚拟化与KVM内存管理
    本文详细介绍了现代服务器架构中的CPU虚拟化技术,包括SMP、NUMA和MPP三种多处理器结构,并深入探讨了KVM的内存虚拟化机制。通过对比不同架构的特点和应用场景,帮助读者理解如何选择最适合的架构以优化性能。 ... [详细]
  • 本文探讨了《魔兽世界》中红蓝两方阵营在备战阶段的策略与实现方法,通过代码展示了双方如何根据资源和兵种特性进行战士生产。 ... [详细]
  • 本题通过将每个矩形视为一个节点,根据其相对位置构建拓扑图,并利用深度优先搜索(DFS)或状态压缩动态规划(DP)求解最小涂色次数。本文详细解析了该问题的建模思路与算法实现。 ... [详细]
  • 使用GDI的一些AIP函数我们可以轻易的绘制出简 ... [详细]
  • 华为USG基于源地址的多出口策略路由配置
    网络拓扑如下:组网情况:企业用户主要有技术部(VLAN10)和行政部(VLAN20),通过汇聚交换机连接到USG。企业分别通过两个不同运营商(ISP1和ISP2)连接到 ... [详细]
  • 深入解析TCP/IP五层协议
    本文详细介绍了TCP/IP五层协议模型,包括物理层、数据链路层、网络层、传输层和应用层。每层的功能及其相互关系将被逐一解释,帮助读者理解互联网通信的原理。此外,还特别讨论了UDP和TCP协议的特点以及三次握手、四次挥手的过程。 ... [详细]
  • 采用IKE方式建立IPsec安全隧道
    一、【组网和实验环境】按如上的接口ip先作配置,再作ipsec的相关配置,配置文本见文章最后本文实验采用的交换机是H3C模拟器,下载地址如 ... [详细]
author-avatar
呆瓜.
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有