diff --git a/.gitignore b/.gitignore
index b79ebe2942680058581bffac633a1294b5e282f4..4932f75ebf81e9cb959ef74864810b575ed65baa 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,4 +6,3 @@
 .settings
 .DS_Store
 target
-thrift
diff --git a/build.xml b/build.xml
index cdea14c7ef4982b658d8e0ce0fe74198c3154cc5..5d4b82dfafcd891fe5812f1a53d330410ab5e65c 100644
--- a/build.xml
+++ b/build.xml
@@ -23,6 +23,7 @@
 <project default="dist" name="Floodlight">
 
     <property name="target" location="target"/>
+    <property name="lib" location="lib"/>
     <property name="build" location="${target}/bin"/>
     <property name="build-test" location="${target}/bin-test"/>
     <property name="test-output" location="${target}/test"/>
@@ -32,9 +33,9 @@
     <property name="python-src" location="src/main/python"/>
     <property name="docs" location="${target}/docs"/>
     <property name="main-class" value="net.floodlightcontroller.core.Main"/>
-    <property name="packetstreamer-gen" location="${target}/gen-java" />
-    <property name="packetstreamer-gen-build" location="${target}/gen-java-bin"/>
-    <property name="packetstreamer-thrift-jar" location="${target}/lib/packetstreamer-thrift.jar"/>
+    <property name="packetstreamer-gen" location="${lib}/gen-java" />
+    <property name="packetstreamer-gen-build" location="${lib}/gen-java-bin"/>
+    <property name="packetstreamer-thrift-jar" location="${lib}/packetstreamer-thrift.jar"/>
     <property name="floodlight-jar" location="${target}/floodlight.jar"/>
     <property name="floodlight-test-jar" location="${target}/floodlight-test.jar"/>
 
@@ -54,9 +55,9 @@
         <include name="args4j-2.0.16.jar"/>
         <include name="concurrentlinkedhashmap-lru-1.2.jar"/>
         <include name="jython-2.5.2.jar"/>
+        <include name="libthrift-0.7.0.jar"/>
     </patternset>
     <patternset id="genlib">
-        <include name="libthrift-0.7.0.jar"/>
         <include name="packetstreamer-thrift.jar"/>
     </patternset>
 
@@ -84,7 +85,6 @@
     </path>
 
     <target name="init">
-        <exec executable="${basedir}/setup.sh" failonerror="true"/>
         <mkdir dir="${build}"/>
         <mkdir dir="${build-test}"/>
         <mkdir dir="${target}/lib"/>
@@ -125,6 +125,8 @@
 
     <target name="clean">
         <delete dir="${target}"/>
+        <delete dir="${packetstreamer-gen-build}"/>
+        <delete file="${packetstreamer-thrift-jar}"/>
     </target>
 
     <target name="run" depends="dist">
diff --git a/lib/gen-java/net/floodlightcontroller/packetstreamer/thrift/Constants.java b/lib/gen-java/net/floodlightcontroller/packetstreamer/thrift/Constants.java
new file mode 100644
index 0000000000000000000000000000000000000000..5ea3e7be998aa59d0adb56e2b4cefe56f7c4e8f1
--- /dev/null
+++ b/lib/gen-java/net/floodlightcontroller/packetstreamer/thrift/Constants.java
@@ -0,0 +1,27 @@
+/**
+ * Autogenerated by Thrift Compiler (0.7.0)
+ *
+ * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+ */
+package net.floodlightcontroller.packetstreamer.thrift;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.EnumMap;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.EnumSet;
+import java.util.Collections;
+import java.util.BitSet;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Constants {
+
+  public static final String VERSION = "0.1.0";
+
+}
diff --git a/lib/gen-java/net/floodlightcontroller/packetstreamer/thrift/Message.java b/lib/gen-java/net/floodlightcontroller/packetstreamer/thrift/Message.java
new file mode 100644
index 0000000000000000000000000000000000000000..45def5b0cd051b7b7c91ae1c2d91c632081dfbbb
--- /dev/null
+++ b/lib/gen-java/net/floodlightcontroller/packetstreamer/thrift/Message.java
@@ -0,0 +1,446 @@
+/**
+ * Autogenerated by Thrift Compiler (0.7.0)
+ *
+ * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+ */
+package net.floodlightcontroller.packetstreamer.thrift;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.EnumMap;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.EnumSet;
+import java.util.Collections;
+import java.util.BitSet;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Message implements org.apache.thrift.TBase<Message, Message._Fields>, java.io.Serializable, Cloneable {
+  private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("Message");
+
+  private static final org.apache.thrift.protocol.TField SESSION_IDS_FIELD_DESC = new org.apache.thrift.protocol.TField("sessionIDs", org.apache.thrift.protocol.TType.LIST, (short)1);
+  private static final org.apache.thrift.protocol.TField PACKET_FIELD_DESC = new org.apache.thrift.protocol.TField("packet", org.apache.thrift.protocol.TType.STRUCT, (short)2);
+
+  public List<String> sessionIDs; // required
+  public Packet packet; // required
+
+  /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+  public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+    SESSION_IDS((short)1, "sessionIDs"),
+    PACKET((short)2, "packet");
+
+    private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+    static {
+      for (_Fields field : EnumSet.allOf(_Fields.class)) {
+        byName.put(field.getFieldName(), field);
+      }
+    }
+
+    /**
+     * Find the _Fields constant that matches fieldId, or null if its not found.
+     */
+    public static _Fields findByThriftId(int fieldId) {
+      switch(fieldId) {
+        case 1: // SESSION_IDS
+          return SESSION_IDS;
+        case 2: // PACKET
+          return PACKET;
+        default:
+          return null;
+      }
+    }
+
+    /**
+     * Find the _Fields constant that matches fieldId, throwing an exception
+     * if it is not found.
+     */
+    public static _Fields findByThriftIdOrThrow(int fieldId) {
+      _Fields fields = findByThriftId(fieldId);
+      if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+      return fields;
+    }
+
+    /**
+     * Find the _Fields constant that matches name, or null if its not found.
+     */
+    public static _Fields findByName(String name) {
+      return byName.get(name);
+    }
+
+    private final short _thriftId;
+    private final String _fieldName;
+
+    _Fields(short thriftId, String fieldName) {
+      _thriftId = thriftId;
+      _fieldName = fieldName;
+    }
+
+    public short getThriftFieldId() {
+      return _thriftId;
+    }
+
+    public String getFieldName() {
+      return _fieldName;
+    }
+  }
+
+  // isset id assignments
+
+  public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+  static {
+    Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+    tmpMap.put(_Fields.SESSION_IDS, new org.apache.thrift.meta_data.FieldMetaData("sessionIDs", org.apache.thrift.TFieldRequirementType.DEFAULT, 
+        new org.apache.thrift.meta_data.ListMetaData(org.apache.thrift.protocol.TType.LIST, 
+            new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))));
+    tmpMap.put(_Fields.PACKET, new org.apache.thrift.meta_data.FieldMetaData("packet", org.apache.thrift.TFieldRequirementType.DEFAULT, 
+        new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, Packet.class)));
+    metaDataMap = Collections.unmodifiableMap(tmpMap);
+    org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(Message.class, metaDataMap);
+  }
+
+  public Message() {
+  }
+
+  public Message(
+    List<String> sessionIDs,
+    Packet packet)
+  {
+    this();
+    this.sessionIDs = sessionIDs;
+    this.packet = packet;
+  }
+
+  /**
+   * Performs a deep copy on <i>other</i>.
+   */
+  public Message(Message other) {
+    if (other.isSetSessionIDs()) {
+      List<String> __this__sessionIDs = new ArrayList<String>();
+      for (String other_element : other.sessionIDs) {
+        __this__sessionIDs.add(other_element);
+      }
+      this.sessionIDs = __this__sessionIDs;
+    }
+    if (other.isSetPacket()) {
+      this.packet = new Packet(other.packet);
+    }
+  }
+
+  public Message deepCopy() {
+    return new Message(this);
+  }
+
+  @Override
+  public void clear() {
+    this.sessionIDs = null;
+    this.packet = null;
+  }
+
+  public int getSessionIDsSize() {
+    return (this.sessionIDs == null) ? 0 : this.sessionIDs.size();
+  }
+
+  public java.util.Iterator<String> getSessionIDsIterator() {
+    return (this.sessionIDs == null) ? null : this.sessionIDs.iterator();
+  }
+
+  public void addToSessionIDs(String elem) {
+    if (this.sessionIDs == null) {
+      this.sessionIDs = new ArrayList<String>();
+    }
+    this.sessionIDs.add(elem);
+  }
+
+  public List<String> getSessionIDs() {
+    return this.sessionIDs;
+  }
+
+  public Message setSessionIDs(List<String> sessionIDs) {
+    this.sessionIDs = sessionIDs;
+    return this;
+  }
+
+  public void unsetSessionIDs() {
+    this.sessionIDs = null;
+  }
+
+  /** Returns true if field sessionIDs is set (has been assigned a value) and false otherwise */
+  public boolean isSetSessionIDs() {
+    return this.sessionIDs != null;
+  }
+
+  public void setSessionIDsIsSet(boolean value) {
+    if (!value) {
+      this.sessionIDs = null;
+    }
+  }
+
+  public Packet getPacket() {
+    return this.packet;
+  }
+
+  public Message setPacket(Packet packet) {
+    this.packet = packet;
+    return this;
+  }
+
+  public void unsetPacket() {
+    this.packet = null;
+  }
+
+  /** Returns true if field packet is set (has been assigned a value) and false otherwise */
+  public boolean isSetPacket() {
+    return this.packet != null;
+  }
+
+  public void setPacketIsSet(boolean value) {
+    if (!value) {
+      this.packet = null;
+    }
+  }
+
+  public void setFieldValue(_Fields field, Object value) {
+    switch (field) {
+    case SESSION_IDS:
+      if (value == null) {
+        unsetSessionIDs();
+      } else {
+        setSessionIDs((List<String>)value);
+      }
+      break;
+
+    case PACKET:
+      if (value == null) {
+        unsetPacket();
+      } else {
+        setPacket((Packet)value);
+      }
+      break;
+
+    }
+  }
+
+  public Object getFieldValue(_Fields field) {
+    switch (field) {
+    case SESSION_IDS:
+      return getSessionIDs();
+
+    case PACKET:
+      return getPacket();
+
+    }
+    throw new IllegalStateException();
+  }
+
+  /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+  public boolean isSet(_Fields field) {
+    if (field == null) {
+      throw new IllegalArgumentException();
+    }
+
+    switch (field) {
+    case SESSION_IDS:
+      return isSetSessionIDs();
+    case PACKET:
+      return isSetPacket();
+    }
+    throw new IllegalStateException();
+  }
+
+  @Override
+  public boolean equals(Object that) {
+    if (that == null)
+      return false;
+    if (that instanceof Message)
+      return this.equals((Message)that);
+    return false;
+  }
+
+  public boolean equals(Message that) {
+    if (that == null)
+      return false;
+
+    boolean this_present_sessionIDs = true && this.isSetSessionIDs();
+    boolean that_present_sessionIDs = true && that.isSetSessionIDs();
+    if (this_present_sessionIDs || that_present_sessionIDs) {
+      if (!(this_present_sessionIDs && that_present_sessionIDs))
+        return false;
+      if (!this.sessionIDs.equals(that.sessionIDs))
+        return false;
+    }
+
+    boolean this_present_packet = true && this.isSetPacket();
+    boolean that_present_packet = true && that.isSetPacket();
+    if (this_present_packet || that_present_packet) {
+      if (!(this_present_packet && that_present_packet))
+        return false;
+      if (!this.packet.equals(that.packet))
+        return false;
+    }
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    return 0;
+  }
+
+  public int compareTo(Message other) {
+    if (!getClass().equals(other.getClass())) {
+      return getClass().getName().compareTo(other.getClass().getName());
+    }
+
+    int lastComparison = 0;
+    Message typedOther = (Message)other;
+
+    lastComparison = Boolean.valueOf(isSetSessionIDs()).compareTo(typedOther.isSetSessionIDs());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetSessionIDs()) {
+      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sessionIDs, typedOther.sessionIDs);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
+    lastComparison = Boolean.valueOf(isSetPacket()).compareTo(typedOther.isSetPacket());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetPacket()) {
+      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.packet, typedOther.packet);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
+    return 0;
+  }
+
+  public _Fields fieldForId(int fieldId) {
+    return _Fields.findByThriftId(fieldId);
+  }
+
+  public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+    org.apache.thrift.protocol.TField field;
+    iprot.readStructBegin();
+    while (true)
+    {
+      field = iprot.readFieldBegin();
+      if (field.type == org.apache.thrift.protocol.TType.STOP) { 
+        break;
+      }
+      switch (field.id) {
+        case 1: // SESSION_IDS
+          if (field.type == org.apache.thrift.protocol.TType.LIST) {
+            {
+              org.apache.thrift.protocol.TList _list0 = iprot.readListBegin();
+              this.sessionIDs = new ArrayList<String>(_list0.size);
+              for (int _i1 = 0; _i1 < _list0.size; ++_i1)
+              {
+                String _elem2; // required
+                _elem2 = iprot.readString();
+                this.sessionIDs.add(_elem2);
+              }
+              iprot.readListEnd();
+            }
+          } else { 
+            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
+          }
+          break;
+        case 2: // PACKET
+          if (field.type == org.apache.thrift.protocol.TType.STRUCT) {
+            this.packet = new Packet();
+            this.packet.read(iprot);
+          } else { 
+            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
+          }
+          break;
+        default:
+          org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
+      }
+      iprot.readFieldEnd();
+    }
+    iprot.readStructEnd();
+
+    // check for required fields of primitive type, which can't be checked in the validate method
+    validate();
+  }
+
+  public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+    validate();
+
+    oprot.writeStructBegin(STRUCT_DESC);
+    if (this.sessionIDs != null) {
+      oprot.writeFieldBegin(SESSION_IDS_FIELD_DESC);
+      {
+        oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, this.sessionIDs.size()));
+        for (String _iter3 : this.sessionIDs)
+        {
+          oprot.writeString(_iter3);
+        }
+        oprot.writeListEnd();
+      }
+      oprot.writeFieldEnd();
+    }
+    if (this.packet != null) {
+      oprot.writeFieldBegin(PACKET_FIELD_DESC);
+      this.packet.write(oprot);
+      oprot.writeFieldEnd();
+    }
+    oprot.writeFieldStop();
+    oprot.writeStructEnd();
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder sb = new StringBuilder("Message(");
+    boolean first = true;
+
+    sb.append("sessionIDs:");
+    if (this.sessionIDs == null) {
+      sb.append("null");
+    } else {
+      sb.append(this.sessionIDs);
+    }
+    first = false;
+    if (!first) sb.append(", ");
+    sb.append("packet:");
+    if (this.packet == null) {
+      sb.append("null");
+    } else {
+      sb.append(this.packet);
+    }
+    first = false;
+    sb.append(")");
+    return sb.toString();
+  }
+
+  public void validate() throws org.apache.thrift.TException {
+    // check for required fields
+  }
+
+  private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+    try {
+      write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+    } catch (org.apache.thrift.TException te) {
+      throw new java.io.IOException(te);
+    }
+  }
+
+  private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+    try {
+      read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+    } catch (org.apache.thrift.TException te) {
+      throw new java.io.IOException(te);
+    }
+  }
+
+}
+
diff --git a/lib/gen-java/net/floodlightcontroller/packetstreamer/thrift/OFMessageType.java b/lib/gen-java/net/floodlightcontroller/packetstreamer/thrift/OFMessageType.java
new file mode 100644
index 0000000000000000000000000000000000000000..5c911ca450cd600b9981f292a85f6c4a2e72763f
--- /dev/null
+++ b/lib/gen-java/net/floodlightcontroller/packetstreamer/thrift/OFMessageType.java
@@ -0,0 +1,102 @@
+/**
+ * Autogenerated by Thrift Compiler (0.7.0)
+ *
+ * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+ */
+package net.floodlightcontroller.packetstreamer.thrift;
+
+
+import java.util.Map;
+import java.util.HashMap;
+import org.apache.thrift.TEnum;
+
+/**
+ * OFMessage type
+ * 
+ */
+public enum OFMessageType implements org.apache.thrift.TEnum {
+  HELLO(0),
+  ERROR(1),
+  ECHO_REQUEST(2),
+  ECHO_REPLY(3),
+  VENDOR(4),
+  FEATURES_REQUEST(5),
+  FEATURES_REPLY(6),
+  GET_CONFIG_REQUEST(7),
+  GET_CONFIG_REPLY(8),
+  SET_CONFIG(9),
+  PACKET_IN(10),
+  FLOW_REMOVED(11),
+  PORT_STATUS(12),
+  PACKET_OUT(13),
+  FLOW_MOD(14),
+  PORT_MOD(15),
+  STATS_REQUEST(16),
+  STATS_REPLY(17),
+  BARRIER_REQUEST(18),
+  BARRIER_REPLY(19);
+
+  private final int value;
+
+  private OFMessageType(int value) {
+    this.value = value;
+  }
+
+  /**
+   * Get the integer value of this enum value, as defined in the Thrift IDL.
+   */
+  public int getValue() {
+    return value;
+  }
+
+  /**
+   * Find a the enum type by its integer value, as defined in the Thrift IDL.
+   * @return null if the value is not found.
+   */
+  public static OFMessageType findByValue(int value) { 
+    switch (value) {
+      case 0:
+        return HELLO;
+      case 1:
+        return ERROR;
+      case 2:
+        return ECHO_REQUEST;
+      case 3:
+        return ECHO_REPLY;
+      case 4:
+        return VENDOR;
+      case 5:
+        return FEATURES_REQUEST;
+      case 6:
+        return FEATURES_REPLY;
+      case 7:
+        return GET_CONFIG_REQUEST;
+      case 8:
+        return GET_CONFIG_REPLY;
+      case 9:
+        return SET_CONFIG;
+      case 10:
+        return PACKET_IN;
+      case 11:
+        return FLOW_REMOVED;
+      case 12:
+        return PORT_STATUS;
+      case 13:
+        return PACKET_OUT;
+      case 14:
+        return FLOW_MOD;
+      case 15:
+        return PORT_MOD;
+      case 16:
+        return STATS_REQUEST;
+      case 17:
+        return STATS_REPLY;
+      case 18:
+        return BARRIER_REQUEST;
+      case 19:
+        return BARRIER_REPLY;
+      default:
+        return null;
+    }
+  }
+}
diff --git a/lib/gen-java/net/floodlightcontroller/packetstreamer/thrift/Packet.java b/lib/gen-java/net/floodlightcontroller/packetstreamer/thrift/Packet.java
new file mode 100644
index 0000000000000000000000000000000000000000..7f4a0fab26d93603c5640304c46e91b5685e82da
--- /dev/null
+++ b/lib/gen-java/net/floodlightcontroller/packetstreamer/thrift/Packet.java
@@ -0,0 +1,525 @@
+/**
+ * Autogenerated by Thrift Compiler (0.7.0)
+ *
+ * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+ */
+package net.floodlightcontroller.packetstreamer.thrift;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.EnumMap;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.EnumSet;
+import java.util.Collections;
+import java.util.BitSet;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Packet implements org.apache.thrift.TBase<Packet, Packet._Fields>, java.io.Serializable, Cloneable {
+  private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("Packet");
+
+  private static final org.apache.thrift.protocol.TField MESSAGE_TYPE_FIELD_DESC = new org.apache.thrift.protocol.TField("messageType", org.apache.thrift.protocol.TType.I32, (short)1);
+  private static final org.apache.thrift.protocol.TField SW_PORT_TUPLE_FIELD_DESC = new org.apache.thrift.protocol.TField("swPortTuple", org.apache.thrift.protocol.TType.STRUCT, (short)2);
+  private static final org.apache.thrift.protocol.TField DATA_FIELD_DESC = new org.apache.thrift.protocol.TField("data", org.apache.thrift.protocol.TType.STRING, (short)3);
+
+  /**
+   * 
+   * @see OFMessageType
+   */
+  public OFMessageType messageType; // required
+  public SwitchPortTuple swPortTuple; // required
+  public ByteBuffer data; // required
+
+  /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+  public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+    /**
+     * 
+     * @see OFMessageType
+     */
+    MESSAGE_TYPE((short)1, "messageType"),
+    SW_PORT_TUPLE((short)2, "swPortTuple"),
+    DATA((short)3, "data");
+
+    private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+    static {
+      for (_Fields field : EnumSet.allOf(_Fields.class)) {
+        byName.put(field.getFieldName(), field);
+      }
+    }
+
+    /**
+     * Find the _Fields constant that matches fieldId, or null if its not found.
+     */
+    public static _Fields findByThriftId(int fieldId) {
+      switch(fieldId) {
+        case 1: // MESSAGE_TYPE
+          return MESSAGE_TYPE;
+        case 2: // SW_PORT_TUPLE
+          return SW_PORT_TUPLE;
+        case 3: // DATA
+          return DATA;
+        default:
+          return null;
+      }
+    }
+
+    /**
+     * Find the _Fields constant that matches fieldId, throwing an exception
+     * if it is not found.
+     */
+    public static _Fields findByThriftIdOrThrow(int fieldId) {
+      _Fields fields = findByThriftId(fieldId);
+      if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+      return fields;
+    }
+
+    /**
+     * Find the _Fields constant that matches name, or null if its not found.
+     */
+    public static _Fields findByName(String name) {
+      return byName.get(name);
+    }
+
+    private final short _thriftId;
+    private final String _fieldName;
+
+    _Fields(short thriftId, String fieldName) {
+      _thriftId = thriftId;
+      _fieldName = fieldName;
+    }
+
+    public short getThriftFieldId() {
+      return _thriftId;
+    }
+
+    public String getFieldName() {
+      return _fieldName;
+    }
+  }
+
+  // isset id assignments
+
+  public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+  static {
+    Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+    tmpMap.put(_Fields.MESSAGE_TYPE, new org.apache.thrift.meta_data.FieldMetaData("messageType", org.apache.thrift.TFieldRequirementType.DEFAULT, 
+        new org.apache.thrift.meta_data.EnumMetaData(org.apache.thrift.protocol.TType.ENUM, OFMessageType.class)));
+    tmpMap.put(_Fields.SW_PORT_TUPLE, new org.apache.thrift.meta_data.FieldMetaData("swPortTuple", org.apache.thrift.TFieldRequirementType.DEFAULT, 
+        new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, SwitchPortTuple.class)));
+    tmpMap.put(_Fields.DATA, new org.apache.thrift.meta_data.FieldMetaData("data", org.apache.thrift.TFieldRequirementType.DEFAULT, 
+        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING        , true)));
+    metaDataMap = Collections.unmodifiableMap(tmpMap);
+    org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(Packet.class, metaDataMap);
+  }
+
+  public Packet() {
+  }
+
+  public Packet(
+    OFMessageType messageType,
+    SwitchPortTuple swPortTuple,
+    ByteBuffer data)
+  {
+    this();
+    this.messageType = messageType;
+    this.swPortTuple = swPortTuple;
+    this.data = data;
+  }
+
+  /**
+   * Performs a deep copy on <i>other</i>.
+   */
+  public Packet(Packet other) {
+    if (other.isSetMessageType()) {
+      this.messageType = other.messageType;
+    }
+    if (other.isSetSwPortTuple()) {
+      this.swPortTuple = new SwitchPortTuple(other.swPortTuple);
+    }
+    if (other.isSetData()) {
+      this.data = org.apache.thrift.TBaseHelper.copyBinary(other.data);
+;
+    }
+  }
+
+  public Packet deepCopy() {
+    return new Packet(this);
+  }
+
+  @Override
+  public void clear() {
+    this.messageType = null;
+    this.swPortTuple = null;
+    this.data = null;
+  }
+
+  /**
+   * 
+   * @see OFMessageType
+   */
+  public OFMessageType getMessageType() {
+    return this.messageType;
+  }
+
+  /**
+   * 
+   * @see OFMessageType
+   */
+  public Packet setMessageType(OFMessageType messageType) {
+    this.messageType = messageType;
+    return this;
+  }
+
+  public void unsetMessageType() {
+    this.messageType = null;
+  }
+
+  /** Returns true if field messageType is set (has been assigned a value) and false otherwise */
+  public boolean isSetMessageType() {
+    return this.messageType != null;
+  }
+
+  public void setMessageTypeIsSet(boolean value) {
+    if (!value) {
+      this.messageType = null;
+    }
+  }
+
+  public SwitchPortTuple getSwPortTuple() {
+    return this.swPortTuple;
+  }
+
+  public Packet setSwPortTuple(SwitchPortTuple swPortTuple) {
+    this.swPortTuple = swPortTuple;
+    return this;
+  }
+
+  public void unsetSwPortTuple() {
+    this.swPortTuple = null;
+  }
+
+  /** Returns true if field swPortTuple is set (has been assigned a value) and false otherwise */
+  public boolean isSetSwPortTuple() {
+    return this.swPortTuple != null;
+  }
+
+  public void setSwPortTupleIsSet(boolean value) {
+    if (!value) {
+      this.swPortTuple = null;
+    }
+  }
+
+  public byte[] getData() {
+    setData(org.apache.thrift.TBaseHelper.rightSize(data));
+    return data == null ? null : data.array();
+  }
+
+  public ByteBuffer bufferForData() {
+    return data;
+  }
+
+  public Packet setData(byte[] data) {
+    setData(data == null ? (ByteBuffer)null : ByteBuffer.wrap(data));
+    return this;
+  }
+
+  public Packet setData(ByteBuffer data) {
+    this.data = data;
+    return this;
+  }
+
+  public void unsetData() {
+    this.data = null;
+  }
+
+  /** Returns true if field data is set (has been assigned a value) and false otherwise */
+  public boolean isSetData() {
+    return this.data != null;
+  }
+
+  public void setDataIsSet(boolean value) {
+    if (!value) {
+      this.data = null;
+    }
+  }
+
+  public void setFieldValue(_Fields field, Object value) {
+    switch (field) {
+    case MESSAGE_TYPE:
+      if (value == null) {
+        unsetMessageType();
+      } else {
+        setMessageType((OFMessageType)value);
+      }
+      break;
+
+    case SW_PORT_TUPLE:
+      if (value == null) {
+        unsetSwPortTuple();
+      } else {
+        setSwPortTuple((SwitchPortTuple)value);
+      }
+      break;
+
+    case DATA:
+      if (value == null) {
+        unsetData();
+      } else {
+        setData((ByteBuffer)value);
+      }
+      break;
+
+    }
+  }
+
+  public Object getFieldValue(_Fields field) {
+    switch (field) {
+    case MESSAGE_TYPE:
+      return getMessageType();
+
+    case SW_PORT_TUPLE:
+      return getSwPortTuple();
+
+    case DATA:
+      return getData();
+
+    }
+    throw new IllegalStateException();
+  }
+
+  /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+  public boolean isSet(_Fields field) {
+    if (field == null) {
+      throw new IllegalArgumentException();
+    }
+
+    switch (field) {
+    case MESSAGE_TYPE:
+      return isSetMessageType();
+    case SW_PORT_TUPLE:
+      return isSetSwPortTuple();
+    case DATA:
+      return isSetData();
+    }
+    throw new IllegalStateException();
+  }
+
+  @Override
+  public boolean equals(Object that) {
+    if (that == null)
+      return false;
+    if (that instanceof Packet)
+      return this.equals((Packet)that);
+    return false;
+  }
+
+  public boolean equals(Packet that) {
+    if (that == null)
+      return false;
+
+    boolean this_present_messageType = true && this.isSetMessageType();
+    boolean that_present_messageType = true && that.isSetMessageType();
+    if (this_present_messageType || that_present_messageType) {
+      if (!(this_present_messageType && that_present_messageType))
+        return false;
+      if (!this.messageType.equals(that.messageType))
+        return false;
+    }
+
+    boolean this_present_swPortTuple = true && this.isSetSwPortTuple();
+    boolean that_present_swPortTuple = true && that.isSetSwPortTuple();
+    if (this_present_swPortTuple || that_present_swPortTuple) {
+      if (!(this_present_swPortTuple && that_present_swPortTuple))
+        return false;
+      if (!this.swPortTuple.equals(that.swPortTuple))
+        return false;
+    }
+
+    boolean this_present_data = true && this.isSetData();
+    boolean that_present_data = true && that.isSetData();
+    if (this_present_data || that_present_data) {
+      if (!(this_present_data && that_present_data))
+        return false;
+      if (!this.data.equals(that.data))
+        return false;
+    }
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    return 0;
+  }
+
+  public int compareTo(Packet other) {
+    if (!getClass().equals(other.getClass())) {
+      return getClass().getName().compareTo(other.getClass().getName());
+    }
+
+    int lastComparison = 0;
+    Packet typedOther = (Packet)other;
+
+    lastComparison = Boolean.valueOf(isSetMessageType()).compareTo(typedOther.isSetMessageType());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetMessageType()) {
+      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.messageType, typedOther.messageType);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
+    lastComparison = Boolean.valueOf(isSetSwPortTuple()).compareTo(typedOther.isSetSwPortTuple());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetSwPortTuple()) {
+      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.swPortTuple, typedOther.swPortTuple);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
+    lastComparison = Boolean.valueOf(isSetData()).compareTo(typedOther.isSetData());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetData()) {
+      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.data, typedOther.data);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
+    return 0;
+  }
+
+  public _Fields fieldForId(int fieldId) {
+    return _Fields.findByThriftId(fieldId);
+  }
+
+  public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+    org.apache.thrift.protocol.TField field;
+    iprot.readStructBegin();
+    while (true)
+    {
+      field = iprot.readFieldBegin();
+      if (field.type == org.apache.thrift.protocol.TType.STOP) { 
+        break;
+      }
+      switch (field.id) {
+        case 1: // MESSAGE_TYPE
+          if (field.type == org.apache.thrift.protocol.TType.I32) {
+            this.messageType = OFMessageType.findByValue(iprot.readI32());
+          } else { 
+            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
+          }
+          break;
+        case 2: // SW_PORT_TUPLE
+          if (field.type == org.apache.thrift.protocol.TType.STRUCT) {
+            this.swPortTuple = new SwitchPortTuple();
+            this.swPortTuple.read(iprot);
+          } else { 
+            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
+          }
+          break;
+        case 3: // DATA
+          if (field.type == org.apache.thrift.protocol.TType.STRING) {
+            this.data = iprot.readBinary();
+          } else { 
+            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
+          }
+          break;
+        default:
+          org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
+      }
+      iprot.readFieldEnd();
+    }
+    iprot.readStructEnd();
+
+    // check for required fields of primitive type, which can't be checked in the validate method
+    validate();
+  }
+
+  public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+    validate();
+
+    oprot.writeStructBegin(STRUCT_DESC);
+    if (this.messageType != null) {
+      oprot.writeFieldBegin(MESSAGE_TYPE_FIELD_DESC);
+      oprot.writeI32(this.messageType.getValue());
+      oprot.writeFieldEnd();
+    }
+    if (this.swPortTuple != null) {
+      oprot.writeFieldBegin(SW_PORT_TUPLE_FIELD_DESC);
+      this.swPortTuple.write(oprot);
+      oprot.writeFieldEnd();
+    }
+    if (this.data != null) {
+      oprot.writeFieldBegin(DATA_FIELD_DESC);
+      oprot.writeBinary(this.data);
+      oprot.writeFieldEnd();
+    }
+    oprot.writeFieldStop();
+    oprot.writeStructEnd();
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder sb = new StringBuilder("Packet(");
+    boolean first = true;
+
+    sb.append("messageType:");
+    if (this.messageType == null) {
+      sb.append("null");
+    } else {
+      sb.append(this.messageType);
+    }
+    first = false;
+    if (!first) sb.append(", ");
+    sb.append("swPortTuple:");
+    if (this.swPortTuple == null) {
+      sb.append("null");
+    } else {
+      sb.append(this.swPortTuple);
+    }
+    first = false;
+    if (!first) sb.append(", ");
+    sb.append("data:");
+    if (this.data == null) {
+      sb.append("null");
+    } else {
+      org.apache.thrift.TBaseHelper.toString(this.data, sb);
+    }
+    first = false;
+    sb.append(")");
+    return sb.toString();
+  }
+
+  public void validate() throws org.apache.thrift.TException {
+    // check for required fields
+  }
+
+  private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+    try {
+      write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+    } catch (org.apache.thrift.TException te) {
+      throw new java.io.IOException(te);
+    }
+  }
+
+  private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+    try {
+      read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+    } catch (org.apache.thrift.TException te) {
+      throw new java.io.IOException(te);
+    }
+  }
+
+}
+
diff --git a/lib/gen-java/net/floodlightcontroller/packetstreamer/thrift/PacketStreamer.java b/lib/gen-java/net/floodlightcontroller/packetstreamer/thrift/PacketStreamer.java
new file mode 100644
index 0000000000000000000000000000000000000000..da4f8f335e15c393417403cf5da5c298286ade72
--- /dev/null
+++ b/lib/gen-java/net/floodlightcontroller/packetstreamer/thrift/PacketStreamer.java
@@ -0,0 +1,2425 @@
+/**
+ * Autogenerated by Thrift Compiler (0.7.0)
+ *
+ * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+ */
+package net.floodlightcontroller.packetstreamer.thrift;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.EnumMap;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.EnumSet;
+import java.util.Collections;
+import java.util.BitSet;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class PacketStreamer {
+
+  /**
+   * Packetstreamer API
+   */
+  public interface Iface {
+
+    /**
+     * Synchronous method to get packets for a given sessionid
+     * 
+     * @param sessionid
+     */
+    public List<ByteBuffer> getPackets(String sessionid) throws org.apache.thrift.TException;
+
+    /**
+     * Synchronous method to publish a packet.
+     * It ensure the order that the packets are pushed
+     * 
+     * @param packet
+     */
+    public int pushMessageSync(Message packet) throws org.apache.thrift.TException;
+
+    /**
+     * Asynchronous method to publish a packet.
+     * Order is not guaranteed.
+     * 
+     * @param packet
+     */
+    public void pushMessageAsync(Message packet) throws org.apache.thrift.TException;
+
+    /**
+     * Terminate a session
+     * 
+     * @param sessionid
+     */
+    public void terminateSession(String sessionid) throws org.apache.thrift.TException;
+
+  }
+
+  public interface AsyncIface {
+
+    public void getPackets(String sessionid, org.apache.thrift.async.AsyncMethodCallback<AsyncClient.getPackets_call> resultHandler) throws org.apache.thrift.TException;
+
+    public void pushMessageSync(Message packet, org.apache.thrift.async.AsyncMethodCallback<AsyncClient.pushMessageSync_call> resultHandler) throws org.apache.thrift.TException;
+
+    public void pushMessageAsync(Message packet, org.apache.thrift.async.AsyncMethodCallback<AsyncClient.pushMessageAsync_call> resultHandler) throws org.apache.thrift.TException;
+
+    public void terminateSession(String sessionid, org.apache.thrift.async.AsyncMethodCallback<AsyncClient.terminateSession_call> resultHandler) throws org.apache.thrift.TException;
+
+  }
+
+  public static class Client extends org.apache.thrift.TServiceClient implements Iface {
+    public static class Factory implements org.apache.thrift.TServiceClientFactory<Client> {
+      public Factory() {}
+      public Client getClient(org.apache.thrift.protocol.TProtocol prot) {
+        return new Client(prot);
+      }
+      public Client getClient(org.apache.thrift.protocol.TProtocol iprot, org.apache.thrift.protocol.TProtocol oprot) {
+        return new Client(iprot, oprot);
+      }
+    }
+
+    public Client(org.apache.thrift.protocol.TProtocol prot)
+    {
+      super(prot, prot);
+    }
+
+    public Client(org.apache.thrift.protocol.TProtocol iprot, org.apache.thrift.protocol.TProtocol oprot) {
+      super(iprot, oprot);
+    }
+
+    public List<ByteBuffer> getPackets(String sessionid) throws org.apache.thrift.TException
+    {
+      send_getPackets(sessionid);
+      return recv_getPackets();
+    }
+
+    public void send_getPackets(String sessionid) throws org.apache.thrift.TException
+    {
+      getPackets_args args = new getPackets_args();
+      args.setSessionid(sessionid);
+      sendBase("getPackets", args);
+    }
+
+    public List<ByteBuffer> recv_getPackets() throws org.apache.thrift.TException
+    {
+      getPackets_result result = new getPackets_result();
+      receiveBase(result, "getPackets");
+      if (result.isSetSuccess()) {
+        return result.success;
+      }
+      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "getPackets failed: unknown result");
+    }
+
+    public int pushMessageSync(Message packet) throws org.apache.thrift.TException
+    {
+      send_pushMessageSync(packet);
+      return recv_pushMessageSync();
+    }
+
+    public void send_pushMessageSync(Message packet) throws org.apache.thrift.TException
+    {
+      pushMessageSync_args args = new pushMessageSync_args();
+      args.setPacket(packet);
+      sendBase("pushMessageSync", args);
+    }
+
+    public int recv_pushMessageSync() throws org.apache.thrift.TException
+    {
+      pushMessageSync_result result = new pushMessageSync_result();
+      receiveBase(result, "pushMessageSync");
+      if (result.isSetSuccess()) {
+        return result.success;
+      }
+      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "pushMessageSync failed: unknown result");
+    }
+
+    public void pushMessageAsync(Message packet) throws org.apache.thrift.TException
+    {
+      send_pushMessageAsync(packet);
+    }
+
+    public void send_pushMessageAsync(Message packet) throws org.apache.thrift.TException
+    {
+      pushMessageAsync_args args = new pushMessageAsync_args();
+      args.setPacket(packet);
+      sendBase("pushMessageAsync", args);
+    }
+
+    public void terminateSession(String sessionid) throws org.apache.thrift.TException
+    {
+      send_terminateSession(sessionid);
+      recv_terminateSession();
+    }
+
+    public void send_terminateSession(String sessionid) throws org.apache.thrift.TException
+    {
+      terminateSession_args args = new terminateSession_args();
+      args.setSessionid(sessionid);
+      sendBase("terminateSession", args);
+    }
+
+    public void recv_terminateSession() throws org.apache.thrift.TException
+    {
+      terminateSession_result result = new terminateSession_result();
+      receiveBase(result, "terminateSession");
+      return;
+    }
+
+  }
+  public static class AsyncClient extends org.apache.thrift.async.TAsyncClient implements AsyncIface {
+    public static class Factory implements org.apache.thrift.async.TAsyncClientFactory<AsyncClient> {
+      private org.apache.thrift.async.TAsyncClientManager clientManager;
+      private org.apache.thrift.protocol.TProtocolFactory protocolFactory;
+      public Factory(org.apache.thrift.async.TAsyncClientManager clientManager, org.apache.thrift.protocol.TProtocolFactory protocolFactory) {
+        this.clientManager = clientManager;
+        this.protocolFactory = protocolFactory;
+      }
+      public AsyncClient getAsyncClient(org.apache.thrift.transport.TNonblockingTransport transport) {
+        return new AsyncClient(protocolFactory, clientManager, transport);
+      }
+    }
+
+    public AsyncClient(org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.async.TAsyncClientManager clientManager, org.apache.thrift.transport.TNonblockingTransport transport) {
+      super(protocolFactory, clientManager, transport);
+    }
+
+    public void getPackets(String sessionid, org.apache.thrift.async.AsyncMethodCallback<getPackets_call> resultHandler) throws org.apache.thrift.TException {
+      checkReady();
+      getPackets_call method_call = new getPackets_call(sessionid, resultHandler, this, ___protocolFactory, ___transport);
+      this.___currentMethod = method_call;
+      ___manager.call(method_call);
+    }
+
+    public static class getPackets_call extends org.apache.thrift.async.TAsyncMethodCall {
+      private String sessionid;
+      public getPackets_call(String sessionid, org.apache.thrift.async.AsyncMethodCallback<getPackets_call> resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
+        super(client, protocolFactory, transport, resultHandler, false);
+        this.sessionid = sessionid;
+      }
+
+      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
+        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("getPackets", org.apache.thrift.protocol.TMessageType.CALL, 0));
+        getPackets_args args = new getPackets_args();
+        args.setSessionid(sessionid);
+        args.write(prot);
+        prot.writeMessageEnd();
+      }
+
+      public List<ByteBuffer> getResult() throws org.apache.thrift.TException {
+        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
+          throw new IllegalStateException("Method call not finished!");
+        }
+        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
+        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
+        return (new Client(prot)).recv_getPackets();
+      }
+    }
+
+    public void pushMessageSync(Message packet, org.apache.thrift.async.AsyncMethodCallback<pushMessageSync_call> resultHandler) throws org.apache.thrift.TException {
+      checkReady();
+      pushMessageSync_call method_call = new pushMessageSync_call(packet, resultHandler, this, ___protocolFactory, ___transport);
+      this.___currentMethod = method_call;
+      ___manager.call(method_call);
+    }
+
+    public static class pushMessageSync_call extends org.apache.thrift.async.TAsyncMethodCall {
+      private Message packet;
+      public pushMessageSync_call(Message packet, org.apache.thrift.async.AsyncMethodCallback<pushMessageSync_call> resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
+        super(client, protocolFactory, transport, resultHandler, false);
+        this.packet = packet;
+      }
+
+      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
+        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("pushMessageSync", org.apache.thrift.protocol.TMessageType.CALL, 0));
+        pushMessageSync_args args = new pushMessageSync_args();
+        args.setPacket(packet);
+        args.write(prot);
+        prot.writeMessageEnd();
+      }
+
+      public int getResult() throws org.apache.thrift.TException {
+        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
+          throw new IllegalStateException("Method call not finished!");
+        }
+        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
+        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
+        return (new Client(prot)).recv_pushMessageSync();
+      }
+    }
+
+    public void pushMessageAsync(Message packet, org.apache.thrift.async.AsyncMethodCallback<pushMessageAsync_call> resultHandler) throws org.apache.thrift.TException {
+      checkReady();
+      pushMessageAsync_call method_call = new pushMessageAsync_call(packet, resultHandler, this, ___protocolFactory, ___transport);
+      this.___currentMethod = method_call;
+      ___manager.call(method_call);
+    }
+
+    public static class pushMessageAsync_call extends org.apache.thrift.async.TAsyncMethodCall {
+      private Message packet;
+      public pushMessageAsync_call(Message packet, org.apache.thrift.async.AsyncMethodCallback<pushMessageAsync_call> resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
+        super(client, protocolFactory, transport, resultHandler, true);
+        this.packet = packet;
+      }
+
+      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
+        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("pushMessageAsync", org.apache.thrift.protocol.TMessageType.CALL, 0));
+        pushMessageAsync_args args = new pushMessageAsync_args();
+        args.setPacket(packet);
+        args.write(prot);
+        prot.writeMessageEnd();
+      }
+
+      public void getResult() throws org.apache.thrift.TException {
+        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
+          throw new IllegalStateException("Method call not finished!");
+        }
+        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
+        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
+      }
+    }
+
+    public void terminateSession(String sessionid, org.apache.thrift.async.AsyncMethodCallback<terminateSession_call> resultHandler) throws org.apache.thrift.TException {
+      checkReady();
+      terminateSession_call method_call = new terminateSession_call(sessionid, resultHandler, this, ___protocolFactory, ___transport);
+      this.___currentMethod = method_call;
+      ___manager.call(method_call);
+    }
+
+    public static class terminateSession_call extends org.apache.thrift.async.TAsyncMethodCall {
+      private String sessionid;
+      public terminateSession_call(String sessionid, org.apache.thrift.async.AsyncMethodCallback<terminateSession_call> resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
+        super(client, protocolFactory, transport, resultHandler, false);
+        this.sessionid = sessionid;
+      }
+
+      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
+        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("terminateSession", org.apache.thrift.protocol.TMessageType.CALL, 0));
+        terminateSession_args args = new terminateSession_args();
+        args.setSessionid(sessionid);
+        args.write(prot);
+        prot.writeMessageEnd();
+      }
+
+      public void getResult() throws org.apache.thrift.TException {
+        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
+          throw new IllegalStateException("Method call not finished!");
+        }
+        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
+        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
+        (new Client(prot)).recv_terminateSession();
+      }
+    }
+
+  }
+
+  public static class Processor<I extends Iface> extends org.apache.thrift.TBaseProcessor implements org.apache.thrift.TProcessor {
+    private static final Logger LOGGER = LoggerFactory.getLogger(Processor.class.getName());
+    public Processor(I iface) {
+      super(iface, getProcessMap(new HashMap<String, org.apache.thrift.ProcessFunction<I, ? extends org.apache.thrift.TBase>>()));
+    }
+
+    protected Processor(I iface, Map<String,  org.apache.thrift.ProcessFunction<I, ? extends  org.apache.thrift.TBase>> processMap) {
+      super(iface, getProcessMap(processMap));
+    }
+
+    private static <I extends Iface> Map<String,  org.apache.thrift.ProcessFunction<I, ? extends  org.apache.thrift.TBase>> getProcessMap(Map<String,  org.apache.thrift.ProcessFunction<I, ? extends  org.apache.thrift.TBase>> processMap) {
+      processMap.put("getPackets", new getPackets());
+      processMap.put("pushMessageSync", new pushMessageSync());
+      processMap.put("pushMessageAsync", new pushMessageAsync());
+      processMap.put("terminateSession", new terminateSession());
+      return processMap;
+    }
+
+    private static class getPackets<I extends Iface> extends org.apache.thrift.ProcessFunction<I, getPackets_args> {
+      public getPackets() {
+        super("getPackets");
+      }
+
+      protected getPackets_args getEmptyArgsInstance() {
+        return new getPackets_args();
+      }
+
+      protected getPackets_result getResult(I iface, getPackets_args args) throws org.apache.thrift.TException {
+        getPackets_result result = new getPackets_result();
+        result.success = iface.getPackets(args.sessionid);
+        return result;
+      }
+    }
+
+    private static class pushMessageSync<I extends Iface> extends org.apache.thrift.ProcessFunction<I, pushMessageSync_args> {
+      public pushMessageSync() {
+        super("pushMessageSync");
+      }
+
+      protected pushMessageSync_args getEmptyArgsInstance() {
+        return new pushMessageSync_args();
+      }
+
+      protected pushMessageSync_result getResult(I iface, pushMessageSync_args args) throws org.apache.thrift.TException {
+        pushMessageSync_result result = new pushMessageSync_result();
+        result.success = iface.pushMessageSync(args.packet);
+        result.setSuccessIsSet(true);
+        return result;
+      }
+    }
+
+    private static class pushMessageAsync<I extends Iface> extends org.apache.thrift.ProcessFunction<I, pushMessageAsync_args> {
+      public pushMessageAsync() {
+        super("pushMessageAsync");
+      }
+
+      protected pushMessageAsync_args getEmptyArgsInstance() {
+        return new pushMessageAsync_args();
+      }
+
+      protected org.apache.thrift.TBase getResult(I iface, pushMessageAsync_args args) throws org.apache.thrift.TException {
+        iface.pushMessageAsync(args.packet);
+        return null;
+      }
+    }
+
+    private static class terminateSession<I extends Iface> extends org.apache.thrift.ProcessFunction<I, terminateSession_args> {
+      public terminateSession() {
+        super("terminateSession");
+      }
+
+      protected terminateSession_args getEmptyArgsInstance() {
+        return new terminateSession_args();
+      }
+
+      protected terminateSession_result getResult(I iface, terminateSession_args args) throws org.apache.thrift.TException {
+        terminateSession_result result = new terminateSession_result();
+        iface.terminateSession(args.sessionid);
+        return result;
+      }
+    }
+
+  }
+
+  public static class getPackets_args implements org.apache.thrift.TBase<getPackets_args, getPackets_args._Fields>, java.io.Serializable, Cloneable   {
+    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getPackets_args");
+
+    private static final org.apache.thrift.protocol.TField SESSIONID_FIELD_DESC = new org.apache.thrift.protocol.TField("sessionid", org.apache.thrift.protocol.TType.STRING, (short)1);
+
+    public String sessionid; // required
+
+    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+      SESSIONID((short)1, "sessionid");
+
+      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+      static {
+        for (_Fields field : EnumSet.allOf(_Fields.class)) {
+          byName.put(field.getFieldName(), field);
+        }
+      }
+
+      /**
+       * Find the _Fields constant that matches fieldId, or null if its not found.
+       */
+      public static _Fields findByThriftId(int fieldId) {
+        switch(fieldId) {
+          case 1: // SESSIONID
+            return SESSIONID;
+          default:
+            return null;
+        }
+      }
+
+      /**
+       * Find the _Fields constant that matches fieldId, throwing an exception
+       * if it is not found.
+       */
+      public static _Fields findByThriftIdOrThrow(int fieldId) {
+        _Fields fields = findByThriftId(fieldId);
+        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+        return fields;
+      }
+
+      /**
+       * Find the _Fields constant that matches name, or null if its not found.
+       */
+      public static _Fields findByName(String name) {
+        return byName.get(name);
+      }
+
+      private final short _thriftId;
+      private final String _fieldName;
+
+      _Fields(short thriftId, String fieldName) {
+        _thriftId = thriftId;
+        _fieldName = fieldName;
+      }
+
+      public short getThriftFieldId() {
+        return _thriftId;
+      }
+
+      public String getFieldName() {
+        return _fieldName;
+      }
+    }
+
+    // isset id assignments
+
+    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+    static {
+      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+      tmpMap.put(_Fields.SESSIONID, new org.apache.thrift.meta_data.FieldMetaData("sessionid", org.apache.thrift.TFieldRequirementType.DEFAULT, 
+          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+      metaDataMap = Collections.unmodifiableMap(tmpMap);
+      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getPackets_args.class, metaDataMap);
+    }
+
+    public getPackets_args() {
+    }
+
+    public getPackets_args(
+      String sessionid)
+    {
+      this();
+      this.sessionid = sessionid;
+    }
+
+    /**
+     * Performs a deep copy on <i>other</i>.
+     */
+    public getPackets_args(getPackets_args other) {
+      if (other.isSetSessionid()) {
+        this.sessionid = other.sessionid;
+      }
+    }
+
+    public getPackets_args deepCopy() {
+      return new getPackets_args(this);
+    }
+
+    @Override
+    public void clear() {
+      this.sessionid = null;
+    }
+
+    public String getSessionid() {
+      return this.sessionid;
+    }
+
+    public getPackets_args setSessionid(String sessionid) {
+      this.sessionid = sessionid;
+      return this;
+    }
+
+    public void unsetSessionid() {
+      this.sessionid = null;
+    }
+
+    /** Returns true if field sessionid is set (has been assigned a value) and false otherwise */
+    public boolean isSetSessionid() {
+      return this.sessionid != null;
+    }
+
+    public void setSessionidIsSet(boolean value) {
+      if (!value) {
+        this.sessionid = null;
+      }
+    }
+
+    public void setFieldValue(_Fields field, Object value) {
+      switch (field) {
+      case SESSIONID:
+        if (value == null) {
+          unsetSessionid();
+        } else {
+          setSessionid((String)value);
+        }
+        break;
+
+      }
+    }
+
+    public Object getFieldValue(_Fields field) {
+      switch (field) {
+      case SESSIONID:
+        return getSessionid();
+
+      }
+      throw new IllegalStateException();
+    }
+
+    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+    public boolean isSet(_Fields field) {
+      if (field == null) {
+        throw new IllegalArgumentException();
+      }
+
+      switch (field) {
+      case SESSIONID:
+        return isSetSessionid();
+      }
+      throw new IllegalStateException();
+    }
+
+    @Override
+    public boolean equals(Object that) {
+      if (that == null)
+        return false;
+      if (that instanceof getPackets_args)
+        return this.equals((getPackets_args)that);
+      return false;
+    }
+
+    public boolean equals(getPackets_args that) {
+      if (that == null)
+        return false;
+
+      boolean this_present_sessionid = true && this.isSetSessionid();
+      boolean that_present_sessionid = true && that.isSetSessionid();
+      if (this_present_sessionid || that_present_sessionid) {
+        if (!(this_present_sessionid && that_present_sessionid))
+          return false;
+        if (!this.sessionid.equals(that.sessionid))
+          return false;
+      }
+
+      return true;
+    }
+
+    @Override
+    public int hashCode() {
+      return 0;
+    }
+
+    public int compareTo(getPackets_args other) {
+      if (!getClass().equals(other.getClass())) {
+        return getClass().getName().compareTo(other.getClass().getName());
+      }
+
+      int lastComparison = 0;
+      getPackets_args typedOther = (getPackets_args)other;
+
+      lastComparison = Boolean.valueOf(isSetSessionid()).compareTo(typedOther.isSetSessionid());
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+      if (isSetSessionid()) {
+        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sessionid, typedOther.sessionid);
+        if (lastComparison != 0) {
+          return lastComparison;
+        }
+      }
+      return 0;
+    }
+
+    public _Fields fieldForId(int fieldId) {
+      return _Fields.findByThriftId(fieldId);
+    }
+
+    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+      org.apache.thrift.protocol.TField field;
+      iprot.readStructBegin();
+      while (true)
+      {
+        field = iprot.readFieldBegin();
+        if (field.type == org.apache.thrift.protocol.TType.STOP) { 
+          break;
+        }
+        switch (field.id) {
+          case 1: // SESSIONID
+            if (field.type == org.apache.thrift.protocol.TType.STRING) {
+              this.sessionid = iprot.readString();
+            } else { 
+              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
+            }
+            break;
+          default:
+            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
+        }
+        iprot.readFieldEnd();
+      }
+      iprot.readStructEnd();
+
+      // check for required fields of primitive type, which can't be checked in the validate method
+      validate();
+    }
+
+    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+      validate();
+
+      oprot.writeStructBegin(STRUCT_DESC);
+      if (this.sessionid != null) {
+        oprot.writeFieldBegin(SESSIONID_FIELD_DESC);
+        oprot.writeString(this.sessionid);
+        oprot.writeFieldEnd();
+      }
+      oprot.writeFieldStop();
+      oprot.writeStructEnd();
+    }
+
+    @Override
+    public String toString() {
+      StringBuilder sb = new StringBuilder("getPackets_args(");
+      boolean first = true;
+
+      sb.append("sessionid:");
+      if (this.sessionid == null) {
+        sb.append("null");
+      } else {
+        sb.append(this.sessionid);
+      }
+      first = false;
+      sb.append(")");
+      return sb.toString();
+    }
+
+    public void validate() throws org.apache.thrift.TException {
+      // check for required fields
+    }
+
+    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+      try {
+        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+      } catch (org.apache.thrift.TException te) {
+        throw new java.io.IOException(te);
+      }
+    }
+
+    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+      try {
+        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+      } catch (org.apache.thrift.TException te) {
+        throw new java.io.IOException(te);
+      }
+    }
+
+  }
+
+  public static class getPackets_result implements org.apache.thrift.TBase<getPackets_result, getPackets_result._Fields>, java.io.Serializable, Cloneable   {
+    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getPackets_result");
+
+    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.LIST, (short)0);
+
+    public List<ByteBuffer> success; // required
+
+    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+      SUCCESS((short)0, "success");
+
+      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+      static {
+        for (_Fields field : EnumSet.allOf(_Fields.class)) {
+          byName.put(field.getFieldName(), field);
+        }
+      }
+
+      /**
+       * Find the _Fields constant that matches fieldId, or null if its not found.
+       */
+      public static _Fields findByThriftId(int fieldId) {
+        switch(fieldId) {
+          case 0: // SUCCESS
+            return SUCCESS;
+          default:
+            return null;
+        }
+      }
+
+      /**
+       * Find the _Fields constant that matches fieldId, throwing an exception
+       * if it is not found.
+       */
+      public static _Fields findByThriftIdOrThrow(int fieldId) {
+        _Fields fields = findByThriftId(fieldId);
+        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+        return fields;
+      }
+
+      /**
+       * Find the _Fields constant that matches name, or null if its not found.
+       */
+      public static _Fields findByName(String name) {
+        return byName.get(name);
+      }
+
+      private final short _thriftId;
+      private final String _fieldName;
+
+      _Fields(short thriftId, String fieldName) {
+        _thriftId = thriftId;
+        _fieldName = fieldName;
+      }
+
+      public short getThriftFieldId() {
+        return _thriftId;
+      }
+
+      public String getFieldName() {
+        return _fieldName;
+      }
+    }
+
+    // isset id assignments
+
+    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+    static {
+      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
+          new org.apache.thrift.meta_data.ListMetaData(org.apache.thrift.protocol.TType.LIST, 
+              new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING              , true))));
+      metaDataMap = Collections.unmodifiableMap(tmpMap);
+      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getPackets_result.class, metaDataMap);
+    }
+
+    public getPackets_result() {
+    }
+
+    public getPackets_result(
+      List<ByteBuffer> success)
+    {
+      this();
+      this.success = success;
+    }
+
+    /**
+     * Performs a deep copy on <i>other</i>.
+     */
+    public getPackets_result(getPackets_result other) {
+      if (other.isSetSuccess()) {
+        List<ByteBuffer> __this__success = new ArrayList<ByteBuffer>();
+        for (ByteBuffer other_element : other.success) {
+          ByteBuffer temp_binary_element = org.apache.thrift.TBaseHelper.copyBinary(other_element);
+;
+          __this__success.add(temp_binary_element);
+        }
+        this.success = __this__success;
+      }
+    }
+
+    public getPackets_result deepCopy() {
+      return new getPackets_result(this);
+    }
+
+    @Override
+    public void clear() {
+      this.success = null;
+    }
+
+    public int getSuccessSize() {
+      return (this.success == null) ? 0 : this.success.size();
+    }
+
+    public java.util.Iterator<ByteBuffer> getSuccessIterator() {
+      return (this.success == null) ? null : this.success.iterator();
+    }
+
+    public void addToSuccess(ByteBuffer elem) {
+      if (this.success == null) {
+        this.success = new ArrayList<ByteBuffer>();
+      }
+      this.success.add(elem);
+    }
+
+    public List<ByteBuffer> getSuccess() {
+      return this.success;
+    }
+
+    public getPackets_result setSuccess(List<ByteBuffer> success) {
+      this.success = success;
+      return this;
+    }
+
+    public void unsetSuccess() {
+      this.success = null;
+    }
+
+    /** Returns true if field success is set (has been assigned a value) and false otherwise */
+    public boolean isSetSuccess() {
+      return this.success != null;
+    }
+
+    public void setSuccessIsSet(boolean value) {
+      if (!value) {
+        this.success = null;
+      }
+    }
+
+    public void setFieldValue(_Fields field, Object value) {
+      switch (field) {
+      case SUCCESS:
+        if (value == null) {
+          unsetSuccess();
+        } else {
+          setSuccess((List<ByteBuffer>)value);
+        }
+        break;
+
+      }
+    }
+
+    public Object getFieldValue(_Fields field) {
+      switch (field) {
+      case SUCCESS:
+        return getSuccess();
+
+      }
+      throw new IllegalStateException();
+    }
+
+    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+    public boolean isSet(_Fields field) {
+      if (field == null) {
+        throw new IllegalArgumentException();
+      }
+
+      switch (field) {
+      case SUCCESS:
+        return isSetSuccess();
+      }
+      throw new IllegalStateException();
+    }
+
+    @Override
+    public boolean equals(Object that) {
+      if (that == null)
+        return false;
+      if (that instanceof getPackets_result)
+        return this.equals((getPackets_result)that);
+      return false;
+    }
+
+    public boolean equals(getPackets_result that) {
+      if (that == null)
+        return false;
+
+      boolean this_present_success = true && this.isSetSuccess();
+      boolean that_present_success = true && that.isSetSuccess();
+      if (this_present_success || that_present_success) {
+        if (!(this_present_success && that_present_success))
+          return false;
+        if (!this.success.equals(that.success))
+          return false;
+      }
+
+      return true;
+    }
+
+    @Override
+    public int hashCode() {
+      return 0;
+    }
+
+    public int compareTo(getPackets_result other) {
+      if (!getClass().equals(other.getClass())) {
+        return getClass().getName().compareTo(other.getClass().getName());
+      }
+
+      int lastComparison = 0;
+      getPackets_result typedOther = (getPackets_result)other;
+
+      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(typedOther.isSetSuccess());
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+      if (isSetSuccess()) {
+        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, typedOther.success);
+        if (lastComparison != 0) {
+          return lastComparison;
+        }
+      }
+      return 0;
+    }
+
+    public _Fields fieldForId(int fieldId) {
+      return _Fields.findByThriftId(fieldId);
+    }
+
+    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+      org.apache.thrift.protocol.TField field;
+      iprot.readStructBegin();
+      while (true)
+      {
+        field = iprot.readFieldBegin();
+        if (field.type == org.apache.thrift.protocol.TType.STOP) { 
+          break;
+        }
+        switch (field.id) {
+          case 0: // SUCCESS
+            if (field.type == org.apache.thrift.protocol.TType.LIST) {
+              {
+                org.apache.thrift.protocol.TList _list4 = iprot.readListBegin();
+                this.success = new ArrayList<ByteBuffer>(_list4.size);
+                for (int _i5 = 0; _i5 < _list4.size; ++_i5)
+                {
+                  ByteBuffer _elem6; // required
+                  _elem6 = iprot.readBinary();
+                  this.success.add(_elem6);
+                }
+                iprot.readListEnd();
+              }
+            } else { 
+              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
+            }
+            break;
+          default:
+            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
+        }
+        iprot.readFieldEnd();
+      }
+      iprot.readStructEnd();
+
+      // check for required fields of primitive type, which can't be checked in the validate method
+      validate();
+    }
+
+    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+      oprot.writeStructBegin(STRUCT_DESC);
+
+      if (this.isSetSuccess()) {
+        oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
+        {
+          oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, this.success.size()));
+          for (ByteBuffer _iter7 : this.success)
+          {
+            oprot.writeBinary(_iter7);
+          }
+          oprot.writeListEnd();
+        }
+        oprot.writeFieldEnd();
+      }
+      oprot.writeFieldStop();
+      oprot.writeStructEnd();
+    }
+
+    @Override
+    public String toString() {
+      StringBuilder sb = new StringBuilder("getPackets_result(");
+      boolean first = true;
+
+      sb.append("success:");
+      if (this.success == null) {
+        sb.append("null");
+      } else {
+        sb.append(this.success);
+      }
+      first = false;
+      sb.append(")");
+      return sb.toString();
+    }
+
+    public void validate() throws org.apache.thrift.TException {
+      // check for required fields
+    }
+
+    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+      try {
+        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+      } catch (org.apache.thrift.TException te) {
+        throw new java.io.IOException(te);
+      }
+    }
+
+    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+      try {
+        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+      } catch (org.apache.thrift.TException te) {
+        throw new java.io.IOException(te);
+      }
+    }
+
+  }
+
+  public static class pushMessageSync_args implements org.apache.thrift.TBase<pushMessageSync_args, pushMessageSync_args._Fields>, java.io.Serializable, Cloneable   {
+    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("pushMessageSync_args");
+
+    private static final org.apache.thrift.protocol.TField PACKET_FIELD_DESC = new org.apache.thrift.protocol.TField("packet", org.apache.thrift.protocol.TType.STRUCT, (short)1);
+
+    public Message packet; // required
+
+    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+      PACKET((short)1, "packet");
+
+      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+      static {
+        for (_Fields field : EnumSet.allOf(_Fields.class)) {
+          byName.put(field.getFieldName(), field);
+        }
+      }
+
+      /**
+       * Find the _Fields constant that matches fieldId, or null if its not found.
+       */
+      public static _Fields findByThriftId(int fieldId) {
+        switch(fieldId) {
+          case 1: // PACKET
+            return PACKET;
+          default:
+            return null;
+        }
+      }
+
+      /**
+       * Find the _Fields constant that matches fieldId, throwing an exception
+       * if it is not found.
+       */
+      public static _Fields findByThriftIdOrThrow(int fieldId) {
+        _Fields fields = findByThriftId(fieldId);
+        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+        return fields;
+      }
+
+      /**
+       * Find the _Fields constant that matches name, or null if its not found.
+       */
+      public static _Fields findByName(String name) {
+        return byName.get(name);
+      }
+
+      private final short _thriftId;
+      private final String _fieldName;
+
+      _Fields(short thriftId, String fieldName) {
+        _thriftId = thriftId;
+        _fieldName = fieldName;
+      }
+
+      public short getThriftFieldId() {
+        return _thriftId;
+      }
+
+      public String getFieldName() {
+        return _fieldName;
+      }
+    }
+
+    // isset id assignments
+
+    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+    static {
+      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+      tmpMap.put(_Fields.PACKET, new org.apache.thrift.meta_data.FieldMetaData("packet", org.apache.thrift.TFieldRequirementType.DEFAULT, 
+          new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, Message.class)));
+      metaDataMap = Collections.unmodifiableMap(tmpMap);
+      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(pushMessageSync_args.class, metaDataMap);
+    }
+
+    public pushMessageSync_args() {
+    }
+
+    public pushMessageSync_args(
+      Message packet)
+    {
+      this();
+      this.packet = packet;
+    }
+
+    /**
+     * Performs a deep copy on <i>other</i>.
+     */
+    public pushMessageSync_args(pushMessageSync_args other) {
+      if (other.isSetPacket()) {
+        this.packet = new Message(other.packet);
+      }
+    }
+
+    public pushMessageSync_args deepCopy() {
+      return new pushMessageSync_args(this);
+    }
+
+    @Override
+    public void clear() {
+      this.packet = null;
+    }
+
+    public Message getPacket() {
+      return this.packet;
+    }
+
+    public pushMessageSync_args setPacket(Message packet) {
+      this.packet = packet;
+      return this;
+    }
+
+    public void unsetPacket() {
+      this.packet = null;
+    }
+
+    /** Returns true if field packet is set (has been assigned a value) and false otherwise */
+    public boolean isSetPacket() {
+      return this.packet != null;
+    }
+
+    public void setPacketIsSet(boolean value) {
+      if (!value) {
+        this.packet = null;
+      }
+    }
+
+    public void setFieldValue(_Fields field, Object value) {
+      switch (field) {
+      case PACKET:
+        if (value == null) {
+          unsetPacket();
+        } else {
+          setPacket((Message)value);
+        }
+        break;
+
+      }
+    }
+
+    public Object getFieldValue(_Fields field) {
+      switch (field) {
+      case PACKET:
+        return getPacket();
+
+      }
+      throw new IllegalStateException();
+    }
+
+    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+    public boolean isSet(_Fields field) {
+      if (field == null) {
+        throw new IllegalArgumentException();
+      }
+
+      switch (field) {
+      case PACKET:
+        return isSetPacket();
+      }
+      throw new IllegalStateException();
+    }
+
+    @Override
+    public boolean equals(Object that) {
+      if (that == null)
+        return false;
+      if (that instanceof pushMessageSync_args)
+        return this.equals((pushMessageSync_args)that);
+      return false;
+    }
+
+    public boolean equals(pushMessageSync_args that) {
+      if (that == null)
+        return false;
+
+      boolean this_present_packet = true && this.isSetPacket();
+      boolean that_present_packet = true && that.isSetPacket();
+      if (this_present_packet || that_present_packet) {
+        if (!(this_present_packet && that_present_packet))
+          return false;
+        if (!this.packet.equals(that.packet))
+          return false;
+      }
+
+      return true;
+    }
+
+    @Override
+    public int hashCode() {
+      return 0;
+    }
+
+    public int compareTo(pushMessageSync_args other) {
+      if (!getClass().equals(other.getClass())) {
+        return getClass().getName().compareTo(other.getClass().getName());
+      }
+
+      int lastComparison = 0;
+      pushMessageSync_args typedOther = (pushMessageSync_args)other;
+
+      lastComparison = Boolean.valueOf(isSetPacket()).compareTo(typedOther.isSetPacket());
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+      if (isSetPacket()) {
+        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.packet, typedOther.packet);
+        if (lastComparison != 0) {
+          return lastComparison;
+        }
+      }
+      return 0;
+    }
+
+    public _Fields fieldForId(int fieldId) {
+      return _Fields.findByThriftId(fieldId);
+    }
+
+    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+      org.apache.thrift.protocol.TField field;
+      iprot.readStructBegin();
+      while (true)
+      {
+        field = iprot.readFieldBegin();
+        if (field.type == org.apache.thrift.protocol.TType.STOP) { 
+          break;
+        }
+        switch (field.id) {
+          case 1: // PACKET
+            if (field.type == org.apache.thrift.protocol.TType.STRUCT) {
+              this.packet = new Message();
+              this.packet.read(iprot);
+            } else { 
+              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
+            }
+            break;
+          default:
+            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
+        }
+        iprot.readFieldEnd();
+      }
+      iprot.readStructEnd();
+
+      // check for required fields of primitive type, which can't be checked in the validate method
+      validate();
+    }
+
+    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+      validate();
+
+      oprot.writeStructBegin(STRUCT_DESC);
+      if (this.packet != null) {
+        oprot.writeFieldBegin(PACKET_FIELD_DESC);
+        this.packet.write(oprot);
+        oprot.writeFieldEnd();
+      }
+      oprot.writeFieldStop();
+      oprot.writeStructEnd();
+    }
+
+    @Override
+    public String toString() {
+      StringBuilder sb = new StringBuilder("pushMessageSync_args(");
+      boolean first = true;
+
+      sb.append("packet:");
+      if (this.packet == null) {
+        sb.append("null");
+      } else {
+        sb.append(this.packet);
+      }
+      first = false;
+      sb.append(")");
+      return sb.toString();
+    }
+
+    public void validate() throws org.apache.thrift.TException {
+      // check for required fields
+    }
+
+    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+      try {
+        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+      } catch (org.apache.thrift.TException te) {
+        throw new java.io.IOException(te);
+      }
+    }
+
+    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+      try {
+        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+      } catch (org.apache.thrift.TException te) {
+        throw new java.io.IOException(te);
+      }
+    }
+
+  }
+
+  public static class pushMessageSync_result implements org.apache.thrift.TBase<pushMessageSync_result, pushMessageSync_result._Fields>, java.io.Serializable, Cloneable   {
+    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("pushMessageSync_result");
+
+    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.I32, (short)0);
+
+    public int success; // required
+
+    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+      SUCCESS((short)0, "success");
+
+      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+      static {
+        for (_Fields field : EnumSet.allOf(_Fields.class)) {
+          byName.put(field.getFieldName(), field);
+        }
+      }
+
+      /**
+       * Find the _Fields constant that matches fieldId, or null if its not found.
+       */
+      public static _Fields findByThriftId(int fieldId) {
+        switch(fieldId) {
+          case 0: // SUCCESS
+            return SUCCESS;
+          default:
+            return null;
+        }
+      }
+
+      /**
+       * Find the _Fields constant that matches fieldId, throwing an exception
+       * if it is not found.
+       */
+      public static _Fields findByThriftIdOrThrow(int fieldId) {
+        _Fields fields = findByThriftId(fieldId);
+        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+        return fields;
+      }
+
+      /**
+       * Find the _Fields constant that matches name, or null if its not found.
+       */
+      public static _Fields findByName(String name) {
+        return byName.get(name);
+      }
+
+      private final short _thriftId;
+      private final String _fieldName;
+
+      _Fields(short thriftId, String fieldName) {
+        _thriftId = thriftId;
+        _fieldName = fieldName;
+      }
+
+      public short getThriftFieldId() {
+        return _thriftId;
+      }
+
+      public String getFieldName() {
+        return _fieldName;
+      }
+    }
+
+    // isset id assignments
+    private static final int __SUCCESS_ISSET_ID = 0;
+    private BitSet __isset_bit_vector = new BitSet(1);
+
+    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+    static {
+      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
+          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
+      metaDataMap = Collections.unmodifiableMap(tmpMap);
+      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(pushMessageSync_result.class, metaDataMap);
+    }
+
+    public pushMessageSync_result() {
+    }
+
+    public pushMessageSync_result(
+      int success)
+    {
+      this();
+      this.success = success;
+      setSuccessIsSet(true);
+    }
+
+    /**
+     * Performs a deep copy on <i>other</i>.
+     */
+    public pushMessageSync_result(pushMessageSync_result other) {
+      __isset_bit_vector.clear();
+      __isset_bit_vector.or(other.__isset_bit_vector);
+      this.success = other.success;
+    }
+
+    public pushMessageSync_result deepCopy() {
+      return new pushMessageSync_result(this);
+    }
+
+    @Override
+    public void clear() {
+      setSuccessIsSet(false);
+      this.success = 0;
+    }
+
+    public int getSuccess() {
+      return this.success;
+    }
+
+    public pushMessageSync_result setSuccess(int success) {
+      this.success = success;
+      setSuccessIsSet(true);
+      return this;
+    }
+
+    public void unsetSuccess() {
+      __isset_bit_vector.clear(__SUCCESS_ISSET_ID);
+    }
+
+    /** Returns true if field success is set (has been assigned a value) and false otherwise */
+    public boolean isSetSuccess() {
+      return __isset_bit_vector.get(__SUCCESS_ISSET_ID);
+    }
+
+    public void setSuccessIsSet(boolean value) {
+      __isset_bit_vector.set(__SUCCESS_ISSET_ID, value);
+    }
+
+    public void setFieldValue(_Fields field, Object value) {
+      switch (field) {
+      case SUCCESS:
+        if (value == null) {
+          unsetSuccess();
+        } else {
+          setSuccess((Integer)value);
+        }
+        break;
+
+      }
+    }
+
+    public Object getFieldValue(_Fields field) {
+      switch (field) {
+      case SUCCESS:
+        return Integer.valueOf(getSuccess());
+
+      }
+      throw new IllegalStateException();
+    }
+
+    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+    public boolean isSet(_Fields field) {
+      if (field == null) {
+        throw new IllegalArgumentException();
+      }
+
+      switch (field) {
+      case SUCCESS:
+        return isSetSuccess();
+      }
+      throw new IllegalStateException();
+    }
+
+    @Override
+    public boolean equals(Object that) {
+      if (that == null)
+        return false;
+      if (that instanceof pushMessageSync_result)
+        return this.equals((pushMessageSync_result)that);
+      return false;
+    }
+
+    public boolean equals(pushMessageSync_result that) {
+      if (that == null)
+        return false;
+
+      boolean this_present_success = true;
+      boolean that_present_success = true;
+      if (this_present_success || that_present_success) {
+        if (!(this_present_success && that_present_success))
+          return false;
+        if (this.success != that.success)
+          return false;
+      }
+
+      return true;
+    }
+
+    @Override
+    public int hashCode() {
+      return 0;
+    }
+
+    public int compareTo(pushMessageSync_result other) {
+      if (!getClass().equals(other.getClass())) {
+        return getClass().getName().compareTo(other.getClass().getName());
+      }
+
+      int lastComparison = 0;
+      pushMessageSync_result typedOther = (pushMessageSync_result)other;
+
+      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(typedOther.isSetSuccess());
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+      if (isSetSuccess()) {
+        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, typedOther.success);
+        if (lastComparison != 0) {
+          return lastComparison;
+        }
+      }
+      return 0;
+    }
+
+    public _Fields fieldForId(int fieldId) {
+      return _Fields.findByThriftId(fieldId);
+    }
+
+    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+      org.apache.thrift.protocol.TField field;
+      iprot.readStructBegin();
+      while (true)
+      {
+        field = iprot.readFieldBegin();
+        if (field.type == org.apache.thrift.protocol.TType.STOP) { 
+          break;
+        }
+        switch (field.id) {
+          case 0: // SUCCESS
+            if (field.type == org.apache.thrift.protocol.TType.I32) {
+              this.success = iprot.readI32();
+              setSuccessIsSet(true);
+            } else { 
+              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
+            }
+            break;
+          default:
+            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
+        }
+        iprot.readFieldEnd();
+      }
+      iprot.readStructEnd();
+
+      // check for required fields of primitive type, which can't be checked in the validate method
+      validate();
+    }
+
+    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+      oprot.writeStructBegin(STRUCT_DESC);
+
+      if (this.isSetSuccess()) {
+        oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
+        oprot.writeI32(this.success);
+        oprot.writeFieldEnd();
+      }
+      oprot.writeFieldStop();
+      oprot.writeStructEnd();
+    }
+
+    @Override
+    public String toString() {
+      StringBuilder sb = new StringBuilder("pushMessageSync_result(");
+      boolean first = true;
+
+      sb.append("success:");
+      sb.append(this.success);
+      first = false;
+      sb.append(")");
+      return sb.toString();
+    }
+
+    public void validate() throws org.apache.thrift.TException {
+      // check for required fields
+    }
+
+    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+      try {
+        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+      } catch (org.apache.thrift.TException te) {
+        throw new java.io.IOException(te);
+      }
+    }
+
+    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+      try {
+        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+      } catch (org.apache.thrift.TException te) {
+        throw new java.io.IOException(te);
+      }
+    }
+
+  }
+
+  public static class pushMessageAsync_args implements org.apache.thrift.TBase<pushMessageAsync_args, pushMessageAsync_args._Fields>, java.io.Serializable, Cloneable   {
+    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("pushMessageAsync_args");
+
+    private static final org.apache.thrift.protocol.TField PACKET_FIELD_DESC = new org.apache.thrift.protocol.TField("packet", org.apache.thrift.protocol.TType.STRUCT, (short)1);
+
+    public Message packet; // required
+
+    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+      PACKET((short)1, "packet");
+
+      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+      static {
+        for (_Fields field : EnumSet.allOf(_Fields.class)) {
+          byName.put(field.getFieldName(), field);
+        }
+      }
+
+      /**
+       * Find the _Fields constant that matches fieldId, or null if its not found.
+       */
+      public static _Fields findByThriftId(int fieldId) {
+        switch(fieldId) {
+          case 1: // PACKET
+            return PACKET;
+          default:
+            return null;
+        }
+      }
+
+      /**
+       * Find the _Fields constant that matches fieldId, throwing an exception
+       * if it is not found.
+       */
+      public static _Fields findByThriftIdOrThrow(int fieldId) {
+        _Fields fields = findByThriftId(fieldId);
+        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+        return fields;
+      }
+
+      /**
+       * Find the _Fields constant that matches name, or null if its not found.
+       */
+      public static _Fields findByName(String name) {
+        return byName.get(name);
+      }
+
+      private final short _thriftId;
+      private final String _fieldName;
+
+      _Fields(short thriftId, String fieldName) {
+        _thriftId = thriftId;
+        _fieldName = fieldName;
+      }
+
+      public short getThriftFieldId() {
+        return _thriftId;
+      }
+
+      public String getFieldName() {
+        return _fieldName;
+      }
+    }
+
+    // isset id assignments
+
+    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+    static {
+      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+      tmpMap.put(_Fields.PACKET, new org.apache.thrift.meta_data.FieldMetaData("packet", org.apache.thrift.TFieldRequirementType.DEFAULT, 
+          new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, Message.class)));
+      metaDataMap = Collections.unmodifiableMap(tmpMap);
+      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(pushMessageAsync_args.class, metaDataMap);
+    }
+
+    public pushMessageAsync_args() {
+    }
+
+    public pushMessageAsync_args(
+      Message packet)
+    {
+      this();
+      this.packet = packet;
+    }
+
+    /**
+     * Performs a deep copy on <i>other</i>.
+     */
+    public pushMessageAsync_args(pushMessageAsync_args other) {
+      if (other.isSetPacket()) {
+        this.packet = new Message(other.packet);
+      }
+    }
+
+    public pushMessageAsync_args deepCopy() {
+      return new pushMessageAsync_args(this);
+    }
+
+    @Override
+    public void clear() {
+      this.packet = null;
+    }
+
+    public Message getPacket() {
+      return this.packet;
+    }
+
+    public pushMessageAsync_args setPacket(Message packet) {
+      this.packet = packet;
+      return this;
+    }
+
+    public void unsetPacket() {
+      this.packet = null;
+    }
+
+    /** Returns true if field packet is set (has been assigned a value) and false otherwise */
+    public boolean isSetPacket() {
+      return this.packet != null;
+    }
+
+    public void setPacketIsSet(boolean value) {
+      if (!value) {
+        this.packet = null;
+      }
+    }
+
+    public void setFieldValue(_Fields field, Object value) {
+      switch (field) {
+      case PACKET:
+        if (value == null) {
+          unsetPacket();
+        } else {
+          setPacket((Message)value);
+        }
+        break;
+
+      }
+    }
+
+    public Object getFieldValue(_Fields field) {
+      switch (field) {
+      case PACKET:
+        return getPacket();
+
+      }
+      throw new IllegalStateException();
+    }
+
+    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+    public boolean isSet(_Fields field) {
+      if (field == null) {
+        throw new IllegalArgumentException();
+      }
+
+      switch (field) {
+      case PACKET:
+        return isSetPacket();
+      }
+      throw new IllegalStateException();
+    }
+
+    @Override
+    public boolean equals(Object that) {
+      if (that == null)
+        return false;
+      if (that instanceof pushMessageAsync_args)
+        return this.equals((pushMessageAsync_args)that);
+      return false;
+    }
+
+    public boolean equals(pushMessageAsync_args that) {
+      if (that == null)
+        return false;
+
+      boolean this_present_packet = true && this.isSetPacket();
+      boolean that_present_packet = true && that.isSetPacket();
+      if (this_present_packet || that_present_packet) {
+        if (!(this_present_packet && that_present_packet))
+          return false;
+        if (!this.packet.equals(that.packet))
+          return false;
+      }
+
+      return true;
+    }
+
+    @Override
+    public int hashCode() {
+      return 0;
+    }
+
+    public int compareTo(pushMessageAsync_args other) {
+      if (!getClass().equals(other.getClass())) {
+        return getClass().getName().compareTo(other.getClass().getName());
+      }
+
+      int lastComparison = 0;
+      pushMessageAsync_args typedOther = (pushMessageAsync_args)other;
+
+      lastComparison = Boolean.valueOf(isSetPacket()).compareTo(typedOther.isSetPacket());
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+      if (isSetPacket()) {
+        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.packet, typedOther.packet);
+        if (lastComparison != 0) {
+          return lastComparison;
+        }
+      }
+      return 0;
+    }
+
+    public _Fields fieldForId(int fieldId) {
+      return _Fields.findByThriftId(fieldId);
+    }
+
+    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+      org.apache.thrift.protocol.TField field;
+      iprot.readStructBegin();
+      while (true)
+      {
+        field = iprot.readFieldBegin();
+        if (field.type == org.apache.thrift.protocol.TType.STOP) { 
+          break;
+        }
+        switch (field.id) {
+          case 1: // PACKET
+            if (field.type == org.apache.thrift.protocol.TType.STRUCT) {
+              this.packet = new Message();
+              this.packet.read(iprot);
+            } else { 
+              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
+            }
+            break;
+          default:
+            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
+        }
+        iprot.readFieldEnd();
+      }
+      iprot.readStructEnd();
+
+      // check for required fields of primitive type, which can't be checked in the validate method
+      validate();
+    }
+
+    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+      validate();
+
+      oprot.writeStructBegin(STRUCT_DESC);
+      if (this.packet != null) {
+        oprot.writeFieldBegin(PACKET_FIELD_DESC);
+        this.packet.write(oprot);
+        oprot.writeFieldEnd();
+      }
+      oprot.writeFieldStop();
+      oprot.writeStructEnd();
+    }
+
+    @Override
+    public String toString() {
+      StringBuilder sb = new StringBuilder("pushMessageAsync_args(");
+      boolean first = true;
+
+      sb.append("packet:");
+      if (this.packet == null) {
+        sb.append("null");
+      } else {
+        sb.append(this.packet);
+      }
+      first = false;
+      sb.append(")");
+      return sb.toString();
+    }
+
+    public void validate() throws org.apache.thrift.TException {
+      // check for required fields
+    }
+
+    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+      try {
+        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+      } catch (org.apache.thrift.TException te) {
+        throw new java.io.IOException(te);
+      }
+    }
+
+    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+      try {
+        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+      } catch (org.apache.thrift.TException te) {
+        throw new java.io.IOException(te);
+      }
+    }
+
+  }
+
+  public static class terminateSession_args implements org.apache.thrift.TBase<terminateSession_args, terminateSession_args._Fields>, java.io.Serializable, Cloneable   {
+    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("terminateSession_args");
+
+    private static final org.apache.thrift.protocol.TField SESSIONID_FIELD_DESC = new org.apache.thrift.protocol.TField("sessionid", org.apache.thrift.protocol.TType.STRING, (short)1);
+
+    public String sessionid; // required
+
+    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+      SESSIONID((short)1, "sessionid");
+
+      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+      static {
+        for (_Fields field : EnumSet.allOf(_Fields.class)) {
+          byName.put(field.getFieldName(), field);
+        }
+      }
+
+      /**
+       * Find the _Fields constant that matches fieldId, or null if its not found.
+       */
+      public static _Fields findByThriftId(int fieldId) {
+        switch(fieldId) {
+          case 1: // SESSIONID
+            return SESSIONID;
+          default:
+            return null;
+        }
+      }
+
+      /**
+       * Find the _Fields constant that matches fieldId, throwing an exception
+       * if it is not found.
+       */
+      public static _Fields findByThriftIdOrThrow(int fieldId) {
+        _Fields fields = findByThriftId(fieldId);
+        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+        return fields;
+      }
+
+      /**
+       * Find the _Fields constant that matches name, or null if its not found.
+       */
+      public static _Fields findByName(String name) {
+        return byName.get(name);
+      }
+
+      private final short _thriftId;
+      private final String _fieldName;
+
+      _Fields(short thriftId, String fieldName) {
+        _thriftId = thriftId;
+        _fieldName = fieldName;
+      }
+
+      public short getThriftFieldId() {
+        return _thriftId;
+      }
+
+      public String getFieldName() {
+        return _fieldName;
+      }
+    }
+
+    // isset id assignments
+
+    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+    static {
+      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+      tmpMap.put(_Fields.SESSIONID, new org.apache.thrift.meta_data.FieldMetaData("sessionid", org.apache.thrift.TFieldRequirementType.DEFAULT, 
+          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+      metaDataMap = Collections.unmodifiableMap(tmpMap);
+      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(terminateSession_args.class, metaDataMap);
+    }
+
+    public terminateSession_args() {
+    }
+
+    public terminateSession_args(
+      String sessionid)
+    {
+      this();
+      this.sessionid = sessionid;
+    }
+
+    /**
+     * Performs a deep copy on <i>other</i>.
+     */
+    public terminateSession_args(terminateSession_args other) {
+      if (other.isSetSessionid()) {
+        this.sessionid = other.sessionid;
+      }
+    }
+
+    public terminateSession_args deepCopy() {
+      return new terminateSession_args(this);
+    }
+
+    @Override
+    public void clear() {
+      this.sessionid = null;
+    }
+
+    public String getSessionid() {
+      return this.sessionid;
+    }
+
+    public terminateSession_args setSessionid(String sessionid) {
+      this.sessionid = sessionid;
+      return this;
+    }
+
+    public void unsetSessionid() {
+      this.sessionid = null;
+    }
+
+    /** Returns true if field sessionid is set (has been assigned a value) and false otherwise */
+    public boolean isSetSessionid() {
+      return this.sessionid != null;
+    }
+
+    public void setSessionidIsSet(boolean value) {
+      if (!value) {
+        this.sessionid = null;
+      }
+    }
+
+    public void setFieldValue(_Fields field, Object value) {
+      switch (field) {
+      case SESSIONID:
+        if (value == null) {
+          unsetSessionid();
+        } else {
+          setSessionid((String)value);
+        }
+        break;
+
+      }
+    }
+
+    public Object getFieldValue(_Fields field) {
+      switch (field) {
+      case SESSIONID:
+        return getSessionid();
+
+      }
+      throw new IllegalStateException();
+    }
+
+    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+    public boolean isSet(_Fields field) {
+      if (field == null) {
+        throw new IllegalArgumentException();
+      }
+
+      switch (field) {
+      case SESSIONID:
+        return isSetSessionid();
+      }
+      throw new IllegalStateException();
+    }
+
+    @Override
+    public boolean equals(Object that) {
+      if (that == null)
+        return false;
+      if (that instanceof terminateSession_args)
+        return this.equals((terminateSession_args)that);
+      return false;
+    }
+
+    public boolean equals(terminateSession_args that) {
+      if (that == null)
+        return false;
+
+      boolean this_present_sessionid = true && this.isSetSessionid();
+      boolean that_present_sessionid = true && that.isSetSessionid();
+      if (this_present_sessionid || that_present_sessionid) {
+        if (!(this_present_sessionid && that_present_sessionid))
+          return false;
+        if (!this.sessionid.equals(that.sessionid))
+          return false;
+      }
+
+      return true;
+    }
+
+    @Override
+    public int hashCode() {
+      return 0;
+    }
+
+    public int compareTo(terminateSession_args other) {
+      if (!getClass().equals(other.getClass())) {
+        return getClass().getName().compareTo(other.getClass().getName());
+      }
+
+      int lastComparison = 0;
+      terminateSession_args typedOther = (terminateSession_args)other;
+
+      lastComparison = Boolean.valueOf(isSetSessionid()).compareTo(typedOther.isSetSessionid());
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+      if (isSetSessionid()) {
+        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sessionid, typedOther.sessionid);
+        if (lastComparison != 0) {
+          return lastComparison;
+        }
+      }
+      return 0;
+    }
+
+    public _Fields fieldForId(int fieldId) {
+      return _Fields.findByThriftId(fieldId);
+    }
+
+    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+      org.apache.thrift.protocol.TField field;
+      iprot.readStructBegin();
+      while (true)
+      {
+        field = iprot.readFieldBegin();
+        if (field.type == org.apache.thrift.protocol.TType.STOP) { 
+          break;
+        }
+        switch (field.id) {
+          case 1: // SESSIONID
+            if (field.type == org.apache.thrift.protocol.TType.STRING) {
+              this.sessionid = iprot.readString();
+            } else { 
+              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
+            }
+            break;
+          default:
+            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
+        }
+        iprot.readFieldEnd();
+      }
+      iprot.readStructEnd();
+
+      // check for required fields of primitive type, which can't be checked in the validate method
+      validate();
+    }
+
+    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+      validate();
+
+      oprot.writeStructBegin(STRUCT_DESC);
+      if (this.sessionid != null) {
+        oprot.writeFieldBegin(SESSIONID_FIELD_DESC);
+        oprot.writeString(this.sessionid);
+        oprot.writeFieldEnd();
+      }
+      oprot.writeFieldStop();
+      oprot.writeStructEnd();
+    }
+
+    @Override
+    public String toString() {
+      StringBuilder sb = new StringBuilder("terminateSession_args(");
+      boolean first = true;
+
+      sb.append("sessionid:");
+      if (this.sessionid == null) {
+        sb.append("null");
+      } else {
+        sb.append(this.sessionid);
+      }
+      first = false;
+      sb.append(")");
+      return sb.toString();
+    }
+
+    public void validate() throws org.apache.thrift.TException {
+      // check for required fields
+    }
+
+    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+      try {
+        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+      } catch (org.apache.thrift.TException te) {
+        throw new java.io.IOException(te);
+      }
+    }
+
+    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+      try {
+        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+      } catch (org.apache.thrift.TException te) {
+        throw new java.io.IOException(te);
+      }
+    }
+
+  }
+
+  public static class terminateSession_result implements org.apache.thrift.TBase<terminateSession_result, terminateSession_result._Fields>, java.io.Serializable, Cloneable   {
+    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("terminateSession_result");
+
+
+
+    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+;
+
+      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+      static {
+        for (_Fields field : EnumSet.allOf(_Fields.class)) {
+          byName.put(field.getFieldName(), field);
+        }
+      }
+
+      /**
+       * Find the _Fields constant that matches fieldId, or null if its not found.
+       */
+      public static _Fields findByThriftId(int fieldId) {
+        switch(fieldId) {
+          default:
+            return null;
+        }
+      }
+
+      /**
+       * Find the _Fields constant that matches fieldId, throwing an exception
+       * if it is not found.
+       */
+      public static _Fields findByThriftIdOrThrow(int fieldId) {
+        _Fields fields = findByThriftId(fieldId);
+        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+        return fields;
+      }
+
+      /**
+       * Find the _Fields constant that matches name, or null if its not found.
+       */
+      public static _Fields findByName(String name) {
+        return byName.get(name);
+      }
+
+      private final short _thriftId;
+      private final String _fieldName;
+
+      _Fields(short thriftId, String fieldName) {
+        _thriftId = thriftId;
+        _fieldName = fieldName;
+      }
+
+      public short getThriftFieldId() {
+        return _thriftId;
+      }
+
+      public String getFieldName() {
+        return _fieldName;
+      }
+    }
+    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+    static {
+      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+      metaDataMap = Collections.unmodifiableMap(tmpMap);
+      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(terminateSession_result.class, metaDataMap);
+    }
+
+    public terminateSession_result() {
+    }
+
+    /**
+     * Performs a deep copy on <i>other</i>.
+     */
+    public terminateSession_result(terminateSession_result other) {
+    }
+
+    public terminateSession_result deepCopy() {
+      return new terminateSession_result(this);
+    }
+
+    @Override
+    public void clear() {
+    }
+
+    public void setFieldValue(_Fields field, Object value) {
+      switch (field) {
+      }
+    }
+
+    public Object getFieldValue(_Fields field) {
+      switch (field) {
+      }
+      throw new IllegalStateException();
+    }
+
+    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+    public boolean isSet(_Fields field) {
+      if (field == null) {
+        throw new IllegalArgumentException();
+      }
+
+      switch (field) {
+      }
+      throw new IllegalStateException();
+    }
+
+    @Override
+    public boolean equals(Object that) {
+      if (that == null)
+        return false;
+      if (that instanceof terminateSession_result)
+        return this.equals((terminateSession_result)that);
+      return false;
+    }
+
+    public boolean equals(terminateSession_result that) {
+      if (that == null)
+        return false;
+
+      return true;
+    }
+
+    @Override
+    public int hashCode() {
+      return 0;
+    }
+
+    public int compareTo(terminateSession_result other) {
+      if (!getClass().equals(other.getClass())) {
+        return getClass().getName().compareTo(other.getClass().getName());
+      }
+
+      int lastComparison = 0;
+      terminateSession_result typedOther = (terminateSession_result)other;
+
+      return 0;
+    }
+
+    public _Fields fieldForId(int fieldId) {
+      return _Fields.findByThriftId(fieldId);
+    }
+
+    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+      org.apache.thrift.protocol.TField field;
+      iprot.readStructBegin();
+      while (true)
+      {
+        field = iprot.readFieldBegin();
+        if (field.type == org.apache.thrift.protocol.TType.STOP) { 
+          break;
+        }
+        switch (field.id) {
+          default:
+            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
+        }
+        iprot.readFieldEnd();
+      }
+      iprot.readStructEnd();
+
+      // check for required fields of primitive type, which can't be checked in the validate method
+      validate();
+    }
+
+    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+      oprot.writeStructBegin(STRUCT_DESC);
+
+      oprot.writeFieldStop();
+      oprot.writeStructEnd();
+    }
+
+    @Override
+    public String toString() {
+      StringBuilder sb = new StringBuilder("terminateSession_result(");
+      boolean first = true;
+
+      sb.append(")");
+      return sb.toString();
+    }
+
+    public void validate() throws org.apache.thrift.TException {
+      // check for required fields
+    }
+
+    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+      try {
+        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+      } catch (org.apache.thrift.TException te) {
+        throw new java.io.IOException(te);
+      }
+    }
+
+    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+      try {
+        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+      } catch (org.apache.thrift.TException te) {
+        throw new java.io.IOException(te);
+      }
+    }
+
+  }
+
+}
diff --git a/lib/gen-java/net/floodlightcontroller/packetstreamer/thrift/SwitchPortTuple.java b/lib/gen-java/net/floodlightcontroller/packetstreamer/thrift/SwitchPortTuple.java
new file mode 100644
index 0000000000000000000000000000000000000000..61d1a2b65a780d70cb32cb1fa7cac5f4fc4ffac5
--- /dev/null
+++ b/lib/gen-java/net/floodlightcontroller/packetstreamer/thrift/SwitchPortTuple.java
@@ -0,0 +1,406 @@
+/**
+ * Autogenerated by Thrift Compiler (0.7.0)
+ *
+ * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+ */
+package net.floodlightcontroller.packetstreamer.thrift;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.EnumMap;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.EnumSet;
+import java.util.Collections;
+import java.util.BitSet;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A struct that defines switch port tuple
+ */
+public class SwitchPortTuple implements org.apache.thrift.TBase<SwitchPortTuple, SwitchPortTuple._Fields>, java.io.Serializable, Cloneable {
+  private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("SwitchPortTuple");
+
+  private static final org.apache.thrift.protocol.TField DPID_FIELD_DESC = new org.apache.thrift.protocol.TField("dpid", org.apache.thrift.protocol.TType.I64, (short)1);
+  private static final org.apache.thrift.protocol.TField PORT_FIELD_DESC = new org.apache.thrift.protocol.TField("port", org.apache.thrift.protocol.TType.I16, (short)2);
+
+  public long dpid; // required
+  public short port; // required
+
+  /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+  public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+    DPID((short)1, "dpid"),
+    PORT((short)2, "port");
+
+    private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+    static {
+      for (_Fields field : EnumSet.allOf(_Fields.class)) {
+        byName.put(field.getFieldName(), field);
+      }
+    }
+
+    /**
+     * Find the _Fields constant that matches fieldId, or null if its not found.
+     */
+    public static _Fields findByThriftId(int fieldId) {
+      switch(fieldId) {
+        case 1: // DPID
+          return DPID;
+        case 2: // PORT
+          return PORT;
+        default:
+          return null;
+      }
+    }
+
+    /**
+     * Find the _Fields constant that matches fieldId, throwing an exception
+     * if it is not found.
+     */
+    public static _Fields findByThriftIdOrThrow(int fieldId) {
+      _Fields fields = findByThriftId(fieldId);
+      if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+      return fields;
+    }
+
+    /**
+     * Find the _Fields constant that matches name, or null if its not found.
+     */
+    public static _Fields findByName(String name) {
+      return byName.get(name);
+    }
+
+    private final short _thriftId;
+    private final String _fieldName;
+
+    _Fields(short thriftId, String fieldName) {
+      _thriftId = thriftId;
+      _fieldName = fieldName;
+    }
+
+    public short getThriftFieldId() {
+      return _thriftId;
+    }
+
+    public String getFieldName() {
+      return _fieldName;
+    }
+  }
+
+  // isset id assignments
+  private static final int __DPID_ISSET_ID = 0;
+  private static final int __PORT_ISSET_ID = 1;
+  private BitSet __isset_bit_vector = new BitSet(2);
+
+  public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+  static {
+    Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+    tmpMap.put(_Fields.DPID, new org.apache.thrift.meta_data.FieldMetaData("dpid", org.apache.thrift.TFieldRequirementType.DEFAULT, 
+        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I64)));
+    tmpMap.put(_Fields.PORT, new org.apache.thrift.meta_data.FieldMetaData("port", org.apache.thrift.TFieldRequirementType.DEFAULT, 
+        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I16)));
+    metaDataMap = Collections.unmodifiableMap(tmpMap);
+    org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(SwitchPortTuple.class, metaDataMap);
+  }
+
+  public SwitchPortTuple() {
+  }
+
+  public SwitchPortTuple(
+    long dpid,
+    short port)
+  {
+    this();
+    this.dpid = dpid;
+    setDpidIsSet(true);
+    this.port = port;
+    setPortIsSet(true);
+  }
+
+  /**
+   * Performs a deep copy on <i>other</i>.
+   */
+  public SwitchPortTuple(SwitchPortTuple other) {
+    __isset_bit_vector.clear();
+    __isset_bit_vector.or(other.__isset_bit_vector);
+    this.dpid = other.dpid;
+    this.port = other.port;
+  }
+
+  public SwitchPortTuple deepCopy() {
+    return new SwitchPortTuple(this);
+  }
+
+  @Override
+  public void clear() {
+    setDpidIsSet(false);
+    this.dpid = 0;
+    setPortIsSet(false);
+    this.port = 0;
+  }
+
+  public long getDpid() {
+    return this.dpid;
+  }
+
+  public SwitchPortTuple setDpid(long dpid) {
+    this.dpid = dpid;
+    setDpidIsSet(true);
+    return this;
+  }
+
+  public void unsetDpid() {
+    __isset_bit_vector.clear(__DPID_ISSET_ID);
+  }
+
+  /** Returns true if field dpid is set (has been assigned a value) and false otherwise */
+  public boolean isSetDpid() {
+    return __isset_bit_vector.get(__DPID_ISSET_ID);
+  }
+
+  public void setDpidIsSet(boolean value) {
+    __isset_bit_vector.set(__DPID_ISSET_ID, value);
+  }
+
+  public short getPort() {
+    return this.port;
+  }
+
+  public SwitchPortTuple setPort(short port) {
+    this.port = port;
+    setPortIsSet(true);
+    return this;
+  }
+
+  public void unsetPort() {
+    __isset_bit_vector.clear(__PORT_ISSET_ID);
+  }
+
+  /** Returns true if field port is set (has been assigned a value) and false otherwise */
+  public boolean isSetPort() {
+    return __isset_bit_vector.get(__PORT_ISSET_ID);
+  }
+
+  public void setPortIsSet(boolean value) {
+    __isset_bit_vector.set(__PORT_ISSET_ID, value);
+  }
+
+  public void setFieldValue(_Fields field, Object value) {
+    switch (field) {
+    case DPID:
+      if (value == null) {
+        unsetDpid();
+      } else {
+        setDpid((Long)value);
+      }
+      break;
+
+    case PORT:
+      if (value == null) {
+        unsetPort();
+      } else {
+        setPort((Short)value);
+      }
+      break;
+
+    }
+  }
+
+  public Object getFieldValue(_Fields field) {
+    switch (field) {
+    case DPID:
+      return Long.valueOf(getDpid());
+
+    case PORT:
+      return Short.valueOf(getPort());
+
+    }
+    throw new IllegalStateException();
+  }
+
+  /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+  public boolean isSet(_Fields field) {
+    if (field == null) {
+      throw new IllegalArgumentException();
+    }
+
+    switch (field) {
+    case DPID:
+      return isSetDpid();
+    case PORT:
+      return isSetPort();
+    }
+    throw new IllegalStateException();
+  }
+
+  @Override
+  public boolean equals(Object that) {
+    if (that == null)
+      return false;
+    if (that instanceof SwitchPortTuple)
+      return this.equals((SwitchPortTuple)that);
+    return false;
+  }
+
+  public boolean equals(SwitchPortTuple that) {
+    if (that == null)
+      return false;
+
+    boolean this_present_dpid = true;
+    boolean that_present_dpid = true;
+    if (this_present_dpid || that_present_dpid) {
+      if (!(this_present_dpid && that_present_dpid))
+        return false;
+      if (this.dpid != that.dpid)
+        return false;
+    }
+
+    boolean this_present_port = true;
+    boolean that_present_port = true;
+    if (this_present_port || that_present_port) {
+      if (!(this_present_port && that_present_port))
+        return false;
+      if (this.port != that.port)
+        return false;
+    }
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    return 0;
+  }
+
+  public int compareTo(SwitchPortTuple other) {
+    if (!getClass().equals(other.getClass())) {
+      return getClass().getName().compareTo(other.getClass().getName());
+    }
+
+    int lastComparison = 0;
+    SwitchPortTuple typedOther = (SwitchPortTuple)other;
+
+    lastComparison = Boolean.valueOf(isSetDpid()).compareTo(typedOther.isSetDpid());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetDpid()) {
+      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.dpid, typedOther.dpid);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
+    lastComparison = Boolean.valueOf(isSetPort()).compareTo(typedOther.isSetPort());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetPort()) {
+      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.port, typedOther.port);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
+    return 0;
+  }
+
+  public _Fields fieldForId(int fieldId) {
+    return _Fields.findByThriftId(fieldId);
+  }
+
+  public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+    org.apache.thrift.protocol.TField field;
+    iprot.readStructBegin();
+    while (true)
+    {
+      field = iprot.readFieldBegin();
+      if (field.type == org.apache.thrift.protocol.TType.STOP) { 
+        break;
+      }
+      switch (field.id) {
+        case 1: // DPID
+          if (field.type == org.apache.thrift.protocol.TType.I64) {
+            this.dpid = iprot.readI64();
+            setDpidIsSet(true);
+          } else { 
+            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
+          }
+          break;
+        case 2: // PORT
+          if (field.type == org.apache.thrift.protocol.TType.I16) {
+            this.port = iprot.readI16();
+            setPortIsSet(true);
+          } else { 
+            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
+          }
+          break;
+        default:
+          org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
+      }
+      iprot.readFieldEnd();
+    }
+    iprot.readStructEnd();
+
+    // check for required fields of primitive type, which can't be checked in the validate method
+    validate();
+  }
+
+  public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+    validate();
+
+    oprot.writeStructBegin(STRUCT_DESC);
+    oprot.writeFieldBegin(DPID_FIELD_DESC);
+    oprot.writeI64(this.dpid);
+    oprot.writeFieldEnd();
+    oprot.writeFieldBegin(PORT_FIELD_DESC);
+    oprot.writeI16(this.port);
+    oprot.writeFieldEnd();
+    oprot.writeFieldStop();
+    oprot.writeStructEnd();
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder sb = new StringBuilder("SwitchPortTuple(");
+    boolean first = true;
+
+    sb.append("dpid:");
+    sb.append(this.dpid);
+    first = false;
+    if (!first) sb.append(", ");
+    sb.append("port:");
+    sb.append(this.port);
+    first = false;
+    sb.append(")");
+    return sb.toString();
+  }
+
+  public void validate() throws org.apache.thrift.TException {
+    // check for required fields
+  }
+
+  private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+    try {
+      write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+    } catch (org.apache.thrift.TException te) {
+      throw new java.io.IOException(te);
+    }
+  }
+
+  private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+    try {
+      // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
+      __isset_bit_vector = new BitSet(1);
+      read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+    } catch (org.apache.thrift.TException te) {
+      throw new java.io.IOException(te);
+    }
+  }
+
+}
+
diff --git a/lib/libthrift-0.7.0.jar b/lib/libthrift-0.7.0.jar
new file mode 100644
index 0000000000000000000000000000000000000000..e0b0083bf1cb27ce6ec1aed027d9ff9029e530a5
Binary files /dev/null and b/lib/libthrift-0.7.0.jar differ
diff --git a/setup.sh b/setup.sh
deleted file mode 100755
index 6448a2f32fc23107b2f02ad4da546c016bc254a3..0000000000000000000000000000000000000000
--- a/setup.sh
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/bin/bash
-
-set -ex
-
-DOWNLOADS=${DOWNLOADS:-${HOME}/Downloads}
-mkdir -p ${DOWNLOADS}
-TARGET=target
-PACKAGELIB=${TARGET}/lib
-
-THRIFT_VERSION=0.7.0
-THRIFT_PKG=thrift-${THRIFT_VERSION}.tar.gz
-THRIFT_PKG_HOST=http://apache.osuosl.org/thrift/${THRIFT_VERSION}
-
-if [ ! -d thrift ]; then
-    if [ ! -f ${DOWNLOADS}/${THRIFT_PKG} ]; then
-        if [ -e /usr/bin/curl ]; then
-	    curl ${THRIFT_PKG_HOST}/${THRIFT_PKG} -o ${DOWNLOADS}/${THRIFT_PKG}
-        else
-            wget -nc http://download.nextag.com/apache/thrift/${THRIFT_VERSION}/${THRIFT_PKG}
-            mv ${THRIFT_PKG} ${DOWNLOADS}/.
-        fi
-    fi
-    rm -rf thrift-${THRIFT_VERSION}
-    tar -z -x -f ${DOWNLOADS}/${THRIFT_PKG}
-    mv thrift-${THRIFT_VERSION} thrift
-fi
-
-if [ ! -f ${PACKAGELIB}/libthrift-${THRIFT_VERSION}.jar -o ! -f thrift/compiler/cpp/thrift ]; then
-  (
-      cd thrift
-      chmod +x ./configure 
-      ./configure --with-cpp=no --with-erlang=no --with-perl=no --with-php=no --with-php_extension=no --with-ruby=no --with-haskell=no 
-      ARCHFLAGS="-arch i386 -arch x86_64" make -j4 all 
-      cd lib/java 
-      ant
-  )
-  mkdir -p ${PACKAGELIB}
-  cp thrift/lib/java/build/libthrift-${THRIFT_VERSION}.jar ${PACKAGELIB}
-fi
-
-./thrift/compiler/cpp/thrift --gen py --gen java -o ${TARGET} src/main/thrift/packetstreamer.thrift
-
diff --git a/src/main/java/net/floodlightcontroller/core/web/JacksonCustomConverter.java b/src/main/java/net/floodlightcontroller/core/web/JacksonCustomConverter.java
index 9c45515a04e6ab588ad405b6a44e367f6d34b2d3..e8d76376c4fdfe0491154bf1722a12b1a23352df 100644
--- a/src/main/java/net/floodlightcontroller/core/web/JacksonCustomConverter.java
+++ b/src/main/java/net/floodlightcontroller/core/web/JacksonCustomConverter.java
@@ -19,9 +19,6 @@ package net.floodlightcontroller.core.web;
 
 import java.util.List;
 
-import net.floodlightcontroller.core.web.serializers.DeviceAttachmentPointJSONSerializer;
-import net.floodlightcontroller.core.web.serializers.DeviceJSONSerializer;
-import net.floodlightcontroller.core.web.serializers.DeviceNetworkAddressJSONSerializer;
 import net.floodlightcontroller.core.web.serializers.EventHistoryAttachmentPointJSONSerializer;
 import net.floodlightcontroller.core.web.serializers.EventHistoryBaseInfoJSONSerializer;
 import net.floodlightcontroller.core.web.serializers.EventHistoryTopologyClusterJSONSerializer;
@@ -76,9 +73,6 @@ public class JacksonCustomConverter extends JacksonConverter {
         jsonModule.addSerializer(new EventHistoryTopologySwitchJSONSerializer());
         jsonModule.addSerializer(new EventHistoryTopologyLinkJSONSerializer());
         jsonModule.addSerializer(new EventHistoryTopologyClusterJSONSerializer());
-        jsonModule.addSerializer(new DeviceJSONSerializer());
-        jsonModule.addSerializer(new DeviceNetworkAddressJSONSerializer());
-        jsonModule.addSerializer(new DeviceAttachmentPointJSONSerializer());
         jsonObjectMapper.registerModule(jsonModule);
     }
 
diff --git a/src/main/java/net/floodlightcontroller/core/web/serializers/DeviceAttachmentPointJSONSerializer.java b/src/main/java/net/floodlightcontroller/core/web/serializers/DeviceAttachmentPointJSONSerializer.java
deleted file mode 100644
index 7f9bd630b03eec933c1ba0dcbeac4ad7ae4ebb73..0000000000000000000000000000000000000000
--- a/src/main/java/net/floodlightcontroller/core/web/serializers/DeviceAttachmentPointJSONSerializer.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package net.floodlightcontroller.core.web.serializers;
-
-import java.io.IOException;
-
-import net.floodlightcontroller.devicemanager.DeviceAttachmentPoint;
-
-import org.codehaus.jackson.JsonGenerator;
-import org.codehaus.jackson.JsonProcessingException;
-import org.codehaus.jackson.map.JsonSerializer;
-import org.codehaus.jackson.map.SerializerProvider;
-
-public class DeviceAttachmentPointJSONSerializer extends JsonSerializer<DeviceAttachmentPoint> {
-    @Override
-    public void serialize(DeviceAttachmentPoint dap, JsonGenerator jgen, SerializerProvider sp) 
-            throws IOException, JsonProcessingException {
-        jgen.writeStartObject();
-        jgen.writeStringField("switch", dap.getSwitchPort().getSw().getStringId());
-        jgen.writeNumberField("port", dap.getSwitchPort().getPort());
-        jgen.writeStringField("last-seen", dap.getLastSeen().toString());
-        jgen.writeEndObject();
-    }
-    
-    @Override
-    public Class<DeviceAttachmentPoint> handledType() {
-        return DeviceAttachmentPoint.class;
-    }
-}
diff --git a/src/main/java/net/floodlightcontroller/core/web/serializers/DeviceJSONSerializer.java b/src/main/java/net/floodlightcontroller/core/web/serializers/DeviceJSONSerializer.java
deleted file mode 100644
index c2c0eb53f0883058a634d0355950f1fe2cbb232f..0000000000000000000000000000000000000000
--- a/src/main/java/net/floodlightcontroller/core/web/serializers/DeviceJSONSerializer.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package net.floodlightcontroller.core.web.serializers;
-
-import java.io.IOException;
-
-import net.floodlightcontroller.devicemanager.Device;
-import net.floodlightcontroller.devicemanager.DeviceAttachmentPoint;
-import net.floodlightcontroller.devicemanager.DeviceNetworkAddress;
-
-import org.codehaus.jackson.JsonGenerator;
-import org.codehaus.jackson.JsonProcessingException;
-import org.codehaus.jackson.map.JsonSerializer;
-import org.codehaus.jackson.map.SerializerProvider;
-
-public class DeviceJSONSerializer extends JsonSerializer<Device> {
-
-    @Override
-    public void serialize(Device device, JsonGenerator jgen, SerializerProvider sp)
-            throws IOException, JsonProcessingException {
-        jgen.writeStartObject();
-        jgen.writeStringField("last-seen", device.getLastSeen().toString());
-        if (device.getVlanId() != null)
-            jgen.writeNumberField("vlan", device.getVlanId());
-        else
-            jgen.writeNullField("vlan");
-        jgen.writeArrayFieldStart("network-addresses");
-        for (DeviceNetworkAddress dna : device.getNetworkAddresses()) {
-            sp.defaultSerializeValue(dna, jgen);
-        }
-        jgen.writeEndArray();
-        jgen.writeArrayFieldStart("attachment-points");
-        for (DeviceAttachmentPoint dap : device.getAttachmentPoints()) {
-            sp.defaultSerializeValue(dap, jgen);
-        }
-        jgen.writeEndArray();
-        jgen.writeEndObject();
-    }
-
-    @Override
-    public Class<Device> handledType() {
-        return Device.class;
-    }
-}
diff --git a/src/main/java/net/floodlightcontroller/core/web/serializers/DeviceNetworkAddressJSONSerializer.java b/src/main/java/net/floodlightcontroller/core/web/serializers/DeviceNetworkAddressJSONSerializer.java
deleted file mode 100644
index fb4c0ce9914770fb61e5ba274625cf0ad6c47109..0000000000000000000000000000000000000000
--- a/src/main/java/net/floodlightcontroller/core/web/serializers/DeviceNetworkAddressJSONSerializer.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package net.floodlightcontroller.core.web.serializers;
-
-import java.io.IOException;
-
-import net.floodlightcontroller.devicemanager.DeviceNetworkAddress;
-import net.floodlightcontroller.packet.IPv4;
-
-import org.codehaus.jackson.JsonGenerator;
-import org.codehaus.jackson.JsonProcessingException;
-import org.codehaus.jackson.map.JsonSerializer;
-import org.codehaus.jackson.map.SerializerProvider;
-
-public class DeviceNetworkAddressJSONSerializer extends JsonSerializer<DeviceNetworkAddress> {
-
-    @Override
-    public void serialize(DeviceNetworkAddress dna, JsonGenerator jgen, SerializerProvider sp)
-                                  throws IOException, JsonProcessingException {
-        jgen.writeStartObject();
-        jgen.writeStringField("ip", IPv4.fromIPv4Address(dna.getNetworkAddress()));
-        jgen.writeStringField("last-seen", dna.getLastSeen().toString());
-        jgen.writeEndObject();
-    }
-    
-    @Override
-    public Class<DeviceNetworkAddress> handledType() {
-        return DeviceNetworkAddress.class;
-    }
-}
diff --git a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java
index 8189dd2caadd010ec3f7f00a06ebb90f1ba9c58f..d2099fe5954bd7501fd4b0c814661515ded435fb 100755
--- a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java
+++ b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java
@@ -32,10 +32,7 @@ import java.util.Map;
 import java.util.Set;
 import java.util.Collection;
 import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
 import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeoutException;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
@@ -62,7 +59,6 @@ import net.floodlightcontroller.linkdiscovery.SwitchPortTuple;
 import net.floodlightcontroller.packet.ARP;
 import net.floodlightcontroller.packet.Ethernet;
 import net.floodlightcontroller.packet.IPv4;
-import net.floodlightcontroller.restserver.IRestApiService;
 import net.floodlightcontroller.routing.ForwardingBase;
 import net.floodlightcontroller.storage.IResultSet;
 import net.floodlightcontroller.storage.IStorageSourceListener;
@@ -371,8 +367,8 @@ public class DeviceManagerImpl implements IDeviceManagerService, IOFMessageListe
             // Update the individual devices by updating its attachment points
             for (Device d : switchPortDevices.values()) {
                 // Remove the device from the switch->device mapping
-                delDevAttachmentPoint(d, swPrt);
-                evHistAttachmtPt(d, swPrt, EvAction.REMOVED,
+                delDevAttachmentPoint(d.getDataLayerAddressAsLong(), swPrt);
+                evHistAttachmtPt(d.getDataLayerAddressAsLong(), swPrt, EvAction.REMOVED,
                                                         "SwitchPort removed");
             }
         }
@@ -443,8 +439,8 @@ public class DeviceManagerImpl implements IDeviceManagerService, IOFMessageListe
                 delFromIpv4AddressDeviceMap(nwAddr, d);
                 dCopy.removeNetworkAddress(na);
                 updateMaps(dCopy);
+                removeNetworkAddressFromStorage(d, na);
             }
-            d = null; // to catch if anyone is using this reference
         }
         
         /**
@@ -503,8 +499,9 @@ public class DeviceManagerImpl implements IDeviceManagerService, IOFMessageListe
          * @param d the device
          * @param swPort the {@link SwitchPortTuple} to remove
          */
-        protected void delDevAttachmentPoint(Device d, SwitchPortTuple swPort) {
-            delDevAttachmentPoint(d, swPort.getSw(), swPort.getPort());
+        protected void delDevAttachmentPoint(long dlAddr, SwitchPortTuple swPort) {
+            delDevAttachmentPoint(devMgrMaps.getDeviceByDataLayerAddr(dlAddr), 
+            		swPort.getSw(), swPort.getPort());
         }
 
         /**
@@ -537,11 +534,12 @@ public class DeviceManagerImpl implements IDeviceManagerService, IOFMessageListe
             // the old copy
             updateMaps(dCopy);
             if (log.isDebugEnabled()) {
-                log.debug("Device 1 {}", d);
-                log.debug("Device 2 {}", dCopy);
+            	log.debug("Remove AP {} post {} prev {} for Device {}", 
+            			new Object[] {dap, dCopy.getAttachmentPoints().size(),
+            			d.getAttachmentPoints().size(), dCopy});
             }
             removeAttachmentPointFromStorage(d, dap);
-            d = null; // to catch if anyone is using this reference
+            d = null;
             return true;
         }
 
@@ -632,15 +630,14 @@ public class DeviceManagerImpl implements IDeviceManagerService, IOFMessageListe
     protected ITopologyService topology;
     protected IStorageSourceService storageSource;
     protected IThreadPoolService threadPool;
-    protected IRestApiService restApi;
 
     protected Runnable deviceAgingTimer;
     protected SingletonTask deviceUpdateTask;
     protected Date previousStorageAudit;
 
-    protected final static int DEVICE_MAX_AGE    = 60 * 60 * 24;
-    protected final static int DEVICE_NA_MAX_AGE = 60 * 60 *  2;
-    protected final static int DEVICE_AP_MAX_AGE = 60 * 60 *  2;
+    protected static int DEVICE_MAX_AGE    = 60 * 60 * 24;
+    protected static int DEVICE_NA_MAX_AGE = 60 * 60 *  2;
+    protected static int DEVICE_AP_MAX_AGE = 60 * 60 *  2;
 
     // Constants for accessing storage
     // Table names
@@ -983,7 +980,7 @@ public class DeviceManagerImpl implements IDeviceManagerService, IOFMessageListe
                             newAttachmentPoint = false;
                         } else {
                             nd.addAttachmentPoint(attachmentPoint);
-                            evHistAttachmtPt(nd, 
+                            evHistAttachmtPt(nd.getDataLayerAddressAsLong(), 
                                              attachmentPoint.getSwitchPort(),
                                              EvAction.ADDED, 
                                              "New AP from pkt-in");
@@ -1113,7 +1110,7 @@ public class DeviceManagerImpl implements IDeviceManagerService, IOFMessageListe
                 log.info("Unblocking {} for device {}",
                          attachmentPoint.getSwitchPort(), device);
                 attachmentPoint.setBlocked(false);
-                evHistAttachmtPt(device, swPort, 
+                evHistAttachmtPt(device.getDataLayerAddressAsLong(), swPort, 
                     EvAction.UNBLOCKED, "packet-in after block timer expired");
             }
             // Remove from old list
@@ -1123,7 +1120,8 @@ public class DeviceManagerImpl implements IDeviceManagerService, IOFMessageListe
         // Update mappings
         devMgrMaps.addDevAttachmentPoint(
                 device.getDataLayerAddressAsLong(), swPort, currentDate);
-        evHistAttachmtPt(device, swPort, EvAction.ADDED, "packet-in GNAP");
+        evHistAttachmtPt(device.getDataLayerAddressAsLong(), swPort, 
+        		EvAction.ADDED, "packet-in GNAP");
 
         // If curAttachmentPoint exists, we mark it a conflict and may block it.
         if (curAttachmentPoint != null) {
@@ -1136,7 +1134,8 @@ public class DeviceManagerImpl implements IDeviceManagerService, IOFMessageListe
                 curAttachmentPoint.setConflict(currentDate);
                 if (curAttachmentPoint.isFlapping()) {
                     curAttachmentPoint.setBlocked(true);
-                    evHistAttachmtPt(device, curAttachmentPoint.getSwitchPort(),
+                    evHistAttachmtPt(device.getDataLayerAddressAsLong(), 
+                    		curAttachmentPoint.getSwitchPort(),
                             EvAction.BLOCKED, "Conflict");
                     writeAttachmentPointToStorage(device, curAttachmentPoint, 
                                                 currentDate);
@@ -1146,8 +1145,9 @@ public class DeviceManagerImpl implements IDeviceManagerService, IOFMessageListe
                         curAttachmentPoint.getSwitchPort()});
                 } else {
                     removeAttachmentPointFromStorage(device, curAttachmentPoint);
-                    evHistAttachmtPt(device, curAttachmentPoint.getSwitchPort(), 
-                                     EvAction.REMOVED, "Conflict");
+                    evHistAttachmtPt(device.getDataLayerAddressAsLong(), 
+                    		curAttachmentPoint.getSwitchPort(), 
+                            EvAction.REMOVED, "Conflict");
                 }
             }
             updateMoved(device, curAttachmentPoint.getSwitchPort(), 
@@ -1401,8 +1401,9 @@ public class DeviceManagerImpl implements IDeviceManagerService, IOFMessageListe
         device.clearAttachmentPoints();
         evHistAttachmtPt(device, 0L, (short)(-1), EvAction.CLEARED, "Moved");
         device.addAttachmentPoint(newDap);
-        evHistAttachmtPt(device, newDap.getSwitchPort(), 
-                                                    EvAction.ADDED, "Moved");
+        evHistAttachmtPt(device.getDataLayerAddressAsLong(), 
+        		newDap.getSwitchPort(), 
+                EvAction.ADDED, "Moved");
         
         synchronized (updates) {
             Update update = new Update(UpdateType.MOVED);
@@ -1562,7 +1563,7 @@ public class DeviceManagerImpl implements IDeviceManagerService, IOFMessageListe
             storageSource.deleteRowAsync(
                         DEVICE_ATTACHMENT_POINT_TABLE_NAME, attachmentPointId);
         } catch (NullPointerException e) {
-            log.debug("Null ptr exception for device {} attach-point {}",
+            log.warn("Null ptr exception for device {} attach-point {}",
                     device, attachmentPoint);
         }
     }
@@ -1802,7 +1803,6 @@ public class DeviceManagerImpl implements IDeviceManagerService, IOFMessageListe
             if (address.getLastSeen().before(agedBoundary)) {
                 devMgrMaps.delNwAddrByDataLayerAddr(device.getDataLayerAddressAsLong(), 
                     address.getNetworkAddress().intValue());
-                removeNetworkAddressFromStorage(device, address);
             }
         }
         
@@ -1819,6 +1819,7 @@ public class DeviceManagerImpl implements IDeviceManagerService, IOFMessageListe
     private Device removeAgedAttachmentPoints(Device device, Date currentDate) {
         Collection<DeviceAttachmentPoint> aps = device.getAttachmentPoints();
 
+        long dlAddr = device.getDataLayerAddressAsLong();
         for (DeviceAttachmentPoint ap : aps) {
             int expire = ap.getExpire();
 
@@ -1827,10 +1828,10 @@ public class DeviceManagerImpl implements IDeviceManagerService, IOFMessageListe
             }
             Date agedBoundary = ageBoundaryDifference(currentDate, expire);
             if (ap.getLastSeen().before(agedBoundary)) {
-                devMgrMaps.delDevAttachmentPoint(device, ap.getSwitchPort());
-                evHistAttachmtPt(device, ap.getSwitchPort(), EvAction.REMOVED,
+                devMgrMaps.delDevAttachmentPoint(dlAddr, ap.getSwitchPort());
+                evHistAttachmtPt(device.getDataLayerAddressAsLong(), 
+                		ap.getSwitchPort(), EvAction.REMOVED,
                         "Aged");
-                removeAttachmentPointFromStorage(device, ap);
             }
         }
         
@@ -1856,124 +1857,9 @@ public class DeviceManagerImpl implements IDeviceManagerService, IOFMessageListe
             }
         } 
     }
-
-    /**
-     * Removes aged rows in a table, based on the tables LAST_SEEN_COLUMN_NAME,
-     * requiring 'last_seen' to exist in the table.
-     * 
-     * @param tableName
-     * @param aging
-     * @param currentDate
-     */
-    private void removeAgedRowsFromStorage(String tableName,
-                                           String hostIdFieldName,
-                                           int aging,
-                                           Date currentDate) {
-        if (aging == 0) {
-            return;
-        }
-
-        Date ageBoundary = ageBoundaryDifference(currentDate, DEVICE_MAX_AGE);
-        IResultSet resultSet = null;
-        try {
-            /**
-             * The reason this storage call is asynchronous even though it's 
-             * immediately followed by a synchronous get is that there may be 
-             * other queued up asynchronous storage operations that would affect
-             * the results of executing this query. So we make this call 
-             * asynchronous as well so that we see the affects of the previous 
-             * asynchronous calls.
-             */
-            Future<IResultSet> future = 
-                storageSource.executeQueryAsync(tableName, null,
-                    new OperatorPredicate(LAST_SEEN_COLUMN_NAME, 
-                            OperatorPredicate.Operator.LT, ageBoundary),null);
-            // FIXME: What timeout should we use here?
-            resultSet = future.get(30, TimeUnit.SECONDS);
-            while (resultSet.next()) {
-
-                String dlAddrStr = resultSet.getString(hostIdFieldName);
-                if (dlAddrStr == null) {
-                    continue;
-                }
-
-                long dlAddr = HexString.toLong(dlAddrStr);
-
-                log.debug("removeRowsFromTable:" + hostIdFieldName + " " +
-                   resultSet.getString(hostIdFieldName) + " " + dlAddr +
-                   " " + resultSet.getDate(LAST_SEEN_COLUMN_NAME).toString() +
-                   " " + currentDate.toString());
-
-                lock.writeLock().lock();
-                try {
-                    devMgrMaps.delFromMaps(dlAddr);
-                } finally {
-                    lock.writeLock().unlock();
-                }                
-                resultSet.deleteRow();
-            }
-            resultSet.save();
-            resultSet.close();
-            resultSet = null;
-        }
-        catch (ExecutionException exc) {
-            log.error("Error accessing storage to remove old devices", exc);
-        }
-        catch (InterruptedException exc) {
-            log.error("Interruption accessing storage to remove old devices", 
-                                                                        exc);
-        }
-        catch (TimeoutException exc) {
-            log.warn("Timeout accessing storage to remove old devices", exc);
-        }
-        finally {
-            if (resultSet != null) {
-                resultSet.close();
-            }
-        }
-    }
-
-    /**
-     * Expire all age-out managed state.  Not intended to be called
-     * frequently since storage is queried.
-     */
-    private void removeAgedDeviceStorageState(Date currentDate) {
-        removeAgedRowsFromStorage(DEVICE_TABLE_NAME,
-                                  MAC_COLUMN_NAME,
-                                  DEVICE_MAX_AGE, 
-                                  currentDate);
-
-        removeAgedRowsFromStorage(DEVICE_ATTACHMENT_POINT_TABLE_NAME,
-                                  DEVICE_COLUMN_NAME,
-                                  DEVICE_AP_MAX_AGE, 
-                                  currentDate);
-
-        removeAgedRowsFromStorage(DEVICE_NETWORK_ADDRESS_TABLE_NAME,
-                                  DEVICE_COLUMN_NAME,
-                                  DEVICE_NA_MAX_AGE,
-                                  currentDate);
-    }
-
-    private void removeAgedDeviceState() {
-        Date currentDate = new Date();
-        long dayInMsec = TimeUnit.MILLISECONDS.convert(1, TimeUnit.DAYS);
-
-        removeAgedDevices(currentDate);
-
-        /*
-         * Once a day review the storage state to expire very
-         * old entries.
-         */
-        Date yesterday = new Date(currentDate.getTime() - dayInMsec);
-        if ((previousStorageAudit == null) ||
-            (previousStorageAudit.before(yesterday))) {
-            previousStorageAudit = currentDate;
-            removeAgedDeviceStorageState(currentDate);
-        }
-    }
-
-    private static final int DEVICE_AGING_TIMER= 15; // in minutes
-    private static final int DEVICE_AGING_TIMER_INTERVAL = 1; // in seconds
+     
+    protected static int DEVICE_AGING_TIMER= 60 * 15; // in seconds
+    protected static final int DEVICE_AGING_TIMER_INTERVAL = 1; // in seconds
 
     /**
      * Create the deviceAgingTimer, which calls removeAgedDeviceState()
@@ -1987,14 +1873,13 @@ public class DeviceManagerImpl implements IDeviceManagerService, IOFMessageListe
         deviceAgingTimer = new Runnable() {
             @Override
             public void run() {
-                log.debug("Running device aging timer {} minutes",
-                                DEVICE_AGING_TIMER);
-                removeAgedDeviceState();
+                Date currentDate = new Date();
+                removeAgedDevices(currentDate);
 
                 if (deviceAgingTimer != null) {
                     ScheduledExecutorService ses =
                         threadPool.getScheduledExecutor();
-                    ses.schedule(this, DEVICE_AGING_TIMER, TimeUnit.MINUTES);
+                    ses.schedule(this, DEVICE_AGING_TIMER, TimeUnit.SECONDS);
                 }
             }
         };
@@ -2096,10 +1981,10 @@ public class DeviceManagerImpl implements IDeviceManagerService, IOFMessageListe
     public EventHistory<EventHistoryAttachmentPoint> evHistDevMgrAttachPt;
     public EventHistoryAttachmentPoint evHAP;
 
-    private void evHistAttachmtPt(Device d, SwitchPortTuple swPrt,
+    private void evHistAttachmtPt(long dlAddr, SwitchPortTuple swPrt,
                                             EvAction action, String reason) {
         evHistAttachmtPt(
-                d.getDataLayerAddressAsLong(),
+                dlAddr,
                 swPrt.getSw().getId(),
                 swPrt.getPort(), action, reason);
     }
@@ -2170,7 +2055,6 @@ public class DeviceManagerImpl implements IDeviceManagerService, IOFMessageListe
         l.add(ILinkDiscoveryService.class);
         l.add(IStorageSourceService.class);
         l.add(IThreadPoolService.class);
-        l.add(IRestApiService.class);
         return l;
     }
 
@@ -2188,8 +2072,6 @@ public class DeviceManagerImpl implements IDeviceManagerService, IOFMessageListe
                 context.getServiceImpl(IStorageSourceService.class);
         threadPool =
                 context.getServiceImpl(IThreadPoolService.class);
-        restApi =
-                context.getServiceImpl(IRestApiService.class);
         
         // We create this here because there is no ordering guarantee
         this.deviceManagerAware = new HashSet<IDeviceManagerAware>();
@@ -2238,14 +2120,11 @@ public class DeviceManagerImpl implements IDeviceManagerService, IOFMessageListe
         // Register for switch events
         floodlightProvider.addOFSwitchListener(this);
         floodlightProvider.addInfoProvider("summary", this);
-        
-        // Register our REST API
-        restApi.addRestletRoutable(new DeviceManagerWebRoutable());
-        
-         // Device and storage aging.
-        enableDeviceAgingTimer();
+
         // Read all our device state (MACs, IPs, attachment points) from storage
         readAllDeviceStateFromStorage();
+        // Device and storage aging.
+        enableDeviceAgingTimer();
     }
 
     @Override
diff --git a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerWebRoutable.java b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerWebRoutable.java
deleted file mode 100644
index cc87b3944efbd57b7c54b15f96a25f846c1ef0bd..0000000000000000000000000000000000000000
--- a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerWebRoutable.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package net.floodlightcontroller.devicemanager.internal;
-
-import org.restlet.Context;
-import org.restlet.Restlet;
-import org.restlet.routing.Router;
-
-import net.floodlightcontroller.restserver.RestletRoutable;
-
-/**
- * Restlet Routable to handle DeviceManager API
- * @author alexreimers
- *
- */
-public class DeviceManagerWebRoutable implements RestletRoutable {
-
-    @Override
-    public Restlet getRestlet(Context context) {
-        Router router = new Router(context);
-        router.attach("/device/{device}/json", DeviceResource.class);
-        return router;
-    }
-
-    @Override
-    public String basePath() {
-        return "/wm/devicemanager";
-    }
-}
diff --git a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceResource.java b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceResource.java
deleted file mode 100644
index fa1cfce11f7ecc89b97c9da9a4adc17c329fdf7e..0000000000000000000000000000000000000000
--- a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceResource.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package net.floodlightcontroller.devicemanager.internal;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import net.floodlightcontroller.devicemanager.Device;
-import net.floodlightcontroller.devicemanager.IDeviceManagerService;
-
-import org.openflow.util.HexString;
-import org.restlet.resource.Get;
-import org.restlet.resource.ServerResource;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class DeviceResource extends ServerResource {
-    protected static Logger log = 
-            LoggerFactory.getLogger(DeviceResource.class);
-    
-    @Get("json")
-    public Map<String, Device> retrieve() {
-        Map<String, Device> retMap = new HashMap<String, Device>();
-        IDeviceManagerService dm = 
-            (IDeviceManagerService)getContext().getAttributes().
-                get(IDeviceManagerService.class.getCanonicalName());
-        
-        String param = (String) getRequestAttributes().get("device");
-        
-        if (param.toLowerCase().equals("all")) {
-            // Get all devices
-            for (Device d : dm.getDevices()) {
-                retMap.put(HexString.toHexString(d.getDataLayerAddress()), d);
-            }
-        } else {
-            // Get device by MAC
-            Device dev = null;
-            byte[] devMac = HexString.fromHexString(param);
-            dev = dm.getDeviceByDataLayerAddress(devMac);
-            if (dev != null) {
-                retMap.put(HexString.toHexString(dev.getDataLayerAddress()), dev);
-            }
-        }
-        
-        return retMap;
-    }
-}
diff --git a/src/test/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImplTest.java b/src/test/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImplTest.java
index bbf0628dda24b159fd84930b25c25b6243cb09cd..2f3cc22726c5e6ca452823590c26af448adaf913 100644
--- a/src/test/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImplTest.java
+++ b/src/test/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImplTest.java
@@ -61,12 +61,11 @@ import org.openflow.protocol.OFPhysicalPort;
  * @author David Erickson (daviderickson@cs.stanford.edu)
  */
 public class DeviceManagerImplTest extends FloodlightTestCase {
-    protected OFPacketIn packetIn_1, packetIn_2, packetIn_3, packetIn_4, packetIn_5;
+    protected OFPacketIn packetIn_1, packetIn_2, packetIn_3;
     protected IPacket testARPReplyPacket_1, testARPReplyPacket_2, testARPReplyPacket_3;
     protected IPacket testARPReqPacket_1, testARPReqPacket_2;
     protected byte[] testARPReplyPacket_1_Serialized, testARPReplyPacket_2_Serialized;
     private byte[] testARPReplyPacket_3_Serialized;
-    private byte[] testARPReqPacket_1_Serialized, testARPReqPacket_2_Serialized;
     MockFloodlightProvider mockFloodlightProvider;
     DeviceManagerImpl deviceManager;
     MemoryStorageSource storageSource;
@@ -96,7 +95,7 @@ public class DeviceManagerImplTest extends FloodlightTestCase {
         
         // Build our test packet
         this.testARPReplyPacket_1 = new Ethernet()
-            .setSourceMACAddress("00:44:33:22:11:00")
+            .setSourceMACAddress("00:44:33:22:11:01")
             .setDestinationMACAddress("00:11:22:33:44:55")
             .setEtherType(Ethernet.TYPE_ARP)
             .setVlanID((short)5)
@@ -107,7 +106,7 @@ public class DeviceManagerImplTest extends FloodlightTestCase {
                     .setHardwareAddressLength((byte) 6)
                     .setProtocolAddressLength((byte) 4)
                     .setOpCode(ARP.OP_REPLY)
-                    .setSenderHardwareAddress(Ethernet.toMACAddress("00:44:33:22:11:00"))
+                    .setSenderHardwareAddress(Ethernet.toMACAddress("00:44:33:22:11:01"))
                     .setSenderProtocolAddress(IPv4.toIPv4AddressBytes("192.168.1.1"))
                     .setTargetHardwareAddress(Ethernet.toMACAddress("00:11:22:33:44:55"))
                     .setTargetProtocolAddress(IPv4.toIPv4AddressBytes("192.168.1.2")));
@@ -148,40 +147,6 @@ public class DeviceManagerImplTest extends FloodlightTestCase {
                 .setTargetProtocolAddress(IPv4.toIPv4AddressBytes("192.168.1.2")));
         this.testARPReplyPacket_3_Serialized = testARPReplyPacket_3.serialize();
         
-        this.testARPReqPacket_1 = new Ethernet()
-        .setSourceMACAddress("00:44:33:22:11:04")
-        .setDestinationMACAddress("ff:ff:ff:ff:ff:ff")
-        .setEtherType(Ethernet.TYPE_ARP)
-        .setPayload(
-                new ARP()
-                .setHardwareType(ARP.HW_TYPE_ETHERNET)
-                .setProtocolType(ARP.PROTO_TYPE_IP)
-                .setHardwareAddressLength((byte) 6)
-                .setProtocolAddressLength((byte) 4)
-                .setOpCode(ARP.OP_REQUEST)
-                .setSenderHardwareAddress(Ethernet.toMACAddress("00:44:33:22:11:04"))
-                .setSenderProtocolAddress(IPv4.toIPv4AddressBytes("192.168.1.4"))
-                .setTargetHardwareAddress(Ethernet.toMACAddress("00:00:00:00:00:00"))
-                .setTargetProtocolAddress(IPv4.toIPv4AddressBytes("192.168.1.2")));
-        this.testARPReqPacket_1_Serialized = testARPReqPacket_1.serialize();
-        
-        this.testARPReqPacket_2 = new Ethernet()
-        .setSourceMACAddress("00:44:33:22:11:04")
-        .setDestinationMACAddress("ff:ff:ff:ff:ff:ff")
-        .setEtherType(Ethernet.TYPE_ARP)
-        .setPayload(
-                new ARP()
-                .setHardwareType(ARP.HW_TYPE_ETHERNET)
-                .setProtocolType(ARP.PROTO_TYPE_IP)
-                .setHardwareAddressLength((byte) 6)
-                .setProtocolAddressLength((byte) 4)
-                .setOpCode(ARP.OP_REQUEST)
-                .setSenderHardwareAddress(Ethernet.toMACAddress("00:44:33:22:11:04"))
-                .setSenderProtocolAddress(IPv4.toIPv4AddressBytes("192.168.1.14"))
-                .setTargetHardwareAddress(Ethernet.toMACAddress("00:00:00:00:00:00"))
-                .setTargetProtocolAddress(IPv4.toIPv4AddressBytes("192.168.1.2")));
-        this.testARPReqPacket_2_Serialized = testARPReqPacket_2.serialize();
-        
         // Build the PacketIn
         this.packetIn_1 = ((OFPacketIn) mockFloodlightProvider.getOFMessageFactory().getMessage(OFType.PACKET_IN))
             .setBufferId(-1)
@@ -205,22 +170,6 @@ public class DeviceManagerImplTest extends FloodlightTestCase {
             .setPacketData(this.testARPReplyPacket_3_Serialized)
             .setReason(OFPacketInReason.NO_MATCH)
             .setTotalLength((short) this.testARPReplyPacket_3_Serialized.length);
-        
-        // Build the PacketIn
-        this.packetIn_4 = ((OFPacketIn) mockFloodlightProvider.getOFMessageFactory().getMessage(OFType.PACKET_IN))
-            .setBufferId(-1)
-            .setInPort((short) 1)
-            .setPacketData(this.testARPReqPacket_1_Serialized)
-            .setReason(OFPacketInReason.NO_MATCH)
-            .setTotalLength((short) this.testARPReqPacket_1_Serialized.length);
-        
-        // Build the PacketIn
-        this.packetIn_5 = ((OFPacketIn) mockFloodlightProvider.getOFMessageFactory().getMessage(OFType.PACKET_IN))
-            .setBufferId(-1)
-            .setInPort((short) 1)
-            .setPacketData(this.testARPReqPacket_2_Serialized)
-            .setReason(OFPacketInReason.NO_MATCH)
-            .setTotalLength((short) this.testARPReqPacket_2_Serialized.length);
     }
 
     
@@ -241,6 +190,83 @@ public class DeviceManagerImplTest extends FloodlightTestCase {
         assertEquals((int)2, d.getAttachmentPoints().size());
     }
     
+    @Test
+    public void testDeviceAging() throws Exception {
+        
+        byte[] dataLayerSource = ((Ethernet)this.testARPReplyPacket_1).getSourceMACAddress();
+
+        // Mock up our expected behavior
+        IOFSwitch mockSwitch1 = createMock(IOFSwitch.class);
+        expect(mockSwitch1.getId()).andReturn(1L).anyTimes();
+        expect(mockSwitch1.getStringId()).andReturn("00:00:00:00:00:00:00:01").anyTimes();
+        IOFSwitch mockSwitch2 = createMock(IOFSwitch.class);
+        ITopologyService mockTopology = createMock(ITopologyService.class);
+        expect(mockTopology.isInternal(1L, (short)1)).andReturn(false);
+        expect(mockTopology.getSwitchClusterId(1L)).andReturn(1L).atLeastOnce();
+        deviceManager.setTopology(mockTopology);
+        // reduce the aging period
+        DeviceManagerImpl.DEVICE_AGING_TIMER = 2;
+        DeviceManagerImpl.DEVICE_AP_MAX_AGE = 1;
+        DeviceManagerImpl.DEVICE_NA_MAX_AGE = 1;
+        DeviceManagerImpl.DEVICE_MAX_AGE = 3;
+
+        Date currentDate = new Date();
+        
+        // build our expected Device
+        Device device = new Device();
+        device.setDataLayerAddress(dataLayerSource);
+        device.addAttachmentPoint(new SwitchPortTuple(mockSwitch1, (short)1), currentDate);
+        Integer ipaddr = IPv4.toIPv4Address("192.168.1.1");
+        device.addNetworkAddress(ipaddr, currentDate);
+        expect(mockSwitch2.getId()).andReturn(2L).anyTimes();
+        expect(mockSwitch2.getStringId()).andReturn("00:00:00:00:00:00:00:02").anyTimes();
+        expect(mockTopology.isInternal(2L, (short)2)).andReturn(false);
+        expect(mockTopology.inSameCluster(2L, 1L)).andReturn(false);
+        expect(mockTopology.getSwitchClusterId(2L)).andReturn(2L).atLeastOnce();
+        
+        
+        // Start recording the replay on the mocks
+        replay(mockSwitch1, mockSwitch2, mockTopology);
+        // Get the listener and trigger the packet in
+        mockFloodlightProvider.dispatchMessage(mockSwitch1, this.packetIn_1);
+        
+        // Get the listener and trigger the packet in
+        mockFloodlightProvider.dispatchMessage(mockSwitch2, this.packetIn_3.setInPort((short)2));
+
+        // Verify the replay matched our expectations
+        verify(mockSwitch1, mockSwitch2, mockTopology);
+        // Verify the device
+        Device rdevice = deviceManager.getDeviceByDataLayerAddress(dataLayerSource);
+        assertEquals(device, rdevice);
+        assertEquals(2, rdevice.getAttachmentPoints().size());
+        assertEquals(2, rdevice.getNetworkAddresses().size());
+        
+        // Sleep to make sure the aging thread has run
+        Thread.sleep((DeviceManagerImpl.DEVICE_AGING_TIMER + DeviceManagerImpl.DEVICE_AGING_TIMER_INTERVAL)*1000);
+        
+        rdevice = deviceManager.getDeviceByDataLayerAddress(dataLayerSource);
+        assertEquals(0, rdevice.getAttachmentPoints().size());
+        assertEquals(0, rdevice.getNetworkAddresses().size());
+        
+        // Make sure the device's AP and NA were removed from storage
+        deviceManager.readAllDeviceStateFromStorage();
+        rdevice = deviceManager.getDeviceByDataLayerAddress(dataLayerSource);
+        assertEquals(0, rdevice.getAttachmentPoints().size());
+        assertEquals(0, rdevice.getNetworkAddresses().size());
+        
+        // Sleep 4 more seconds to allow device aging thread to run
+        Thread.sleep(DeviceManagerImpl.DEVICE_MAX_AGE*1000);
+
+        assertNull(deviceManager.getDeviceByDataLayerAddress(dataLayerSource));
+        
+        // Make sure the device's AP and NA were removed from storage
+        deviceManager.readAllDeviceStateFromStorage();
+        assertNull(deviceManager.getDeviceByDataLayerAddress(dataLayerSource));
+        
+        // Reset the device cache
+        deviceManager.clearAllDeviceStateFromMemory();
+    }
+    
     @Test
     public void testDeviceDiscover() throws Exception {