当前位置: 首页 > news >正文

linux之网络子系统-本机发包到本机 实现

一、前言

在linux之网络子系统-网络协议栈 发包收包详解-CSDN博客 文章中,详细介绍了跨主机之间的数据包发送的源码流程。除了跨主机,还有本机发包到本机是如何实现的?就是 saddr ip地址为 127.0.0.1 .

二、发送数据包到 127.0.0.1

首先,127.0.0.1 就是指 lo (本地回环网络设备):

 这个lo设备是在 网络设备子系统 初始化时注册的:

static int __init net_dev_init(void)
{

.....
        if (register_pernet_device(&loopback_net_ops))
                goto out;
...

}

 接着看 loopback_net_ops:

/* Registered in net/core/dev.c */
struct pernet_operations __net_initdata loopback_net_ops = {
        .init = loopback_net_init,
};
 

接着  loopback_net_init:

/* Setup and register the loopback device. */
static __net_init int loopback_net_init(struct net *net)
{
        struct net_device *dev;
        int err;

        err = -ENOMEM;

//初始化 lo 网络设备
        dev = alloc_netdev(0, "lo", NET_NAME_UNKNOWN, loopback_setup); 
        if (!dev)
                goto out;

        dev_net_set(dev, net);

//注册lo 网络设备
        err = register_netdev(dev);
        if (err)
                goto out_free_netdev;

        BUG_ON(dev->ifindex != LOOPBACK_IFINDEX);
        net->loopback_dev = dev;
        return 0;

out_free_netdev:
        free_netdev(dev);
out:
        if (net_eq(net, &init_net))
                panic("loopback: Failed to register netdevice: %d\n", err);
        return err;
}
 

 

上面是 网络设备子系统初始化完成,那么如何被调用到?

根据之前的文章中,描述了跨主机的发包过程:

 发包过程中,到达 网络设备子系统 dev_queue_xmit 时,会选择 lo 网络设备驱动的ndo_start_xmit 回调函数。这个驱动没有实际的硬件设备,纯属软件意义上的驱动。

lo 驱动是如何定义 ndo_start_xmit 回调函数?

函数调用链:

loopback_net_init ->

        loopback_setup->

                gen_lo_setup

 static void loopback_setup(struct net_device *dev)
{
        gen_lo_setup(dev, (64 * 1024), &loopback_ethtool_ops, &eth_header_ops,
                     &loopback_ops, loopback_dev_free);
}

 loopback_ops 定义如下:

static const struct net_device_ops loopback_ops = {
        .ndo_init        = loopback_dev_init,
        .ndo_start_xmit  = loopback_xmit,
        .ndo_get_stats64 = loopback_get_stats64,
        .ndo_set_mac_address = eth_mac_addr,
};
 

 本机发送数据包时,调用 loopback_xmit 函数:

/* The higher levels take care of making this non-reentrant (it's
 * called with bh's disabled).
 */
static netdev_tx_t loopback_xmit(struct sk_buff *skb,
                                 struct net_device *dev)
{
        int len;

        skb_tx_timestamp(skb);

        /* do not fool net_timestamp_check() with various clock bases */
        skb->tstamp = 0;

        skb_orphan(skb);

        /* Before queueing this packet to netif_rx(),
         * make sure dst is refcounted.
         */
        skb_dst_force(skb);

        skb->protocol = eth_type_trans(skb, dev);

        len = skb->len;
        if (likely(netif_rx(skb) == NET_RX_SUCCESS)) // lo 驱动中直接调用 接收数据包的软中断。
                dev_lstats_add(dev, len);

        return NETDEV_TX_OK;
}
 

 看到了驱动与网络设备子系统的接口函数netif_rx ,然后会触发软中断,接收数据包。

上面已经把主机发包到本机的流程已经分析完毕,和跨主机的流程基本一致,都是到驱动层。

本机网络 IO 需要进行 IP 分片吗?

因为和正常的网络层处理过程一样,如果 skb 大于 MTU 的话,仍然会进行分片。
只不过 lo 的 MTU 比 Ethernet 要大很多。
通过 ifconfig 命令就可以查到,普通网卡一般为 1500,而 lO 虚拟接口能有 65535。

在内核源码中, 65535 是用 (64*1024)表示的,单位是字节。


 

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 1比25万基础电子地图(广东版)
  • 踏进互动科技世界使用Arduino
  • 【测开能力提升-Javascript】JavaScript运算符流程结构
  • 构建高效Node.js中间层:探索请求合并转发的艺术
  • 深入解析sizeof和strlen的区别与联系
  • 麒麟V10安装nginx、mysql报错缺少包:error while loading shared libraries libssl.so.10
  • Sparksql常用的json相关函数
  • PostgreSQL 中如何处理数据的唯一性约束?
  • JVM 21 的优化指南:如何进行JVM调优,JVM调优参数有哪些
  • 标签嵌套规则/行内元素/块元素的使用
  • 算法通关:006_1二分查找
  • 设计模式简述(一)
  • 【北京迅为】《i.MX8MM嵌入式Linux开发指南》-第三篇 嵌入式Linux驱动开发篇-第三十九章 Linux MISC驱动
  • Java实战中如何使用多线程(线程池)及其为什么使用?
  • 科技引领水资源管理新篇章:深入剖析智慧水利解决方案,展现其在提升水资源利用效率、优化水环境管理方面的创新实践
  • Druid 在有赞的实践
  • iOS动画编程-View动画[ 1 ] 基础View动画
  • Java多态
  • JS基础之数据类型、对象、原型、原型链、继承
  • KMP算法及优化
  • Linux后台研发超实用命令总结
  • python3 使用 asyncio 代替线程
  • scrapy学习之路4(itemloder的使用)
  • 半理解系列--Promise的进化史
  • 道格拉斯-普克 抽稀算法 附javascript实现
  • 动态魔术使用DBMS_SQL
  • 汉诺塔算法
  • 力扣(LeetCode)56
  • 如何在GitHub上创建个人博客
  • 数据库写操作弃用“SELECT ... FOR UPDATE”解决方案
  • 微信开放平台全网发布【失败】的几点排查方法
  • 学习Vue.js的五个小例子
  • Oracle Portal 11g Diagnostics using Remote Diagnostic Agent (RDA) [ID 1059805.
  • 哈罗单车融资几十亿元,蚂蚁金服与春华资本加持 ...
  • ​​快速排序(四)——挖坑法,前后指针法与非递归
  • ​LeetCode解法汇总2670. 找出不同元素数目差数组
  • ​一、什么是射频识别?二、射频识别系统组成及工作原理三、射频识别系统分类四、RFID与物联网​
  • # 学号 2017-2018-20172309 《程序设计与数据结构》实验三报告
  • #1015 : KMP算法
  • (14)目标检测_SSD训练代码基于pytorch搭建代码
  • (175)FPGA门控时钟技术
  • (4)通过调用hadoop的java api实现本地文件上传到hadoop文件系统上
  • (CPU/GPU)粒子继承贴图颜色发射
  • (八)Docker网络跨主机通讯vxlan和vlan
  • (八十八)VFL语言初步 - 实现布局
  • (二)c52学习之旅-简单了解单片机
  • (十)T检验-第一部分
  • (太强大了) - Linux 性能监控、测试、优化工具
  • (一)Linux+Windows下安装ffmpeg
  • (一)项目实践-利用Appdesigner制作目标跟踪仿真软件
  • (已更新)关于Visual Studio 2019安装时VS installer无法下载文件,进度条为0,显示网络有问题的解决办法
  • (转)AS3正则:元子符,元序列,标志,数量表达符
  • .【机器学习】隐马尔可夫模型(Hidden Markov Model,HMM)
  • .mkp勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复
  • .NET Core WebAPI中使用Log4net 日志级别分类并记录到数据库