【博客633】linux vxlan设备工作原理
linux vxlan设备工作原理
vxlan处理包的原理:以k8s cni flannel组件创建的vxlan设备为例
1、k8s cni组件创建flannel设备flannel.1,且这个设备为vxlan类型的设备
root@10.10.10.12:/home/ubuntu# ethtool -i flannel.1
driver: vxlan
version: 0.1
firmware-version:
expansion-rom-version:
bus-info:
supports-statistics: no
supports-test: no
supports-eeprom-access: no
supports-register-dump: no
supports-priv-flags: no
2、vxlan设备创建的时候是有绑带其vtep通信的设备,比如:eth0
root@10.10.10.12:/home/ubuntu# ip -d link show flannel.1
6: flannel.1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN mode DEFAULT group defaultlink/ether 7e:b8:27:c7:4b:76 brd ff:ff:ff:ff:ff:ff promiscuity 0 minmtu 68 maxmtu 65535vxlan id 1 local 10.10.10.12 dev eth0 srcport 0 0 dstport 8472 nolearning ttl auto ageing 300 udpcsum noudp6zerocsumtx noudp6zerocsumrx addrgenmode eui64 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535
3、flannel的agent会维护fdb表,查看flannel.1设备的fdb表
root@10-234-68-12:/home/ubuntu# bridge fdb show dev flannel.1
3e:5f:25:8e:e0:cd dst 10.10.10.12 self permanent
16:1d:36:f4:ab:26 dst 10.10.10.13 self permanent
a6:a0:56:1f:aa:4c dst 10.10.10.14 self permanent
76:50:cc:8d:7a:67 dst 10.10.10.15 self permanent
4、每个vxlan设备创建的时候会绑定一个udp socket,此时会有udp的vxlan端口的在监听,从而接收udp隧道包进行处理
# vxaln监听着8472的vxlan默认udp端口:
ubuntu@10.10.10.12:~$ netstat -uanv
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
udp 0 0 0.0.0.0:53851 0.0.0.0:*
udp 0 0 127.0.0.53:53 0.0.0.0:*
udp 0 0 0.0.0.0:111 0.0.0.0:*
udp 0 0 0.0.0.0:2049 0.0.0.0:*
udp 0 0 0.0.0.0:37543 0.0.0.0:*
udp 0 0 0.0.0.0:37554 0.0.0.0:*
udp 0 0 0.0.0.0:39762 0.0.0.0:*
udp 0 0 0.0.0.0:8472 0.0.0.0:*
udp6 0 0 :::52508 :::*
udp6 0 0 :::54535 :::*
udp6 0 0 :::59285 :::*
udp6 0 0 :::111 :::*
udp6 0 0 :::2049 :::*
udp6 0 0 :::40104 :::*
细节剖析
1、vxlan模块回调函数在哪里设置:在vxlan 模块初始化中做:vxlan_init_module
1、register_pernet_device内部执行init函数rc = register_pernet_device(&vxlan_net_ops);
static struct pernet_operations vxlan_net_ops = {.init = vxlan_init_net,.exit = vxlan_exit_net,.id = &vxlan_net_id,.size = sizeof(struct vxlan_net),
};2、设置收包的vxlan回调函数/* Disable multicast loopback */
inet_sk(sk)->mc_loop = 0;/* Mark socket as an encapsulation socket. */
udp_sk(sk)->encap_type = 1;
udp_sk(sk)->encap_rcv = vxlan_udp_encap_recv;
2、包如何来到vxlan的回调处理函数
已经知道vxlan是 MAC IN UDP中的封装,因此,在解封装之前,一切按照原有流程走
2-1、从网卡收到包来到协议栈开始:__netif_receive_skb_core**
/*type,二层封装内的协议,IP为 0x0800*/
type = skb->protocol;
/*获取协议注册的入口函数,ip为 ip_rcv,声明的变量为 ip_packet_type*/
list_for_each_entry_rcu(ptype,&ptype_base[ntohs(type) & PTYPE_HASH_MASK], list) {if (ptype->type == type &&(ptype->dev == null_or_dev || ptype->dev == skb->dev ||ptype->dev == orig_dev)) {if (pt_prev)ret = deliver_skb(skb, pt_prev, orig_dev);pt_prev = ptype;}
}
2-2、ip_rcv
此函数只是对报文进行可靠性验证,最后到 钩子函数 ‘NF_HOOK’。
钩子函数中就是配置的netfilter,通过验证就会直接进入函数 ‘ip_rcv_finish’。
2-3、ip_rcv_finish
/*sysctl_ip_early_demux 是二进制值,该值用于对发往本地数据包的优化。
当前仅对建立连接的套接字起作用。*/
if (sysctl_ip_early_demux && !skb_dst(skb) && skb->sk == NULL) {const struct net_protocol *ipprot;int protocol = iph->protocol;ipprot = rcu_dereference(inet_protos[protocol]);if (ipprot && ipprot->early_demux) {ipprot->early_demux(skb);/* must reload iph, skb->head might have changed */iph = ip_hdr(skb);}}
/*这一部分时查找路由,判断是local in还是 forwarding。本次分析按照 local in分析*/
if (!skb_dst(skb)) {int err = ip_route_input_noref(skb, iph->daddr, iph->saddr,iph->tos, skb->dev);if (unlikely(err)) {if (err == -EXDEV)NET_INC_STATS_BH(dev_net(skb->dev),LINUX_MIB_IPRPFILTER);goto drop;}}
……/*按照local in分析,则此处相当于调用 ip_local_deliver(可深入 查找路由函数,里面有函数指针赋值)*/return dst_input(skb);
2-4、ip_local_deliver
钩子函数检测,不深入,直接到最后。
2-5、ip_local_deliver_finish
ipprot = rcu_dereference(inet_protos[protocol]);
……ret = ipprot->handler(skb);
……
到了传输层注册的入口函数。UDP入口函数为 ‘udp_rcv’。
2-6、__udp4_lib_rcv
/*根据源目端口号及IP查找 插口*/
sk = __udp4_lib_lookup_skb(skb, uh->source, uh->dest, udptable);
……/*进入udp队列收包流程*/int ret = udp_queue_rcv_skb(sk, skb);
……
2-7、udp_queue_rcv_skb
/*插口如果是封装类型,vxlan等,则进入封装处理入口,下面开始分析vxlan部分代码*/
encap_rcv = ACCESS_ONCE(up->encap_rcv);
if (skb->len > sizeof(struct udphdr) && encap_rcv != NULL) {int ret;ret = encap_rcv(sk, skb);if (ret <= 0) {UDP_INC_STATS_BH(sock_net(sk),UDP_MIB_INDATAGRAMS,is_udplite);return -ret;}
}
3、vxlan的udp并不会上送到udp socket监听的进程,与传统用户态监听udp socket不同
vxlan的udp并不会上送到udp socket监听的进程,因为没有这个进程,vxlan设备是为udp socket注册了回调,让协议栈调这个回调来处理这个包,而不是上送到用户进程。这个回调函数进行包的拆解后把原包再经过协议栈,然后上送用户态进程
UDP有两条处理路径:
- 1、放到sk的接收队列,通知等待进程
- 2、调用udp_sock的encap_rcv函数,类似vxlan的实现,可以直接在内核中进行处理
如果udp_sock定义了encap_rcv函数,将会把报文交给该函数处理,而不是传统的保存到sock队列,唤醒进程收包。
总结:linux对vxlan包的处理过程
- 创建vxlan设备的时候会创建udp socket来向内核注册对udp包的处理,这个udp socket还绑定了vxlan处理的回调函数
- 当udp包来了,内核发现有相应的udp socket在监听,就将包给这个udp socket指定的回调来处理,如果有设置回调的话,vxlan的udp socker设置的vxlan包回调处理函数就会在这里调用,
从而有机会处理vxlan udp隧道包。 - 包到了之后通过udp socket指定的vxlan回调处理函数进行包的拆解然后才是把里面的原包上送协议栈,从而送到用户态进程
- vxlan的收包和发包是从另外的设备那里拿和发到那个设备的,这个设备在创建vxlan设备的时候,用dev参数指定的
- vxlan设备创建的时候没有指定remote端vetp的信息就会去查转发表,此时就可以通过自己的agent来维护转发表,从而实现自己的大三层网络拓扑
相关文章:
【博客633】linux vxlan设备工作原理
linux vxlan设备工作原理 vxlan处理包的原理:以k8s cni flannel组件创建的vxlan设备为例 1、k8s cni组件创建flannel设备flannel.1,且这个设备为vxlan类型的设备 root10.10.10.12:/home/ubuntu# ethtool -i flannel.1 driver: vxlan version: 0.1 fi…...

3.12学习周报
文章目录前言文献阅读摘要简介方法介绍讨论结论相关性分析总结前言 本周阅读文献《Streamflow and rainfall forecasting by two long short-term memory-based models》,文献主要提出两种基于长短时记忆网络的混合模型用于对水流量和降雨量进行预测。小波-LSTM&am…...

电力电子中逐波限流控制以及dsp实现
逐波限流是指在电力系统运行中,对电力设备进行电流保护的一种措施。它的实现方式是通过对电力系统的电流进行逐波监测和控制,每一波电流都可以独立地进行限制,从而保护电力系统设备不受过载损坏或短路故障的影响。 逐波限流的作用是提高电力…...

【数据结构】 顺序表
文章目录1 线性表2 顺序表2.1 概念及结构2.2 接口实现2.3 数组相关面试题2.4 顺序表的问题与思考1 线性表 线性表(linear list)是n个具有相同特性的数据元素的有限序列。线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序…...
Elasticsearch 集群规划- 单台机器核心数计算公式
在做集群规划的时候,到底需要给集群的每个节点多少个核心数?这个问题一直困扰了我很久。最近一段时间做千亿数据,PB存储量集群规划的时候,突然想明白了这件事,大致可以用一个公式来计算!我觉得这是一个非常…...

Tesla都使用什么编程语言?
作者 | 初光 出品 | 车端 备注 | 转载请阅读文中版权声明 知圈 | 进“汽车电子与AutoSAR开发”群,请加微“cloud2sunshine” 总目录链接>> AutoSAR入门和实战系列总目录 带着对更美好未来的愿景,特斯拉不仅成为有史以来最有价值的汽车公司&…...

1143. 最长公共子序列——【Leetcode每日刷题】
1143. 最长公共子序列 给定两个字符串 text1 和 text2,返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 ,返回 0 。 一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些…...
【并发基础】线程的通知与等待:obj.wait()、obj.notify()、obj.notifyAll()详解
目录 〇、先总结一下这三个方法带来的Java线程状态变化 一、obj.wait() 1.1 作用 1.2 使用前需要持有线程共享对象的锁 1.3 使用技巧 二、obj.notify(All)() 1.1 notify() 方法 1.1.1 调用notify()或notifyAll()不会释放线程的锁 1.2 notifyAll() 方法 1.3 使用技巧 三、使用实…...

css黏性定位-实现商城的分类滚动的标题吸附
传统的黏性定位是使用js通过计算高度来实现的,当元素滚动到一定位置时吸附在当前位置。下面我们通过css来实现黏性定位功能。 黏性定位 黏性定位目前主流的浏览器已经全部支持,顾名思义,黏性定位具有吸附的效果,其实它是positio…...
@Component和@bean注解在容器中创建实例区别
Component和Bean的区别 在Spring Boot中,Component注解和Bean注解都可以用于创建bean。它们的主要区别在于它们的作用范围和创建方式。 Component注解是一种通用的注解,可以用于标注任何类。被标注的类将被Spring容器自动扫描并创建为一个bean。这个bea…...

不写注释就是垃圾
最近Linux6.2出来了增加了很多新的东西,有看点的是,Linux确实要可以在Apple M1上面运行了,这应该是一个很大的新闻,如果有这么稳定的硬件支持,那对于Linux来说相当于又打下了一大片的江山。其中关于Linux6.2的特性罗列…...
深信服一面
1.C变量存储在哪里,生命周期是怎样的 2.静态成员变量和成员函数的特性,在哪里用过吗 3.new和delete是什么,和malloc和free对比有啥优势 4.new能不能重载,重载new有什么用 5.多态是怎么实现的,有什么优势和目的 6.…...

【C语言】深度理解指针(中)
前言✈上回说到,我们学习了一些与指针相关的数据类型,如指针数组,数组指针,函数指针等等,我们还学习了转移表的基本概念,学会了如何利用转移表来实现一个简易计算器。详情请点击传送门:【C语言】…...
步进电机运动八大算法
引导一种模块化(Module)设计思想,将传统步进电机的控制器(controller)、驱动器(Driver)、运动算法(Arithmetic)三合一。 对比国内外步进电机驱动原理和已有工作,结合各种硬件特性,改进或实现了可实际移植并用于步进电机控制八大算法。本产品…...
如果你持续大量的教坏ChatGPT,它确实会变坏
你输出的很多数据是经过人工标注吗,以确保可以正常对外展示出来,而不是有性别歧视、种族歧视或者其它意识形态为多数人所不认同的内容产生? 作为AI语言模型,我并不直接处理或输出任何数据,我的任务是通过对输入的自然语…...

opencv学习(二)图像阈值和平滑处理
图像阈值ret, dst cv2.threshold(src, thresh, maxval, type)src: 输入图,只能输入单通道图像,通常来说为灰度图dst: 输出图thresh: 阈值maxval: 当像素值超过了阈值(或者小于阈值,…...

【含源码】用python做游戏有多简单好玩
有很多同学问我还有其他什么小游戏吗,游戏是怎么做的,难不难。我就用两篇文章来介绍一下,如何使用Python做游戏。 兔子与灌 俄罗斯方块 休闲五子棋 走迷宫 推箱子 消消乐 超多小游戏玩转不停↓ 更多小游戏可以评论区讨论哦,喜欢…...
C++常用函数
std::sort std::sort 函数用于对数组或容器进行排序,可以按照默认的升序排序或指定比较函数进行排序。 语法如下: template <class RandomAccessIterator> void sort(RandomAccessIterator first, RandomAccessIterator last);template <clas…...
Android Framework基础到深入篇
Android Framework基础到深入篇 KernelSU Android上基于内核的Root方案 Android系统源码下载/编译篇...

【Go进阶训练营】聊一下go的gc原理
背景 正好周末时间,就打算梳理以下自己对go gc的理解。跳出语言层面来说,gc分为两种,一种是手动创建,手动销毁。另一种就是由自动分配自动销毁,前者就是c,c的代表,后者就是java,go。 而整个流程…...

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...
【杂谈】-递归进化:人工智能的自我改进与监管挑战
递归进化:人工智能的自我改进与监管挑战 文章目录 递归进化:人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管?3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

基于Flask实现的医疗保险欺诈识别监测模型
基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施,由雇主和个人按一定比例缴纳保险费,建立社会医疗保险基金,支付雇员医疗费用的一种医疗保险制度, 它是促进社会文明和进步的…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...

mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包
文章目录 现象:mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时,可能是因为以下几个原因:1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...

OPENCV形态学基础之二腐蚀
一.腐蚀的原理 (图1) 数学表达式:dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一,腐蚀跟膨胀属于反向操作,膨胀是把图像图像变大,而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...
2023赣州旅游投资集团
单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...

Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)
Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习) 一、Aspose.PDF 简介二、说明(⚠️仅供学习与研究使用)三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...

深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用
文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么?1.1.2 感知机的工作原理 1.2 感知机的简单应用:基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...