写在前面
这算是看的第一篇完整的论文,对算法的地方整理了笔记和做了理解。如有错误之处,请指正。
其中有很多不足,比如目前还缺乏对数据层规则放置问题及其他相关研究这一点的整体理解。路漫漫其修远兮。
回顾摘要
TCAM用来存储(cache)规则(rule)的,数据包(packet)可以通过TCAM快速查找到高优先级的规则。
具体TCAM如何工作?基于TCAM的 Packet classification
TCAM的优势众所周知,但是这里有几点问题,也是文章的解决思路:
- TCAM容量限制:两种switch,①TCAM(存储popluar rule)容量大,快速更新;②sofeware switch(存储cache miss)快速匹配。→怎样区分popular和miss规则,需要规则放置→涉及规则依赖问题
- TCAM不能快速更新规则:怎样规则替换→
引出规则依赖问题
CacheFlow模型
- 核心CacheMaster:控制层面。提供openflow接口,
- 数据层面:SW,TCAM
rule-dependency analysis
- R4、R5直接依赖,R5、R6直接依赖,则R4、R6间接依赖。
- 子→父
- 当一个规则cache到TCAM中,与之依赖的规则也应该存入TCAM→导致连锁反应
- eg:若只有R5、R6。根据优先级,R6存入则R5必须存入,否则packet hit错误;但R5存入则R6不必存入。
- (补充)注意间接依赖的规则之间可能具有直接依赖也可能没有(如①有依赖:R1和R3。可以添加一条箭头R1→R3;②没有依赖:R4和R6)
三个算法:
Constructing the Dependency DAG(构建依赖图)
伪代码:
// Add dependency edges
1 func addParents(R:Rule, P:Parents) begin
2 deps = (∅);
// p.o : priority order
3 packets = R.match; //①
4 for each Rj in P in descending p.o: do
5 if (packets ∩ Rj.match) != ∅ then
6 deps = deps ∪ {(R,Rj)}; //②
7 reaches(R,Rj) = packets ∩ Rj; //③
8 packets = packets - Rj.match; //④
9 return deps;
10 for each R:Rule in Pol:Policy do
11 potentialParents = [Rj in Pol | Rj.p.o ≤ R.p.o];
12 addParentEdges(R, potentialParents);
- 规则→节点,直接依赖→边
- (★)P:Parents来自于11行 potentialParents(很重要,在后面算法中有用到,这里简称P),在这里表示比R优先级小的所有节点(不是所有父类节点,范围更大)。
- 从优先级最高开始(即R1)
- ①将待查节点R的match(通配符)打包到packet,依次发送到所有R的P中;
- ②deps确定R(子)到Rj(父)的直接依赖边;
- ③reaches(R,Rj)收集边上的依赖(重叠)match部分;
- ④packets = packets - Rj.match更新packet:即减去packet的已依赖部分,接着遍历下个Rj(即将packet发送到下个Rj)。
- 时间复杂度 O(n2),在动态网络中添加、删除成本太高
分析:
eg1:以R1为例,
R1(000)的P有:R2(00x)、R3(0xx)、R4、R5、R6、R0(xxx)【优先级递减】
for1:
- ①packets=000
- ②deps=(R1,R2)
- ③reaches(R1,R2)=R1→R2,携带000
- ④新的packets=000-00x=∅ //接着依次遍历,结束
eg2:以R4为例,
R1(11x)的P有:R5(1x0)、R6(10x)、R0(xxx)
for1:
- ①packets=11x
- ②deps=(R4,R5)
- ③reaches(R4,R5)=R4→R5,110
- ④新的packets=11x(110、111)-1x0(100、110)=111
for2:
- ①for1中的packets=111
- ②deps=(R4,R5)∪(R4,R0)
- ③reaches(R4,R0)=R4→R0,111
- ④新的packets=111-xxx=∅ //结束
Incremental Insert(插入)
伪代码:
func FindAffectedEdges(rule, newRule) begin
2 for each C in Children(rule) do //①C为rule的子
3 if Priority(C) > priority(newRule) then //②以下待查节点C为newrule的子
4 if reaches(C,rule) ∩ newRule.match !=∅ then
5 reaches(C, rule) -= newRule.match;
6 add (C, Node) to affEdges
7 else //③以下待查节点C为newrule的父
8 if Pred(C) ∪ newRule.match != ∅ then //④?
9 add C to potentialParents;
10 FindAffectedEdges(C, newRule);
11 func processAffectedEdges(affEdges) begin
12 for each childList in groupByChild(affEdges)
do
13 deps = deps ∪ {(child, newRule)};
14 edgeList = sortByParent(childList);
15 reaches(child, newRule) =reaches(edgeList[0]);
16 func Insert(G=(V, E), newNode) begin
17 affEdges = { };
18 potentialParents = [R0];
19 FindAffectedEdges(R0, newNode);
20 ProcessAffectedEdges(affEdges);
21 addParents(newNode, potentialParents);
- 整体算法是递归操作(先序遍历)。更新时对无关部分不做处理
- 从R0开始遍历,且R0必须添加到P中
步骤:
1. 递归遍历现有生成树,找到需要更新的边(节点)
2. 通过检查match交集和优先权,需要更新的分为两种:
- 该待查节点C为newrule的子 :更新旧边,将(C,node)添加到affEdges
- 该节点C为newrule的父:将C添加到P中
分析:具体算法细节还有疑问,待更新。
Incremental Delete(删除某节点)
删除算法算是最简单的
伪代码:
1 func Delete(G=(V, E), oldRule) begin
2 for each c in Children(oldRule) do
3 potentialParents = Parents(c) - {oldRule}; //②更新
4 for each p in Parents(oldRule) do
//Find if deletion adds an edge E(c, p)
5 if reaches(c, oldRule) ∩ p.match != ∅
then
6 add p to potentialParents //①创建
7 addParents(C, potentialParents)
8 Remove all edges involving oldRule //③删除
- ①创建新的边:对于待删除节点oldrule的所有子节点C,根据条件(reaches(c, oldRule) ∩ p.match != ∅),会创建oldR的子→oldR的父,也可能不创建
- ②更新现有的边:oldR的子→{oldR的子的父-oldR}
- ③删除:删除与oldR直接依赖的边
CACHING ALGORITHMS
规则如何放置。rule caching问题涉及到规则的依赖和网络的动态变化。
- 运营商重写策略简化
- 通过算法实现
文章研究后者
- weight:该rule预计能匹配的packet数量
- cost:该rule 被依赖的规则数量,本身及其所有孩子
- ratio:∆W/ ∆C
brute-force algorithm(蛮力算法):
从n个中取出k个:C nk=n(n-1)…(n-k+1)=O(nk)
Dependent-Set:
Maximize ∑i=1nwici
subject to ∑i=1nci ≤k
c i − c j ≥ 0 if Ri.is_descendant(R j ) ∀i, j ∈ {1, … , n}
//c i 为父,c j 为子,若父在,子必须在
c i ∈ {0,1} ∀i ∈ {1, … , n}
- 是贪心算法,但增加 c i − c j ≥ 0 的条件
- 时间复杂度O(nk)
- 缺点:导致高cost
Cover-Set:
将popluar rule规则(如R)存入TCAM,而将依赖于R的miss rule规则(根据优先级,即R的所有子)存入到software switch中。并将R
∗
(R
∗
的action为to_ss)cover到TCAM中
- 好处:降低R的cost
- 缺点:由于重定位,导致wight可能升高
Mixed-Set:
1 func Mixed_Set(rule_table) begin
2 create_heap();
3 for r ∈ rule_table do
4 heap.insert(r.dep_set);
5 heap.insert(r.cover_set);
6 total_cost = 0;
7 while total_cost < threshold do
// pick element with maximum ∆ ∆W C
8 max_rule = heap.get_max();
// delete both dep-set and cover-set
9 heap.delete(max_rule);
10 if max_rule is dep_set then
11 for r1 ∈ dep_set(max_node) do
12 heap_delete(r1);
13 heap_update_ancestors(r1);
14 if max_rule is cover_set then
15 for r1 ∈ cover_set(max_rule) do
16 heap_update_ancestors(r1);
17 Add_Cache(max_rule.mixed_set);
Updating the TCAM Incrementally
cache-replacement strategies
更新缓存:时间变化→包流量分布变化→规则缓存算法改变→更新TCAN策略
问题:
- 两种规则之间的转化需要过渡时间
- The nuclear option从头删除和插入,是非线性的
伪代码:
1 func TCAM_Update(old_cache, new_cache)
begin
2 for mixed_set ∈ (old_cache − new_cache) do //①
3 for each rule in mixed_set do
4 if rule is normal then
5 rule.normal_ref−−;
6 if rule.normal_ref==0 then
7 delete_normal(rule)
8 else
9 rule.star_ref−−;
10 if rule.star_ref==0 then
11 delete_star(rule)
12 for mixed_set ∈ (new_cache − old_cache) do //②
13 for each rule in mixed_set do
14 if rule is normal then
15 if rule.normal_ref==0 then
16 install_normal(rule)
17 rule.normal_ref++;
18 else
19 if rule.star_ref==0 then
20 install_star(rule)
21 rule.star_ref++;
// Simply retain in TCAM, mixed_set ∈ new_cache ∩ old_cache. //③
- ①we first decompose/remove the old
mixed-sets (that are not cached anymore) from the TCAM
(lines 2-11) - ②compose with the new mixed sets
(lines 12-21) - ③retaining the mixed-sets common to
both the versions of the cache - Reference counting