@@ -12,8 +12,10 @@ class Rule(object):
12
12
Pyretic actions.
13
13
"""
14
14
15
- # Matches m should be of the match class. Actions acts should be a list of
16
- # either modify, identity, or drop policies.
15
+ # Matches m should be of the match class. Actions acts should be a set of
16
+ # modify, identity, drop, and/or Controller/CountBucket/FwdBucket policies.
17
+ # Actions is Rule are semantically meant to run in parallel
18
+ # unlike OpenFlow rules.
17
19
def __init__ (self ,m ,acts ):
18
20
self .match = m
19
21
self .actions = acts
@@ -127,11 +129,11 @@ def __invert__(self):
127
129
from pyretic .core .language import drop , identity
128
130
c = copy .copy (self )
129
131
for r in c .rules :
130
- assert len (set ( r .actions ) ) == 1
131
- if r .actions [ 0 ] == identity :
132
- r .actions = [ drop ]
133
- elif r .actions [ 0 ] == drop :
134
- r .actions = [ identity ]
132
+ assert len (r .actions ) == 1
133
+ if r .actions == { identity } :
134
+ r .actions = { drop }
135
+ elif r .actions == { drop } :
136
+ r .actions = { identity }
135
137
else :
136
138
raise TypeError # TODO MAKE A CompileError TYPE
137
139
return c
@@ -146,10 +148,9 @@ def _cross(r1,r2):
146
148
if intersection != drop :
147
149
# TODO (josh) logic for detecting when sets of actions can't be combined
148
150
# e.g., [modify(dstip='10.0.0.1'),fwd(1)] + [modify(srcip='10.0.0.2'),fwd(2)]
149
- actions = r1 .actions + r2 .actions
150
- actions = filter (lambda a : a != drop ,actions )
151
- if len (actions ) == 0 :
152
- actions = [drop ]
151
+ actions = r1 .actions | r2 .actions
152
+ if len (actions ) > 1 :
153
+ actions .discard (drop )
153
154
return Rule (intersection , actions )
154
155
else :
155
156
return None
@@ -165,7 +166,7 @@ def _cross(r1,r2):
165
166
c3 .append (crossed_r )
166
167
# if the classifier is empty, add a drop-all rule
167
168
if len (c3 ) == 0 :
168
- c3 .append (Rule (identity ,[ drop ] ))
169
+ c3 .append (Rule (identity ,{ drop } ))
169
170
# and optimize the classifier
170
171
else :
171
172
c3 = c3 .optimize ()
@@ -214,27 +215,27 @@ def _sequence_actions(a1, as2):
214
215
while isinstance (a1 , DerivedPolicy ):
215
216
a1 = a1 .policy
216
217
# TODO: be uniform about returning copied or modified objects.
217
- new_actions = []
218
218
if a1 == drop :
219
- return [ drop ]
219
+ return { drop }
220
220
elif a1 == Controller or isinstance (a1 , CountBucket ):
221
- return [ a1 ]
221
+ return { a1 }
222
222
elif a1 == identity :
223
223
return as2
224
224
elif isinstance (a1 , modify ):
225
+ new_actions = set ()
225
226
for a2 in as2 :
226
227
while isinstance (a2 , DerivedPolicy ):
227
228
a2 = a2 .policy
228
229
if a2 == drop :
229
- new_actions .append (drop )
230
+ new_actions .add (drop )
230
231
elif a2 == Controller or isinstance (a2 , CountBucket ):
231
- new_actions .append (a2 )
232
+ new_actions .add (a2 )
232
233
elif a2 == identity :
233
- new_actions .append (a1 )
234
+ new_actions .add (a1 )
234
235
elif isinstance (a2 , modify ):
235
236
new_a1 = modify (** a1 .map .copy ())
236
237
new_a1 .map .update (a2 .map )
237
- new_actions .append (new_a1 )
238
+ new_actions .add (new_a1 )
238
239
else :
239
240
raise TypeError
240
241
return new_actions
@@ -246,7 +247,7 @@ def _sequence_actions(a1, as2):
246
247
def _cross_act (r1 ,act ,r2 ):
247
248
m = r1 .match .intersect (_commute_test (act , r2 .match ))
248
249
actions = _sequence_actions (act ,r2 .actions )
249
- if actions == [ drop ] :
250
+ if actions == { drop } :
250
251
return Classifier ([Rule (r1 .match ,actions )])
251
252
elif m == drop :
252
253
return None
0 commit comments