网络设备之net_device结构与操作
net_device结构是二层中一个非常重要的结构,其结构中成员很多,包含了硬件信息,接口信息,其他辅助信息,以及设备操作函数等等;下面对其中重要的字段含义进行了标注,目前仍在阅读代码过程中,其中某些字段含义会在后面进行补充或者更新;
struct net_device {
/* 设备名称,如eth0 */
char name[IFNAMSIZ];
/* 名称hash */
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; /* 设备自有内存映射到I/O内存的起始地址 */
unsigned long base_addr; /*
设备与内核对话的中断编号,此值可由多个设备共享
驱动程序使用request_irq函数分配此变量,使用free_irq予以释放
*/
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.
*/ /*
网络队列子系统使用的一组标识
由__LINK_STATE_xxx标识
*/
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; /*
用于存在其他一些设备功能
可报告适配卡的功能,以便与CPU通信
使用NETIF_F_XXX标识功能特性
*/
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;
netdev_features_t gso_partial_features; /* 网络设备索引号 */
int ifindex; /* 设备组,默认都属于0组 */
int group; struct net_device_stats stats; atomic_long_t rx_dropped;
atomic_long_t tx_dropped;
atomic_long_t rx_nohandler; #ifdef CONFIG_WIRELESS_EXT
const struct iw_handler_def *wireless_handlers;
struct iw_public_data *wireless_data;
#endif
/* 设备操作接口 */
const struct net_device_ops *netdev_ops;
/* ethtool操作接口 */
const struct ethtool_ops *ethtool_ops;
#ifdef CONFIG_NET_SWITCHDEV
const struct switchdev_ops *switchdev_ops;
#endif
#ifdef CONFIG_NET_L3_MASTER_DEV
const struct l3mdev_ops *l3mdev_ops;
#endif
#if IS_ENABLED(CONFIG_IPV6)
const struct ndisc_ops *ndisc_ops;
#endif #ifdef CONFIG_XFRM
const struct xfrmdev_ops *xfrmdev_ops;
#endif /* 头部一些操作,如链路层缓存,校验等 */
const struct header_ops *header_ops; /* 标识接口特性,IFF_XXX,如IFF_UP */
unsigned int flags; /*
用于存储用户空间不可见的标识
由VLAN和Bridge虚拟设备使用
*/
unsigned int priv_flags; /* 几乎不使用,为了兼容保留 */
unsigned short gflags; /* 结构对齐填充 */
unsigned short padded; /* 与interface group mib中的IfOperStatus相关 */
unsigned char operstate;
unsigned char link_mode; /*
接口使用的端口类型
*/
unsigned char if_port; /*
设备使用的DMA通道
并非所有设备都可以用DMA,有些总线不支持DMA
*/
unsigned char dma; /*
最大传输单元,标识设备能处理帧的最大尺寸
Ethernet-1500
*/
unsigned int mtu;
/* 最小mtu,Ethernet-68 */
unsigned int min_mtu;
/* 最大mut,Ethernet-65535 */
unsigned int max_mtu; /* 设备所属类型
ARP模块中,用type判断接口的硬件地址类型
以太网接口为ARPHRD_ETHER
*/
unsigned short type;
/*
设备头部长度
Ethernet报头是ETH_HLEN=14字节
*/
unsigned short hard_header_len;
unsigned char min_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;
/* 设备名赋值类型,如NET_NAME_UNKNOWN */
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_SYSFS
struct kset *queues_kset;
#endif
/* 混杂模式开启数量 */
unsigned 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;
#endif
void *atalk_ptr;
/* ip指向in_device结构 */
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())
*/
/* Interface address info used in eth_type_trans() */
unsigned char *dev_addr; #ifdef CONFIG_SYSFS
/* 接收队列 */
struct netdev_rx_queue *_rx; /* 接收队列数 */
unsigned int num_rx_queues;
unsigned int real_num_rx_queues;
#endif struct bpf_prog __rcu *xdp_prog;
unsigned long gro_flush_timeout; /* 如网桥等的收包回调 */
rx_handler_func_t __rcu *rx_handler;
/* 回调参数 */
void __rcu *rx_handler_data; #ifdef CONFIG_NET_CLS_ACT
struct tcf_proto __rcu *ingress_cl_list;
#endif
struct netdev_queue __rcu *ingress_queue;
#ifdef CONFIG_NETFILTER_INGRESS
/* netfilter入口 */
struct nf_hook_entry __rcu *nf_hooks_ingress;
#endif /* 链路层广播地址 */
unsigned char broadcast[MAX_ADDR_LEN];
#ifdef CONFIG_RFS_ACCEL
struct cpu_rmap *rx_cpu_rmap;
#endif
/* 接口索引hash */
struct 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;
#ifdef CONFIG_NET_SCHED
DECLARE_HASHTABLE (qdisc_hash, );
#endif
/*
可在设备发送队列中排队的最大数据包数
*/
unsigned long tx_queue_len;
spinlock_t tx_global_lock; /* 网络层确定传输超时,
调用驱动程序tx_timeout接口的最短时间
*/
int watchdog_timeo; #ifdef CONFIG_XPS
struct xps_dev_maps __rcu *xps_maps;
#endif
#ifdef CONFIG_NET_CLS_ACT
struct tcf_proto __rcu *egress_cl_list;
#endif /* These may be needed for future network-power-down code. */
/* watchdog定时器 */
struct timer_list watchdog_timer; /* 引用计数 */
int __percpu *pcpu_refcnt; /* 网络设备的注册和除名以两步进行,
该字段用于处理第二步
*/
struct list_head todo_list; struct list_head link_watch_list; /* 设备的注册状态 */
enum { NETREG_UNINITIALIZED=,
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:; /* 设备要被释放标记 */
bool dismantle; enum {
RTNL_LINK_INITIALIZED,
RTNL_LINK_INITIALIZING,
} rtnl_link_state:; bool needs_free_netdev;
void (*priv_destructor)(struct net_device *dev); #ifdef CONFIG_NETPOLL
struct netpoll_info __rcu *npinfo;
#endif possible_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;
}; #if IS_ENABLED(CONFIG_GARP)
struct garp_port __rcu *garp_port;
#endif
#if IS_ENABLED(CONFIG_MRP)
struct mrp_port __rcu *mrp_port;
#endif struct device dev;
const struct attribute_group *sysfs_groups[];
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 65536
unsigned int gso_max_size;
#define GSO_MAX_SEGS 65535
u16 gso_max_segs; #ifdef CONFIG_DCB
const struct dcbnl_rtnl_ops *dcbnl_ops;
#endif
u8 num_tc;
struct netdev_tc_txq tc_to_txq[TC_MAX_QUEUE];
u8 prio_tc_map[TC_BITMASK + ]; #if IS_ENABLED(CONFIG_FCOE)
unsigned int fcoe_ddp_xid;
#endif
#if IS_ENABLED(CONFIG_CGROUP_NET_PRIO)
struct netprio_map __rcu *priomap;
#endif
struct phy_device *phydev;
struct lock_class_key *qdisc_tx_busylock;
struct lock_class_key *qdisc_running_key;
bool proto_down;
};
上述net_device结构中的netdev_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);
netdev_features_t (*ndo_features_check)(struct sk_buff *skb,
struct net_device *dev,
netdev_features_t features);
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); void (*ndo_get_stats64)(struct net_device *dev,
struct rtnl_link_stats64 *storage);
bool (*ndo_has_offload_stats)(const struct net_device *dev, int attr_id);
int (*ndo_get_offload_stats)(int attr_id,
const struct net_device *dev,
void *attr_data);
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_CONTROLLER
void (*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
int (*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, __be16 proto);
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_set_vf_trust)(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_get_vf_stats)(struct net_device *dev,
int vf,
struct ifla_vf_stats
*vf_stats);
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_guid)(struct net_device *dev,
int vf, u64 guid,
int guid_type);
int (*ndo_set_vf_rss_query_en)(
struct net_device *dev,
int vf, bool setting);
int (*ndo_setup_tc)(struct net_device *dev,
u32 handle,
__be16 protocol,
struct tc_to_netdev *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 1
int (*ndo_fcoe_get_wwn)(struct net_device *dev,
u64 *wwn, int type);
#endif #ifdef CONFIG_RFS_ACCEL
int (*ndo_rx_flow_steer)(struct net_device *dev,
const struct sk_buff *skb,
u16 rxq_index,
u32 flow_id);
#endif
int (*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 net_device *dev,
struct neighbour *n);
void (*ndo_neigh_destroy)(struct net_device *dev,
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_udp_tunnel_add)(struct net_device *dev,
struct udp_tunnel_info *ti);
void (*ndo_udp_tunnel_del)(struct net_device *dev,
struct udp_tunnel_info *ti);
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);
int (*ndo_set_tx_maxrate)(struct net_device *dev,
int queue_index,
u32 maxrate);
int (*ndo_get_iflink)(const struct net_device *dev);
int (*ndo_change_proto_down)(struct net_device *dev,
bool proto_down);
int (*ndo_fill_metadata_dst)(struct net_device *dev,
struct sk_buff *skb);
void (*ndo_set_rx_headroom)(struct net_device *dev,
int needed_headroom);
int (*ndo_xdp)(struct net_device *dev,
struct netdev_xdp *xdp);
};
上述net_device结构中的header_ops成员用来进行链路头部操作,邻居子系统在发送数据包时会用到该结构的成员函数,比如以太网的实现,会通过cache函数将以太头缓存到邻居子系统的hh中,数据包发送前,直接拷贝缓存的以太头即可,无需重新组装;
struct header_ops {
int (*create) (struct sk_buff *skb, struct net_device *dev,
unsigned short type, const void *daddr,
const void *saddr, unsigned int len);
int (*parse)(const struct sk_buff *skb, unsigned char *haddr);
int (*cache)(const struct neighbour *neigh, struct hh_cache *hh, __be16 type);
void (*cache_update)(struct hh_cache *hh,
const struct net_device *dev,
const unsigned char *haddr);
bool (*validate)(const char *ll_header, unsigned int len);
};
网络设备之net_device结构与操作的更多相关文章
- 网络设备之分配net_device结构
注册网络设备时,会调用pci_driver->probe函数,以e100为例,最终会调用alloc_netdev_mqs来分配内存,并且在分配内存后调用setup函数(以太网为ether_set ...
- 网络驱动移植之net_device结构体及其相关的操作函数
内核源码:Linux-2.6.38.8.tar.bz2 在Linux系统中,网络设备都被抽象为struct net_device结构体.它是网络设备硬件与上层协议之间联系的接口,了解它对编写网络驱动程 ...
- 网络驱动之net_device结构体
在Linux系统中,网络设备都被抽象为struct net_device结构体.它是网络设备硬件与上层协议之间联系的接口,了解它对编写网络驱动程序非常有益,所以本文将着手简要介绍linux-2.6.3 ...
- 异步编程的类型系统:promise & future & closure & observable----异步编程类型的结构和操作
异步编程类型的结构和操作. 上下文维护. A promise represents the eventual result of an asynchronous operation. The prim ...
- net_device 结构体分析
/* * The DEVICE structure. * Actually, this whole structure is a big mistake. It mixes I/O * data wi ...
- Mysql-数据库及数据表结构和操作
1.数据库系统:数据库系统是用来维护和管理数据库的系统工具,数据库系统拥有自己的用户名和密码 1.1.显示该系统中的数据库:Show databases; 1.2.创建数据库:Create datab ...
- javaproject积累——树形结构的操作
近期一直被树形结构整的非常头大,又是递归.又是循环.可是,好在我们在经历了千辛万苦后.最终弄出来了.事实上就是组织机构的常规操作,有些是我们过度设计.有些是我们想错了.而对数的逻辑读取,我们就属于想错 ...
- Linux之旅第一篇-目录结构及操作目录
一.引言 Linux对java开发来说也是一项必备的技能,因为项目基本都是部署在Linux操作系统的服务器中,虽然项目不一定需要我们去部署,但不管是自己测试环境部署,还是一些生产环境中日志的查看,Li ...
- 图的存储结构与操作--C语言实现
图(graph)是一种比树结构还要复杂的数据结构,它的术语,存储方式,遍历方式,用途都比较广,所以如果想要一次性完成所有的代码,那代码会非常长.所以,我将分两次来完成图的代码.这一次,我会完成图的五种 ...
随机推荐
- EasyUI 学习笔记
EasyUI常见错误 1 . 无论是用HMTL形式实现组件还是使用代码 + HTML 形式实现组件 , 在为组件设置属性时 , 要注意属性值的类型问题 string:必须加引号 number:不加任何 ...
- [C/C++] char data[0](柔性数组)
转自:http://blog.csdn.net/yby4769250/article/details/7294696 在标准C和C++中0长数组如charArray[0]是不允许使用的,因为这从语义逻 ...
- Codeforces 498B Name That Tune
不想说啥了…这是我被卡常数卡得最惨的一次… 首先根据期望的线性性,我们考虑每首歌能够被认出来的概率,也就是每首歌对答案贡献的期望.那么定义F[i]为第i首歌被认出来的概率是做不了的,自然想到F[i][ ...
- 【bzoj2929】[Poi1999]洞穴攀行 网络流最大流
题目描述 洞穴学者在Byte Mountain的Grate Cave里组织了一次训练.训练中,每一位洞穴学者要从最高的一个室到达最底下的一个室.他们只能向下走.一条路上每一个连续的室都要比它的前一个低 ...
- Python使用requests模块下载图片
MySQL中事先保存好爬取到的图片链接地址. 然后使用多线程把图片下载到本地. # coding: utf-8 import MySQLdb import requests import os imp ...
- CF449C:Jzzhu and Apples——题解
https://vjudge.net/problem/CodeForces-449C 题目大意:1-n编号的苹果两两一对,他们的最大公约数不为1,求这些对的最大匹配. ———————————————— ...
- C++中swap函数
本文是我用到swap函数时,对其产生好奇,所以结合网上有关博文写下的.个人水平有限,若有错误的地方,欢迎留言指出.谢谢! 一.通用的函数交换模板 template<class T> voi ...
- BAT-Python面试题
Python语言特性 1 Python的函数参数传递 看两个如下例子,分析运行结果: 代码一: a = 1 def fun(a): a = 2 fun(a) print(a) # 1 代码二: a = ...
- 在局域网中基于Windows文件共享的git环境搭建
本文的思想是在局域网中用一台电脑作为服务器,在其中建立一个文件夹,作为总的公开版本库.然后将这个文件夹共享,使其他客户机都可以访问,从而进行代码的管理. 一.下载安装文件 1.git核心: git-f ...
- C语言预处理
1.由源码到可执行程序的过程(1)源码.c->(编译)->elf可执行程序(2)源码.c->(编译)->目标文件.o->(链接)->elf可执行程序(3)源码.c- ...