blob: c55b2758d3b92b200dcaa41918487ab8a3ac764b [file] [log] [blame]
Andreas Wundsam40e14f72013-05-06 14:49:08 -07001import os
2import errno
3import re
4import subprocess
5import time
6
7def name_c_to_camel(name):
8 """ 'of_stats_reply' -> 'ofStatsReply' """
9 tokens = name.split('_')
10 for i in range(1, len(tokens)):
11 tokens[i] = tokens[i].title()
12 return "".join(tokens)
13
14def name_c_to_caps_camel(name):
15 """ 'of_stats_reply' to 'OFStatsReply' """
16 camel = name_c_to_camel(name.title())
17 if camel.startswith('Of'):
18 return camel.replace('Of','OF',1)
19 else:
20 return camel
21
22
23class JType(object):
24 """ Wrapper class to hold C to Java type conversion information """
25 def __init__(self, pub_type, priv_type=None, size=None, read_op=None, write_op=None):
26 self.pub_type = pub_type # the type we expose externally, e.g. 'U8'
27 if priv_type is None:
28 priv_type = pub_type
29 self.priv_type = priv_type # the internal storage type
30 self.size = size # bytes on the wire; None == variable length or hard to calc
31 if read_op is None:
32 read_op = 'ChannelUtils.read%s(this, "$name", bb)' % self.pub_type
33 if write_op is None:
34 write_op = 'ChannelUtils.write($name)'
35 self._read_op = read_op
36 self.write_op = write_op
37
38 @property
39 def public_type(self):
40 """ return the public type """
41 return self.pub_type
42
43 def priv(self):
44 """ return the public type """
45 return self.priv_type
46
47 def has_priv(self):
48 """ Is the private type different from the public one?"""
49 return self.pub_type != self.priv_type
50
51 def read_op(self, version=None):
52 if callable(self._read_op):
53 return self._read_op(version)
54 else:
55 return self._read_op
56
57hello_elem_list = JType("List<OFHelloElement>",
58 read_op = 'ChannelUtils.readHelloElementList(bb)',
59 write_op = 'ChannelUtils.writeHelloElementList(bb)'
60 )
61
62u8 = JType('byte', size=1, read_op='bb.readByte()',
63 write_op='bb.writeByte($name)')
64u16 = JType('int', 'int', size=2, read_op='U16.f(bb.readShort())',
65 write_op='bb.writeShort(U16.t($name))')
66u32 = JType('int', 'int', size=4, read_op='bb.readInt()',
67 write_op='bb.writeInt($name)')
68u64 = JType('U64', 'U64', size=8, read_op='U64.of(bb.readLong())',
69 write_op='bb.writeLong($name.getLong())')
70of_port= JType('OFPort',size=None,
71 read_op=lambda(version): 'OFPort.ofShort(bb.readShort())' if version.int_version < 2 else 'OFPort.ofInt(bb.readInt())',
72 write_op='$name.writeTo(bb)')
73one_byte_array = JType('byte[]', size=1,
74 read_op = 'ChannelUtils.readBytes(bb, 1)',
75 write_op = 'ChannelUtils.writeBytes(bb, $name)')
76two_byte_array = JType('byte[]', size=2,
77 read_op = 'ChannelUtils.readBytes(bb, 2)',
78 write_op = 'ChannelUtils.writeBytes(bb, $name)')
79three_byte_array = JType('byte[]', size=3,
80 read_op = 'ChannelUtils.readBytes(bb, 3)',
81 write_op = 'ChannelUtils.writeBytes(bb, $name)')
82four_byte_array = JType('byte[]', size=4,
83 read_op = 'ChannelUtils.readBytes(bb, 4)',
84 write_op = 'ChannelUtils.writeBytes(bb, $name)')
85five_byte_array = JType('byte[]', size=5,
86 read_op = 'ChannelUtils.readBytes(bb, 5)',
87 write_op = 'ChannelUtils.writeBytes(bb, $name)')
88six_byte_array = JType('byte[]', size=6,
89 read_op = 'ChannelUtils.readBytes(bb, 6)',
90 write_op = 'ChannelUtils.writeBytes(bb, $name)')
91seven_byte_array = JType('byte[]', size=7,
92 read_op = 'ChannelUtils.readBytes(bb, 7)',
93 write_op = 'ChannelUtils.writeBytes(bb, $name)')
94actions_list = JType('List<OFAction>', size='ChannelUtils.calcListSize($name)',
95 read_op = 'ChannelUtils.readActionsList(bb, length - MINIMUM_LENGTH)',
96 write_op = 'ChannelUtils.writeList(this, $name)')
97instructions_list = JType('List<OFInstruction>', size='ChannelUtils.calcListSize($name)',
98 read_op = 'ChannelUtils.readInstructionsList(bb, length - MINIMUM_LENGTH)',
99 write_op = 'ChannelUtils.writeList(this, $name)')
100buckets_list = JType('List<OFBucket>', size='ChannelUtils.calcListSize($name)',
101 read_op = 'ChannelUtils.readBucketList(bb, length - MINIMUM_LENGTH)',
102 write_op = 'ChannelUtils.writeList(this, $name)')
103port_desc_list = JType('List<OFPhysicalPort>', size='ChannelUtils.calcListSize($name)',
104 read_op = 'ChannelUtils.readPhysicalPortList(bb, length - MINIMUM_LENGTH)',
105 write_op = 'ChannelUtils.writeList(this, $name)')
106port_desc = JType('OFPhysicalPort', size='$name.getLength()',
107 read_op = 'ChannelUtils.readPhysicalPort(bb)',
108 write_op = 'ChannelUtils.write(this, $name)')
109packet_queue_list = JType('List<OFPacketQueue>', size='ChannelUtils.calcListSize($name)',
110 read_op = 'ChannelUtils.readPacketQueueList(bb, length - MINIMUM_LENGTH)',
111 write_op = 'ChannelUtils.writeList(this, $name)')
112octets = JType('byte[]', size="length - MINIMUM_LENGTH",
113 read_op = 'ChannelUtils.readBytes(bb, length - MINIMUM_LENGTH)',
114 write_op = 'ChannelUtils.writeBytes(bb, this.$name)')
115of_match = JType('Match', size="$name.getLength()",
116 read_op = 'ChannelUtils.readOFMatch(bb)',
117 write_op = 'ChannelUtils.writeOFMatch(this, $name)')
118flow_mod_cmd = JType('OFFlowModCmd', size="$name.getLength()",
119 read_op = 'ChannelUtils.readOFFlowModCmd(bb)',
120 write_op = 'ChannelUtils.writeOFFlowModCmd(this, $name)')
121mac_addr = JType('MacAddress', 'byte[]', size=6,
122 read_op = 'MacAddress.readFrom(bb)',
123 write_op = 'ChannelUtils.writeBytes(bb, $name)')
124bsn_interface_list = JType("List<OFBsnInterface>",
125 read_op = 'ChannelUtils.readBsnInterfaceList(bb)',
126 write_op = 'ChannelUtils.writeBsnInterfaceList(bb)'
127 )
128meter_band_list = JType("List<OFMeterBand>",
129 read_op = 'ChannelUtils.readMeterBandList(bb)',
130 write_op = 'ChannelUtils.writeMeterBandList(bb, $name)'
131 )
132
133
134
135
136
137default_mtype_to_jtype_convert_map = {
138 'uint8_t' : u8,
139 'uint16_t' : u16,
140 'uint32_t' : u32,
141 'uint64_t' : u64,
142 'uint8_t[1]' : one_byte_array,
143 'uint8_t[2]' : two_byte_array,
144 'uint8_t[3]' : three_byte_array,
145 'uint8_t[4]' : four_byte_array,
146 'uint8_t[5]' : five_byte_array,
147 'uint8_t[6]' : six_byte_array,
148 'uint8_t[7]' : seven_byte_array,
149 'of_port_no_t' : of_port,
150 'of_list_action_t' : actions_list,
151 'of_list_instruction_t' : instructions_list,
152 'of_list_bucket_t': buckets_list,
153 'of_list_port_desc_t' : port_desc_list,
154 'of_list_packet_queue_t' : packet_queue_list,
155 'of_octets_t' : octets,
156 'of_match_t': of_match,
157 'of_fm_cmd_t': flow_mod_cmd,
158 'of_mac_addr_t': mac_addr,
159 'of_port_desc_t': port_desc,
160 'of_list_bsn_interface_t': bsn_interface_list,
161 'of_list_hello_elem_t': hello_elem_list,
162 'of_list_meter_band_t': meter_band_list
163 }
164
165## This is where we drop in special case handling for certain types
166exceptions = {
167 'OFPacketIn': {
168 'data' : octets
169 },
170 }
171
172
173def convert_to_jtype(obj_name, field_name, c_type):
174 """ Convert from a C type ("uint_32") to a java type ("U32")
175 and return a JType object with the size, internal type, and marshalling functions"""
176 if obj_name in exceptions and field_name in exceptions[obj_name]:
177 return exceptions[obj_name][field_name]
178 elif c_type in default_mtype_to_jtype_convert_map:
179 return default_mtype_to_jtype_convert_map[c_type]
180 else:
181 print "WARN: Couldn't find java type conversion for '%s' in %s:%s" % (c_type, obj_name, field_name)
182 jtype = name_c_to_caps_camel(c_type) # not sure... try to fake it
183 return JType(jtype)
184
185
186def mkdir_p(path):
187 """ Emulates `mkdir -p` """
188 try:
189 os.makedirs(path)
190 except OSError as exc: # Python >2.5
191 if exc.errno == errno.EEXIST:
192 pass
193 else: raise
194
195def copy_file_with_boiler_plate(src_name, dst_name, with_boiler=True):
196 with open("java_gen/pre-written/%s" % src_name, "r") as src:
197 with open(dst_name, "w") as dst:
198 if with_boiler:
199 print_boiler_plate(os.path.basename(dst_name), dst)
200 dst.writelines(src.readlines())
201
202def frob(s, **kwargs):
203 """ Step through string s and for each key in kwargs,
204 replace $key with kwargs[key] in s.
205 """
206 for k,v in kwargs.iteritems():
207 s = s.replace('$%s' % k, v)
208 return s
209
210def copy_prewrite_tree(basedir):
211 """ Recursively copy the directory structure from ./java_gen/pre-write
212 into $basedir"""
213 print "Copying pre-written files into %s" % basedir
214# subprocess.call("cd java_gen/pre-written && tar cpf - . | ( cd ../../%s && tar xvpf - )" % basedir,
215# shell=True)