Linux驱动开发16 网络设备驱动框架
嵌入式下的网络硬件接口
MII/RMII 接口
MDIO 接口
RJ45 接口
PHY 芯片详解
PHY的前16个寄存器详解
Linux 内核网络驱动框架
net_device 结构体(注册与注销)
struct net_device {char name[IFNAMSIZ];struct hlist_node name_hlist;char *ifalias;/** I/O specific fields* FIXME: Merge these and struct ifmap into one*/unsigned long mem_end;unsigned long mem_start;unsigned long base_addr;int irq;atomic_t carrier_changes;/** Some hardware also needs these fields (state,dev_list,* napi_list,unreg_list,close_list) but they are not* part of the usual set specified in Space.c.*/unsigned long state;struct list_head dev_list;struct list_head napi_list;struct list_head unreg_list;struct list_head close_list;struct list_head ptype_all;struct list_head ptype_specific;struct {struct list_head upper;struct list_head lower;} adj_list;struct {struct list_head upper;struct list_head lower;} all_adj_list;netdev_features_t features;netdev_features_t hw_features;netdev_features_t wanted_features;netdev_features_t vlan_features;netdev_features_t hw_enc_features;netdev_features_t mpls_features;int ifindex;int group;struct net_device_stats stats;atomic_long_t rx_dropped;atomic_long_t tx_dropped;#ifdef CONFIG_WIRELESS_EXTconst struct iw_handler_def * wireless_handlers;struct iw_public_data * wireless_data;
#endifconst struct net_device_ops *netdev_ops;const struct ethtool_ops *ethtool_ops;
#ifdef CONFIG_NET_SWITCHDEVconst struct swdev_ops *swdev_ops;
#endifconst struct header_ops *header_ops;unsigned int flags;unsigned int priv_flags;unsigned short gflags;unsigned short padded;unsigned char operstate;unsigned char link_mode;unsigned char if_port;unsigned char dma;unsigned int mtu;unsigned short type;unsigned short hard_header_len;unsigned short needed_headroom;unsigned short needed_tailroom;/* Interface address info. */unsigned char perm_addr[MAX_ADDR_LEN];unsigned char addr_assign_type;unsigned char addr_len;unsigned short neigh_priv_len;unsigned short dev_id;unsigned short dev_port;spinlock_t addr_list_lock;unsigned char name_assign_type;bool uc_promisc;struct netdev_hw_addr_list uc;struct netdev_hw_addr_list mc;struct netdev_hw_addr_list dev_addrs;#ifdef CONFIG_SYSFSstruct kset *queues_kset;
#endifunsigned int promiscuity;unsigned int allmulti;/* Protocol specific pointers */#if IS_ENABLED(CONFIG_VLAN_8021Q)struct vlan_info __rcu *vlan_info;
#endif
#if IS_ENABLED(CONFIG_NET_DSA)struct dsa_switch_tree *dsa_ptr;
#endif
#if IS_ENABLED(CONFIG_TIPC)struct tipc_bearer __rcu *tipc_ptr;
#endifvoid *atalk_ptr;struct in_device __rcu *ip_ptr;struct dn_dev __rcu *dn_ptr;struct inet6_dev __rcu *ip6_ptr;void *ax25_ptr;struct wireless_dev *ieee80211_ptr;struct wpan_dev *ieee802154_ptr;
#if IS_ENABLED(CONFIG_MPLS_ROUTING)struct mpls_dev __rcu *mpls_ptr;
#endif/** Cache lines mostly used on receive path (including eth_type_trans())*/unsigned long last_rx;/* Interface address info used in eth_type_trans() */unsigned char *dev_addr;#ifdef CONFIG_SYSFSstruct netdev_rx_queue *_rx;unsigned int num_rx_queues;unsigned int real_num_rx_queues;#endifunsigned long gro_flush_timeout;rx_handler_func_t __rcu *rx_handler;void __rcu *rx_handler_data;struct netdev_queue __rcu *ingress_queue;unsigned char broadcast[MAX_ADDR_LEN];
#ifdef CONFIG_RFS_ACCELstruct cpu_rmap *rx_cpu_rmap;
#endifstruct hlist_node index_hlist;/** Cache lines mostly used on transmit path*/struct netdev_queue *_tx ____cacheline_aligned_in_smp;unsigned int num_tx_queues;unsigned int real_num_tx_queues;struct Qdisc *qdisc;unsigned long tx_queue_len;spinlock_t tx_global_lock;int watchdog_timeo;#ifdef CONFIG_XPSstruct xps_dev_maps __rcu *xps_maps;
#endif/* These may be needed for future network-power-down code. *//** trans_start here is expensive for high speed devices on SMP,* please use netdev_queue->trans_start instead.*/unsigned long trans_start;struct timer_list watchdog_timer;int __percpu *pcpu_refcnt;struct list_head todo_list;struct list_head link_watch_list;enum { NETREG_UNINITIALIZED=0,NETREG_REGISTERED, /* completed register_netdevice */NETREG_UNREGISTERING, /* called unregister_netdevice */NETREG_UNREGISTERED, /* completed unregister todo */NETREG_RELEASED, /* called free_netdev */NETREG_DUMMY, /* dummy device for NAPI poll */} reg_state:8;bool dismantle;enum {RTNL_LINK_INITIALIZED,RTNL_LINK_INITIALIZING,} rtnl_link_state:16;void (*destructor)(struct net_device *dev);#ifdef CONFIG_NETPOLLstruct netpoll_info __rcu *npinfo;
#endifpossible_net_t nd_net;/* mid-layer private */union {void *ml_priv;struct pcpu_lstats __percpu *lstats;struct pcpu_sw_netstats __percpu *tstats;struct pcpu_dstats __percpu *dstats;struct pcpu_vstats __percpu *vstats;};struct garp_port __rcu *garp_port;struct mrp_port __rcu *mrp_port;struct device dev;const struct attribute_group *sysfs_groups[4];const struct attribute_group *sysfs_rx_queue_group;const struct rtnl_link_ops *rtnl_link_ops;/* for setting kernel sock attribute on TCP connection setup */
#define GSO_MAX_SIZE 65536unsigned int gso_max_size;
#define GSO_MAX_SEGS 65535u16 gso_max_segs;u16 gso_min_segs;
#ifdef CONFIG_DCBconst struct dcbnl_rtnl_ops *dcbnl_ops;
#endifu8 num_tc;struct netdev_tc_txq tc_to_txq[TC_MAX_QUEUE];u8 prio_tc_map[TC_BITMASK + 1];#if IS_ENABLED(CONFIG_FCOE)unsigned int fcoe_ddp_xid;
#endif
#if IS_ENABLED(CONFIG_CGROUP_NET_PRIO)struct netprio_map __rcu *priomap;
#endifstruct phy_device *phydev;struct lock_class_key *qdisc_tx_busylock;
};
net_device_ops 结构体(网络设备操作集)
struct net_device_ops {int (*ndo_init)(struct net_device *dev);void (*ndo_uninit)(struct net_device *dev);int (*ndo_open)(struct net_device *dev);int (*ndo_stop)(struct net_device *dev);netdev_tx_t (*ndo_start_xmit) (struct sk_buff *skb,struct net_device *dev);u16 (*ndo_select_queue)(struct net_device *dev,struct sk_buff *skb,void *accel_priv,select_queue_fallback_t fallback);void (*ndo_change_rx_flags)(struct net_device *dev,int flags);void (*ndo_set_rx_mode)(struct net_device *dev);int (*ndo_set_mac_address)(struct net_device *dev,void *addr);int (*ndo_validate_addr)(struct net_device *dev);int (*ndo_do_ioctl)(struct net_device *dev,struct ifreq *ifr, int cmd);int (*ndo_set_config)(struct net_device *dev,struct ifmap *map);int (*ndo_change_mtu)(struct net_device *dev,int new_mtu);int (*ndo_neigh_setup)(struct net_device *dev,struct neigh_parms *);void (*ndo_tx_timeout) (struct net_device *dev);struct rtnl_link_stats64* (*ndo_get_stats64)(struct net_device *dev,struct rtnl_link_stats64 *storage);struct net_device_stats* (*ndo_get_stats)(struct net_device *dev);int (*ndo_vlan_rx_add_vid)(struct net_device *dev,__be16 proto, u16 vid);int (*ndo_vlan_rx_kill_vid)(struct net_device *dev,__be16 proto, u16 vid);
#ifdef CONFIG_NET_POLL_CONTROLLERvoid (*ndo_poll_controller)(struct net_device *dev);int (*ndo_netpoll_setup)(struct net_device *dev,struct netpoll_info *info);void (*ndo_netpoll_cleanup)(struct net_device *dev);
#endif
#ifdef CONFIG_NET_RX_BUSY_POLLint (*ndo_busy_poll)(struct napi_struct *dev);
#endifint (*ndo_set_vf_mac)(struct net_device *dev,int queue, u8 *mac);int (*ndo_set_vf_vlan)(struct net_device *dev,int queue, u16 vlan, u8 qos);int (*ndo_set_vf_rate)(struct net_device *dev,int vf, int min_tx_rate,int max_tx_rate);int (*ndo_set_vf_spoofchk)(struct net_device *dev,int vf, bool setting);int (*ndo_get_vf_config)(struct net_device *dev,int vf,struct ifla_vf_info *ivf);int (*ndo_set_vf_link_state)(struct net_device *dev,int vf, int link_state);int (*ndo_set_vf_port)(struct net_device *dev,int vf,struct nlattr *port[]);int (*ndo_get_vf_port)(struct net_device *dev,int vf, struct sk_buff *skb);int (*ndo_set_vf_rss_query_en)(struct net_device *dev,int vf, bool setting);int (*ndo_setup_tc)(struct net_device *dev, u8 tc);
#if IS_ENABLED(CONFIG_FCOE)int (*ndo_fcoe_enable)(struct net_device *dev);int (*ndo_fcoe_disable)(struct net_device *dev);int (*ndo_fcoe_ddp_setup)(struct net_device *dev,u16 xid,struct scatterlist *sgl,unsigned int sgc);int (*ndo_fcoe_ddp_done)(struct net_device *dev,u16 xid);int (*ndo_fcoe_ddp_target)(struct net_device *dev,u16 xid,struct scatterlist *sgl,unsigned int sgc);int (*ndo_fcoe_get_hbainfo)(struct net_device *dev,struct netdev_fcoe_hbainfo *hbainfo);
#endif#if IS_ENABLED(CONFIG_LIBFCOE)
#define NETDEV_FCOE_WWNN 0
#define NETDEV_FCOE_WWPN 1int (*ndo_fcoe_get_wwn)(struct net_device *dev,u64 *wwn, int type);
#endif#ifdef CONFIG_RFS_ACCELint (*ndo_rx_flow_steer)(struct net_device *dev,const struct sk_buff *skb,u16 rxq_index,u32 flow_id);
#endifint (*ndo_add_slave)(struct net_device *dev,struct net_device *slave_dev);int (*ndo_del_slave)(struct net_device *dev,struct net_device *slave_dev);netdev_features_t (*ndo_fix_features)(struct net_device *dev,netdev_features_t features);int (*ndo_set_features)(struct net_device *dev,netdev_features_t features);int (*ndo_neigh_construct)(struct neighbour *n);void (*ndo_neigh_destroy)(struct neighbour *n);int (*ndo_fdb_add)(struct ndmsg *ndm,struct nlattr *tb[],struct net_device *dev,const unsigned char *addr,u16 vid,u16 flags);int (*ndo_fdb_del)(struct ndmsg *ndm,struct nlattr *tb[],struct net_device *dev,const unsigned char *addr,u16 vid);int (*ndo_fdb_dump)(struct sk_buff *skb,struct netlink_callback *cb,struct net_device *dev,struct net_device *filter_dev,int idx);int (*ndo_bridge_setlink)(struct net_device *dev,struct nlmsghdr *nlh,u16 flags);int (*ndo_bridge_getlink)(struct sk_buff *skb,u32 pid, u32 seq,struct net_device *dev,u32 filter_mask,int nlflags);int (*ndo_bridge_dellink)(struct net_device *dev,struct nlmsghdr *nlh,u16 flags);int (*ndo_change_carrier)(struct net_device *dev,bool new_carrier);int (*ndo_get_phys_port_id)(struct net_device *dev,struct netdev_phys_item_id *ppid);int (*ndo_get_phys_port_name)(struct net_device *dev,char *name, size_t len);void (*ndo_add_vxlan_port)(struct net_device *dev,sa_family_t sa_family,__be16 port);void (*ndo_del_vxlan_port)(struct net_device *dev,sa_family_t sa_family,__be16 port);void* (*ndo_dfwd_add_station)(struct net_device *pdev,struct net_device *dev);void (*ndo_dfwd_del_station)(struct net_device *pdev,void *priv);netdev_tx_t (*ndo_dfwd_start_xmit) (struct sk_buff *skb,struct net_device *dev,void *priv);int (*ndo_get_lock_subclass)(struct net_device *dev);netdev_features_t (*ndo_features_check) (struct sk_buff *skb,struct net_device *dev,netdev_features_t features);int (*ndo_set_tx_maxrate)(struct net_device *dev,int queue_index,u32 maxrate);int (*ndo_get_iflink)(const struct net_device *dev);
};
第 2 行:ndo_init 函数,当第一次注册网络设备的时候此函数会执行,设备可以在此函数中做一些需要退后初始化的内容,不过一般驱动中不使用此函数,虚拟网络设备可能会使用。第 3 行:ndo_uninit 函数,卸载网络设备的时候此函数会执行。第 4 行:ndo_open 函数,打开网络设备的时候此函数会执行,网络驱动程序需要实现此函数,非常重要!以 NXP 的 I.MX 系列 SOC 网络驱动为例,会在此函数中做如下工作:·使能网络外设时钟。·申请网络所使用的环形缓冲区。·初始化 MAC 外设。·绑定接口对应的 PHY。·如果使用 NAPI 的话要使能 NAPI 模块,通过 napi_enable 函数来使能。·开启 PHY。·调用 netif_tx_start_all_queues 来使能传输队列,也可能调用 netif_start_queue 函数。·……第 5 行:ndo_stop 函数,关闭网络设备的时候此函数会执行,网络驱动程序也需要实现此函数。以 NXP 的 I.MX 系列 SOC 网络驱动为例,会在此函数中做如下工作:·停止 PHY。·停止 NAPI 功能。·停止发送功能。·关闭 MAC。·断开 PHY 连接。·关闭网络时钟。·释放数据缓冲区。·……第 6 行:ndo_start_xmit 函数,当需要发送数据的时候此函数就会执行,此函数有一个参数为 sk_buff 结构体指针,sk_buff 结构体在 Linux 的网络驱动中非常重要,sk_buff 保存了上层传递给网络驱动层的数据。也就是说,要发送出去的数据都存在了 sk_buff 中,关于 sk_buff 稍后会做详细的讲解。如果发送成功的话此函数返回 NETDEV_TX_OK,如果发送失败了就返回NETDEV_TX_BUSY,如果发送失败了我们就需要停止队列。第 8 行:ndo_select_queue 函数,当设备支持多传输队列的时候选择使用哪个队列第 14 行:ndo_set_rx_mode 函数,此函数用于改变地址过滤列表,根据 net_device 的 flags 成员变量来设置 SOC 的网络外设寄存器。比如 flags 可能为 IFF_PROMISC、IFF_ALLMULTI 或 IFF_MULTICAST,分别表示混杂模式、单播模式或多播模式。第 15 行:ndo_set_mac_address 函数,此函数用于修改网卡的 MAC 地址,设置 net_device的 dev_addr 成员变量,并且将 MAC 地址写入到网络外设的硬件寄存器中。第 17 行:ndo_validate_addr 函数,验证 MAC 地址是否合法,也即是验证 net_device 的 dev_addr 中的 MAC 地址是否合法,直接调用 is_valid_ether_addr 函数。第 18 行:ndo_do_ioctl 函数,用户程序调用 ioctl 的时候此函数就会执行,比如 PHY 芯片相关的命令操作,一般会直接调用 phy_mii_ioctl 函数。第 22 行:ndo_change_mtu 函数,更改 MTU 大小。第 26 行:ndo_tx_timeout 函数,当发送超时的时候产生会执行,一般都是网络出问题了导致发送超时。一般可能会重启 MAC 和 PHY,重新开始数据发送等。第 37 行:ndo_poll_controller 函数,使用查询方式来处理网卡数据的收发。第 104 行:ndo_set_features 函数,修改 net_device 的 features 属性,设置相应的硬件属性。
sk_buff 结构体(管理数据包)
针对 sk_buff 内核提供了一系列的操作与管理函数,我们简单看一些常见的 API 函数:
网络 NAPI 处理机制 与 napi_struct 实例
实验
不需要写代码 真正如果需要写网络驱动框架去看懂NXP官方的即可
Linux驱动开发16 网络设备驱动框架相关推荐
- 浅谈 Linux 内核开发之网络设备驱动
网络设备介绍 网络设备是计算机体系结构中必不可少的一部分,处理器如果想与外界通信,通常都会选择网络设备作为通信接口.众所周知,在 OSI(Open Systems Interconnection,开放 ...
- 浅谈 Linux 内核开发之网络设备驱动[转]
本文来自:http://www.ibm.com/developerworks/cn/linux/l-cn-networkdriver/ 网络设备介绍 网络 设备是计算机体系结构中必不可少的一部分,处理 ...
- Linux驱动开发1:驱动开发与裸机开发的区别
Linux驱动开发1:驱动开发与裸机开发的区别 1.裸机驱动开发回顾: 裸机驱动开发是非常底层的,跟寄存器打交道,有些MCU为了方便我们开发,提供了一些库,让我们通过调用API函数来间接的实现利用寄存 ...
- <Linux开发>驱动开发 -之-platform 驱动
<Linux开发>驱动开发 -之-platform 驱动 交叉编译环境搭建: <Linux开发> linux开发工具-之-交叉编译环境搭建 uboot移植可参考以下: < ...
- <Linux开发>--驱动开发-- 字符设备驱动(3) 过程详细记录
<Linux开发>–驱动开发-- 字符设备驱动(3) 过程详细记录 驱动开发是建立再系统之上的,前面作者也记录了系统移植的过程记录,如果有兴趣,可进入博主的主页查看相关文章,这里就不添加链 ...
- Linux驱动开发—内核I2C驱动详解
Linux驱动开发--内核I2C驱动 I2C驱动文件结构 I2C数据传输过程 i2c_transfer i2c_msg I2C通讯常用的接口函数(老版本) 快速读写接口函数:(连续读写) 常用的读操作 ...
- Linux嵌入式驱动开发07——GPIO驱动过程记录(飞凌开发板)
文章目录 全系列传送门 1. 在/arch/arm/boot/dts/imx6q-pinfunc.h查找 2. 在设备树配置文件中添加设备节点定义以及其引脚定义 3. 修改设备树文件添加配置 4. d ...
- Linux 设备驱动开发 —— platform设备驱动应用实例解析
前面我们已经学习了platform设备的理论知识Linux 设备驱动开发 -- platform 设备驱动 ,下面将通过一个实例来深入我们的学习. 一.platform 驱动的工作过程 platfor ...
- STM32MP157驱动开发——platform设备驱动(中)
STM32MP157驱动开发--platform设备驱动(中) 0.前言 一.platform设备模块--设备信息解析 二.platform驱动模块--加载设备 三.测试App 四.编译及运行 相关文 ...
最新文章
- java语言的主要的知识点
- 【转】ASP.NET中页面传值
- vue修改打包后静态资源路径
- Python实训day05am【正则表达式、网络爬虫】
- Python的seaborn库(图比较炫)
- flash可以编辑html文本吗,flash中怎么插入并编辑文字字体样式?
- mysql concat 日期_mysql group_concat时间用法
- JSP文件中Java代码的几种形式(JSP脚本)
- java决策树_【Java】决策树介绍和使用
- 【离散数学】图的着色与对偶图
- var和function谁先优先执行_浅谈JavaScript 的执行顺序
- tab控件的使用心得
- cmos和ttl_CMOS与TTL电路的详细对比区别
- Swift开发笔记-Mac OS X 天气预报应用开发(Xcode7.2)
- JavaWeb框架-Spring(基本概念)
- 支付宝授权登陆php,支付宝app登录授权的infoStr授权登录流程
- INNODB记录格式
- OpenGL实现在三维空间拖拽物体
- 短信宝接入发送短信实测 Java
- html语言如何排版,html语言,使用table排版.docx