1.介绍
2.交换机组件
一个openflow交换机包括多个流表和一个组表,用来匹配和转发包。控制器可以通过openflow协议主动地或者被动地增加、更新、删除流表项。
每个流表都有一组流表项,流表项按照优先级匹配包,在每个流表中首先匹配的流表项将会被使用。如果在一个流表中没有匹配,可能发生以下动作:转发给控制器,丢弃,继续匹配下一个流表。
流表项关联的指令如果是pipeline,那么就允许把包发送给接下来的流表,知道一个匹配的流表项没有确定下一个流表。
4.OpenFlow Tables
1.Match Fields:匹配包。包括入口,包头,还有可选的元信息。
2.counters:对匹配的包更新,计数器
3.instructions:修改动作集,或者流水线处理。
4.1.1 Pipeline Processing
openflow交换机有二种:一种是只支持openflow,一种是混杂的,也就是支持openflow操作和传统的以太网交换机操作(vlan隔离,3层路由,qos,acl)。openflow混杂交换机允许一个包从openflow pipeline转到正常的处理,通过normal和flood虚拟保留端口。
每一个openflow交换机的openflow pipeline都包括很多流表,每一个流表都有很多流表项。openflow pipeline决定包怎样和这些流表交互。一个openflow交换机只有一个流表也是有效的。这种情况,pipeline将会大大简化。
附录:常用数据结构
flow是用来匹配流表项的头域。流表项的意思。
struct flow {
uint32_t nw_src; /* IP source address. */
uint32_t nw_dst; /* IP destination address. */
uint16_t in_port; /* Input switch port. */
uint16_t dl_vlan; /* Input VLAN id. */
uint16_t dl_type; /* Ethernet frame type. */
uint16_t tp_src; /* TCP/UDP source port. */
uint16_t tp_dst; /* TCP/UDP destination port. */
uint8_t dl_src[6]; /* Ethernet source address. */
uint8_t dl_dst[6]; /* Ethernet destination address. */
uint8_t dl_vlan_pcp; /* Input VLAN priority. */
uint8_t nw_tos; /* IPv4 DSCP. */
uint8_t nw_proto; /* IP protocol. */
uint8_t pad[3];
};
流表项,包含通配符。
/* Identification data for a flow. */
struct sw_flow_key {
struct flow flow; /* Flow data (in network byte order). */
uint32_t wildcards; /* Wildcard fields (in host byte order). */
uint32_t nw_src_mask; /* 1-bit in each significant nw_src bit. */
uint32_t nw_dst_mask; /* 1-bit in each significant nw_dst bit. */
};
流表包含的动作
struct sw_flow_actions {
size_t actions_len;
struct ofp_action_header actions[0];
};
完整流表项
struct sw_flow {
struct sw_flow_key key;
uint64_t cookie; /* Opaque controller-issued identifier. */
uint16_t priority; /* Only used on entries with wildcards. */
uint16_t idle_timeout; /* Idle time before discarding (seconds). */
uint16_t hard_timeout; /* Hard expiration time (seconds) */
uint64_t used; /* Last used time. */
uint64_t created; /* When the flow was created. */
uint64_t packet_count; /* Number of packets seen. */
uint64_t byte_count; /* Number of bytes seen. */
uint8_t reason; /* Reason flow removed (one of OFPRR_*). */
uint8_t send_flow_rem; /* Send a flow removed to the controller */
uint8_t emerg_flow; /* Emergency flow indicator */
struct sw_flow_actions *sf_acts;
/* Private to table implementations. */
struct list node;
struct list iter_node;
unsigned long int serial;
};
以太网包头
struct eth_header {
uint8_t eth_dst[ETH_ADDR_LEN];
uint8_t eth_src[ETH_ADDR_LEN];
uint16_t eth_type;
} __attribute__((packed));
datapath
struct datapath {
/* Remote connections. */
struct list remotes; /* All connections (including controller). */
/* Listeners. */
struct pvconn **listeners;
size_t n_listeners;
time_t last_timeout;
/* Unique identifier for this datapath */
uint64_t id;
char dp_desc[DESC_STR_LEN]; /* human readible comment to ID this DP */
struct sw_chain *chain; /* Forwarding rules. 包括了流表*/
/* Configuration set from controller. */
uint16_t flags;
uint16_t miss_send_len;
/* Switch ports. */
struct sw_port ports[DP_MAX_PORTS];
struct sw_port *local_port; /* OFPP_LOCAL port, if any. */
struct list port_list; /* All ports, including local_port. */
};
流表链,包含了交换机中的流表
struct sw_chain {
int n_tables; /* Number of working tables, not includes
* protection (emergency) table. */
struct sw_table *tables[CHAIN_MAX_TABLES];
struct sw_table *emerg_table;
struct datapath *dp;
};
/* A single table of flows. 一个流表*/
struct sw_table {
/* The number of packets that have been looked up and matched,
* respecitvely. To make these 100% accurate, they should be atomic.
* However, we're primarily concerned about speed.
这二个变量应该被原子更新,统计这个流表查找的次数和匹配的次数*/
unsigned long long n_lookup;
unsigned long long n_matched;
/* Searches 'table' for a flow matching 'key', 不能有通配符,
* 如果匹配成功,返回对应的流表项
*/
struct sw_flow *(*lookup)(struct sw_table *table,
const struct sw_flow_key *key);
/* Inserts 'flow' into 'table', replacing any duplicate flow. Returns
* 0 if successful or a negative error. Error can be due to an
* over-capacity table or because the flow is not one of the kind that
* the table accepts.
*
* If successful, 'flow' becomes owned by 'table', otherwise it is
* retained by the caller. 如果成功,这个流表项就被流表拥有*/
int (*insert)(struct sw_table *table, struct sw_flow *flow);
/* Modifies the actions in 'table' that match 'key'. If 'strict'
* set, wildcards and priority must match. Returns the number of flows
* that were modified.修改匹配流表项,对应的动作 */
int (*modify)(struct sw_table *table, const struct sw_flow_key *key,
uint16_t priority, int strict,
const struct ofp_action_header *actions, size_t actions_len);
/* Checks whether 'table' has an equal priotiry entry of thethat conflicts
* with 'key'. If 'strict' is set, wildcards must match.
* Returns the number of flows that were modified. */
int (*has_conflict)(struct sw_table *table, const struct sw_flow_key *key,
uint16_t priority, int strict);
/* Deletes from 'table' any and all flows that match 'key' from
* 'table'. If 'out_port' is not OFPP_NONE, then matching entries
* must have that port as an argument for an output action. If
* 'strict' is set, wildcards and priority must match. Returns the
* number of flows that were deleted. */
int (*delete)(struct datapath *dp, struct sw_table *table,
const struct sw_flow_key *key,
uint16_t out_port, uint16_t priority, int strict);
/* Performs timeout processing on all the flow entries in 'table'.
* Appends all the flow entries removed from 'table' to 'deleted' for the
* caller to free. */
void (*timeout)(struct sw_table *table, struct list *deleted);
/* Destroys 'table', which must not have any users. */
void (*destroy)(struct sw_table *table);
/* Iterates through the flow entries in 'table', passing each one
* matches 'key' and output port 'out_port' to 'callback'. The
* callback function should return 0 to continue iteration or a
* nonzero error code to stop. The iterator function returns either
* 0 if the table iteration completed or the value returned by the
* callback function otherwise.
*
* The iteration starts at 'position', which may be initialized to
* all-zero-bits to iterate from the beginning of the table. If the
* iteration terminates due to an error from the callback function,
* 'position' is updated to a value that can be passed back to the
* iterator function to resume iteration later with the following
* flow. */
int (*iterate)(struct sw_table *table,
const struct sw_flow_key *key, uint16_t out_port,
struct sw_table_position *position,
int (*callback)(struct sw_flow *flow, void *private),
void *private);
/* Dumps statistics for 'table' into 'stats'. */
void (*stats)(struct sw_table *table, struct sw_table_stats *stats);
};