学习linux协议栈关键数据结构
0x01 缘由
0x02 关键结构
![](/assets/blank.gif)
1.struct sk_buff - socket buffer
![](/assets/blank.gif)
struct sk_buff {/* 这两个结构必须放在此结构的前面,主要方便数据的强制转换*/struct sk_buff *next; //双向链表结构,指向下一个sk_buffstruct sk_buff *prev; //指向前一个sk_buff结构struct sock *sk; //这个指针指向一个套接字sock数据结构。当数据在本地产生或者本地进程接受时,需要这个指针;里面的数据会有tcp/udp和用户态程序使用。如果是转发此指针为NULL。后续详解。ktime_t tstamp; //包到达的时间戳struct net_device *dev; //网络设备,哪个网卡、虚拟网卡,后续结构详解。unsigned long _skb_dst; /** 这是控制缓冲区。 每层都可以自由使用 请把您的私有变量放在那里。 如果你想让他们跨层,你必须先做一个skb_clone()。 这是由谁拥有skb排队的ATM拥有。*/char cb[48];unsigned int len, //数据包的全部数据长度,包括data指向的数据和end后面的分片的数据的总长data_len; //本分片所包含的数据长度__u16 mac_len, //mac包头长度hdr_len; //硬件头部长度union {__wsum csum;struct {__u16 csum_start;__u16 csum_offset;};}; //校验和__u32 priority; //QoS等级kmemcheck_bitfield_begin(flags1);__u8 local_df:1,cloned:1,ip_summed:2,nohdr:1,nfctinfo:3;__u8 pkt_type:3, // 根据L2层帧的目的地址进行类型划分。fclone:2, //sk_buff克隆状态ipvs_property:1, //IP虚拟服务器属性peeked:1, //这个数据包已经被看到了,所以已经做了统计,不要再做了nf_trace:1; //netfilter 包记录标识__be16 protocol:16; //从L2层设备驱动看使用在下一个较高层的协议。kmemcheck_bitfield_end(flags1);void (*destructor)(struct sk_buff *skb); //析构函数
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)struct nf_conntrack *nfct; skb与连接的关系struct sk_buff *nfct_reasm; netfilter conntrack重组指针
#endif
#ifdef CONFIG_BRIDGE_NETFILTERstruct nf_bridge_info *nf_bridge;//桥接帧数据
#endifint iif; //到达的设备的索引,网卡索引编号
#ifdef CONFIG_NET_SCHED__u16 tc_index; //流量控制索引
#ifdef CONFIG_NET_CLS_ACT__u16 tc_verd; //流量控制决定
#endif
#endifkmemcheck_bitfield_begin(flags2);__u16 queue_mapping:16; //多队列网卡设备的映射关系
#ifdef CONFIG_IPV6_NDISC_NODETYPE__u8 ndisc_nodetype:2; //路由类型,来自链路层;
#endifkmemcheck_bitfield_end(flags2);/* 0/14 bit hole */#ifdef CONFIG_NET_DMAdma_cookie_t dma_cookie; //被DMA相关函数完成的相关操作cookeie
#endif
#ifdef CONFIG_NETWORK_SECMARK__u32 secmark; //安全相关标记
#endif__u32 mark; //通用标记__u16 vlan_tci; //vlan标签控制信息sk_buff_data_t transport_header; //传输层头sk_buff_data_t network_header; //网络层头sk_buff_data_t mac_header; //以太网层头/* These elements must be at the end, see alloc_skb() for details. */sk_buff_data_t tail; sk_buff_data_t end; unsigned char *head, *data; //head和end指向的是数据区的开端和尾、,data和tail指向的是实际数据的开头和结尾unsigned int truesize; //此缓冲区总大小,包括sk_buff。sk_buff只不过是个指针的集合,他所指的才是真正的数据区,所以是两部分。atomic_t users; //引用计数,使用这个sk_buff的使用者的数目,可能有多个函数要使用同一个sk_buff所以防止提前释放掉,设置此计数
};
2.struct sock - scokets的网络层描述
![](/assets/blank.gif)
struct sock {sock_common __sk_common; //套接口在网络层的最小表示
#define sk_node __sk_common.skc_node
#define sk_nulls_node __sk_common.skc_nulls_node
#define sk_refcnt __sk_common.skc_refcnt#define sk_copy_start __sk_common.skc_hash
#define sk_hash __sk_common.skc_hash
#define sk_family __sk_common.skc_family
#define sk_state __sk_common.skc_state
#define sk_reuse __sk_common.skc_reuse
#define sk_bound_dev_if __sk_common.skc_bound_dev_if
#define sk_bind_node __sk_common.skc_bind_node
#define sk_prot __sk_common.skc_prot
#define sk_net __sk_common.skc_netkmemcheck_bitfield_begin(flags);unsigned int sk_shutdown : 2, //是一组标志位,SEND_SHUTDOWN and/or RCV_SHUTDOWN。sk_no_check : 2, //不对包进行检查标识sk_userlocks : 4, // %SO_SNDBUF 和 %SO_RCVBUF 缓存设置锁sk_protocol : 8, sk_type : 16;kmemcheck_bitfield_end(flags);int sk_rcvbuf; //接收缓存区大小socket_lock_t sk_lock; //同步锁/** The backlog queue is special, it is always used with* the per-socket spinlock held and requires low latency* access. Therefore we special case it's implementation.*/struct {struct sk_buff *head;struct sk_buff *tail;} sk_backlog; //总是被自旋锁持有wait_queue_head_t *sk_sleep; //在队列中等待的socketstruct dst_entry *sk_dst_cache; //目的地址的缓存
#ifdef CONFIG_XFRMstruct xfrm_policy *sk_policy[2];
#endifrwlock_t sk_dst_lock; //目的缓存读写锁atomic_t sk_rmem_alloc; //表示接收队列已提交的字节数。atomic_t sk_wmem_alloc; //表示发送队列已提交的字节数。atomic_t sk_omem_alloc; //用“O”或“other”做选项int sk_sndbuf;struct sk_buff_head sk_receive_queue; //表示接收的数据包的队列。struct sk_buff_head sk_write_queue; //表示发送的数据包的队列。
#ifdef CONFIG_NET_DMAstruct sk_buff_head sk_async_wait_queue; //DMA复制数据包
#endifint sk_wmem_queued; //维持的队列大小int sk_forward_alloc; //转发空间分配gfp_t sk_allocation; //分配空间的模式int sk_route_caps; //路由容量int sk_gso_type; //GSO type (e.g. %SKB_GSO_TCPV4)unsigned int sk_gso_max_size;//最大的GSO段大小int sk_rcvlowat; //unsigned long sk_flags; //%SO_LINGER (l_onoff), %SO_BROADCAST, %SO_KEEPALIVE, %SO_OOBINLINE 标识设定, %SO_TIMESTAMPING 标识设定unsigned long sk_lingertime; //SO_LINGER设定struct sk_buff_head sk_error_queue; //非常少用struct proto *sk_prot_creator; //原始socket创建器rwlock_t sk_callback_lock; //int sk_err,sk_err_soft;atomic_t sk_drops; //raw/udp drop计数unsigned short sk_ack_backlog; //当前监听队列数unsigned short sk_max_ack_backlog; //在listen()中设置的数目__u32 sk_priority; //优先级struct ucred sk_peercred;long sk_rcvtimeo;long sk_sndtimeo;struct sk_filter *sk_filter; //socket 过滤结构void *sk_protinfo; //私有区域struct timer_list sk_timer; //socket清理定时器ktime_t sk_stamp; //最后一包接收时间struct socket *sk_socket; //IO信号void *sk_user_data; //RPC层私有数据struct page *sk_sndmsg_page; //sndmsg缓存struct sk_buff *sk_send_head; //转发数据头__u32 sk_sndmsg_off; // sndmsg缓存偏移int sk_write_pending;
#ifdef CONFIG_SECURITYvoid *sk_security;
#endif__u32 sk_mark;/* XXX 4 bytes hole on 64 bit */void (*sk_state_change)(struct sock *sk);void (*sk_data_ready)(struct sock *sk, int bytes);void (*sk_write_space)(struct sock *sk);void (*sk_error_report)(struct sock *sk);int (*sk_backlog_rcv)(struct sock *sk,struct sk_buff *skb); void (*sk_destruct)(struct sock *sk);
};struct sock_common {unsigned short skc_family; /*地址族*/volatile unsigned char skc_state; /*连接状态*/unsigned char skc_reuse; /*SO_REUSEADDR设置*/int skc_bound_dev_if;struct hlist_node skc_node;struct hlist_node skc_bind_node; /*哈希表相关*/atomic_t skc_refcnt; /*引用计数*/
};
3.struct net_device
![](/assets/blank.gif)
struct net_device
{char name[IFNAMSIZ]; //网络设备名称,如eth0struct hlist_node name_hlist; //这个字段用于构建网络设备名的哈希散列表,而struct net中的name_hlist就指向每个哈希散列表的链表头;char *ifalias; //网络设备的别名;/*网络设备内存映射时在主机中的内存区域*/unsigned long mem_end; /* 共享内存结束 */unsigned long mem_start; /* 共享内存开始 */unsigned long base_addr; /* 网络设备I/O基地址 */unsigned int irq; /* 设备终端号*/unsigned char if_port; /* 传输介质,如双绞线、同轴电缆等,在多端口设备中指定使用哪个端口*/unsigned char dma; /* DMA通道*/unsigned long state; /* 网络设备物理上的工作状态 */struct list_head dev_list; //网络设备链表struct list_head napi_list;//支持NAPI传输的网络设备链表/* Net device features */unsigned long features; //设备硬件功能特性
#define NETIF_F_SG 1 /* Scatter/gather IO. */
#define NETIF_F_IP_CSUM 2 /* Can checksum TCP/UDP over IPv4. */
#define NETIF_F_NO_CSUM 4 /* Does not require checksum. F.e. loopack. */
#define NETIF_F_HW_CSUM 8 /* Can checksum all the packets. */
#define NETIF_F_IPV6_CSUM 16 /* Can checksum TCP/UDP over IPV6 */
#define NETIF_F_HIGHDMA 32 /* Can DMA to high memory. */
#define NETIF_F_FRAGLIST 64 /* Scatter/gather IO. */
#define NETIF_F_HW_VLAN_TX 128 /* Transmit VLAN hw acceleration */
#define NETIF_F_HW_VLAN_RX 256 /* Receive VLAN hw acceleration */
#define NETIF_F_HW_VLAN_FILTER 512 /* Receive filtering on VLAN */
#define NETIF_F_VLAN_CHALLENGED 1024 /* Device cannot handle VLAN packets */
#define NETIF_F_GSO 2048 /* Enable software GSO. */
#define NETIF_F_LLTX 4096 /* LockLess TX - deprecated. Please *//* do not use LLTX in new drivers */
#define NETIF_F_NETNS_LOCAL 8192 /* Does not change network namespaces */
#define NETIF_F_GRO 16384 /* Generic receive offload */
#define NETIF_F_LRO 32768 /* large receive offload *//* the GSO_MASK reserves bits 16 through 23 */
#define NETIF_F_FCOE_CRC (1 << 24) /* FCoE CRC32 */
#define NETIF_F_SCTP_CSUM (1 << 25) /* SCTP checksum offload */
#define NETIF_F_FCOE_MTU (1 << 26) /* Supports max FCoE MTU, 2158 bytes*//* Segmentation offload features */
#define NETIF_F_GSO_SHIFT 16
#define NETIF_F_GSO_MASK 0x00ff0000
#define NETIF_F_TSO (SKB_GSO_TCPV4 << NETIF_F_GSO_SHIFT)
#define NETIF_F_UFO (SKB_GSO_UDP << NETIF_F_GSO_SHIFT)
#define NETIF_F_GSO_ROBUST (SKB_GSO_DODGY << NETIF_F_GSO_SHIFT)
#define NETIF_F_TSO_ECN (SKB_GSO_TCP_ECN << NETIF_F_GSO_SHIFT)
#define NETIF_F_TSO6 (SKB_GSO_TCPV6 << NETIF_F_GSO_SHIFT)
#define NETIF_F_FSO (SKB_GSO_FCOE << NETIF_F_GSO_SHIFT)/* List of features with software fallbacks. */
#define NETIF_F_GSO_SOFTWARE (NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6)#define NETIF_F_GEN_CSUM (NETIF_F_NO_CSUM | NETIF_F_HW_CSUM)
#define NETIF_F_V4_CSUM (NETIF_F_GEN_CSUM | NETIF_F_IP_CSUM)
#define NETIF_F_V6_CSUM (NETIF_F_GEN_CSUM | NETIF_F_IPV6_CSUM)
#define NETIF_F_ALL_CSUM (NETIF_F_V4_CSUM | NETIF_F_V6_CSUM)/** If one device supports one of these features, then enable them* for all in netdev_increment_features.*/
#define NETIF_F_ONE_FOR_ALL (NETIF_F_GSO_SOFTWARE | NETIF_F_GSO_ROBUST | \NETIF_F_SG | NETIF_F_HIGHDMA | \NETIF_F_FRAGLIST)/* Interface index. Unique device identifier */int ifindex;//标识网络设备的唯一索引号 int iflink;//用于虚拟网络设备struct net_device_stats stats; //统计信息#ifdef CONFIG_WIRELESS_EXT/* List of functions to handle Wireless Extensions (instead of ioctl).* See <net/iw_handler.h> for details. Jean II */const struct iw_handler_def * wireless_handlers;/* Instance data managed by the core of Wireless Extensions. */struct iw_public_data * wireless_data;
#endif/* Management operations */const struct net_device_ops *netdev_ops;//网络设备驱动程序需要实现的一组操作函数const struct ethtool_ops *ethtool_ops;//支持ethtool功能的一组操作函数 /* Hardware header description */const struct header_ops *header_ops;//数据链路层协议头相关的一组操作函数unsigned int flags; /* 它们的可能取值定义在linux-2.6.38.8/include/linux/if.h文件中。*/unsigned short gflags;unsigned short priv_flags; /* Like 'flags' but invisible to userspace. */unsigned short padded; /* 分配net_device结构体及其私有数据时为对齐所需的填充位数目*/unsigned char operstate; /*//RFC 2863操作状态 */unsigned char link_mode; /* 映射到RFC2863兼容状态的策略 */unsigned mtu; /* MTU */unsigned short type; /* 网络设备硬件类型,如10Mbps以太网ARPHRD_ETHER */unsigned short hard_header_len; /* 硬件数据帧头的长度,以太网为14字节 *//* extra head- and tailroom the hardware may need, but not in all cases* can this be guaranteed, especially tailroom. Some cases also use* LL_MAX_HEADER instead to allocate the skb.*/unsigned short needed_headroom; //分配套接字缓冲区时预留空间的长度unsigned short needed_tailroom;struct net_device *master; /* 分组状态 *//* 硬件(如MAC)地址长度以及设备的硬件地址 */unsigned char perm_addr[MAX_ADDR_LEN]; /* permanent hw address */unsigned char addr_len; /* hardware address length */unsigned short dev_id; /* for shared network cards */struct netdev_hw_addr_list uc; /* 网络设备硬件地址组成的链表 */int uc_promisc; //混杂模式时的单播地址个数 spinlock_t addr_list_lock;//防止单播地址链表和组播地址链表被并发访问的自旋锁 struct dev_addr_list *mc_list; /* Multicast mac addresses */int mc_count; /* Number of installed mcasts */unsigned int promiscuity; //混杂模式的计数器unsigned int allmulti;//监听所有组播地址 /* 网络层协议特定数据 */#ifdef CONFIG_NET_DSAvoid *dsa_ptr; /* dsa specific data */
#endifvoid *atalk_ptr; /* AppleTalk link */void *ip_ptr; /* IPv4 specific data */void *dn_ptr; /* DECnet specific data */void *ip6_ptr; /* IPv6 specific data */void *ec_ptr; /* Econet specific data */void *ax25_ptr; /* AX.25 specific data */struct wireless_dev *ieee80211_ptr; /* IEEE 802.11 specific data,assign before registering *//** Cache line 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; /* hw address, (before bcastbecause most packets areunicast) */struct netdev_hw_addr_list dev_addrs; /* //网络设备硬件地址组成的链表 */unsigned char broadcast[MAX_ADDR_LEN]; /* //广播地址 */struct netdev_queue rx_queue; //接收队列,RPS(Receive Packet Steering)特性 struct netdev_queue *_tx ____cacheline_aligned_in_smp;/* Number of TX queues allocated at alloc_netdev_mq() time */unsigned int num_tx_queues; //发送队列/* Number of TX queues currently active in device */unsigned int real_num_tx_queues;/* root qdisc from userspace point of view */struct Qdisc *qdisc;unsigned long tx_queue_len; /* Max frames per queue allowed */spinlock_t tx_global_lock;
/** One part is mostly used on xmit path (device)*//* 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; /* //最近传送数据包的时间 */int watchdog_timeo; //发生传输超时时,设置的标志 struct timer_list watchdog_timer;//网络层设置的传送数据包超时的时钟 /* Number of references to this device */atomic_t refcnt ____cacheline_aligned_in_smp;/* delayed register/unregister */struct list_head todo_list;//延迟注册/注销的网络设备链表 /* device index hash chain */struct hlist_node index_hlist;//以索引号为关键字的网络设备哈希链表 struct net_device *link_watch_next;/* register/unregister state machine */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; //设备注册/注销状态机/* Called from unregister, can be used to call free_netdev */void (*destructor)(struct net_device *dev);#ifdef CONFIG_NETPOLLstruct netpoll_info *npinfo;//NETPOLL相关信息
#endif#ifdef CONFIG_NET_NS/* Network namespace this network device is inside */struct net *nd_net; //网络命名空间
#endif/* mid-layer private */void *ml_priv; //中间层的私有数据/* bridge stuff */struct net_bridge_port *br_port; //桥接模式/* macvlan */struct macvlan_port *macvlan_port;/* GARP */struct garp_port *garp_port;/* class/net/name entry */struct device dev; //在sysfs文件系统中输出网络设备信息/* space for optional statistics and wireless sysfs groups */const struct attribute_group *sysfs_groups[3];/* rtnetlink link ops */const struct rtnl_link_ops *rtnl_link_ops; //rtnetlink操作函数 /* VLAN feature mask */unsigned long vlan_features; //虚拟局域网相关 /* for setting kernel sock attribute on TCP connection setup */
#define GSO_MAX_SIZE 65536unsigned int gso_max_size; //GSO最大值 #ifdef CONFIG_DCB/* Data Center Bridging netlink ops */struct dcbnl_rtnl_ops *dcbnl_ops; //DCB操作函数
#endif#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)/* max exchange id for FCoE LRO by ddp */unsigned int fcoe_ddp_xid;
#endif
};
0x03 总结
学习linux协议栈关键数据结构相关推荐
- 如何学习 Linux
1.应用场景 在现在的生活,生产,研究等领域,Linux已经无所不在. 从我们使用的手机,车载设备,到服务器,桌面电脑等,Linux已经成为这个世界方方面面的基石. 尤其对于参与技术有关工作的你学习L ...
- linux协议栈学习 第七节 GRO的实现
linux协议栈学习 第七节 GRO的实现 GRO (generic receive offload) 概述: GRO是在协议栈接收报文时进行减负的一种处理方式,该方式在设计上考虑了多种协议报文.主要 ...
- linux 协议栈学习 第八节 链路层GRO的处理
linux 协议栈学习 第八节 链路层GRO的处理 链路层的接收匹配函数__napi_gro_receive(napi, skb): 该函数对报文进行匹配,并不合并报文. 匹配规则必须同时满足以下两个 ...
- 学习linux/unix编程方法的建议-转
假设你是计算机科班出身,计算机系的基本课程如数据结构.操作系统.体系结构.编译原理.计算机网络你全修过 我想大概可以分为4个阶段,水平从低到高 从安装使用=>linux常用命令=>li ...
- 如何系统学习Linux
linux太难用了!(一通鼠标点击,进入/etc) 学习linux,你忘记windows的思维方式了吗? 怎么安装软件阿?那一堆文件是干什么的阿? 学习linux,你还在浮躁吗? 进入linux,随便 ...
- 学习Linux的几点忠告(转贴)
学习Linux的几点忠告(转贴) 可能是很老的帖子了吧............ 最近因为工作的需要和个人的兴趣,开始学习linux的知识,也转了不少的网站,许多问题在不同的地方得到了解决,进步是一方 ...
- 像听故事一样学习Linux操作系统
如今的软件开发行业,服务器端市场基本被 Linux 系统占领了.移动端中的 Android 系统是基于 Linux 内核开发的,那些很火的虚拟化.消息队列.云计算.大数据等技术,都默认支持 Linux ...
- 对国产板子有阴影这些软硬件开源的ARM开发板可以学习Linux驱动
对国产板子有阴影?这些软硬件开源的ARM开发板可以学习Linux驱动开发 为了点亮一块MIPI屏幕,我们除了要了解MIPI DSI的工作原理之外,大前提要了解整个MIPI DSI图显系统的组成,更需要 ...
- linux协议栈skb操作函数,linux协议栈skb操作函数
1,struct sk_buff数据结构 struct sk_buff{ //这两个结构必须放在最前面 struct sk_buff *next; struct sk_buff *prev; stru ...
最新文章
- 设置读取plc时间_最简单的一种方法来step7 读取PLC时间日期
- 小余学调度:调度指令票系列讲解1(持续更新中ing)
- CNN基础知识(1)
- js map 排序_数组方法写给女友的一系列 JS 数组操作(建议收藏 | 内附思维导图)...
- 【转载】C#中List集合使用Exists方法判断是否存在符合条件的元素对象
- mysql buffer_mysql read_buffer_size 设置多少合适
- keepalived(9)——sorry_server
- python的if和else、for、while语法_python-变量、if else语句 、for循环、while循环(4月26号)...
- 拒绝网络*** 如何防御Sniffer***
- python弹窗输入_Python中使用tkinter弹窗获取输入文本
- java-银行业务调度系统《十一》
- PyTorch 入坑九:权重初始化
- 移动端tap或touch类型事件的点透问题认识
- 下软件,就靠这几个网站
- 数据库 casewhen 的用法
- 图像特征的特点及其常用的特征提取与匹配方法
- 了凡四训 第一篇《立命之学》
- 零基础如何学习SEO网站优化
- NB-IoT与OneNET平台HTTP通信
- 基于微信小程序图书借阅管理系统(微信小程序毕业设计)
热门文章
- 微信小程序访问数据库
- 通过Ajax实现注册登陆的表单验证,一看就会。
- 全新二改广告横幅在线生成源码 无数据库
- 首页小房子图标html代码,html5及css3做的3D小房子
- 2020电力计算机英语,粤电力B:2020年年度报告(英文版)
- 开启灯光就是近光吗_汉兰达自动大灯怎么用,自动大灯AUTO时是近光还是远光 - 闹太套汽车之家...
- 对不平行的两条直线进行连接
- 中文、日文、韩文的unicode范围
- 网络知识入门,探讨DNS服务器在网页请求中的作用(二)
- [牛客网Wannafly挑战赛24F]wyf的超级多项式