blob: e88458a0d4fcec3a44ac85822f5fe767d4c4a251 [file] [log] [blame]
Andreas Wundsam27303462013-07-16 12:52:35 -07001import os
2import errno
3import re
4import subprocess
5import time
6
7def name_c_to_camel(name):
8 """ 'of_stats_reply' -> 'ofStatsReply' """
9 name = re.sub(r'^_','', name)
10 tokens = name.split('_')
11 for i in range(1, len(tokens)):
12 tokens[i] = tokens[i].title()
13 return "".join(tokens)
14
15def name_c_to_caps_camel(name):
16 """ 'of_stats_reply' to 'OFStatsReply' """
17 camel = name_c_to_camel(name.title())
18 if camel.startswith('Of'):
19 return camel.replace('Of','OF',1)
20 else:
21 return camel
22
23
24class JType(object):
25 """ Wrapper class to hold C to Java type conversion information """
26 def __init__(self, pub_type, priv_type=None, size=None, read_op=None, write_op=None):
27 self.pub_type = pub_type # the type we expose externally, e.g. 'U8'
28 if priv_type is None:
29 priv_type = pub_type
30 self.priv_type = priv_type # the internal storage type
31 self.size = size # bytes on the wire; None == variable length or hard to calc
32 if read_op is None:
33 read_op = 'ChannelUtils.read%s(bb)' % self.pub_type
34 if write_op is None:
35 write_op = 'ChannelUtils.write%s(bb, $name)' % self.pub_type
36 self._read_op = read_op
37 self._write_op = write_op
38
39 @property
40 def public_type(self):
41 """ return the public type """
42 return self.pub_type
43
44 def priv(self):
45 """ return the public type """
46 return self.priv_type
47
48 def has_priv(self):
49 """ Is the private type different from the public one?"""
50 return self.pub_type != self.priv_type
51
52 def read_op(self, version=None, length=None):
53 if length is None:
54 length = "length - bb.readerIndex()";
55
56 if callable(self._read_op):
57 return self._read_op(version)
58 else:
Andreas Wundsam8807dfe2013-07-24 16:09:53 -070059 return self._read_op.replace("$length", str(length)).replace("$version", version.of_version)
Andreas Wundsam27303462013-07-16 12:52:35 -070060
61 def write_op(self, version=None, name=None):
62 if callable(self._write_op):
63 return self._write_op(version, name)
64 else:
Andreas Wundsam8807dfe2013-07-24 16:09:53 -070065 return self._write_op.replace("$name", str(name)).replace("$version", version.of_version)
Andreas Wundsam27303462013-07-16 12:52:35 -070066
67hello_elem_list = JType("List<OFHelloElement>",
68 read_op = 'ChannelUtils.readHelloElementList(bb)',
69 write_op = 'ChannelUtils.writeHelloElementList(bb)'
70 )
71u8 = JType('byte', size=1, read_op='bb.readByte()',
72 write_op='bb.writeByte($name)')
73u8_list = JType('List<U8>', size=1, read_op='bb.readByte()',
74 write_op='bb.writeByte($name)')
75u16 = JType('int', 'int', size=2, read_op='U16.f(bb.readShort())',
76 write_op='bb.writeShort(U16.t($name))')
77u32 = JType('int', 'int', size=4, read_op='bb.readInt()',
78 write_op='bb.writeInt($name)')
79u32_list = JType('List<U32>', 'int[]', size=4, read_op='bb.readInt()',
80 write_op='bb.writeInt($name)')
81u64 = JType('U64', 'U64', size=8, read_op='U64.of(bb.readLong())',
82 write_op='bb.writeLong($name.getValue())')
83of_port= JType('OFPort',size=None,
Yotam Harchol161a5d52013-07-25 17:17:48 -070084 read_op = "OFPort.SERIALIZER_V$version.readFrom(bb)",
85 write_op = "OFPort.SERIALIZER_V$version.writeTo($name, bb)")
Andreas Wundsam27303462013-07-16 12:52:35 -070086one_byte_array = JType('byte[]', size=1,
87 read_op = 'ChannelUtils.readBytes(bb, 1)',
88 write_op = 'ChannelUtils.writeBytes(bb, $name)')
89two_byte_array = JType('byte[]', size=2,
90 read_op = 'ChannelUtils.readBytes(bb, 2)',
91 write_op = 'ChannelUtils.writeBytes(bb, $name)')
92three_byte_array = JType('byte[]', size=3,
93 read_op = 'ChannelUtils.readBytes(bb, 3)',
94 write_op = 'ChannelUtils.writeBytes(bb, $name)')
95four_byte_array = JType('byte[]', size=4,
96 read_op = 'ChannelUtils.readBytes(bb, 4)',
97 write_op = 'ChannelUtils.writeBytes(bb, $name)')
98five_byte_array = JType('byte[]', size=5,
99 read_op = 'ChannelUtils.readBytes(bb, 5)',
100 write_op = 'ChannelUtils.writeBytes(bb, $name)')
101six_byte_array = JType('byte[]', size=6,
102 read_op = 'ChannelUtils.readBytes(bb, 6)',
103 write_op = 'ChannelUtils.writeBytes(bb, $name)')
104seven_byte_array = JType('byte[]', size=7,
105 read_op = 'ChannelUtils.readBytes(bb, 7)',
106 write_op = 'ChannelUtils.writeBytes(bb, $name)')
107actions_list = JType('List<OFAction>', size='ChannelUtils.calcListSize($name)',
108 read_op = 'ChannelUtils.readActionsList(bb, $length)',
109 write_op = 'ChannelUtils.writeActionsList(bb, $name);')
110instructions_list = JType('List<OFInstruction>', size='ChannelUtils.calcListSize($name)',
111 read_op = 'ChannelUtils.readInstructionsList(bb, $length)',
112 write_op = 'ChannelUtils.writeList(bb, $name)')
113buckets_list = JType('List<OFBucket>', size='ChannelUtils.calcListSize($name)',
114 read_op = 'ChannelUtils.readBucketList(bb, $length)',
115 write_op = 'ChannelUtils.writeList(bb, $name)')
116port_desc_list = JType('List<OFPhysicalPort>', size='ChannelUtils.calcListSize($name)',
117 read_op = 'ChannelUtils.readPhysicalPortList(bb, $length)',
118 write_op = 'ChannelUtils.writeList(bb, $name)')
119port_desc = JType('OFPortDesc', size='$name.getLength()',
120 read_op = 'null; // TODO OFPortDescVer$version.READER.read(bb)',
121 write_op = '$name.writeTo(bb)')
122packet_queue_list = JType('List<OFPacketQueue>', size='ChannelUtils.calcListSize($name)',
123 read_op = 'ChannelUtils.readPacketQueueList(bb, $length)',
124 write_op = 'ChannelUtils.writeList(bb, $name)')
125octets = JType('byte[]', size="$length",
126 read_op = 'ChannelUtils.readBytes(bb, $length)',
127 write_op = 'bb.writeBytes($name)')
128of_match = JType('Match', size="$name.getLength()",
129 read_op = 'ChannelUtils.readOFMatch(bb)',
130 write_op = 'ChannelUtils.writeOFMatch(bb, $name)')
131flow_mod_cmd = JType('OFFlowModCommand', 'short', size="$name.getLength()",
132 read_op = lambda v: "bb.readShort()" if v.int_version == 1 else "bb.readByte()",
133 write_op = lambda v, name: "bb.writeShort(%s)" % name if v.int_version == 1 else "bb.writeByte(%s)" % name)
134mac_addr = JType('MacAddress', 'byte[]', size=6,
Yotam Harchol161a5d52013-07-25 17:17:48 -0700135 read_op = "MacAddress.SERIALIZER_V$version.readFrom(bb)",
136 write_op = "MacAddress.SERIALIZER_V$version.writeTo($name, bb)")
Andreas Wundsam27303462013-07-16 12:52:35 -0700137port_name = JType('String', size=16,
138 read_op = 'ChannelUtils.readFixedLengthString(bb, 16)',
139 write_op = 'ChannelUtils.writeFixedLengthString(bb, $name, 16)')
140desc_str = JType('String', size=256,
141 read_op = 'ChannelUtils.readFixedLengthString(bb, 256)',
142 write_op = 'ChannelUtils.writeFixedLengthString(bb, $name, 256)')
143serial_num = JType('String', size=32,
144 read_op = 'ChannelUtils.readFixedLengthString(bb, 32)',
145 write_op = 'ChannelUtils.writeFixedLengthString(bb, $name, 32)')
146table_name = JType('String', size=32,
147 read_op = 'ChannelUtils.readFixedLengthString(bb, 32)',
148 write_op = 'ChannelUtils.writeFixedLengthString(bb, $name, 32)')
149ipv4 = JType("IPv4",
Yotam Harchol161a5d52013-07-25 17:17:48 -0700150 read_op = "IPv4.SERIALIZER_V$version.readFrom(bb)",
151 write_op = "IPv4.SERIALIZER_V$version.writeTo($name, bb)")
Andreas Wundsam27303462013-07-16 12:52:35 -0700152ipv6 = JType("IPv6",
Yotam Harchol161a5d52013-07-25 17:17:48 -0700153 read_op = "IPv6.SERIALIZER_V$version.readFrom(bb)",
154 write_op = "IPv6.SERIALIZER_V$version.writeTo($name, bb)")
Andreas Wundsam27303462013-07-16 12:52:35 -0700155
156default_mtype_to_jtype_convert_map = {
157 'uint8_t' : u8,
158 'uint16_t' : u16,
159 'uint32_t' : u32,
160 'uint64_t' : u64,
161 'uint8_t[1]' : one_byte_array,
162 'uint8_t[2]' : two_byte_array,
163 'uint8_t[3]' : three_byte_array,
164 'uint8_t[4]' : four_byte_array,
165 'uint8_t[5]' : five_byte_array,
166 'uint8_t[6]' : six_byte_array,
167 'uint8_t[7]' : seven_byte_array,
168 'of_port_no_t' : of_port,
169 'list(of_action_t)' : actions_list,
170 'list(of_instruction_t)' : instructions_list,
171 'list(of_bucket_t)': buckets_list,
172 'list(of_port_desc_t)' : port_desc_list,
173 'list(of_packet_queue_t)' : packet_queue_list,
174 'list(of_uint32_t)' : u32_list,
175 'list(of_uint8_t)' : u8_list,
176 'of_octets_t' : octets,
177 'of_match_t': of_match,
178 'of_fm_cmd_t': flow_mod_cmd,
179 'of_mac_addr_t': mac_addr,
180 'of_port_desc_t': port_desc,
181 'of_desc_str_t': desc_str,
182 'of_serial_num_t': serial_num,
183 'of_port_name_t': port_name,
184 'of_table_name_t': table_name,
185 'of_ipv4_t': ipv4,
186 'of_ipv6_t': ipv6,
187 'of_wc_bmap_t': JType("Wildcards")
188 }
189
190## This is where we drop in special case handling for certain types
191exceptions = {
192 'OFPacketIn': {
193 'data' : octets
194 },
195}
196
197
198def make_standard_list_jtype(c_type):
199 m = re.match(r'list\(of_([a-zA-Z_]+)_t\)', c_type)
200 if not m:
201 raise Exception("Not a recgonized standard list type declaration: %s" % c_type)
202 base_name = m.group(1)
203 java_base_name = name_c_to_caps_camel(base_name)
204 return JType("List<OF%s>" % java_base_name,
205 read_op = 'ChannelUtils.read%sList(bb)' % java_base_name,
206 write_op = 'ChannelUtils.write%sList(bb, $name)' % java_base_name
207 )
208
209def convert_to_jtype(obj_name, field_name, c_type):
210 """ Convert from a C type ("uint_32") to a java type ("U32")
211 and return a JType object with the size, internal type, and marshalling functions"""
212 if obj_name in exceptions and field_name in exceptions[obj_name]:
213 return exceptions[obj_name][field_name]
214 elif field_name == "type" and c_type == "uint8_t":
215 return JType("OFType", 'byte', size=1, read_op='bb.readByte()',
216 write_op='bb.writeByte($name)')
217 elif field_name == "type" and re.match(r'of_action.*', obj_name):
218 return JType("OFActionType", 'short', size=2, read_op='bb.readShort()',
219 write_op='bb.writeShort($name)')
220 elif field_name == "version" and c_type == "uint8_t":
221 return JType("OFVersion", 'byte', size=1, read_op='bb.readByte()',
222 write_op='bb.writeByte($name)')
223 elif c_type in default_mtype_to_jtype_convert_map:
224 return default_mtype_to_jtype_convert_map[c_type]
225 elif re.match(r'list\(of_([a-zA-Z_]+)_t\)', c_type):
226 return make_standard_list_jtype(c_type)
227 else:
228 print "WARN: Couldn't find java type conversion for '%s' in %s:%s" % (c_type, obj_name, field_name)
229 jtype = name_c_to_caps_camel(re.sub(r'_t$', "", c_type))
230 return JType(jtype)