虚拟网卡驱动和DM9000C移植

网卡驱动程序框架

网卡驱动程序“收发功能”:

只要把上层的数据发给网卡,从网卡来的数据构造成包给上层即可。网卡只需要

“socket”编程,不需要打开某设备。

驱动程序都是以面向对象的思想写的,都有相关的结构体。

编程步骤

1,分配某结构体:alloc_netdev net_device

2,设置结构体。

①,提供一个发包函数:hard_start_xmit()

②,提供收包的功能 : net_interrupt(int irq, void *dev_id)-->netif_rx(skb);

收到数据后,网卡里面一般都有中断程序。在中断程序中有一个上报数据的函数。

3,注册结构体:register_netdev(dev) 真实驱动中使用的是此注册函数。

4,硬件相关操作。

看内核中的“cs89x.c”这个真实的网卡驱动程序:

int __init init_module(void)

    -->分配一个 net_device 结构体

    struct net_device *dev = alloc_etherdev(sizeof(struct net_local));

        --->alloc_netdev(sizeof_priv, "eth%d", ether_setup); 分配时用了eth%d这样的名字。

    -->设置 net_device 结构 :

    MAC 地址,硬件相关操作

    dev->dev_addr[0] = 0x08;

    dev->dev_addr[1] = 0x89;

    dev->dev_addr[2] = 0x89;

    dev->dev_addr[3] = 0x89;

    dev->dev_addr[4] = 0x89;

    dev->dev_addr[5] = 0x89; //以上为MAC地址。

    --> 硬件相关设置

    -->ret = cs89x0_probe1(dev, io, 1);

    -->net_device结构中有open,read等函数。

    dev->open = net_open;

    dev->stop = net_close;

    dev->tx_timeout = net_timeout;

    dev->watchdog_timeo = HZ;

    dev->hard_start_xmit = net_send_packet; //硬件启动传输。这是发包函数。

    dev->get_stats = net_get_stats;

    dev->set_multicast_list = set_multicast_list;

    dev->set_mac_address = set_mac_address;

    -->retval = register_netdev(dev);

接收到包后是上报了一个“sk_buff”缓冲(netif_rx(skb))

sk_buff 结构 是纽带,运用“hard_start_xmit()”和“netif_rx()”:

网卡在中断程序中收到数据后,从芯片里把数据读出来构造一个“skb_buff”结构数据,

调用“netif_rx()”上报数据给应用层。

接收到数据要做的事情:

irqreturn_t net_interrupt(int irq, void *dev_id)

    -->net_rx(dev);

    -->从硬件芯片里读出来

    status = readword(ioaddr, RX_FRAME_PORT);

    length = readword(ioaddr, RX_FRAME_PORT);

    -->skb = dev_alloc_skb(length + 2); 分配一个skb缓冲。

    -->netif_rx(skb);

    -->netif_wake_queue(dev); 发送完数据后就唤醒队列

应用层构造好一个包后,放到“skb_buff”结构交给网卡驱动,调用

“hard_start_xmit()”来发送。

发包函数:

int net_send_packet(struct sk_buff *skb, struct net_device *dev)

    -->netif_stop_queue(dev); 先停止队列

    -->将“skb_buff”中数据写到网卡芯片:

    writeword(dev->base_addr, TX_CMD_PORT, lp->send_cmd);

    writeword(dev->base_addr, TX_LEN_PORT, skb->len);

    writewords(dev->base_addr, TX_FRAME_PORT,skb->data,(skb->len+1) >>1);

    -->dev_kfree_skb (skb); 然后释放skb_buff

16th_virt_net难懂代码分析

测试ifconfig vnet0 3.3.3.3

ping 3.3.3.4

模拟真实网卡ping功能

static void emulator_rx_packet(struct sk_buff *skb, struct net_device *dev)

{

    /* 参考LDD3 */

    unsigned char *type;

    struct iphdr *ih;

    __be32 *saddr, *daddr, tmp;

    unsigned char    tmp_dev_addr[ETH_ALEN];

    struct ethhdr *ethhdr;

    

    struct sk_buff *rx_skb;

        

    // 从硬件读出/保存数据

    /* 对调"源/目的"的mac地址 */

    ethhdr = (struct ethhdr *)skb->data;

    memcpy(tmp_dev_addr, ethhdr->h_dest, ETH_ALEN);

    memcpy(ethhdr->h_dest, ethhdr->h_source, ETH_ALEN);

    memcpy(ethhdr->h_source, tmp_dev_addr, ETH_ALEN);

    /* 对调"源/目的"的ip地址 */    

    ih = (struct iphdr *)(skb->data + sizeof(struct ethhdr));

    saddr = &ih->saddr;

    daddr = &ih->daddr;

    tmp = *saddr;

    *saddr = *daddr;

    *daddr = tmp;

    

    //((u8 *)saddr)[2] ^= 1; /* change the third octet (class C) */

    //((u8 *)daddr)[2] ^= 1;

    type = skb->data + sizeof(struct ethhdr) + sizeof(struct iphdr);

    //printk("tx package type = %02x\n", *type);

    // 修改类型, 原来0x8表示ping

    *type = 0; /* 0表示reply */

    

    ih->check = 0;           /* and rebuild the checksum (ip needs it) */

    ih->check = ip_fast_csum((unsigned char *)ih,ih->ihl);

    

    // 构造一个sk_buff

    rx_skb = dev_alloc_skb(skb->len + 2);

    skb_reserve(rx_skb, 2); /* align IP on 16B boundary */    

    memcpy(skb_put(rx_skb, skb->len), skb->data, skb->len);

    /* Write metadata, and then pass to the receive level */

    rx_skb->dev = dev;

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

    rx_skb->ip_summed = CHECKSUM_UNNECESSARY; /* don't check it */

    dev->stats.rx_packets++;

    dev->stats.rx_bytes += skb->len;

    // 提交sk_buff

    netif_rx(rx_skb);

}

DM9000移植修改

修改点:

1.网卡基地址,位宽,中断号

2.设置网卡访问时序

jz2440在ubuntu18.0 挂载

mount -t nfs -o nolock,vers=3 10.10.60.95:/home/book/jz2440/nfs_rootfs/fs_test_mini_new /mnt

使用在ubuntu18.0 nfs启动

set  bootargs noinitrd root=/dev/nfs nfsroot=10.10.60.95:/home/book/jz2440/nfs_rootfs/fs_test_mini_new,v3,tcp ip=10.10.60.40:10.10.60.95:10.10.60.1:255.255.255.0::eth0:off init=/linuxrc console=ttySAC0,115200

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/61495.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

image compare pyqt 实现

默认显示image1, 鼠标滑动滚动条切换图片显示 可视化效果: image_compare.py import sys from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QSlider, QVBoxLayout, QHBoxLayout from PyQt5.QtCore import Qt, QSize from PyQt5.QtGui import QPixmap, QPainte…

【单片机基础】定时器/计数器的工作原理

单片机中的定时器/计数器(Timer/Counter)是用于时间测量和事件计数的重要模块。它们可以用来生成精确的延时、测量外部信号的频率或周期、捕获外部事件的时间戳等。理解定时器/计数器的工作原理对于单片机编程和系统设计非常重要。以下是定时器/计数器的…

在自动驾驶进行大数据量因果推理实验时,如何减少无用功,提高实验效率?

在对实验结果做反事实推理时,通常需要对数据进行多次循环,然后对多次循环的结果进行处理,如果只在最后结果结束时,再进行处理,可能会由于反事实过程中某个参数设置错误,导致整个反事实实验出现错误&#xf…

浅谈软件开发中的yield关键字:从餐厅服务理解异步编程之美

在现代软件开发中,处理大量数据流时经常会遇到性能和内存消耗的问题。传统的编程方式往往是一次性获取所有数据,这就像餐厅厨师要把所有菜品做完才上菜一样,既不高效也不够灵活。而yield关键字的出现,为我们提供了一种优雅的解决方…

绕过CDN寻找真实IP

在新型涉网案件中,我们在搜集到目标主站之后常常需要获取对方网站的真实IP去进一步的信息搜集,但是现在网站大多都部署了CDN,将资源部署分发到边缘服务器,实现均衡负载,降低网络堵塞,让用户能够更快地访问自…

前后端请求响应

引入 在之前的例子中,我们编写了一个简单的web类,我们运行启动类,启动内嵌的tomcat后就可以在浏览器通过特定的路径访问tomcat中的应用程序。 但之前编写的程序仅仅是个简单的java类,其并未实现某个接口或继承某个类&…

深度学习:神经网络中的损失函数的使用

深度学习:神经网络中的损失函数的使用 损失函数是监督学习中的关键组成部分,用于衡量模型预测值与真实值之间的差异。优化算法(如梯度下降)通过最小化损失函数来调整模型参数,以提高模型的预测精度。以下是几种常用的…

ThreeJS入门(142):THREE.WebGLRenderTarget 知识详解,示例代码

作者: 还是大剑师兰特 ,曾为美国某知名大学计算机专业研究生,现为国内GIS领域高级前端工程师,CSDN知名博主,深耕openlayers、leaflet、mapbox、cesium,webgl,ThreeJS,canvas&#xf…

GitLab 部署和配置指南

GitLab 部署和配置指南 1. GitLab 容器配置概述 在部署 GitLab 时,可能涉及以下几部分内容: 内置 Nginx 的配置和调整。HTTPS 证书的申请、使用和续期。通过 FRP 映射内网服务到外部服务器。阿里云服务器的 Nginx 配置和反向代理。 本文将完整涵盖这…

Streamlit + AI大模型API实现视频字幕提取

简介 在本文中,我将带你探讨如何使用Streamlit和AI大模型API来实现视频字幕提取的技术。Streamlit是一个开源的Python库,用于快速构建数据应用的Web界面,而AI大模型API,如OpenAI,提供了强大的语言处理能力&#xff0c…

SpringBoot - spring.profiles.active最佳实践

文章目录 Pre概述为什么需要多环境配置多环境配置实现步骤1. 配置文件准备2. 激活特定环境方法1:命令行参数方法2:环境变量方法3:IDE 配置方法4:全局配置文件默认设置 3. 配置文件加载顺序配置生效的原理 4. 常见问题多个配置文件…

深入理解 Vue 3 中的 emit

深入理解 Vue 3 中的 emit 在 Vue 3 中,组件通信是开发中非常重要的一部分,其中通过 emit 实现父子组件通信是最常见的方式之一。emit 的作用是:子组件可以通过触发自定义事件将数据传递给父组件。 在本篇文章中,我们将从以下几…

C++结构型设计模式之适配器模式概述

适配器模式的意图和动机 意图:适配器模式(Adapter Pattern)是一种结构型设计模式,其意图是将一个类的接口转换成客户端所期望的另一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的类可以协同工作。 动机&#xff1a…

网安瞭望台第2期:零日漏洞密集爆发、2024年常见网络安全漏洞类型及分析

国内外要闻 Ubuntu 服务器 Needrestart 软件包惊现严重安全漏洞 近日,Ubuntu 服务器(自 21.04 版本起默认安装)的 Needrestart 软件包被曝存在多个可追溯至数十年前的安全漏洞。这些漏洞允许本地攻击者在无需用户交互的情况下获取根…

【Linux】apt 关闭 ssl 认证

【注意】apt 关闭 ssl 认证可能会引起软件安装风险,请尽量避免关闭。 执行以下命令可以实现全局关闭 sll 验证。 echo Acquire::https::Verify-Peer "false"; >> /etc/apt/apt.conf.d/99disable-signature-verificationecho Acquire::https::Verif…

Java前端基础——CSS

一、CSS介绍 1.1 什么是CSS CSS(Cascading Style Sheet),层叠样式表,用于控制页面的样式. CSS 能够对网页中元素位置的排版进行像素级精确控制, 实现美化页面的效果. 能够做到页面的样式和结构分离. 1.2 基本语法规范 选择器 {⼀条/N条声明} • 选择器决定针…

浅议Flink中的通讯工具: Akka

在Flink中,各个组件之间需要频繁交换数据和控制信息。Flink选择了基于Actor模型的Akka框架作为通信基础。 Akka是什么 Actor模型 Actor模型是用于单个进程中并发的场景。 在Actor模型中: ActorSystem负责管理actor生命周期 将每个实体视为独立的 Ac…

Java-05 深入浅出 MyBatis - 配置深入 动态 SQL 参数、循环、片段

点一下关注吧!!!非常感谢!!持续更新!!! 大数据篇正在更新!https://blog.csdn.net/w776341482/category_12713819.html 目前已经更新到了: MyBatis&#xff…

Vue.js 自定义指令:从零开始创建自己的指令

vue使用directive 前言vue2使用vue3使用 前言 关于使用自定义指令在官网中是这样描述的 vue2:对普通 DOM 元素进行底层操作,这时候就会用到自定义指令。 vue3:自定义指令主要是为了重用涉及普通元素的底层 DOM 访问的逻辑。 在 Vue.js 中使用自定义指令&#xf…

uni-app快速入门(十一)--常用JS API(上)

在前面学习了uni-app的布局、组件、路由等知识点以后,还要掌握uni-app的JS API ,也可以理解为基于uni-app的java script。本节介绍uni-app的request请求、文件上传、数据缓存、获取位置、获取系统信息、获取手机的网络状态、拨打电话API。 一、request请求 使用uni…