Merge into master from pull request #213:
Adding unpadded Instruction Ids for ofp_table_features_prop_instructions* (https://github.com/floodlight/loxigen/pull/213)
diff --git a/c_gen/c_test_gen.py b/c_gen/c_test_gen.py
index cf03e0e..5b74649 100644
--- a/c_gen/c_test_gen.py
+++ b/c_gen/c_test_gen.py
@@ -68,6 +68,8 @@
import c_gen.identifiers as identifiers
import util
import test_data
+import loxi_globals
+from loxi_ir import *
def var_name_map(m_type):
"""
@@ -124,40 +126,14 @@
or those that should not be messed with
or whose types we're not ready to deal with yet.
"""
- # This will probably need more granularity as more extensions are added
- if (type_maps.class_is_extension(cls, version) and (
- m_name == "experimenter" or
- m_name == "subtype")):
+
+ uclass = loxi_globals.unified.class_by_name(cls)
+ if not uclass:
return True
- classes = ["of_bsn_lacp_stats_request",
- "of_bsn_lacp_stats_reply",
- "of_bsn_switch_pipeline_stats_request",
- "of_bsn_switch_pipeline_stats_reply",
- "of_bsn_port_counter_stats_request",
- "of_bsn_port_counter_stats_reply",
- "of_bsn_vlan_counter_stats_request",
- "of_bsn_vlan_counter_stats_reply",
- "of_bsn_gentable_entry_desc_stats_request",
- "of_bsn_gentable_entry_desc_stats_reply",
- "of_bsn_gentable_entry_stats_request",
- "of_bsn_gentable_entry_stats_reply",
- "of_bsn_gentable_desc_stats_request",
- "of_bsn_gentable_desc_stats_reply",
- "of_bsn_gentable_stats_request",
- "of_bsn_gentable_stats_reply",
- "of_bsn_gentable_bucket_stats_request",
- "of_bsn_gentable_bucket_stats_reply",
- "of_bsn_flow_checksum_bucket_stats_request",
- "of_bsn_flow_checksum_bucket_stats_reply",
- "of_bsn_table_checksum_stats_request",
- "of_bsn_table_checksum_stats_reply",
- ]
-
- if (cls in classes and (
- m_name == "experimenter" or
- m_name == "subtype")):
+ if not isinstance(uclass.member_by_name(m_name), OFDataMember):
return True
+
return loxi_utils.skip_member_name(m_name) or m_type not in scalar_types
def gen_fill_string(out):
diff --git a/c_gen/codegen.py b/c_gen/codegen.py
index 3249747..121bc42 100644
--- a/c_gen/codegen.py
+++ b/c_gen/codegen.py
@@ -35,6 +35,7 @@
from itertools import groupby
from StringIO import StringIO
import template_utils
+from generic_utils import chunks
import loxi_globals
import loxi_ir.ir as ir
import util
@@ -43,6 +44,8 @@
import c_gen.type_maps as type_maps
import c_gen.c_type_maps as c_type_maps
+CLASS_CHUNK_SIZE = 32
+
PushWireTypesData = namedtuple('PushWireTypesData',
['class_name', 'versioned_type_members'])
PushWireTypesMember = namedtuple('PushWireTypesMember',
@@ -75,14 +78,18 @@
class_name=uclass.name,
versioned_type_members=versioned_type_members)
+# Output multiple LOCI classes into each C file. This reduces the overhead of
+# parsing header files, which takes longer than compiling the actual code
+# for many classes. It also reduces the compiled code size.
def generate_classes(install_dir):
- for uclass in loxi_globals.unified.classes:
- with template_utils.open_output(install_dir, "loci/src/%s.c" % uclass.name) as out:
- util.render_template(out, "class.c",
- push_wire_types_data=push_wire_types_data(uclass))
- # Append legacy generated code
- c_code_gen.gen_new_function_definitions(out, uclass.name)
- c_code_gen.gen_accessor_definitions(out, uclass.name)
+ for i, chunk in enumerate(chunks(loxi_globals.unified.classes, CLASS_CHUNK_SIZE)):
+ with template_utils.open_output(install_dir, "loci/src/class%02d.c" % i) as out:
+ for uclass in chunk:
+ util.render_template(out, "class.c",
+ push_wire_types_data=push_wire_types_data(uclass))
+ # Append legacy generated code
+ c_code_gen.gen_new_function_definitions(out, uclass.name)
+ c_code_gen.gen_accessor_definitions(out, uclass.name)
# TODO remove header classes and use the corresponding class instead
def generate_header_classes(install_dir):
diff --git a/generic_utils.py b/generic_utils.py
index 1cfba86..5683aa1 100644
--- a/generic_utils.py
+++ b/generic_utils.py
@@ -214,3 +214,11 @@
if func(i):
c +=1
return c
+
+def chunks(l, n):
+ """
+ Yield successive n-sized chunks from l.
+ From http://stackoverflow.com/questions/312443/how-do-you-split-a-list-into-evenly-sized-chunks-in-python
+ """
+ for i in xrange(0, len(l), n):
+ yield l[i:i+n]
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/util/HexString.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/util/HexString.java
index ddf0f25..bcc46f7 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/util/HexString.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/util/HexString.java
@@ -17,8 +17,6 @@
package org.projectfloodlight.openflow.util;
-import java.math.BigInteger;
-
import org.projectfloodlight.openflow.types.U8;
public class HexString {
@@ -86,13 +84,17 @@
return ret;
}
- public static long toLong(final String values) throws NumberFormatException {
- // Long.parseLong() can't handle HexStrings with MSB set. Sigh.
- BigInteger bi = new BigInteger(values.replaceAll(":", ""), 16);
- if (bi.bitLength() > 64)
- throw new NumberFormatException("Input string too big to fit in long: "
- + values);
- return bi.longValue();
+ public static long toLong(String value) throws NumberFormatException {
+ String[] octets = value.split(":");
+ if (octets.length > 8)
+ throw new NumberFormatException("Input string is too big to fit in long: " + value);
+ long l = 0;
+ for (String octet: octets) {
+ if (octet.length() > 2)
+ throw new NumberFormatException("Each colon-separated byte component must consist of 1 or 2 hex digits: " + value);
+ short s = Short.parseShort(octet, 16);
+ l = (l << 8) + s;
+ }
+ return l;
}
-
}
diff --git a/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/util/HexStringTest.java b/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/util/HexStringTest.java
new file mode 100644
index 0000000..360cb5a
--- /dev/null
+++ b/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/util/HexStringTest.java
@@ -0,0 +1,103 @@
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* University
+*
+* Licensed under the Apache License, Version 2.0 (the "License"); you may
+* not use this file except in compliance with the License. You may obtain
+* a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+* License for the specific language governing permissions and limitations
+* under the License.
+**/
+
+package org.projectfloodlight.openflow.util;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+/**
+ * Does hexstring conversion work?
+ *
+ * @author Rob Sherwood (rob.sherwood@stanford.edu)
+ */
+public class HexStringTest {
+
+ @Test
+ public void testMarshalling() throws Exception {
+ String dpidStr = "00:00:00:23:20:2d:16:71";
+ long dpid = HexString.toLong(dpidStr);
+ String testStr = HexString.toHexString(dpid);
+ assertEquals(dpidStr, testStr);
+ }
+
+ @Test
+ public void testToLong() {
+ String dpidStr = "3e:1f:01:fc:72:8c:63:31";
+ long valid = 0x3e1f01fc728c6331L;
+ long testLong = HexString.toLong(dpidStr);
+ assertEquals(valid, testLong);
+ }
+
+ @Test
+ public void testToLong2() {
+ String dpidStr = "1f:1:fc:72:3:f:31";
+ long valid = 0x1f01fc72030f31L;
+ long testLong = HexString.toLong(dpidStr);
+ assertEquals(valid, testLong);
+ }
+
+ @Test
+ public void testToLongMSB() {
+ String dpidStr = "ca:7c:5e:d1:64:7a:95:9b";
+ long valid = -3856102927509056101L;
+ long testLong = HexString.toLong(dpidStr);
+ assertEquals(valid, testLong);
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void testToLongErrorTooManyBytes() {
+ HexString.toLong("09:08:07:06:05:04:03:02:01");
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void testToLongErrorByteValueTooLong() {
+ HexString.toLong("234:01");
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void testToLongErrorEmptyByte() {
+ HexString.toLong("03::01");
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void testToLongErrorInvalidHexDigit() {
+ HexString.toLong("ss:01");
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void testToLongErrorEmptyString() {
+ HexString.toLong("");
+ }
+
+
+ @Test
+ public void testToStringBytes() {
+ byte[] dpid = { 0, 0, 0, 0, 0, 0, 0, -1 };
+ String valid = "00:00:00:00:00:00:00:ff";
+ String testString = HexString.toHexString(dpid);
+ assertEquals(valid, testString);
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void testFromHexStringError() {
+ String invalidStr = "00:00:00:00:00:00:ffff";
+ HexString.fromHexString(invalidStr);
+ }
+}
+