一、ofproto 的功能
所谓的 ofproto,英文全称应该为 OpenFlow Proto(这里的 Proto 意为原型),因为 ofproto 结构体封装了 OpenFlow 交换机的核心功能,而 OpenFlow 交换机特指实现了 OpenFlow 协议的网络设备,所以说 ofproto 本质上也是网桥/交换机的实现。在 网桥 Bridge 相关的结构 中提到过成员变量 *ofproto:
struct ofproto *ofproto 用于指向与这个网桥对应的 ofproto 实例。
由此可见 ofproto 和网桥 Bridge 是一一对应的关系,ofproto 是对网桥 Bridge 功能的具体实现。
二、ofproto 结构体
ofproto 相关的结构体内容都定义在 ovs-main/ofproto/ofproto-provider.h 头文件和 ovs-main\ofproto\ofproto.c 文件中:
/* An OpenFlow switch.
* With few exceptions, ofproto implementations may look at these fields but should not modify them. */
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. */
bool forward_bpdu; /* Option to allow forwarding of BPDU frames when NORMAL action is invoked. */
char *mfr_desc; /* Manufacturer (NULL for default). */
char *hw_desc; /* Hardware (NULL for default). */
char *sw_desc; /* Software version (NULL for default). */
char *serial_desc; /* Serial number (NULL for default). */
char *dp_desc; /* Datapath description (NULL for default). */
enum ofputil_frag_handling frag_handling;
/* Datapath. */
struct hmap ports; /* Contains "struct ofport"s. */
struct shash port_by_name;
struct simap ofp_requests; /* OpenFlow port number requests. */
uint16_t alloc_port_no; /* Last allocated OpenFlow port number. */
uint16_t max_ports; /* Max possible OpenFlow port num, plus one. */
struct hmap ofport_usage; /* Map ofport to last used time. */
uint64_t change_seq; /* Change sequence for netdev status. */
/* Flow tables. */
long long int eviction_group_timer; /* For rate limited reheapification. */
struct oftable *tables;
int n_tables;
ovs_version_t tables_version; /* Controls which rules are visible to table lookups. */
/* Rules indexed on their cookie values, in all flow tables. */
struct hindex cookies OVS_GUARDED_BY(ofproto_mutex);
struct hmap learned_cookies OVS_GUARDED_BY(ofproto_mutex);
/* List of expirable flows, in all flow tables. */
struct ovs_list expirable OVS_GUARDED_BY(ofproto_mutex);
/* List of flows to remove from flow tables. */
struct rule_collection *to_remove OVS_GUARDED_BY(ofproto_mutex);
/* Meter table. */
struct ofputil_meter_features meter_features;
struct hmap meters; /* uint32_t indexed 'struct meter *'. */
uint32_t slowpath_meter_id; /* Datapath slowpath meter. UINT32_MAX if not defined. */
uint32_t controller_meter_id; /* Datapath controller meter. UINT32_MAX if not defined. */
/* OpenFlow connections. */
struct connmgr *connmgr;
int min_mtu; /* Current MTU of non-internal ports. */
/* Groups. */
struct cmap groups; /* Contains "struct ofgroup"s. */
uint32_t n_groups[4] OVS_GUARDED; /* # of existing groups of each type. */
struct ofputil_group_features ogf;
/* Tunnel TLV mapping table. */
OVSRCU_TYPE(struct tun_table *) metadata_tab;
/* Variable length mf_field mapping. Stores all configured variable length meta-flow fields (struct mf_field) in a switch. */
struct vl_mff_map vl_mff_map;
/* refcount to this ofproto, held by rule/group/xlate_caches */
struct ovs_refcount refcount;
};
与网桥 Bridge 的结构体类似,ofproto 本身就是哈希表 all_ofprotos 的一个元素,以便于在所有 ofproto 中快速进行查找和管理,同样 all_ofprotos 定义为:
/* Map from datapath name to struct ofproto, for use by unixctl commands. */
static struct hmap all_ofprotos = HMAP_INITIALIZER(&all_ofprotos);
const struct ofproto_class *ofproto_class 指向该交换机的具体实现类。
字符串 type 和 name 以及整数 datapath_id 分别记录了 ofproto 对应 Datapath 的类型、名称和 ID。接下来还包括制造商、硬件、软件、序列号等描述性信息。
enum ofputil_frag_handling frag_handling 规定了分片处理方式(枚举类型),定义在 ovs-main/include/openvswitch/ofp-switch.h 头文件中:
enum ofputil_frag_handling {
OFPUTIL_FRAG_NORMAL = OFPC_FRAG_NORMAL, /* No special handling. */
OFPUTIL_FRAG_DROP = OFPC_FRAG_DROP, /* Drop fragments. */
OFPUTIL_FRAG_REASM = OFPC_FRAG_REASM, /* Reassemble (if supported). */
OFPUTIL_FRAG_NX_MATCH = OFPC_FRAG_NX_MATCH /* Match on frag bits. */
};
- OFPUTIL_FRAG_NORMAL 表示交换机不会对分片数据包做任何特殊处理,按照正常情况转发
- OFPUTIL_FRAG_DROP 表示交换机会直接丢弃分片数据包
- OFPUTIL_FRAG_REASM 表示交换机会尝试重组分片数据包(如果支持重组功能的话)
- OFPUTIL_FRAG_NX_MATCH 表示交换机可以通过匹配分片相关的字段来对分片数据包做特殊处理。
接下来仍然与与网桥 Bridge 的结构体类似,ofproto 定义了一些哈希表 ports、port_by_name、ofp_requests 和 ofport_usage 用于快速索引相关信息。此外这里还定义了 alloc_port_no 表示最新分配的端口号和 max_ports 表示最大端口数目。
在 ofproto 的定义中,还包括许多 OpenFlow 流表相关的内容:
- eviction_group_timer 表示流表重置定时器
- tables 和 n_tables 分别表示流表数组和流表数量
- tables_version 用于控制流表查找时规则的可见性
- cookies 和 learned_cookies 用于根据 cookie 值建立索引规则
- expirable 记录带有时间戳的流表(可过期的流)
- to_remove 记录所有等待从流表中删除的流
此外还有 meter_features 表示度量表的特性、slowpath_meter_id 记录慢路径度量表的 ID、controller_meter_id 记录控制路径度量表的 ID 等,并通过哈希表 meters 实现快速索引。
struct connmgr *connmgr 指向 OpenFlow 连接管理器。
min_mtu 定义了非内部端口的当前最小 MTU。
groups 定义了所有组的哈希表,并通过 struct ofputil_group_features ogf 定义了组功能特性。
OVSRCU_TYPE(struct tun_table *) metadata_tab 定义了隧道 TLV 映射表。
struct vl_mff_map vl_mff_map 用于存储配置的可变长度元数据字段。
struct ovs_refcount refcount 指向此 ofproto 的引用计数。
三、OpenFlow 端口 ofport
/* An OpenFlow port within a "struct ofproto".
* The port's name is netdev_get_name(port->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;
ofp_port_t ofp_port; /* OpenFlow port number. */
uint64_t change_seq;
long long int created; /* Time created, in msec. */
int mtu;
bool may_enable; /* May be live (OFPPS_LIVE) if link is up. */
};
这个结构体封装了 OpenFlow 端口的各种属性和状态信息,供 OpenFlow 协议实现使用。除了少数例外情况,一般情况下 OpenFlow 协议实现时通常只能查看这些字段,而不能修改它们。
这里关于 ofproto 及其相关的结构体的讲解非常粗略,因为如果全部介绍的话内容太多,所以此处只是简单介绍一下 ofproto 包括什么内容,具有哪些功能,并调用了哪些部分来实现。未来的文章中将会针对特定的功能实现进行详细的展开。
结语:
由于本人水平有限,以上内容如有不足之处欢迎大家指正(评论区/私信均可)。