OpenvSwitch在实现时用了很多面向对象的思想,比如说:类。最典型的一个实现就是ofproto结构里的ofproto_class,含有所有OpenFlow(简称of)主要对象的处理函数的函数指针。这个结构体在ofproto-provider.h中声明,在ofproto-dpif.c中定义(实际上dpif_class和它也密切相关)。我们掠过它的声明部分(委实太长),直接看定义。
const struct ofproto_class ofproto_dpif_class = {
enumerate_types,
enumerate_names,
//ofproto
del,
alloc,
construct,
destruct,
dealloc,
run,
run_fast,
wait,
flush,
get_features,
get_tables,
//ofport
port_alloc,
port_construct,
port_destruct,
port_dealloc,
port_modified,
port_reconfigured,
port_query_by_name,
port_add,
port_del,
port_get_stats,
port_dump_start,
port_dump_next,
port_dump_done,
port_poll,
port_poll_wait,
port_is_lacp_current,
//ofrule
NULL, /* rule_choose_table */
rule_alloc,
rule_construct,
rule_destruct,
rule_dealloc,
rule_get_stats,
rule_execute,
rule_modify_actions,
//others
set_frag_handling,
packet_out,
set_netflow,
get_netflow_ids,
set_sflow,
set_cfm,
get_cfm_fault,
get_cfm_remote_mpids,
get_cfm_health,
set_stp,
get_stp_status,
set_stp_port,
get_stp_port_status,
set_queues,
bundle_set,
bundle_remove,
mirror_set,
mirror_get_stats,
set_flood_vlans,
is_mirror_output_bundle,
forward_bpdu_changed,
set_mac_idle_time,
set_realdev,
};
可以看到这个函数集里面有很多不同的对象,它们都参杂在一起。标准的OO应该将它们都剥离开,但这里因为为了简洁(?),而将所有的函数指针都放在一起。我们看看里面都有什么对象:ofproto(of原型)、ofport、rule、bundle、mirror,以及一些杂七杂八的对象netflow、sflow(数据流监控的协议)等。以及frag、stp、cfm(交换机的具体配置)等分属不同对象的子概念。如上,我们给出了主要的处理函数,并且从函数中看到了对应的五个主要对象,接下来我们就主要对象进行分析。
1、ofproto
是OpenFlow交换机的具体实现,它体现了OpenFlow的意志,其中主要包括了ofport、ofrule的概念,注意到ofrule在这里是用oftable来装载的。
struct ofproto {
struct hmap_node hmap_node; /* In global 'all_ofprotos' hmap. */
const struct ofproto_class *ofproto_class; //就是我们在一开始说的函数集
char *type; /* Datapath type. */
char *name; /* Datapath name. */
/* Settings. */
uint64_t fallback_dpid; /* Datapath ID if no better choice found. */
uint64_t datapath_id; /* Datapath ID. 对应的内核dp id */
unsigned flow_eviction_threshold; /* Threshold at which to begin flow
* table eviction. Only affects the
* ofproto-dpif implementation */
bool forward_bpdu; /* Option to allow forwarding of BPDU frames
* when NORMAL action is invoked. 生成树报文 */
//厂家、参数等。
char *mfr_desc; /* Manufacturer. */
char *hw_desc; /* Hardware. */
char *sw_desc; /* Software version. */
char *serial_desc; /* Serial number. */
char *dp_desc; /* Datapath description. */
enum ofp_config_flags frag_handling; /* One of OFPC_*. */
/* Datapath. 用hmap装载所有port */
struct hmap ports; /* Contains "struct ofport"s. */
struct shash port_by_name;
/* Flow tables.这里的tables是数组,内部是hmap索引的rule集 */
struct oftable *tables;
int n_tables;
/* OpenFlow connections.连接管理结构,可能来自ovs-ctl或controller */
struct connmgr *connmgr;
/* Flow table operation tracking. 待完成的操作都悬挂在pending list上 */
int state; /* Internal state. */
struct list pending; /* List of "struct ofopgroup"s. */
unsigned int n_pending; /* list_size(&pending). */
struct hmap deletions; /* All OFOPERATION_DELETE "ofoperation"s. */
/* Linux VLAN device support (e.g. "eth0.10" for VLAN 10.)
*
* This is deprecated. It is only for compatibility with broken device
* drivers in old versions of Linux that do not properly support VLANs when
* VLAN devices are not used. When broken device drivers are no longer in
* widespread use, we will delete these interfaces. */
unsigned long int *vlan_bitmap; /* 4096-bit bitmap of in-use VLANs. */
bool vlans_changed; /* True if new VLANs are in use. */
int min_mtu; /* Current MTU of non-internal ports. */
};
2、ofport
/* An OpenFlow port within a "struct ofproto".
*
* ofproto拥有ofport,如同bridge拥有port一样。ofport和port也有着对应关系,它们通过interface
* 这个纽带,使用port id进行对应。(当然netdev应该也是等同的)
* With few exceptions, ofproto implementations may look at these fields but
* should not modify them. */
struct ofport {
struct hmap_node hmap_node; /* In struct ofproto's "ports" hmap. */
struct ofproto *ofproto; /* The ofproto that contains this port. */
struct netdev *netdev;
struct ofputil_phy_port pp;
uint16_t ofp_port; /* OpenFlow port number. 和iface中的ofp_port对应*/
unsigned int change_seq;
int mtu;
};
3、ofrule
/* An OpenFlow flow within a "struct ofproto".
*
* With few exceptions, ofproto implementations may look at these fields but
* should not modify them. */
struct rule {
struct list ofproto_node; /* Owned by ofproto base code. */
struct ofproto *ofproto; /* The ofproto that contains this rule. */
//关键结构cls_rule,内含flow && flow_wildcards
//进行流匹配时靠的就是它。但注意它没有反向指向rule,只能用CONTAINER_OF来获得rule指针。
struct cls_rule cr; /* In owning ofproto's classifier. */
//表明当前规则是否被操作,类似锁(?)
struct ofoperation *pending; /* Operation now in progress, if nonnull. */
//在OpenFlow协议中写到“可能会被Controller使用”,但现在还未有相关实现。无用。
ovs_be64 flow_cookie; /* Controller-issued identifier. */
//各种rule参数
long long int created; /* Creation time. */
long long int modified; /* Time of last modification. */
long long int used; /* Last use; time created if never used. */
uint16_t hard_timeout; /* In seconds from ->modified. */
uint16_t idle_timeout; /* In seconds from ->used. */
uint8_t table_id; /* Index in ofproto's 'tables' array. */
bool send_flow_removed; /* Send a flow removed message? */
//溢出组,在流量大于限制时溢出。可选。
/* Eviction groups. */
bool evictable; /* If false, prevents eviction. */
struct heap_node evg_node; /* In eviction_group's "rules" heap. */
struct eviction_group *eviction_group; /* NULL if not in any group. */
union ofp_action *actions; /* OpenFlow actions. */
int n_actions; /* Number of elements in actions[]. */
};
4、bundle
是交换机的端口的集合,它可以是单个端口,也可以是绑定的端口。
/* Bundles. */
/* Registers a "bundle" associated with client data pointer 'aux' in 'ofproto'.
* A bundle is the same concept as a Port in OVSDB, that is, it consists of one
* or more "slave" devices (Interfaces, in OVSDB) along with a VLAN
* configuration plus, if there is more than one slave, a bonding
* configuration.
*
* If 'aux' is already registered then this function updates its configuration
* to 's'. Otherwise, this function registers a new bundle.
*
* Bundles only affect the NXAST_AUTOPATH action and output to the OFPP_NORMAL
* port. */
struct ofbundle {
struct hmap_node hmap_node; /* In struct ofproto's "bundles" hmap. */
struct ofproto_dpif *ofproto; /* Owning ofproto. */
void *aux; /* Key supplied by ofproto's client. */
char *name; /* Identifier for log messages. */
/* Configuration. */
struct list ports; /* Contains "struct ofport"s. */
enum port_vlan_mode vlan_mode; /* VLAN mode */
int vlan; /* -1=trunk port, else a 12-bit VLAN ID. */
unsigned long *trunks; /* Bitmap of trunked VLANs, if 'vlan' == -1.
* NULL if all VLANs are trunked. */
struct lacp *lacp; /* LACP if LACP is enabled, otherwise NULL. */
struct bond *bond; /* Nonnull iff more than one port. */
bool use_priority_tags; /* Use 802.1p tag for frames in VLAN 0? */
/* Status. */
bool floodable; /* True if no port has OFPUTIL_PC_NO_FLOOD set. */
/* Port mirroring info. */
mirror_mask_t src_mirrors; /* Mirrors triggered when packet received. */
mirror_mask_t dst_mirrors; /* Mirrors triggered when packet sent. */
mirror_mask_t mirror_out; /* Mirrors that output to this bundle. */
};
5、mirror
struct mirror {
struct uuid uuid; /* UUID of this "mirror" record in database. */
struct hmap_node hmap_node; /* In struct bridge's "mirrors" hmap. */
struct bridge *bridge;
char *name;
const struct ovsrec_mirror *cfg;
};