Merge branch 'master' of github.com:floodlight/loxigen
diff --git a/.gitignore b/.gitignore
index 8206747..9712e8f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,3 +10,4 @@
.*.swp
.*.swo
*.cache
+openflowj-loxi
diff --git a/Makefile b/Makefile
index c99ae0b..6f0fbaa 100644
--- a/Makefile
+++ b/Makefile
@@ -43,6 +43,7 @@
\! \( -name '*.cache' -o -name '.*' \))
INPUT_FILES = $(wildcard openflow_input/*)
TEST_DATA = $(shell find test_data -name '*.data')
+OPENFLOWJ_WORKSPACE = openflowj-loxi
all: c python
@@ -68,14 +69,19 @@
@echo "HTML documentation output to ${LOXI_OUTPUT_DIR}/pyloxi-doc"
java: .loxi_ts.java
+ mkdir -p ${OPENFLOWJ_WORKSPACE}
+ ln -sf ../java_gen/pre-written/pom.xml ${OPENFLOWJ_WORKSPACE}/pom.xml
+ ln -sf ../java_gen/pre-written/src ${OPENFLOWJ_WORKSPACE}/src
+ rsync --checksum --delete -rv ${LOXI_OUTPUT_DIR}/openflowj/src/ ${OPENFLOWJ_WORKSPACE}/gen-src
.loxi_ts.java: ${LOXI_PY_FILES} ${LOXI_TEMPLATE_FILES} ${INPUT_FILES} ${TEST_DATA}
./loxigen.py --install-dir=${LOXI_OUTPUT_DIR} --lang=java
touch $@
java-eclipse: java
- mkdir -p java-eclipse
- rsync --checksum --delete -rv loxi_output/openflowj/ java_eclipse/
+ cd ${OPENFLOWJ_WORKSPACE} && mvn eclipse:eclipse
+ # Unfortunately, mvn eclipse:eclipse resolves the symlink, which doesn't work with eclipse
+ cd ${OPENFLOWJ_WORKSPACE} && perl -pi -e 's{<classpathentry kind="src" path="[^"]*/java_gen/pre-written/src/}{<classpathentry kind="src" path="src/}' .classpath
clean:
rm -rf loxi_output # only delete generated files in the default directory
@@ -108,10 +114,17 @@
${LOXI_OUTPUT_DIR}/locitest/locitest
check-java: java
- cd ${LOXI_OUTPUT_DIR}/openflowj/ && mvn compile test-compile test
+ cd ${OPENFLOWJ_WORKSPACE} && mvn compile test-compile test
package-java: java
- cd ${LOXI_OUTPUT_DIR}/openflowj/ && mvn package
+ cd ${OPENFLOWJ_WORKSPACE} && mvn package
+
+deploy-java: java
+ cd ${OPENFLOWJ_WORKSPACE} && mvn deploy
+
+install-java: java
+ cd ${OPENFLOWJ_WORKSPACE} && mvn install
+
pylint:
pylint -E ${LOXI_PY_FILES}
diff --git a/java_gen/README.java-lang b/java_gen/README.java-lang
new file mode 100644
index 0000000..754c13b
--- /dev/null
+++ b/java_gen/README.java-lang
@@ -0,0 +1 @@
+Work in progress to port OpenFlow/J to support OpenFlow 1.0, 1.1., 1.2, and 1.3.
diff --git a/java_gen/codegen.py b/java_gen/codegen.py
index 8606682..1b9f445 100644
--- a/java_gen/codegen.py
+++ b/java_gen/codegen.py
@@ -57,8 +57,6 @@
gen.create_of_const_enums()
gen.create_of_factories()
- with open('%s/README.java-lang' % os.path.dirname(__file__)) as readme_src:
- out.writelines(readme_src.readlines())
out.close()
@@ -157,6 +155,3 @@
""" Recursively copy the directory structure from ./java_gen/pre-write
into $basedir"""
print "Copying pre-written files into %s" % basedir
- #subprocess.call("cd java_gen/pre-written && tar cpf - pom.xml | ( cd ../../%s && tar xvpf - )" % basedir,
- # shell=True)
- os.symlink(os.path.abspath("%s/pre-written/pom.xml" % os.path.dirname(__file__)), "%s/pom.xml" % basedir)
diff --git a/java_gen/java_model.py b/java_gen/java_model.py
index 0225af5..bd1967b 100644
--- a/java_gen/java_model.py
+++ b/java_gen/java_model.py
@@ -51,7 +51,8 @@
enum_entry_blacklist = defaultdict(lambda: set(), OFFlowWildcards=set([ "NW_DST_BITS", "NW_SRC_BITS", "NW_SRC_SHIFT", "NW_DST_SHIFT" ]))
# OFUint structs are there for god-knows what in loci. We certainly don't need them.
interface_blacklist = set( ("OFUint8", "OFUint32",))
- write_blacklist = defaultdict(lambda: set(), OFOxm=set(('typeLen',)), OFAction=set(('type',)), OFInstruction=set(('type',)), OFFlowMod=set(('command', )))
+ read_blacklist = defaultdict(lambda: set(), OFExperimenter=set(('data','subtype')), OFActionExperimenter=set(('data',)))
+ write_blacklist = defaultdict(lambda: set(), OFOxm=set(('typeLen',)), OFAction=set(('type',)), OFInstruction=set(('type',)), OFFlowMod=set(('command', )), OFExperimenter=set(('data','subtype')), OFActionExperimenter=set(('data',)))
virtual_interfaces = set(['OFOxm', 'OFInstruction', 'OFFlowMod', 'OFBsnVport' ])
OxmMapEntry = namedtuple("OxmMapEntry", ["type_name", "value", "masked" ])
@@ -346,6 +347,24 @@
else:
self.parent_interface = None
+ @property
+ @memoize
+ def all_parent_interfaces(self):
+ return [ "OFObject" ] + \
+ ([ self.parent_interface ] if self.parent_interface else [] )+ \
+ self.additional_parent_interfaces
+ @property
+ @memoize
+ def additional_parent_interfaces(self):
+ if loxi_utils.class_is_message(self.c_name) and not self.is_virtual:
+ m = re.match(r'(.*)Request$', self.name)
+ if m:
+ reply_name = m.group(1) + "Reply"
+ if model.interface_by_name(reply_name):
+ return ["OFRequest<%s>" % reply_name ]
+ return []
+
+
def is_instance_of(self, other_class):
if self == other_class:
return True
@@ -387,10 +406,12 @@
return ("", "OFStatsReply", None)
elif re.match(r'OFFlow(Add|Modify(Strict)?|Delete(Strict)?)$', self.name):
return ("", "OFFlowMod", None)
- elif loxi_utils.class_is_message(self.c_name) and re.match(r'OFBsn.+$', self.name):
+ elif loxi_utils.class_is_message(self.c_name) and re.match(r'OFBsn.+$', self.name) and self.name != "OFBsnHeader":
return ("", "OFBsnHeader", None)
- elif loxi_utils.class_is_message(self.c_name) and re.match(r'OFNicira.+$', self.name):
+ elif loxi_utils.class_is_message(self.c_name) and re.match(r'OFNicira.+$', self.name) and self.name != "OFNiciraHeader":
return ("", "OFNiciraHeader", None)
+ elif self.name == "OFBsnHeader" or self.name =="OFNiciraHeader":
+ return ("", "OFExperimenter", None)
elif re.match(r'OFMatch.*', self.name):
return ("", "Match", None)
elif loxi_utils.class_is_message(self.c_name):
@@ -400,6 +421,8 @@
return ("action", "OFActionBsn", None)
elif re.match(r'OFActionNicira.+', self.name):
return ("action", "OFActionNicira", None)
+ elif self.name == "OFActionBsn" or self.name == "OFActionNicira":
+ return ("action", "OFActionExperimenter", None)
else:
return ("action", "OFAction", None)
elif re.match(r'OFBsnVport.+$', self.name):
@@ -450,7 +473,7 @@
if of_member.name not in member_map:
member_map[of_member.name] = JavaMember.for_of_member(self, of_member)
- return tuple(member_map.values())
+ return tuple(m for m in member_map.values() if m.name not in model.read_blacklist[self.name])
@property
def virtual_members(self):
diff --git a/java_gen/pre-written/.classpath b/java_gen/pre-written/.classpath
deleted file mode 100644
index b6bc6ad..0000000
--- a/java_gen/pre-written/.classpath
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
- <classpathentry kind="src" path="src/main/java"/>
- <classpathentry kind="lib" path="lib/netty-3.2.6.Final.jar"/>
- <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
- <classpathentry kind="output" path="bin"/>
-</classpath>
diff --git a/java_gen/pre-written/.project b/java_gen/pre-written/.project
deleted file mode 100644
index b347bd6..0000000
--- a/java_gen/pre-written/.project
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
- <name>openflowj-loxi</name>
- <comment></comment>
- <projects>
- </projects>
- <buildSpec>
- <buildCommand>
- <name>org.eclipse.jdt.core.javabuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- </buildSpec>
- <natures>
- <nature>org.eclipse.jdt.core.javanature</nature>
- </natures>
-</projectDescription>
diff --git a/java_gen/pre-written/pom.xml b/java_gen/pre-written/pom.xml
index d01d797..2461cfe 100644
--- a/java_gen/pre-written/pom.xml
+++ b/java_gen/pre-written/pom.xml
@@ -2,9 +2,9 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
- <groupId>org.openflow</groupId>
+ <groupId>org.projectfloodlight</groupId>
<artifactId>openflowj</artifactId>
- <version>2.0-SNAPSHOT</version>
+ <version>0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Loxi-Generated OpenFlow/J</name>
@@ -40,16 +40,77 @@
<version>1.8</version>
<executions>
<execution>
+ <id>gen-src-add-source</id>
<phase>generate-sources</phase>
<goals><goal>add-source</goal></goals>
<configuration>
<sources>
- <source>../../java_gen/pre-written/src/main/java/</source>
+ <source>gen-src/main/java</source>
+ </sources>
+ </configuration>
+ </execution>
+ <execution>
+ <id>add-gen-src-test-source</id>
+ <!-- note: purposefully not using phase generate-test-sources,
+ because that is not picked up by eclipse:eclipse -->
+ <phase>validate</phase>
+ <goals><goal>add-test-source</goal></goals>
+ <configuration>
+ <sources>
+ <source>gen-src/test/java</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
+ <!-- attach sources -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ <version>2.2.1</version>
+ <executions>
+ <execution>
+ <id>attach-sources</id>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <!-- attach javadoc -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <version>2.9.1</version>
+ <executions>
+ <execution>
+ <id>attach-javadocs</id>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-eclipse-plugin</artifactId>
+ <configuration>
+ <downloadSources>true</downloadSources>
+ <downloadJavadocs>true</downloadJavadocs>
+ </configuration>
+ </plugin>
</plugins>
</build>
+<distributionManagement>
+ <repository>
+ <id>deployment</id>
+ <name>Internal Releases</name>
+ <url>http://10.197.128.18:8081/nexus/content/repositories/releases/</url>
+ </repository>
+ <snapshotRepository>
+ <id>deployment</id>
+ <name>Internal Releases</name>
+ <url>http://10.197.128.18:8081/nexus/content/repositories/snapshots/</url>
+ </snapshotRepository>
+</distributionManagement>
</project>
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/OFRequest.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/OFRequest.java
new file mode 100644
index 0000000..6666943
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/OFRequest.java
@@ -0,0 +1,5 @@
+package org.projectfloodlight.openflow.protocol;
+
+/** Type safety interface. Enables type safe combinations of requests and replies */
+public interface OFRequest<REPLY extends OFMessage> extends OFMessage {
+}
diff --git a/java_gen/templates/of_interface.java b/java_gen/templates/of_interface.java
index 8ddaba3..8c9bf25 100644
--- a/java_gen/templates/of_interface.java
+++ b/java_gen/templates/of_interface.java
@@ -36,7 +36,7 @@
//:: include("_imports.java", msg=msg)
-public interface ${msg.name}${ "<%s>" % msg.type_annotation if msg.type_annotation else ""} extends OFObject${", %s" % msg.parent_interface if msg.parent_interface else ""}{
+public interface ${msg.name}${ "<%s>" % msg.type_annotation if msg.type_annotation else ""} extends ${", ".join(msg.all_parent_interfaces)} {
//:: for prop in msg.members:
${prop.java_type.public_type} ${prop.getter_name}()${ "" if prop.is_universal else " throws UnsupportedOperationException"};
//:: #endfor
diff --git a/java_gen/templates/of_virtual_class.java b/java_gen/templates/of_virtual_class.java
index fc6a6c0..55ccc5e 100644
--- a/java_gen/templates/of_virtual_class.java
+++ b/java_gen/templates/of_virtual_class.java
@@ -70,7 +70,7 @@
//:: elif prop.is_fixed_value:
// fixed value property ${prop.name} == ${prop.value}
${prop.java_type.priv_type} ${prop.name} = ${prop.java_type.read_op(version, pub_type=False)};
- if(${prop.name} != ${prop.value})
+ if(${prop.name} != ${prop.priv_value})
throw new OFParseError("Wrong ${prop.name}: Expected=${prop.enum_value}(${prop.value}), got="+${prop.name});
//:: elif prop.is_length_value:
${prop.java_type.public_type} ${prop.name} = ${prop.java_type.read_op(version, pub_type=True)};
diff --git a/openflow_input/standard-1.0 b/openflow_input/standard-1.0
index d78d5bd..5483ff4 100644
--- a/openflow_input/standard-1.0
+++ b/openflow_input/standard-1.0
@@ -335,7 +335,7 @@
uint8_t type == 4;
uint16_t length;
uint32_t xid;
- uint32_t experimenter;
+ uint32_t experimenter == ?;
uint32_t subtype;
of_octets_t data;
};
@@ -525,7 +525,7 @@
struct of_action_experimenter : of_action {
uint16_t type == 65535;
uint16_t len;
- uint32_t experimenter;
+ uint32_t experimenter == ?;
of_octets_t data;
};
@@ -919,7 +919,7 @@
uint32_t xid;
uint16_t stats_type == 0xffff;
uint16_t flags;
- uint32_t experimenter;
+ uint32_t experimenter == ?;
of_octets_t data;
};
@@ -930,7 +930,7 @@
uint32_t xid;
uint16_t stats_type == 0xffff;
uint16_t flags;
- uint32_t experimenter;
+ uint32_t experimenter == ?;
of_octets_t data;
};
diff --git a/openflow_input/standard-1.1 b/openflow_input/standard-1.1
index 1047127..a1127b1 100644
--- a/openflow_input/standard-1.1
+++ b/openflow_input/standard-1.1
@@ -443,7 +443,7 @@
uint8_t type == 4;
uint16_t length;
uint32_t xid;
- uint32_t experimenter;
+ uint32_t experimenter == ?;
uint32_t subtype;
of_octets_t data;
};
@@ -742,7 +742,7 @@
struct of_action_experimenter : of_action {
uint16_t type == 65535;
uint16_t len;
- uint32_t experimenter;
+ uint32_t experimenter == ?;
of_octets_t data;
};
@@ -837,7 +837,7 @@
struct of_instruction_experimenter : of_instruction {
uint16_t type == 65535;
uint16_t len;
- uint32_t experimenter;
+ uint32_t experimenter == ?;
of_octets_t data;
};
@@ -1327,7 +1327,7 @@
uint16_t stats_type == 0xffff;
uint16_t flags;
pad(4);
- uint32_t experimenter;
+ uint32_t experimenter == ?;
pad(4);
of_octets_t data;
};
@@ -1340,7 +1340,7 @@
uint16_t stats_type == 0xffff;
uint16_t flags;
pad(4);
- uint32_t experimenter;
+ uint32_t experimenter == ?;
pad(4);
of_octets_t data;
};
diff --git a/openflow_input/standard-1.2 b/openflow_input/standard-1.2
index e4c8ec2..bfa9a64 100644
--- a/openflow_input/standard-1.2
+++ b/openflow_input/standard-1.2
@@ -483,7 +483,7 @@
uint8_t type == 4;
uint16_t length;
uint32_t xid;
- uint32_t experimenter;
+ uint32_t experimenter == ?;
uint32_t subtype;
of_octets_t data;
};
@@ -699,7 +699,7 @@
struct of_action_experimenter : of_action {
uint16_t type == 65535;
uint16_t len;
- uint32_t experimenter;
+ uint32_t experimenter == ?;
of_octets_t data;
};
@@ -753,7 +753,7 @@
struct of_instruction_experimenter : of_instruction {
uint16_t type == 65535;
uint16_t len;
- uint32_t experimenter;
+ uint32_t experimenter == ?;
of_octets_t data;
};
@@ -1317,7 +1317,7 @@
uint16_t stats_type == 0xffff;
uint16_t flags;
pad(4);
- uint32_t experimenter;
+ uint32_t experimenter == ?;
uint32_t subtype;
of_octets_t data;
};
@@ -1330,7 +1330,7 @@
uint16_t stats_type == 0xffff;
uint16_t flags;
pad(4);
- uint32_t experimenter;
+ uint32_t experimenter == ?;
uint32_t subtype;
of_octets_t data;
};
@@ -1363,7 +1363,7 @@
uint16_t type == 65535;
uint16_t len;
pad(4);
- uint32_t experimenter;
+ uint32_t experimenter == ?;
pad(4);
of_octets_t data;
};
diff --git a/openflow_input/standard-1.3 b/openflow_input/standard-1.3
index b9c5475..119e7a4 100644
--- a/openflow_input/standard-1.3
+++ b/openflow_input/standard-1.3
@@ -608,7 +608,7 @@
uint8_t type == 4;
uint16_t length;
uint32_t xid;
- uint32_t experimenter;
+ uint32_t experimenter == ?;
uint32_t subtype;
of_octets_t data;
};
@@ -833,7 +833,7 @@
struct of_action_experimenter : of_action {
uint16_t type == 65535;
uint16_t len;
- uint32_t experimenter;
+ uint32_t experimenter == ?;
of_octets_t data;
};
@@ -905,7 +905,7 @@
struct of_instruction_experimenter : of_instruction {
uint16_t type == 65535;
uint16_t len;
- uint32_t experimenter;
+ uint32_t experimenter == ?;
of_octets_t data;
};
@@ -1177,7 +1177,8 @@
uint16_t priority;
uint16_t idle_timeout;
uint16_t hard_timeout;
- pad(6);
+ uint16_t flags;
+ pad(4);
uint64_t cookie;
uint64_t packet_count;
uint64_t byte_count;
@@ -1770,7 +1771,7 @@
};
struct of_experimenter_multipart_header {
- uint32_t experimenter;
+ uint32_t experimenter == ?;
uint32_t subtype;
};
@@ -1802,7 +1803,7 @@
uint16_t type == 65535;
uint16_t len;
pad(4);
- uint32_t experimenter;
+ uint32_t experimenter == ?;
pad(4);
of_octets_t data;
};
diff --git a/py_gen/codegen.py b/py_gen/codegen.py
index 6570938..540d212 100644
--- a/py_gen/codegen.py
+++ b/py_gen/codegen.py
@@ -54,13 +54,10 @@
# Create intermediate representation, extended from the LOXI IR
# HACK the oftype member attribute is replaced with an OFType instance
def build_ofclasses(version):
- blacklist = ["of_experimenter", "of_action_experimenter"]
ofclasses = []
for ofclass in of_g.ir[version].classes:
cls = ofclass.name
- if type_maps.class_is_virtual(cls):
- continue
- if cls in blacklist:
+ if ofclass.virtual:
continue
members = []
diff --git a/py_gen/templates/message.py b/py_gen/templates/message.py
index 6754b94..7158545 100644
--- a/py_gen/templates/message.py
+++ b/py_gen/templates/message.py
@@ -226,11 +226,6 @@
const.OFPST_TABLE : table_stats_reply.unpack,
const.OFPST_PORT : port_stats_reply.unpack,
const.OFPST_QUEUE : queue_stats_reply.unpack,
-:: if version < of_g.VERSION_1_1:
- const.OFPST_VENDOR : experimenter_stats_reply.unpack,
-:: else:
- const.OFPST_EXPERIMENTER : experimenter_stats_reply.unpack,
-:: #endif
:: if version >= of_g.VERSION_1_1:
const.OFPST_GROUP : group_stats_reply.unpack,
const.OFPST_GROUP_DESC : group_desc_stats_reply.unpack,
@@ -247,11 +242,6 @@
const.OFPST_TABLE : table_stats_request.unpack,
const.OFPST_PORT : port_stats_request.unpack,
const.OFPST_QUEUE : queue_stats_request.unpack,
-:: if version < of_g.VERSION_1_1:
- const.OFPST_VENDOR : experimenter_stats_request.unpack,
-:: else:
- const.OFPST_EXPERIMENTER : experimenter_stats_request.unpack,
-:: #endif
:: if version >= of_g.VERSION_1_1:
const.OFPST_GROUP : group_stats_request.unpack,
const.OFPST_GROUP_DESC : group_desc_stats_request.unpack,