conjunction match
连接匹配域:
需求背景:
1条openflow流表经常只匹配一个字段(如ip源地址)的一个值。然而,有种场景也经常出现,1条openflow流表匹配一个字段(如ip源地址)的一个集合(比如1.1.1.1、2.2.2.2)。当然也不限于一个字段。
需求:ip_src ∈ {a,b,c,d} and ip_dst ∈ {e,f,g,h}
只要ip_src满足abcd中的一个,且ip_dst满足efgh中的一个,即为命中。
如果不使用连接匹配,则需要4 * 4= 16条流表项,如果使用连接匹配,那么只需要4+4=8条流表项,这在大数量流表环境中,将大幅度减少流表项和命中时间。
实现:
conjunction(id, k/n)
k是当前flow处于的conjunction的维度,n是conjunction所有的维度个数。
conj_id=1234 actions=controller
ip,ip_src=10.0.0.1 actions=conjunction(1234, 1/2)
ip,ip_src=10.0.0.4 actions=conjunction(1234, 1/2)
ip,ip_src=10.0.0.6 actions=conjunction(1234, 1/2)
ip,ip_src=10.0.0.7 actions=conjunction(1234, 1/2)
ip,ip_dst=10.0.0.2 actions=conjunction(1234, 2/2)
ip,ip_dst=10.0.0.5 actions=conjunction(1234, 2/2)
ip,ip_dst=10.0.0.7 actions=conjunction(1234, 2/2)
ip,ip_dst=10.0.0.8 actions=conjunction(1234, 2/2)
所以,在每个维度都命中其中的1条,则conjunction math命中,根据conj_id再次在搜索流表,找到连接匹配对应action.
id是32位的值,只要不重复即可。conj_id是openflow字段,所以可以根据该值去匹配流表。
ovs内部实现:
struct cls_conjunction_set {
/* Link back to the cls_match.
*
* cls_conjunction_set is mostly used during classifier lookup, and, in
* turn, during classifier lookup the most used member of
* cls_conjunction_set is the rule's priority, so we cache it here for fast
* access. */
struct cls_match *match;
int priority; /* Cached copy of match->priority. */
/* Conjunction information.
*
* 'min_n_clauses' allows some optimization during classifier lookup. */
unsigned int n; /* Number of elements in 'conj'. */
unsigned int min_n_clauses; /* Smallest 'n' among elements of 'conj'. */
struct cls_conjunction conj[];
};
struct cls_conjunction_set:表示一条流表对应的conjunction集合,ip,ip_src=10.0.0.1 actions=conjunction(1234, 1/2)。因为1条流表可能对应多个conjunction action,但是id会不同,维度也可能不同,所以是一个集合。
min_n_clauses:该条流表对应的conjunction集合中,最小的维度。用来快速查找,因为如果一条表匹配到了i个流表,且i个流表都是conjunction流表,那么如果命中,该条流对应的conjunction维度最多是i,如过min_n_clauses都大于i,那么肯定没有命中该ocnjunction action的所有维度,那么就为不命中。
相同权限的流表才i个(包含同优先级,不同id的conj_id)。所以,其中1个维度的1条流表的min_n_clauses都大于i,那么肯定未命中。
if (match) {
soft[i] = ovsrcu_get(struct cls_conjunction_set *,
&match->conj_set);
if (!soft[i]) {
/* The flow is a hard match; don't treat as a soft
* match. */
/*
CGM-DEBUG,因为在找match的时候,对于相同flow & mask,只会返回最大优先级的match,如果该match是conj,但是conj失败,那么该conj match之后相同的flow & mask,match可能会比已经找到的其他flow & mask的优先级高,所以要和之前找到的hard match权限比较
*/
if (match->priority > hard_pri) {
hard = match;
hard_pri = hard->priority;
}
}