记得Pascal之父、结构化程序设计的先驱Niklaus Wirth最著名的一本书,书名叫作《算法 + 数据结构 = 程序》。还有位传奇的软件工程师Frederick P. Brooks曾经说过:“给我看你的数据”。因此可见数据结构对于一个程序来说是多么的重要,如果你不了解程序中的数据结构,你根本就无法去理解整个程序的工作流程。所以在分析openVswitch(OVS)源代码之前先来了解下openVswitch中一些重要的数据结构,这将对你分析后面的源代码起着至关重要的作用。
按照数据包的流向来分析下涉及到一些重要的数据结构。
第一、vport端口模块中涉及到的一些数据结构:
// 这是表示网桥中各个端口结构体
struct vport {
struct rcu_head rcu; // 一种锁机制
struct datapath *dp; // 网桥结构体指针,表示该端口是属于哪个网桥的
u32 upcall_portid; // Netlink端口收到的数据包时使用的端口id
u16 port_no; // 端口号,唯一标识该端口
// 因为一个网桥上有多个端口,而这些端口都是用哈希链表来存储的,
// 所以这是链表元素(里面没有数据,只有next和prev前驱后继指针,数据部分就是vport结构体中的其他成员)
struct hlist_node hash_node;
struct hlist_node dp_hash_node; // 这是网桥的哈希链表元素
const struct vport_ops *ops; // 这是端口结构体的操作函数指针结构体,结构体里面存放了很多操作函数的函数指针
struct pcpu_tstats __percpu *percpu_stats;// vport指向每个cpu的统计数据使用和维护
spinlock_t stats_lock; // 自旋锁,防止异步操作,保护下面的两个成员
struct vport_err_stats err_stats; // 错误状态(错误标识)指出错误vport使用和维护的统计数字
struct ovs_vport_stats offset_stats; // 添加到实际统计数据,部分原因是为了兼容
};
// 端口参数,当创建一个新的vport端口是要传入的参数
struct vport_parms {
const char *name; // 新端口的名字
enum ovs_vport_type type; // 新端口的类型(端口不仅仅只有一种类型,后面会分析到)
struct nlattr *options; // 这个没怎么用到过,好像是从Netlink消息中得到的OVS_VPORT_ATTR_OPTIONS属性
/* For ovs_vport_alloc(). */
struct datapath *dp; // 新的端口属于哪个网桥的
u16 port_no; // 新端口的端口号
u32 upcall_portid; // 和Netlink通信时使用的端口id
};
// 这是端口vport操作函数的函数指针结构体,是操作函数的集合,里面存放了所有有关vport操作函数的函数指针
struct vport_ops {
enum ovs_vport_type type; // 端口的类型
u32 flags; // 标识符