blob: 6df956510da421f1115f91f908d685b88fad041e [file] [log] [blame]
Rich Laneca3da272013-05-05 09:07:33 -07001# Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
2# Copyright (c) 2011, 2012 Open Networking Foundation
3# Copyright (c) 2012, 2013 Big Switch Networks, Inc.
4"""
5Utility functions independent of the protocol version
6"""
7
8# Automatically generated by LOXI from template generic_util.py
9# Do not modify
10
11import loxi
12import struct
13
14def unpack_list(reader, deserializer):
15 """
16 The deserializer function should take an OFReader and return the new object.
17 """
18 entries = []
19 while not reader.is_empty():
20 entries.append(deserializer(reader))
21 return entries
22
23def unpack_list_lv16(reader, deserializer):
24 """
25 The deserializer function should take an OFReader and return the new object.
26 """
27 def wrapper(reader):
28 length, = reader.peek('!H')
29 return deserializer(reader.slice(length))
30 return unpack_list(reader, wrapper)
31
32def unpack_list_tlv16(reader, deserializer):
33 """
34 The deserializer function should take an OFReader and an integer type
35 and return the new object.
36 """
37 def wrapper(reader):
38 typ, length, = reader.peek('!HH')
39 return deserializer(reader.slice(length), typ)
40 return unpack_list(reader, wrapper)
41
42class OFReader(object):
43 """
44 Cursor over a read-only buffer
45
46 OpenFlow messages are best thought of as a sequence of elements of
47 variable size, rather than a C-style struct with fixed offsets and
48 known field lengths. This class supports efficiently reading
49 fields sequentially and is intended to be used recursively by the
50 parsers of child objects which will implicitly update the offset.
51 """
52 def __init__(self, buf):
53 self.buf = buf
54 self.offset = 0
55
56 def read(self, fmt):
57 st = struct.Struct(fmt)
58 if self.offset + st.size > len(self.buf):
59 raise loxi.ProtocolError("Buffer too short")
60 result = st.unpack_from(self.buf, self.offset)
61 self.offset += st.size
62 return result
63
64 def read_all(self):
65 buf = buffer(self.buf, self.offset)
66 self.offset += len(buf)
67 return str(buf)
68
69 def peek(self, fmt):
70 st = struct.Struct(fmt)
71 if self.offset + st.size > len(self.buf):
72 raise loxi.ProtocolError("Buffer too short")
73 result = st.unpack_from(self.buf, self.offset)
74 return result
75
76 def skip(self, length):
77 if self.offset + length > len(self.buf):
78 raise loxi.ProtocolError("Buffer too short")
79 self.offset += length
80
81 def is_empty(self):
82 return self.offset == len(self.buf)
83
84 # Used when parsing variable length objects which have external length
85 # fields (e.g. the actions list in an OF 1.0 packet-out message).
86 def slice(self, length):
87 if self.offset + length > len(self.buf):
88 raise loxi.ProtocolError("Buffer too short")
89 buf = OFReader(buffer(self.buf, self.offset, length))
90 self.offset += length
91 return buf