Skip to content

Commit a34cbd0

Browse files
Merge pull request #10 from beba-eu/stats_state_compression
Stats state compression
2 parents 76dc969 + 23cbd8a commit a34cbd0

File tree

7 files changed

+111
-74
lines changed

7 files changed

+111
-74
lines changed

ryu/app/beba/ddos_use_case/simple_monitoring.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,7 @@ def _state_stats_reply_handler(self, ev):
8989

9090
if (msg.body.experimenter == 0XBEBABEBA):
9191
if (msg.body.exp_type == bebaproto.OFPMP_EXP_STATE_STATS_AND_DELETE):
92-
data = msg.body.data
93-
state_stats_list = bebaparser.OFPStateStats.parser(data, 0)
92+
state_stats_list = bebaparser.OFPStateStats.parser(msg, 0)
9493
if (state_stats_list != 0):
9594
for index in range(len(state_stats_list)):
9695
if (state_stats_list[index].entry.state != 0):

ryu/app/beba/ddos_use_case/simple_monitoring_1.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,7 @@ def _state_stats_reply_handler(self, ev):
477477
if (msg.body.experimenter == 0XBEBABEBA):
478478
if (msg.body.exp_type == bebaproto.OFPMP_EXP_STATE_STATS_AND_DELETE):
479479
data = msg.body.data
480-
state_stats_list = bebaparser.OFPStateStats.parser(data, 0)
480+
state_stats_list = bebaparser.OFPStateStats.parser(msg, 0)
481481
if (state_stats_list != 0):
482482
self.replies += 1
483483
for index in range(len(state_stats_list)):

ryu/app/beba/state_sync/get_flow_state.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,11 @@ def switch_features_handler(self, event):
9090
@set_ev_cls(ofp_event.EventOFPExperimenterStatsReply, MAIN_DISPATCHER)
9191
def packet_in_handler(self, event):
9292
msg = event.msg
93-
93+
9494
# State Sync: Parse the response from the switch
9595
if (msg.body.experimenter == 0xBEBABEBA):
9696
if (msg.body.exp_type == bebaproto.OFPMP_EXP_STATE_STATS):
97-
state_entry_list = bebaparser.OFPStateStats.parser(msg.body.data)
97+
state_entry_list = bebaparser.OFPStateStats.parser(msg)
9898
for state_entry in state_entry_list:
9999
print 'State :',state_entry.entry.state
100100
print 'Key :',bebaparser.state_entry_key_to_str(state_entry)

ryu/app/beba/state_sync/get_flows_in_state.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ def packet_in_handler(self, event):
9191

9292
if (msg.body.experimenter == 0xBEBABEBA):
9393
if(msg.body.exp_type == bebaproto.OFPMP_EXP_STATE_STATS):
94-
state_entry_list = bebaparser.OFPStateStats.parser(msg.body.data)
94+
state_entry_list = bebaparser.OFPStateStats.parser(msg)
9595
if (state_entry_list==[]):
9696
print "No key for this state"
9797
else:

ryu/app/beba/tcp_flag_test.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,8 @@ def switch_features_handler(self, event):
8080

8181
@set_ev_cls(ofp_event.EventOFPExperimenterStatsReply, MAIN_DISPATCHER)
8282
def state_stats_reply_handler(self, ev):
83-
#Extract buffer
84-
buff = ev.msg.body.data
85-
tmp_list = osparser.OFPStateStats.parser(buff,0)
83+
#Extract buffer
84+
tmp_list = osparser.OFPStateStats.parser(ev.msg,0)
8685
for i in tmp_list:
8786
out_str = "----> ROUND: " + str(self.cnt) + " PAYLOAD:" + str(i) + " STATE: " + str(i.entry.state) + " KEY: " + str(i.entry.key) + "KEY_CNT: " + str(i.entry.key_count)
8887
LOG.info(out_str)

ryu/ofproto/beba_v1_0.py

+10-8
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,14 @@
6262
OFP_STATE_STATS_REQUEST_0_SIZE)
6363

6464
# struct ofp_state_stats
65-
OFP_STATE_STATS_0_PACK_STR = '!HBxIII'
66-
OFP_STATE_STATS_0_SIZE = 16
67-
assert calcsize(OFP_STATE_STATS_0_PACK_STR) == OFP_STATE_STATS_0_SIZE
68-
OFP_STATE_STATS_ENTRY_SIZE = 56
69-
OFP_STATE_STATS_1_PACK_STR = '!IIII'
70-
OFP_STATE_STATS_1_SIZE = 16
71-
assert calcsize(OFP_STATE_STATS_1_PACK_STR) == OFP_STATE_STATS_1_SIZE
72-
OFP_STATE_STATS_SIZE = OFP_STATE_STATS_0_SIZE + 4*MAX_FIELD_COUNT + OFP_STATE_STATS_ENTRY_SIZE + OFP_STATE_STATS_1_SIZE
65+
OFP_STATE_STATS_PACK_STR = '!HBBIIIIIII'
66+
OFP_STATE_STATS_SIZE = 32
67+
assert calcsize(OFP_STATE_STATS_PACK_STR) == OFP_STATE_STATS_SIZE
68+
69+
# struct ofp_state_stats_short
70+
OFP_STATE_STATS_SHORT_PACK_STR = '!HBBI'
71+
OFP_STATE_STATS_SHORT_SIZE = 8
72+
assert calcsize(OFP_STATE_STATS_SHORT_PACK_STR) == OFP_STATE_STATS_SHORT_SIZE
7373

7474
#struct ofp_exp_msg_pkttmp_mod
7575
OFP_EXP_PKTTMP_MOD_PACK_STR='!Bx'
@@ -124,6 +124,8 @@
124124
OFPMP_EXP_STATE_STATS = 0
125125
OFPMP_EXP_GLOBAL_STATE_STATS = 1
126126
OFPMP_EXP_STATE_STATS_AND_DELETE = 2
127+
OFPMP_EXP_STATE_STATS_SHORT = 3
128+
OFPMP_EXP_STATE_STATS_AND_DELETE_SHORT = 4
127129

128130
# enum ofp_error_type
129131
OFPET_EXPERIMENTER = 0xffff

ryu/ofproto/beba_v1_0_parser.py

+94-57
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,14 @@ def OFPExpMsgKeyExtract(datapath, command, fields, table_id,bit=0):
8787
data+=struct.pack(field_extract_format,fields[f])
8888

8989
exp_type=bebaproto.OFPT_EXP_STATE_MOD
90+
91+
# store lookup-scopes
92+
if command == bebaproto.OFPSC_EXP_SET_L_EXTRACTOR:
93+
if hasattr(datapath, 'lookup_scope'):
94+
datapath.lookup_scope[table_id] = fields
95+
else:
96+
datapath.lookup_scope = {table_id: fields}
97+
9098
return ofproto_parser.OFPExperimenter(datapath=datapath, experimenter=0xBEBABEBA, exp_type=exp_type, data=data)
9199

92100
def OFPExpMsgSetFlowState(datapath, state, keys, table_id, idle_timeout=0, idle_rollback=0, hard_timeout=0, hard_rollback=0, state_mask=0xffffffff):
@@ -140,43 +148,40 @@ def OFPExpResetGlobalState(datapath):
140148
exp_type=bebaproto.OFPT_EXP_STATE_MOD
141149
return ofproto_parser.OFPExperimenter(datapath=datapath, experimenter=0xBEBABEBA, exp_type=exp_type, data=data)
142150

143-
def OFPExpStateStatsMultipartRequest(datapath, table_id=ofproto.OFPTT_ALL, state=None, match=None):
144-
flags = 0 # Zero or ``OFPMPF_REQ_MORE``
151+
def OFPExpStateStatsMultipartRequestBase(datapath, exp_type, table_id=ofproto.OFPTT_ALL, state=None, match=None):
152+
flags = 0 # Zero or ``OFPMPF_REQ_MORE``
145153
get_from_state = 1
146154
if state is None:
147155
get_from_state = 0
148156
state = 0
149-
157+
150158
if match is None:
151159
match = ofproto_parser.OFPMatch()
152160

153-
data=bytearray()
161+
data = bytearray()
154162
msg_pack_into(bebaproto.OFP_STATE_STATS_REQUEST_0_PACK_STR, data, 0, table_id, get_from_state, state)
155-
156-
offset=bebaproto.OFP_STATE_STATS_REQUEST_0_SIZE
163+
164+
offset = bebaproto.OFP_STATE_STATS_REQUEST_0_SIZE
157165
match.serialize(data, offset)
158166

159-
exp_type=bebaproto.OFPMP_EXP_STATE_STATS
160-
return ofproto_parser.OFPExperimenterStatsRequest(datapath=datapath, flags=flags, experimenter=0xBEBABEBA, exp_type=exp_type, data=data)
167+
return ofproto_parser.OFPExperimenterStatsRequest(datapath=datapath, flags=flags, experimenter=0xBEBABEBA,
168+
exp_type=exp_type, data=data)
169+
170+
def OFPExpStateStatsMultipartRequest(datapath, table_id=ofproto.OFPTT_ALL, state=None, match=None):
171+
return OFPExpStateStatsMultipartRequestBase(datapath=datapath, exp_type=bebaproto.OFPMP_EXP_STATE_STATS,
172+
table_id=table_id, state=state, match=match)
161173

162174
def OFPExpStateStatsMultipartRequestAndDelete(datapath, table_id=ofproto.OFPTT_ALL, state=None, match=None):
163-
flags = 0 # Zero or ``OFPMPF_REQ_MORE``
164-
get_from_state = 1
165-
if state is None:
166-
get_from_state = 0
167-
state = 0
168-
169-
if match is None:
170-
match = ofproto_parser.OFPMatch()
175+
return OFPExpStateStatsMultipartRequestBase(datapath=datapath, exp_type=bebaproto.OFPMP_EXP_STATE_STATS_AND_DELETE,
176+
table_id=table_id, state=state, match=match)
171177

172-
data=bytearray()
173-
msg_pack_into(bebaproto.OFP_STATE_STATS_REQUEST_0_PACK_STR, data, 0, table_id, get_from_state, state)
174-
175-
offset=bebaproto.OFP_STATE_STATS_REQUEST_0_SIZE
176-
match.serialize(data, offset)
178+
def OFPExpStateStatsMultipartRequestShort(datapath, table_id=ofproto.OFPTT_ALL, state=None, match=None):
179+
return OFPExpStateStatsMultipartRequestBase(datapath=datapath, exp_type=bebaproto.OFPMP_EXP_STATE_STATS_SHORT,
180+
table_id=table_id, state=state, match=match)
177181

178-
exp_type=bebaproto.OFPMP_EXP_STATE_STATS_AND_DELETE
179-
return ofproto_parser.OFPExperimenterStatsRequest(datapath=datapath, flags=flags, experimenter=0xBEBABEBA, exp_type=exp_type, data=data)
182+
def OFPExpStateStatsMultipartRequestAndDeleteShort(datapath, table_id=ofproto.OFPTT_ALL, state=None, match=None):
183+
return OFPExpStateStatsMultipartRequestBase(datapath=datapath, exp_type=bebaproto.OFPMP_EXP_STATE_STATS_AND_DELETE_SHORT,
184+
table_id=table_id, state=state, match=match)
180185

181186
"""
182187
State Sync: Controller asks for flows in a specific state
@@ -306,28 +311,22 @@ def __init__(self, key_count=None, key=None, state=None):
306311
self.state = state
307312

308313
@classmethod
309-
def parser(cls, buf, offset):
310-
entry = OFPStateEntry()
314+
def parser(cls, buf, offset, key_count, state):
315+
entry = OFPStateEntry(key_count=key_count, state=state)
311316

312-
key_count = struct.unpack_from('!I', buf, offset)
313-
entry.key_count = key_count[0]
314-
offset += 4
315-
entry.key=[]
317+
entry.key = []
316318
if entry.key_count <= bebaproto.MAX_KEY_LEN:
317319
for f in range(entry.key_count):
318320
key=struct.unpack_from('!B',buf,offset,)
319321
entry.key.append(key[0])
320322
offset +=1
321-
offset += (bebaproto.MAX_KEY_LEN - entry.key_count)
322323

323-
state = struct.unpack_from('!I', buf, offset)
324-
entry.state=state[0]
325-
offset += 4
324+
offset += (utils.round_up(entry.key_count, 8) - entry.key_count)
326325

327-
return entry
326+
return entry, offset
328327

329328
class OFPStateStats(StringifyMixin):
330-
def __init__(self, table_id=None, dur_sec=None, dur_nsec=None, field_count=None, fields=None,
329+
def __init__(self, table_id=None, dur_sec=None, dur_nsec=None, field_count=None, fields=None,
331330
entry=None,length=None, hard_rb=None, idle_rb=None, hard_to=None, idle_to=None):
332331
super(OFPStateStats, self).__init__()
333332
self.length = 0
@@ -343,35 +342,73 @@ def __init__(self, table_id=None, dur_sec=None, dur_nsec=None, field_count=None,
343342
self.hard_rb = hard_rb
344343

345344
@classmethod
346-
def parser(cls, buf, offset=0):
345+
def parser(cls, msg, offset=0):
347346
state_stats_list = []
348-
349-
for i in range(len(buf)/bebaproto.OFP_STATE_STATS_SIZE):
347+
348+
buf = msg.body.data
349+
350+
while len(buf)-offset > 0:
351+
state_stats = cls()
352+
353+
(state_stats.length, state_stats.table_id, state_stats.key_len, state_stats.dur_sec,
354+
state_stats.dur_nsec, state_stats.hard_rb, state_stats.idle_rb,state_stats.hard_to,
355+
state_stats.idle_to, state_stats.state) = struct.unpack_from(
356+
bebaproto.OFP_STATE_STATS_PACK_STR, buf, offset)
357+
offset += bebaproto.OFP_STATE_STATS_SIZE
358+
359+
if state_stats.table_id not in msg.datapath.lookup_scope:
360+
continue
361+
state_stats.fields = msg.datapath.lookup_scope[state_stats.table_id]
362+
state_stats.field_count = len(state_stats.fields)
363+
364+
state_stats.entry, offset = OFPStateEntry.parser(buf, offset, state_stats.key_len, state_stats.state)
365+
366+
state_stats_list.append(state_stats)
367+
368+
return state_stats_list
369+
370+
371+
class OFPStateStatsShort(StringifyMixin):
372+
def __init__(self, table_id=None, dur_sec=None, dur_nsec=None, field_count=None, fields=None,
373+
entry=None, length=None, hard_rb=None, idle_rb=None, hard_to=None, idle_to=None):
374+
super(OFPStateStatsShort, self).__init__()
375+
self.length = 0
376+
self.table_id = table_id
377+
self.dur_sec = dur_sec
378+
self.dur_nsec = dur_nsec
379+
self.field_count = field_count
380+
self.fields = fields
381+
self.entry = entry
382+
self.hard_to = hard_to
383+
self.hard_rb = hard_rb
384+
self.idle_to = idle_to
385+
self.hard_rb = hard_rb
386+
387+
@classmethod
388+
def parser(cls, msg, offset=0):
389+
state_stats_list = []
390+
391+
buf = msg.body.data
392+
393+
while len(buf) - offset > 0:
350394
state_stats = cls()
351395

352-
(state_stats.length, state_stats.table_id, state_stats.dur_sec,
353-
state_stats.dur_nsec, state_stats.field_count) = struct.unpack_from(
354-
bebaproto.OFP_STATE_STATS_0_PACK_STR, buf, offset)
355-
offset += bebaproto.OFP_STATE_STATS_0_SIZE
356-
357-
state_stats.fields=[]
358-
field_extract_format='!I'
359-
if state_stats.field_count <= bebaproto.MAX_FIELD_COUNT:
360-
for f in range(state_stats.field_count):
361-
field=struct.unpack_from(field_extract_format,buf,offset)
362-
state_stats.fields.append(field[0])
363-
offset +=4
364-
offset += ((bebaproto.MAX_FIELD_COUNT-state_stats.field_count)*4)
365-
state_stats.entry = OFPStateEntry.parser(buf, offset)
366-
offset += bebaproto.OFP_STATE_STATS_ENTRY_SIZE
367-
368-
(state_stats.hard_rb, state_stats.idle_rb,state_stats.hard_to, state_stats.idle_to) = struct.unpack_from(
369-
bebaproto.OFP_STATE_STATS_1_PACK_STR, buf, offset)
370-
offset += bebaproto.OFP_STATE_STATS_1_SIZE
396+
(state_stats.length, state_stats.table_id, state_stats.key_len, state_stats.state) = struct.unpack_from(
397+
bebaproto.OFP_STATE_STATS_SHORT_PACK_STR, buf, offset)
398+
offset += bebaproto.OFP_STATE_STATS_SHORT_SIZE
399+
400+
if state_stats.table_id not in msg.datapath.lookup_scope:
401+
continue
402+
state_stats.fields = msg.datapath.lookup_scope[state_stats.table_id]
403+
state_stats.field_count = len(state_stats.fields)
404+
405+
state_stats.entry, offset = OFPStateEntry.parser(buf, offset, state_stats.key_len, state_stats.state)
406+
371407
state_stats_list.append(state_stats)
372408

373409
return state_stats_list
374410

411+
375412
class OFPGlobalStateStats(StringifyMixin):
376413
def __init__(self, global_state=None):
377414
super(OFPGlobalStateStats, self).__init__()

0 commit comments

Comments
 (0)