openVswitch(OVS)源代码分析之数据结构
来源:互联网 发布:linux 命令别名配置 编辑:程序博客网 时间:2024/05/29 17:49
转载请注明原文出处,原文地址是:http://blog.csdn.net/yuzhihui_no1/article/details/39188373
记得Pascal之父、结构化程序设计的先驱Niklaus Wirth最著名的一本书,书名叫作《算法 + 数据结构 = 程序》。还有位传奇的软件工程师Frederick P. Brooks曾经说过:“给我看你的数据”。因此可见数据结构对于一个程序来说是多么的重要,如果你不了解程序中的数据结构,你根本就无法去理解整个程序的工作流程。所以在分析openVswitch(OVS)源代码之前先来了解下openVswitch中一些重要的数据结构,这将对你分析后面的源代码起着至关重要的作用。
按照数据包的流向来分析下涉及到一些重要的数据结构。
第一、vport端口模块中涉及到的一些数据结构:
-
- struct vport {
- struct rcu_head rcu;
- struct datapath *dp;
- u32 upcall_portid;
- u16 port_no;
-
-
-
- struct hlist_node hash_node;
- struct hlist_node dp_hash_node;
- const struct vport_ops *ops;
-
- struct pcpu_tstats __percpu *percpu_stats;
-
- spinlock_t stats_lock;
- struct vport_err_stats err_stats;
- struct ovs_vport_stats offset_stats;
- };
-
-
- struct vport_parms {
- const char *name;
- enum ovs_vport_type type;
- struct nlattr *options;
-
-
- struct datapath *dp;
- u16 port_no;
- u32 upcall_portid;
- };
-
-
- struct vport_ops {
- enum ovs_vport_type type;
- u32 flags;
-
-
- int (*init)(void);
- void (*exit)(void);
-
-
- struct vport *(*create)(const struct vport_parms *);
- void (*destroy)(struct vport *);
-
-
- int (*set_options)(struct vport *, struct nlattr *);
- int (*get_options)(const struct vport *, struct sk_buff *);
-
-
- const char *(*get_name)(const struct vport *);
- void (*get_config)(const struct vport *, void *);
- int (*get_ifindex)(const struct vport *);
- int (*send)(struct vport *, struct sk_buff *);
- };
-
-
- enum ovs_vport_type{
- OVS_VPORT_TYPE_UNSPEC,
- OVS_VPORT_TYPE_NETDEV,
- OVS_VPORT_TYPE_INTERNAL,
- OVS_VPORT_TYPE_GRE,
- OVS_VPORT_TYPE_VXLAN,
- OVS_VPORT_TYPE_GRE64 = 104,
- OVS_VPORT_TYPE_LISP = 105,
- _OVS_VPORT_TYPE_MAX
- };
第二、网桥模块datapath中涉及到的一些数据结构:
-
- struct datapath {
- struct rcu_head rcu;
- struct list_head list_node;
-
-
- struct flow_table __rcu *table;
-
-
- struct hlist_head *ports;
-
-
- struct dp_stats_percpu __percpu *stats_percpu;
-
- #ifdef CONFIG_NET_NS
-
- struct net *net;
- #endif
- };
其实上面的网桥结构也表示了整个openVswitch(OVS)的结构,如果能捋顺这些结构的关系,那就对分析openVswitch源代码有很多帮助,下面来看下这些结构的关系图: 第三、流表模块flow中涉及到的一些数据结构:
-
-
- struct sw_flow_key {
-
- struct ovs_key_ipv4_tunnel tun_key;
- struct {
-
- u32 priority;
- u32 skb_mark;
- u16 in_port;
- } phy;
- struct {
- u8 src[ETH_ALEN];
- u8 dst[ETH_ALEN];
- __be16 tci;
- __be16 type;
- } eth;
- struct {
- u8 proto;
- u8 tos;
- u8 ttl;
- u8 frag;
- } ip;
-
- union {
- struct {
- struct {
- __be32 src;
- __be32 dst;
- } addr;
-
- union {
- struct {
- __be16 src;
- __be16 dst;
- } tp;
- struct {
- u8 sha[ETH_ALEN];
- u8 tha[ETH_ALEN];
- } arp;ARP头结构地址提取
- };
- } ipv4;
-
- struct {
- struct {
- struct in6_addr src;
- struct in6_addr dst;
- } addr;
- __be32 label;
- struct {
- __be16 src;
- __be16 dst;
- } tp;
- struct {
- struct in6_addr target;
- u8 sll[ETH_ALEN];
- u8 tll[ETH_ALEN];
- } nd;
- } ipv6;
- };
- };
接下来要分析的数据结构是在网桥结构中涉及的的:struct flow_table __rcu *table;-
- struct flow_table {
- struct flex_array *buckets;
- unsigned int count, n_buckets;
- struct rcu_head rcu;
- struct list_head *mask_list;
- int node_ver;
- u32 hash_seed;
- bool keep_flows;
- };
顺序分析下去,应该是分析哈希桶结构体了,因为这个结构体设计的实在是太巧妙了。所以应该仔细的分析下。 这是一个共用体,是个设计非常巧妙的共用体。因为共用体的特点是:整个共用体的大小是其中最大成员变量的大小。也就是说 共用体成员中某个最大的成员的大小就是共用体的大小。正是利用这一点特性,最后一个char padding[FLEX_ARRAY_BASE_SIZE]其实是没有用的,仅仅是起到一个占位符的作用了。让整个共用体的大小为FLEX_ARRAY_BASE_SIZE(即是一个页的大小:4096),那为什么要这么费劲心机去设计呢?是因为struct flex_array_part *parts[]; 这个结构,这个结构并不多见,因为在标准的c/c++代码中是无效的,只有在GNU下才是合法的。这个称为弹性数组,或者可变数组,和常规的数组不一样。这里这个弹性数组的大小是一个页大小减去前面几个整型成员变量后所剩的大小。
-
- struct flex_array {
-
- union {
-
- struct {
- int element_size;
- int total_nr_elements;
- int elems_per_part;
- u32 reciprocal_elems;
- struct flex_array_part *parts[];
- };
-
-
-
-
- char padding[FLEX_ARRAY_BASE_SIZE];
- };
- };
-
-
- struct flex_array_part {
- char elements[FLEX_ARRAY_PART_SIZE];
- };
-
-
-
- struct sw_flow {
- struct rcu_head rcu;
- struct hlist_node hash_node[2];
- u32 hash;
-
- struct sw_flow_key key;
- struct sw_flow_key unmasked_key;
- struct sw_flow_mask *mask;
- struct sw_flow_actions __rcu *sf_acts;
-
- spinlock_t lock;
- unsigned long used;
- u64 packet_count;
- u64 byte_count;
- u8 tcp_flags;
- };
顺序下来,应该轮到分析mask结构体链表了:
-
- struct sw_flow_mask {
- int ref_count;
- struct rcu_head rcu;
- struct list_head list;
- struct sw_flow_key_range range;
- struct sw_flow_key key;
- };
-
-
- struct sw_flow_key_range {
- size_t start;
- size_t end;
- };
下面是整个openVswitch中数据结构所构成的图示,也是整个openVswitch中主要结构: