Refactor for release; still need integration tests
diff --git a/src/main/java/com/intel/jndn/management/ControlResponse.java b/src/main/java/com/intel/jndn/management/ControlResponse.java
deleted file mode 100644
index c221d7c..0000000
--- a/src/main/java/com/intel/jndn/management/ControlResponse.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * File name: ControlResponse.java
- * 
- * Purpose: Represent a ControlResponse, a Data packet sent in response to a 
- * ControlCommand to the NFD, see http://redmine.named-data.net/projects/nfd/wiki/ControlCommand
- * 
- * © Copyright Intel Corporation. All rights reserved.
- * Intel Corporation, 2200 Mission College Boulevard,
- * Santa Clara, CA 95052-8119, USA
- */
-package com.intel.jndn.management;
-
-import java.util.List;
-import net.named_data.jndn.ControlParameters;
-import net.named_data.jndn.Data;
-import net.named_data.jndn.encoding.EncodingException;
-
-/**
- * 
- * @author Andrew Brown <andrew.brown@intel.com>
- */
-public class ControlResponse {
-	public int StatusCode;
-	public String StatusText;
-	public List<ControlParameters> Body;
-	
-	/**
-	 * Decode input as a ControlResponse in NDN-TLV and set the fields of the
-	 * new object
-	 * 
-	 * @param data
-	 * @return 
-	 */
-	public static ControlResponse decode(Data data) throws EncodingException{
-		ControlResponseDecoder decoder = new ControlResponseDecoder();
-		ControlResponse response = new ControlResponse();
-		decoder.decodeControlResponse(response, data.getContent().buf());
-		return response;
-	}
-}
diff --git a/src/main/java/com/intel/jndn/management/ControlResponseDecoder.java b/src/main/java/com/intel/jndn/management/ControlResponseDecoder.java
deleted file mode 100644
index f52c35a..0000000
--- a/src/main/java/com/intel/jndn/management/ControlResponseDecoder.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * File name: ControlParametersDecoder.java
- * 
- * Purpose: See http://redmine.named-data.net/projects/nfd/wiki/ControlCommand
- * 
- * © Copyright Intel Corporation. All rights reserved.
- * Intel Corporation, 2200 Mission College Boulevard,
- * Santa Clara, CA 95052-8119, USA
- */
-package com.intel.jndn.management;
-
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import net.named_data.jndn.ControlParameters;
-import net.named_data.jndn.encoding.EncodingException;
-import net.named_data.jndn.encoding.TlvWireFormat;
-import net.named_data.jndn.encoding.tlv.Tlv;
-import net.named_data.jndn.encoding.tlv.TlvDecoder;
-import net.named_data.jndn.util.Blob;
-
-/**
- * 
- * @author Andrew Brown <andrew.brown@intel.com>
- */
-public class ControlResponseDecoder extends TlvWireFormat {
-
-	/**
-	 * Use TLV codes from jndn.encoding.tlv.Tlv.java See
-	 * http://redmine.named-data.net/projects/nfd/wiki/ControlCommand
-	 */
-	public final static int ControlResponse = 101;
-	public final static int ControlResponse_StatusCode = 102;
-	public final static int ControlResponse_StatusText = 103;
-
-	/**
-	 * Decode a ControlResponse TLV object; see
-	 * http://redmine.named-data.net/projects/nfd/wiki/ControlCommand
-	 *
-	 * @param controlResponse
-	 * @param input
-	 * @throws EncodingException
-	 */
-	public void decodeControlResponse(ControlResponse controlResponse, ByteBuffer input) throws EncodingException {
-		TlvDecoder decoder = new TlvDecoder(input);
-		int endOffset = decoder.readNestedTlvsStart(ControlResponse);
-
-		// parse
-		controlResponse.StatusCode = (int) decoder.readNonNegativeIntegerTlv(ControlResponse_StatusCode);
-		Blob statusText = new Blob(decoder.readBlobTlv(ControlResponse_StatusText), true); // copy because buffer is immutable
-		controlResponse.StatusText = statusText.toString();
-		controlResponse.Body = new ArrayList<>();
-		while (decoder.peekType(Tlv.ControlParameters_ControlParameters, endOffset)) {
-			ByteBuffer copyInput = input.duplicate();
-			copyInput.position(decoder.getOffset());
-			int internalEndOffset = decoder.readNestedTlvsStart(Tlv.ControlParameters_ControlParameters);
-			// decode
-			ControlParameters copyParameters = new ControlParameters();
-			copyParameters.wireDecode(copyInput);
-			controlResponse.Body.add(copyParameters);
-			decoder.seek(internalEndOffset);
-			// 
-			decoder.finishNestedTlvs(internalEndOffset);
-		}
-
-		// etc...
-		decoder.finishNestedTlvs(endOffset);
-	}
-}
diff --git a/src/main/java/com/intel/jndn/management/EncodingHelper.java b/src/main/java/com/intel/jndn/management/EncodingHelper.java
new file mode 100644
index 0000000..66e3b9d
--- /dev/null
+++ b/src/main/java/com/intel/jndn/management/EncodingHelper.java
@@ -0,0 +1,142 @@
+/*
+ * File name: EncodingHelper.java
+ * 
+ * Purpose: Provide helper methods to cover areas too protected in Tlv0_1_1WireFormat;
+ * this class can be deprecated if WireFormats allow passing in an existing
+ * TlvEncoder/TlvDecoder (currently these methods are protected).
+ * 
+ * © Copyright Intel Corporation. All rights reserved.
+ * Intel Corporation, 2200 Mission College Boulevard,
+ * Santa Clara, CA 95052-8119, USA
+ */
+package com.intel.jndn.management;
+
+import java.nio.ByteBuffer;
+import net.named_data.jndn.ControlParameters;
+import net.named_data.jndn.ForwardingFlags;
+import net.named_data.jndn.Name;
+import net.named_data.jndn.encoding.EncodingException;
+import net.named_data.jndn.encoding.tlv.Tlv;
+import net.named_data.jndn.encoding.tlv.TlvDecoder;
+import net.named_data.jndn.encoding.tlv.TlvEncoder;
+import net.named_data.jndn.util.Blob;
+
+/**
+ * Provide helper methods to cover areas too protected in Tlv0_1_1WireFormat;
+ * this class can be deprecated if WireFormats allow passing in an existing
+ * TlvEncoder/TlvDecoder (currently these methods are protected).
+ *
+ * @author Andrew Brown <andrew.brown@intel.com>
+ */
+public class EncodingHelper {
+
+	/**
+	 * Helper to decode names since Tlv0_1_1WireFormat.java uses its own
+	 * internal, protected implementation.
+	 *
+	 * @param input
+	 * @return
+	 * @throws EncodingException
+	 */
+	public static Name decodeName(ByteBuffer input) throws EncodingException {
+		TlvDecoder decoder = new TlvDecoder(input);
+		return decodeName(decoder);
+	}
+
+	/**
+	 * Helper to decode names using an existing decoding context; could be
+	 * merged to Tlv0_1_1WireFormat.java.
+	 *
+	 * @param decoder
+	 * @return
+	 * @throws EncodingException
+	 */
+	public static Name decodeName(TlvDecoder decoder) throws EncodingException {
+		Name name = new Name();
+		int endOffset = decoder.readNestedTlvsStart(Tlv.Name);
+		while (decoder.getOffset() < endOffset) {
+			name.append(new Blob(decoder.readBlobTlv(Tlv.NameComponent), true));
+		}
+
+		decoder.finishNestedTlvs(endOffset);
+		return name;
+	}
+
+	/**
+	 * Helper to encode names since Tlv0_1_1WireFormat.java uses its own
+	 * internal, protected implementation.
+	 *
+	 * @param name
+	 * @return
+	 */
+	public static Blob encodeName(Name name) {
+		TlvEncoder encoder = new TlvEncoder();
+		encodeName(name, encoder);
+		return new Blob(encoder.getOutput(), false);
+	}
+
+	/**
+	 * Helper to encode names using an existing encoding context; could be
+	 * merged to Tlv0_1_1WireFormat.java.
+	 *
+	 * @param name
+	 * @param encoder
+	 */
+	public static final void encodeName(Name name, TlvEncoder encoder) {
+		int saveLength = encoder.getLength();
+		for (int i = name.size() - 1; i >= 0; --i) {
+			encoder.writeBlobTlv(Tlv.NameComponent, name.get(i).getValue().buf());
+		}
+		encoder.writeTypeAndLength(Tlv.Name, encoder.getLength() - saveLength);
+	}
+
+	/**
+	 * Helper to encode control parameters using an existing encoding context;
+	 * could be merged to Tlv0_1_1WireFormat.java.
+	 *
+	 * @param controlParameters
+	 * @param encoder
+	 */
+	public static final void encodeControlParameters(ControlParameters controlParameters, TlvEncoder encoder) {
+		int saveLength = encoder.getLength();
+
+		// Encode backwards.
+		encoder.writeOptionalNonNegativeIntegerTlvFromDouble(Tlv.ControlParameters_ExpirationPeriod,
+				controlParameters.getExpirationPeriod());
+
+		// Encode strategy
+		if (controlParameters.getStrategy().size() != 0) {
+			int strategySaveLength = encoder.getLength();
+			encodeName(controlParameters.getStrategy(), encoder);
+			encoder.writeTypeAndLength(Tlv.ControlParameters_Strategy,
+					encoder.getLength() - strategySaveLength);
+		}
+
+		// Encode ForwardingFlags
+		int flags = controlParameters.getForwardingFlags().getNfdForwardingFlags();
+		if (flags != new ForwardingFlags().getNfdForwardingFlags()) // The flags are not the default value.
+		{
+			encoder.writeNonNegativeIntegerTlv(Tlv.ControlParameters_Flags, flags);
+		}
+
+		encoder.writeOptionalNonNegativeIntegerTlv(Tlv.ControlParameters_Cost, controlParameters.getCost());
+		encoder.writeOptionalNonNegativeIntegerTlv(Tlv.ControlParameters_Origin, controlParameters.getOrigin());
+		encoder.writeOptionalNonNegativeIntegerTlv(Tlv.ControlParameters_LocalControlFeature,
+				controlParameters.getLocalControlFeature());
+
+		// Encode URI
+		if (!controlParameters.getUri().isEmpty()) {
+			encoder.writeBlobTlv(Tlv.ControlParameters_Uri,
+					new Blob(controlParameters.getUri()).buf());
+		}
+
+		encoder.writeOptionalNonNegativeIntegerTlv(Tlv.ControlParameters_FaceId, controlParameters.getFaceId());
+
+		// Encode name
+		if (controlParameters.getName().size() != 0) {
+			encodeName(controlParameters.getName(), encoder);
+		}
+
+		encoder.writeTypeAndLength(Tlv.ControlParameters_ControlParameters, encoder.getLength() - saveLength);
+	}
+}
diff --git a/src/main/java/com/intel/jndn/management/FaceStatus.java b/src/main/java/com/intel/jndn/management/FaceStatus.java
deleted file mode 100644
index f0a992b..0000000
--- a/src/main/java/com/intel/jndn/management/FaceStatus.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * File name: FaceStatus.java
- * 
- * Purpose: Represent a FaceStatus object from /localhost/nfd/faces/list;
- * see http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt for details
- * 
- * © Copyright Intel Corporation. All rights reserved.
- * Intel Corporation, 2200 Mission College Boulevard,
- * Santa Clara, CA 95052-8119, USA
- */
-package com.intel.jndn.management;
-
-import java.util.List;
-import net.named_data.jndn.Data;
-import net.named_data.jndn.encoding.EncodingException;
-
-/**
- * Represent a FaceStatus object from /localhost/nfd/faces/list;
- * see http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt for details
- * @author Andrew Brown <andrew.brown@intel.com>
- */
-public class FaceStatus {
-
-	public int faceId;
-	public String uri; // can't use URI because some are invalid syntax
-	public String localUri; // can't use URI because some are invalid syntax
-	public int expirationPeriod;
-	public FaceScope faceScope;
-	public FacePersistency facePersistency;
-	public LinkType linkType;
-	public int inInterests;
-	public int outInterests;
-	public int inDatas;
-	public int outDatas;
-	public int inBytes;
-	public int outBytes;
-
-	/**
-	 * Helper method for decoding a list of face statuses from
-	 * /localhost/nfd/faces/list
-	 * @param data
-	 * @return
-	 * @throws EncodingException 
-	 */
-	public static List<FaceStatus> decode(Data data) throws EncodingException{
-		FaceStatusDecoder decoder = new FaceStatusDecoder();
-		return decoder.decodeFaces(data.getContent().buf());
-	}
-}
diff --git a/src/main/java/com/intel/jndn/management/FaceStatusDecoder.java b/src/main/java/com/intel/jndn/management/FaceStatusDecoder.java
deleted file mode 100644
index 346f2cb..0000000
--- a/src/main/java/com/intel/jndn/management/FaceStatusDecoder.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * File name: FaceStatusDecoder.java
- * 
- * Purpose: Decode lists of FaceStatus objects from /localhost/nfd/faces/list
- * 
- * © Copyright Intel Corporation. All rights reserved.
- * Intel Corporation, 2200 Mission College Boulevard,
- * Santa Clara, CA 95052-8119, USA
- */
-package com.intel.jndn.management;
-
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.List;
-import net.named_data.jndn.encoding.EncodingException;
-import net.named_data.jndn.encoding.tlv.TlvDecoder;
-import net.named_data.jndn.util.Blob;
-
-/**
- * Decode lists of FaceStatus objects from /localhost/nfd/faces/list
- * @author Andrew Brown <andrew.brown@intel.com>
- */
-public class FaceStatusDecoder {
-	
-	/**
-	 * Spec from http://redmine.named-data.net/projects/nfd/wiki/ControlCommand
-	 */
-	public static final int FACE_ID = 105; 
-	public static final int URI = 114;
-	public static final int EXPIRATION_PERIOD = 109;
-	
-	/**
-	 * Spec from http://redmine.named-data.net/projects/nfd/widi/FaceMgmt
-	 */
-	public static final int FACE_STATUS = 128;
-	public static final int LOCAL_URI = 129;
-	public static final int CHANNEL_STATUS = 130;
-	public static final int FACE_SCOPE = 132;
-	public static final int FACE_PERSISTENCY = 133;
-	public static final int LINK_TYPE = 134;
-	public static final int N_IN_INTERESTS = 144;
-	public static final int N_IN_DATAS = 145;
-	public static final int N_OUT_INTERESTS = 146;
-	public static final int N_OUT_DATAS = 147;
-	public static final int N_IN_BYTES = 148;
-	public static final int N_OUT_BYTES = 149;
-	
-	/**
-	 * Decode a list of faces according to
-	 * http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt
-	 * @param buffer
-	 * @return
-	 * @throws EncodingException 
-	 */
-	public List<FaceStatus> decodeFaces(ByteBuffer buffer) throws EncodingException{
-		ArrayList<FaceStatus> faces = new ArrayList<>();
-		TlvDecoder decoder = new TlvDecoder(buffer);
-		int parentEndOffset;
-		do{
-			parentEndOffset = decoder.readNestedTlvsStart(FACE_STATUS);
-			faces.add(decodeFaceStatus(decoder, parentEndOffset));
-			decoder.finishNestedTlvs(parentEndOffset);
-		}
-		while(parentEndOffset < buffer.limit());
-		return faces;
-	}
-	
-	/**
-	 * Decode one face status using the current decoder
-	 * @param buffer
-	 * @return
-	 * @throws EncodingException 
-	 */
-	private static FaceStatus decodeFaceStatus(TlvDecoder decoder, int parentEndOffset) throws EncodingException{
-		FaceStatus status = new FaceStatus();
-		
-		// parse
-		status.faceId = (int) decoder.readNonNegativeIntegerTlv(FACE_ID);
-		Blob uri = new Blob(decoder.readBlobTlv(URI), true); // copy because buffer is immutable
-		status.uri = uri.toString();
-		Blob localUri = new Blob(decoder.readBlobTlv(LOCAL_URI), true); // copy because buffer is immutable
-		status.localUri = localUri.toString();
-		status.expirationPeriod = (int) decoder.readOptionalNonNegativeIntegerTlv(EXPIRATION_PERIOD, parentEndOffset);
-		status.faceScope = FaceScope.values()[(int) decoder.readNonNegativeIntegerTlv(FACE_SCOPE)];
-		status.facePersistency = FacePersistency.values()[(int) decoder.readNonNegativeIntegerTlv(FACE_PERSISTENCY)];
-		status.linkType = LinkType.values()[(int) decoder.readNonNegativeIntegerTlv(LINK_TYPE)];
-		status.inInterests = (int) decoder.readNonNegativeIntegerTlv(N_IN_INTERESTS);
-		status.inDatas = (int) decoder.readNonNegativeIntegerTlv(N_IN_DATAS);
-		status.outInterests = (int) decoder.readNonNegativeIntegerTlv(N_OUT_INTERESTS);
-		status.outDatas = (int) decoder.readNonNegativeIntegerTlv(N_OUT_DATAS);
-		status.inBytes = (int) decoder.readNonNegativeIntegerTlv(N_IN_BYTES);
-		status.outBytes = (int) decoder.readNonNegativeIntegerTlv(N_OUT_BYTES);
-		
-		return status;
-	}
-
-}
diff --git a/src/main/java/com/intel/jndn/management/NFD.java b/src/main/java/com/intel/jndn/management/NFD.java
index 07f241f..b5f531f 100644
--- a/src/main/java/com/intel/jndn/management/NFD.java
+++ b/src/main/java/com/intel/jndn/management/NFD.java
@@ -11,6 +11,10 @@
  */
 package com.intel.jndn.management;
 
+import com.intel.jndn.management.types.StatusDataset;
+import com.intel.jndn.management.types.ControlResponse;
+import com.intel.jndn.management.types.FaceStatus;
+import com.intel.jndn.management.types.RibEntry;
 import com.intel.jndn.utils.Client;
 import java.io.IOException;
 import java.util.List;
@@ -22,8 +26,7 @@
 import net.named_data.jndn.Name;
 import net.named_data.jndn.encoding.EncodingException;
 import net.named_data.jndn.security.SecurityException;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
+import java.util.logging.Logger;
 
 /**
  * Helper class for interacting with an NDN forwarder daemon; see
@@ -35,7 +38,7 @@
 public class NFD {
 
 	public final static long DEFAULT_TIMEOUT = 2000;
-	private static final Logger logger = LogManager.getLogger();
+	static private final Logger logger = Logger.getLogger(NFD.class.getName());
 
 	/**
 	 * Ping a forwarder on an existing face to verify that the forwarder is
@@ -43,7 +46,7 @@
 	 * to /localhost/nfd which should always respond if the requestor is on the
 	 * same machine as the NDN forwarding daemon.
 	 *
-	 * @param face 
+	 * @param face
 	 * @return true if successful, false otherwise
 	 */
 	public static boolean pingLocal(Face face) {
@@ -97,7 +100,33 @@
 		}
 
 		// parse packet
-		return FaceStatus.decode(data);
+		return StatusDataset.wireDecode(data.getContent(), FaceStatus.class);
+	}
+
+	/**
+	 * Retrieve a list of routing entries from the RIB; calls
+	 * /localhost/nfd/rib/list which requires a local Face (all non-local
+	 * packets are dropped)
+	 *
+	 * @param forwarder Only a localhost Face
+	 * @return
+	 * @throws Exception
+	 */
+	public static List<RibEntry> getRouteList(Face forwarder) throws Exception {
+		// build management Interest packet; see http://redmine.named-data.net/projects/nfd/wiki/StatusDataset
+		Interest interest = new Interest(new Name("/localhost/nfd/rib/list"));
+		interest.setMustBeFresh(true);
+		interest.setChildSelector(Interest.CHILD_SELECTOR_RIGHT);
+		interest.setInterestLifetimeMilliseconds(DEFAULT_TIMEOUT);
+
+		// send packet
+		Data data = Client.getDefault().getSync(forwarder, interest);
+		if (data == null) {
+			throw new Exception("Failed to retrieve list of faces from the forwarder.");
+		}
+
+		// parse packet
+		return StatusDataset.wireDecode(data.getContent(), RibEntry.class);
 	}
 
 	/**
@@ -143,12 +172,12 @@
 		ControlResponse response = sendCommand(forwarder, new Interest(command));
 
 		// check for body and that status code is OK (TODO: 200 should be replaced with a CONSTANT like ControlResponse.STATUS_OK)
-		if (response.Body.isEmpty() || response.StatusCode != 200) {
-			throw new Exception("Failed to create face: " + uri + " " + response.StatusText != null ? response.StatusText : "");
+		if (response.getBody().isEmpty() || response.getStatusCode() != 200) {
+			throw new Exception("Failed to create face: " + uri + " " + response.getStatusText());
 		}
 
 		// return
-		return response.Body.get(0).getFaceId();
+		return response.getBody().get(0).getFaceId();
 	}
 
 	/**
@@ -273,7 +302,9 @@
 		}
 
 		// return response
-		return ControlResponse.decode(data);
+		ControlResponse response = new ControlResponse();
+		response.wireDecode(data.getContent().buf());
+		return response;
 	}
 
 	/**
@@ -293,10 +324,10 @@
 	 */
 	public static boolean sendCommandAndErrorCheck(Face forwarder, Interest interest) throws SecurityException, IOException, EncodingException {
 		ControlResponse response = sendCommand(forwarder, interest);
-		if (response.StatusCode < 400) {
+		if (response.getStatusCode() < 400) {
 			return true;
 		} else {
-			logger.warn("Command sent but failed: " + response.StatusCode + " " + response.StatusText);
+			logger.warning("Command sent but failed: " + response.getStatusCode() + " " + response.getStatusText());
 			return false;
 		}
 	}
diff --git a/src/main/java/com/intel/jndn/management/types/ControlResponse.java b/src/main/java/com/intel/jndn/management/types/ControlResponse.java
new file mode 100644
index 0000000..425f2d1
--- /dev/null
+++ b/src/main/java/com/intel/jndn/management/types/ControlResponse.java
@@ -0,0 +1,167 @@
+/*
+ * File name: ControlResponse.java
+ * 
+ * Purpose: Represent a ControlResponse, a Data packet sent in response to a 
+ * ControlCommand to the NFD, see http://redmine.named-data.net/projects/nfd/wiki/ControlCommand
+ * 
+ * © Copyright Intel Corporation. All rights reserved.
+ * Intel Corporation, 2200 Mission College Boulevard,
+ * Santa Clara, CA 95052-8119, USA
+ */
+package com.intel.jndn.management.types;
+
+import com.intel.jndn.management.EncodingHelper;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+import net.named_data.jndn.ControlParameters;
+import net.named_data.jndn.encoding.EncodingException;
+import net.named_data.jndn.encoding.tlv.Tlv;
+import net.named_data.jndn.encoding.tlv.TlvDecoder;
+import net.named_data.jndn.encoding.tlv.TlvEncoder;
+import net.named_data.jndn.util.Blob;
+
+/**
+ * Represent a ControlResponse, a Data packet sent in response to a
+ * ControlCommand to the NFD, see
+ * http://redmine.named-data.net/projects/nfd/wiki/ControlCommand
+ *
+ * @author Andrew Brown <andrew.brown@intel.com>
+ */
+public class ControlResponse {
+
+	/**
+	 * Use TLV codes from jndn.encoding.tlv.Tlv.java See
+	 * http://redmine.named-data.net/projects/nfd/wiki/ControlCommand
+	 */
+	public final static int TLV_CONTROL_RESPONSE = 101;
+	public final static int TLV_CONTROL_RESPONSE_STATUS_CODE = 102;
+	public final static int TLV_CONTROL_RESPONSE_STATUS_TEXT = 103;
+
+	/**
+	 * Encode using a new TLV encoder.
+	 *
+	 * @return The encoded buffer.
+	 */
+	public final Blob wireEncode() {
+		TlvEncoder encoder = new TlvEncoder();
+		wireEncode(encoder);
+		return new Blob(encoder.getOutput(), false);
+	}
+
+	/**
+	 * Encode as part of an existing encode context.
+	 *
+	 * @param encoder
+	 */
+	public final void wireEncode(TlvEncoder encoder) {
+		int saveLength = encoder.getLength();
+		for (ControlParameters parameters : body) {
+			EncodingHelper.encodeControlParameters(parameters, encoder);
+		}
+		encoder.writeBlobTlv(TLV_CONTROL_RESPONSE_STATUS_TEXT, new Blob(statusText).buf());
+		encoder.writeNonNegativeIntegerTlv(TLV_CONTROL_RESPONSE_STATUS_CODE, statusCode);
+		encoder.writeTypeAndLength(TLV_CONTROL_RESPONSE, encoder.getLength() - saveLength);
+	}
+
+	/**
+	 * Decode the input from its TLV format.
+	 *
+	 * @param input The input buffer to decode. This reads from position() to
+	 * limit(), but does not change the position.
+	 * @throws net.named_data.jndn.encoding.EncodingException
+	 */
+	public final void wireDecode(ByteBuffer input) throws EncodingException {
+		TlvDecoder decoder = new TlvDecoder(input);
+		wireDecode(decoder, input);
+	}
+
+	/**
+	 * Decode as part of an existing decode context.
+	 *
+	 * @param decoder
+	 * @param input the WireFormat version that decodes ControlParameters does
+	 * not allow passing a TlvDecoder, so we must pass the buffer itself
+	 * @throws EncodingException
+	 */
+	public void wireDecode(TlvDecoder decoder, ByteBuffer input) throws EncodingException {
+		int endOffset = decoder.readNestedTlvsStart(TLV_CONTROL_RESPONSE);
+
+		// parse known TLVs
+		this.statusCode = (int) decoder.readNonNegativeIntegerTlv(TLV_CONTROL_RESPONSE_STATUS_CODE);
+		Blob statusText_ = new Blob(decoder.readBlobTlv(TLV_CONTROL_RESPONSE_STATUS_TEXT), true); // copy because buffer is immutable
+		this.statusText = statusText_.toString();
+
+		// use the already-written decoder for ControlParameters (but we have to copy the buffer)
+		while (decoder.peekType(Tlv.ControlParameters_ControlParameters, endOffset)) {
+			ByteBuffer copyInput = input.duplicate();
+			copyInput.position(decoder.getOffset());
+			int internalEndOffset = decoder.readNestedTlvsStart(Tlv.ControlParameters_ControlParameters);
+			ControlParameters copyParameters = new ControlParameters();
+			copyParameters.wireDecode(copyInput);
+			this.body.add(copyParameters);
+			decoder.seek(internalEndOffset);
+			decoder.finishNestedTlvs(internalEndOffset);
+		}
+
+		decoder.finishNestedTlvs(endOffset);
+	}
+
+	/**
+	 * Get status code
+	 *
+	 * @return
+	 */
+	public int getStatusCode() {
+		return statusCode;
+	}
+
+	/**
+	 * Set status code
+	 *
+	 * @param statusCode
+	 */
+	public void setStatusCode(int statusCode) {
+		this.statusCode = statusCode;
+	}
+
+	/**
+	 * Get status text
+	 *
+	 * @return
+	 */
+	public String getStatusText() {
+		return statusText;
+	}
+
+	/**
+	 * Set status text
+	 *
+	 * @param statusText
+	 */
+	public void setStatusText(String statusText) {
+		this.statusText = statusText;
+	}
+
+	/**
+	 * Get body
+	 *
+	 * @return
+	 */
+	public List<ControlParameters> getBody() {
+		return body;
+	}
+
+	/**
+	 * Set body
+	 *
+	 * @param body
+	 */
+	public void setBody(List<ControlParameters> body) {
+		this.body = body;
+	}
+
+	private int statusCode = -1;
+	private String statusText = "";
+	private List<ControlParameters> body = new ArrayList<>();
+}
diff --git a/src/main/java/com/intel/jndn/management/types/Decodable.java b/src/main/java/com/intel/jndn/management/types/Decodable.java
new file mode 100644
index 0000000..17bb0fa
--- /dev/null
+++ b/src/main/java/com/intel/jndn/management/types/Decodable.java
@@ -0,0 +1,25 @@
+/*
+ * File name: Decodable.java
+ * 
+ * Purpose: Interface used by StatusDataset to decode generic message types; if
+ * they are Decodable, then StatusDataset will instantiate and decode them.
+ * 
+ * Purpose: 
+ * © Copyright Intel Corporation. All rights reserved.
+ * Intel Corporation, 2200 Mission College Boulevard,
+ * Santa Clara, CA 95052-8119, USA
+ */
+package com.intel.jndn.management.types;
+
+import net.named_data.jndn.encoding.EncodingException;
+import net.named_data.jndn.encoding.tlv.TlvDecoder;
+
+/**
+ * Interface used by StatusDataset to decode generic message types; if they are
+ * Decodable, then StatusDataset will instantiate and decode them.
+ *
+ * @author Andrew Brown <andrew.brown@intel.com>
+ */
+public interface Decodable {
+	public void wireDecode(TlvDecoder decoder) throws EncodingException;
+}
diff --git a/src/main/java/com/intel/jndn/management/FacePersistency.java b/src/main/java/com/intel/jndn/management/types/FacePersistency.java
similarity index 94%
rename from src/main/java/com/intel/jndn/management/FacePersistency.java
rename to src/main/java/com/intel/jndn/management/types/FacePersistency.java
index 2f2b5e6..d663acc 100644
--- a/src/main/java/com/intel/jndn/management/FacePersistency.java
+++ b/src/main/java/com/intel/jndn/management/types/FacePersistency.java
@@ -8,7 +8,7 @@
  * Intel Corporation, 2200 Mission College Boulevard,
  * Santa Clara, CA 95052-8119, USA
  */
-package com.intel.jndn.management;
+package com.intel.jndn.management.types;
 
 /**
  * Indicate whether the face is persistent; used by FaceStatus
diff --git a/src/main/java/com/intel/jndn/management/FaceScope.java b/src/main/java/com/intel/jndn/management/types/FaceScope.java
similarity index 94%
rename from src/main/java/com/intel/jndn/management/FaceScope.java
rename to src/main/java/com/intel/jndn/management/types/FaceScope.java
index 17028c5..100befc 100644
--- a/src/main/java/com/intel/jndn/management/FaceScope.java
+++ b/src/main/java/com/intel/jndn/management/types/FaceScope.java
@@ -8,7 +8,7 @@
  * Intel Corporation, 2200 Mission College Boulevard,
  * Santa Clara, CA 95052-8119, USA
  */
-package com.intel.jndn.management;
+package com.intel.jndn.management.types;
 
 /**
  * Indicate whether the face is local for scope control purposes; used by FaceStatus
diff --git a/src/main/java/com/intel/jndn/management/types/FaceStatus.java b/src/main/java/com/intel/jndn/management/types/FaceStatus.java
new file mode 100644
index 0000000..6883d54
--- /dev/null
+++ b/src/main/java/com/intel/jndn/management/types/FaceStatus.java
@@ -0,0 +1,370 @@
+/*
+ * File name: FaceStatus.java
+ * 
+ * Purpose: Represent a FaceStatus object from /localhost/nfd/faces/list;
+ * see http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt for details
+ * 
+ * © Copyright Intel Corporation. All rights reserved.
+ * Intel Corporation, 2200 Mission College Boulevard,
+ * Santa Clara, CA 95052-8119, USA
+ */
+package com.intel.jndn.management.types;
+
+import java.nio.ByteBuffer;
+import net.named_data.jndn.encoding.EncodingException;
+import net.named_data.jndn.encoding.tlv.TlvDecoder;
+import net.named_data.jndn.encoding.tlv.TlvEncoder;
+import net.named_data.jndn.util.Blob;
+
+/**
+ * Represent a FaceStatus object from /localhost/nfd/faces/list; see
+ * http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt for details
+ *
+ * @author Andrew Brown <andrew.brown@intel.com>
+ */
+public class FaceStatus implements Decodable{
+
+	/**
+	 * Spec from http://redmine.named-data.net/projects/nfd/wiki/ControlCommand
+	 */
+	public static final int TLV_FACE_ID = 105;
+	public static final int TLV_URI = 114;
+	public static final int TLV_EXPIRATION_PERIOD = 109;
+
+	/**
+	 * Spec from http://redmine.named-data.net/projects/nfd/widi/FaceMgmt
+	 */
+	public static final int TLV_FACE_STATUS = 128;
+	public static final int TLV_LOCAL_URI = 129;
+	public static final int TLV_CHANNEL_STATUS = 130;
+	public static final int TLV_FACE_SCOPE = 132;
+	public static final int TLV_FACE_PERSISTENCY = 133;
+	public static final int TLV_LINK_TYPE = 134;
+	public static final int TLV_N_IN_INTERESTS = 144;
+	public static final int TLV_N_IN_DATAS = 145;
+	public static final int TLV_N_OUT_INTERESTS = 146;
+	public static final int TLV_N_OUT_DATAS = 147;
+	public static final int TLV_N_IN_BYTES = 148;
+	public static final int TLV_N_OUT_BYTES = 149;
+
+	/**
+	 * Encode using a new TLV encoder.
+	 *
+	 * @return The encoded buffer.
+	 */
+	public final Blob wireEncode() {
+		TlvEncoder encoder = new TlvEncoder();
+		wireEncode(encoder);
+		return new Blob(encoder.getOutput(), false);
+	}
+
+	/**
+	 * Encode as part of an existing encode context.
+	 *
+	 * @param encoder
+	 */
+	public final void wireEncode(TlvEncoder encoder) {
+		int saveLength = encoder.getLength();
+		encoder.writeNonNegativeIntegerTlv(TLV_N_OUT_BYTES, outBytes);
+		encoder.writeNonNegativeIntegerTlv(TLV_N_IN_BYTES, inBytes);
+		encoder.writeNonNegativeIntegerTlv(TLV_N_OUT_DATAS, outDatas);
+		encoder.writeNonNegativeIntegerTlv(TLV_N_OUT_INTERESTS, outInterests);
+		encoder.writeNonNegativeIntegerTlv(TLV_N_IN_DATAS, inDatas);
+		encoder.writeNonNegativeIntegerTlv(TLV_N_IN_INTERESTS, inInterests);
+		encoder.writeNonNegativeIntegerTlv(TLV_LINK_TYPE, linkType.getNumericValue());
+		encoder.writeNonNegativeIntegerTlv(TLV_FACE_PERSISTENCY, facePersistency.getNumericValue());
+		encoder.writeNonNegativeIntegerTlv(TLV_FACE_SCOPE, faceScope.getNumericValue());
+		encoder.writeOptionalNonNegativeIntegerTlv(TLV_EXPIRATION_PERIOD, expirationPeriod);
+		encoder.writeBlobTlv(TLV_LOCAL_URI, new Blob(localUri).buf());
+		encoder.writeBlobTlv(TLV_URI, new Blob(uri).buf());
+		encoder.writeNonNegativeIntegerTlv(TLV_FACE_ID, faceId);
+		encoder.writeTypeAndLength(TLV_FACE_STATUS, encoder.getLength() - saveLength);
+	}
+
+	/**
+	 * Decode the input from its TLV format.
+	 *
+	 * @param input The input buffer to decode. This reads from position() to
+	 * limit(), but does not change the position.
+	 * @throws net.named_data.jndn.encoding.EncodingException
+	 */
+	public final void wireDecode(ByteBuffer input) throws EncodingException {
+		TlvDecoder decoder = new TlvDecoder(input);
+		wireDecode(decoder);
+	}
+
+	/**
+	 * Decode as part of an existing decode context.
+	 *
+	 * @param decoder
+	 * @throws EncodingException
+	 */
+	@Override
+	public void wireDecode(TlvDecoder decoder) throws EncodingException {
+		int endOffset = decoder.readNestedTlvsStart(TLV_FACE_STATUS);
+		// parse
+		this.faceId = (int) decoder.readNonNegativeIntegerTlv(TLV_FACE_ID);
+		Blob uri_ = new Blob(decoder.readBlobTlv(TLV_URI), true); // copy because buffer is immutable
+		this.uri = uri_.toString();
+		Blob localUri_ = new Blob(decoder.readBlobTlv(TLV_LOCAL_URI), true); // copy because buffer is immutable
+		this.localUri = localUri_.toString();
+		this.expirationPeriod = (int) decoder.readOptionalNonNegativeIntegerTlv(TLV_EXPIRATION_PERIOD, endOffset);
+		this.faceScope = FaceScope.values()[(int) decoder.readNonNegativeIntegerTlv(TLV_FACE_SCOPE)];
+		this.facePersistency = FacePersistency.values()[(int) decoder.readNonNegativeIntegerTlv(TLV_FACE_PERSISTENCY)];
+		this.linkType = LinkType.values()[(int) decoder.readNonNegativeIntegerTlv(TLV_LINK_TYPE)];
+		this.inInterests = (int) decoder.readNonNegativeIntegerTlv(TLV_N_IN_INTERESTS);
+		this.inDatas = (int) decoder.readNonNegativeIntegerTlv(TLV_N_IN_DATAS);
+		this.outInterests = (int) decoder.readNonNegativeIntegerTlv(TLV_N_OUT_INTERESTS);
+		this.outDatas = (int) decoder.readNonNegativeIntegerTlv(TLV_N_OUT_DATAS);
+		this.inBytes = (int) decoder.readNonNegativeIntegerTlv(TLV_N_IN_BYTES);
+		this.outBytes = (int) decoder.readNonNegativeIntegerTlv(TLV_N_OUT_BYTES);
+		decoder.finishNestedTlvs(endOffset);
+	}
+
+	/**
+	 * Get face ID
+	 *
+	 * @return
+	 */
+	public int getFaceId() {
+		return faceId;
+	}
+
+	/**
+	 * Set face ID
+	 * 
+	 * @param faceId 
+	 */
+	public void setFaceId(int faceId) {
+		this.faceId = faceId;
+	}
+
+	/**
+	 * Get face ID
+	 *
+	 * @return
+	 */
+	public String getUri() {
+		return uri;
+	}
+
+	/**
+	 * Set URI
+	 * 
+	 * @param uri 
+	 */
+	public void setUri(String uri) {
+		this.uri = uri;
+	}
+
+	/**
+	 * Get face ID
+	 *
+	 * @return
+	 */
+	public String getLocalUri() {
+		return localUri;
+	}
+
+	/**
+	 * Set local URI
+	 * @param localUri 
+	 */
+	public void setLocalUri(String localUri) {
+		this.localUri = localUri;
+	}
+
+	/**
+	 * Get expiration period
+	 *
+	 * @return
+	 */
+	public int getExpirationPeriod() {
+		return expirationPeriod;
+	}
+
+	/**
+	 * Set expiration period
+	 *
+	 * @param expirationPeriod
+	 */
+	public void setExpirationPeriod(int expirationPeriod) {
+		this.expirationPeriod = expirationPeriod;
+	}
+
+	/**
+	 * Get face scope value
+	 *
+	 * @return
+	 */
+	public FaceScope getFaceScope() {
+		return faceScope;
+	}
+
+	/**
+	 * Set face scope value
+	 *
+	 * @param faceScope
+	 */
+	public void setFaceScope(FaceScope faceScope) {
+		this.faceScope = faceScope;
+	}
+
+	/**
+	 * Get face persistency value
+	 *
+	 * @return
+	 */
+	public FacePersistency getFacePersistency() {
+		return facePersistency;
+	}
+
+	/**
+	 * Set face persistency value
+	 *
+	 * @param facePersistency
+	 */
+	public void setFacePersistency(FacePersistency facePersistency) {
+		this.facePersistency = facePersistency;
+	}
+
+	/**
+	 * Get link type
+	 *
+	 * @return
+	 */
+	public LinkType getLinkType() {
+		return linkType;
+	}
+
+	/**
+	 * Set link type
+	 *
+	 * @param linkType
+	 */
+	public void setLinkType(LinkType linkType) {
+		this.linkType = linkType;
+	}
+
+	/**
+	 * Get number of received Interest packets
+	 *
+	 * @return
+	 */
+	public int getInInterests() {
+		return inInterests;
+	}
+
+	/**
+	 * Set number of received Interest packets
+	 *
+	 * @param inInterests
+	 */
+	public void setInInterests(int inInterests) {
+		this.inInterests = inInterests;
+	}
+
+	/**
+	 * Get number of sent Interest packets
+	 *
+	 * @return
+	 */
+	public int getOutInterests() {
+		return outInterests;
+	}
+
+	/**
+	 * Set number of sent Interest packets
+	 *
+	 * @param outInterests
+	 */
+	public void setOutInterests(int outInterests) {
+		this.outInterests = outInterests;
+	}
+
+	/**
+	 * Get number of received Data packets
+	 *
+	 * @return
+	 */
+	public int getInDatas() {
+		return inDatas;
+	}
+
+	/**
+	 * Set number of received Data packets
+	 *
+	 * @param inDatas
+	 */
+	public void setInDatas(int inDatas) {
+		this.inDatas = inDatas;
+	}
+
+	/**
+	 * Get number of sent Data packets
+	 *
+	 * @return
+	 */
+	public int getOutDatas() {
+		return outDatas;
+	}
+
+	/**
+	 * Set number of sent Data packets
+	 *
+	 * @param outDatas
+	 */
+	public void setOutDatas(int outDatas) {
+		this.outDatas = outDatas;
+	}
+
+	/**
+	 * Get number of input bytes
+	 *
+	 * @return
+	 */
+	public int getInBytes() {
+		return inBytes;
+	}
+
+	/**
+	 * Set number of input bytes
+	 *
+	 * @param inBytes
+	 */
+	public void setInBytes(int inBytes) {
+		this.inBytes = inBytes;
+	}
+
+	/**
+	 * Get number of output bytes
+	 *
+	 * @return
+	 */
+	public int getOutBytes() {
+		return outBytes;
+	}
+
+	/**
+	 * Set number of output bytes
+	 *
+	 * @param outBytes
+	 */
+	public void setOutBytes(int outBytes) {
+		this.outBytes = outBytes;
+	}
+
+	private int faceId = -1;
+	private String uri = ""; // can't use URI because some are invalid syntax
+	private String localUri = ""; // can't use URI because some are invalid syntax
+	private int expirationPeriod = 0;
+	private FaceScope faceScope = FaceScope.LOCAL;
+	private FacePersistency facePersistency = FacePersistency.ON_DEMAND;
+	private LinkType linkType = LinkType.POINT_TO_POINT;
+	private int inInterests = 0;
+	private int outInterests = 0;
+	private int inDatas = 0;
+	private int outDatas = 0;
+	private int inBytes = 0;
+	private int outBytes = 0;
+}
diff --git a/src/main/java/com/intel/jndn/management/types/FibEntry.java b/src/main/java/com/intel/jndn/management/types/FibEntry.java
new file mode 100644
index 0000000..31cadbd
--- /dev/null
+++ b/src/main/java/com/intel/jndn/management/types/FibEntry.java
@@ -0,0 +1,126 @@
+/*
+ * File name: FibEntry.java
+ * 
+ * Purpose: Represent a FibEntry returned from /localhost/nfd/fib/list; see
+ * http://redmine.named-data.net/projects/nfd/wiki/FibMgmt#FIB-Dataset
+ * 
+ * © Copyright Intel Corporation. All rights reserved.
+ * Intel Corporation, 2200 Mission College Boulevard,
+ * Santa Clara, CA 95052-8119, USA
+ */
+package com.intel.jndn.management.types;
+
+import com.intel.jndn.management.EncodingHelper;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+import net.named_data.jndn.Name;
+import net.named_data.jndn.encoding.EncodingException;
+import net.named_data.jndn.encoding.tlv.TlvDecoder;
+import net.named_data.jndn.encoding.tlv.TlvEncoder;
+import net.named_data.jndn.util.Blob;
+
+/**
+ * Represent a FibEntry returned from /localhost/nfd/fib/list; see
+ * http://redmine.named-data.net/projects/nfd/wiki/FibMgmt#FIB-Dataset
+ *
+ * @author Andrew Brown <andrew.brown@intel.com>
+ */
+public class FibEntry implements Decodable{
+
+	public final static int TLV_FIB_ENTRY = 128;
+
+	/**
+	 * Encode using a new TLV encoder.
+	 *
+	 * @return The encoded buffer.
+	 */
+	public final Blob wireEncode() {
+		TlvEncoder encoder = new TlvEncoder();
+		wireEncode(encoder);
+		return new Blob(encoder.getOutput(), false);
+	}
+
+	/**
+	 * Encode as part of an existing encode context.
+	 *
+	 * @param encoder
+	 */
+	public final void wireEncode(TlvEncoder encoder) {
+		int saveLength = encoder.getLength();
+		for (NextHopRecord record : records) {
+			record.wireEncode(encoder);
+		}
+		EncodingHelper.encodeName(name, encoder);
+		encoder.writeTypeAndLength(TLV_FIB_ENTRY, encoder.getLength() - saveLength);
+	}
+
+	/**
+	 * Decode the input from its TLV format.
+	 *
+	 * @param input The input buffer to decode. This reads from position() to
+	 * limit(), but does not change the position.
+	 * @throws EncodingException For invalid encoding.
+	 */
+	public final void wireDecode(ByteBuffer input) throws EncodingException {
+		TlvDecoder decoder = new TlvDecoder(input);
+		wireDecode(decoder);
+	}
+
+	/**
+	 * Decode as part of an existing decode context.
+	 *
+	 * @param decoder
+	 * @throws EncodingException
+	 */
+	@Override
+	public final void wireDecode(TlvDecoder decoder) throws EncodingException {
+		int endOffset = decoder.readNestedTlvsStart(TLV_FIB_ENTRY);
+		name = EncodingHelper.decodeName(decoder);
+		while (decoder.getOffset() < endOffset) {
+			NextHopRecord record = new NextHopRecord();
+			record.wireDecode(decoder);
+			records.add(record);
+		}
+		decoder.finishNestedTlvs(endOffset);
+	}
+
+	/**
+	 * Get name
+	 *
+	 * @return
+	 */
+	public Name getName() {
+		return name;
+	}
+
+	/**
+	 * Set name
+	 *
+	 * @param name
+	 */
+	public void setName(Name name) {
+		this.name = name;
+	}
+
+	/**
+	 * Get records
+	 *
+	 * @return
+	 */
+	public List<NextHopRecord> getRecords() {
+		return records;
+	}
+
+	/**
+	 * Set records
+	 *
+	 * @param records
+	 */
+	public void setRecords(List<NextHopRecord> records) {
+		this.records = records;
+	}
+
+	private Name name = new Name();
+	private List<NextHopRecord> records = new ArrayList<>();
+}
diff --git a/src/main/java/com/intel/jndn/management/LinkType.java b/src/main/java/com/intel/jndn/management/types/LinkType.java
similarity index 94%
rename from src/main/java/com/intel/jndn/management/LinkType.java
rename to src/main/java/com/intel/jndn/management/types/LinkType.java
index e69513e..ea09f47 100644
--- a/src/main/java/com/intel/jndn/management/LinkType.java
+++ b/src/main/java/com/intel/jndn/management/types/LinkType.java
@@ -8,7 +8,7 @@
  * Intel Corporation, 2200 Mission College Boulevard,
  * Santa Clara, CA 95052-8119, USA
  */
-package com.intel.jndn.management;
+package com.intel.jndn.management.types;
 
 /**
  * Indicate the type of communication link; used by FaceStatus
diff --git a/src/main/java/com/intel/jndn/management/types/NextHopRecord.java b/src/main/java/com/intel/jndn/management/types/NextHopRecord.java
new file mode 100644
index 0000000..b9001ad
--- /dev/null
+++ b/src/main/java/com/intel/jndn/management/types/NextHopRecord.java
@@ -0,0 +1,117 @@
+/*
+ * File name: NextHopRecord.java
+ * 
+ * Purpose: Represent a NextHopRecord in a FibEntry; see
+ * http://redmine.named-data.net/projects/nfd/wiki/FibMgmt#FIB-Dataset
+ 
+ * 
+ * © Copyright Intel Corporation. All rights reserved.
+ * Intel Corporation, 2200 Mission College Boulevard,
+ * Santa Clara, CA 95052-8119, USA
+ */
+package com.intel.jndn.management.types;
+
+import java.nio.ByteBuffer;
+import net.named_data.jndn.encoding.EncodingException;
+import net.named_data.jndn.encoding.tlv.Tlv;
+import net.named_data.jndn.encoding.tlv.TlvDecoder;
+import net.named_data.jndn.encoding.tlv.TlvEncoder;
+import net.named_data.jndn.util.Blob;
+
+/**
+ * Represent a NextHopRecord in a FibEntry; see
+ * http://redmine.named-data.net/projects/nfd/wiki/FibMgmt#FIB-Dataset
+ *
+ * @author Andrew Brown <andrew.brown@intel.com>
+ */
+public class NextHopRecord {
+
+	public final static int TLV_NEXT_HOP_RECORD = 129;
+
+	/**
+	 * Encode using a new TLV encoder.
+	 *
+	 * @return The encoded buffer.
+	 */
+	public final Blob wireEncode() {
+		TlvEncoder encoder = new TlvEncoder();
+		wireEncode(encoder);
+		return new Blob(encoder.getOutput(), false);
+	}
+
+	/**
+	 * Encode as part of an existing encode context.
+	 *
+	 * @param encoder
+	 */
+	public final void wireEncode(TlvEncoder encoder) {
+		int saveLength = encoder.getLength();
+		encoder.writeNonNegativeIntegerTlv(Tlv.ControlParameters_Cost, cost);
+		encoder.writeNonNegativeIntegerTlv(Tlv.ControlParameters_FaceId, faceId);
+		encoder.writeTypeAndLength(TLV_NEXT_HOP_RECORD, encoder.getLength() - saveLength);
+	}
+
+	/**
+	 * Decode the input from its TLV format.
+	 *
+	 * @param input The input buffer to decode. This reads from position() to
+	 * limit(), but does not change the position.
+	 * @throws EncodingException For invalid encoding.
+	 */
+	public final void wireDecode(ByteBuffer input) throws EncodingException {
+		TlvDecoder decoder = new TlvDecoder(input);
+		wireDecode(decoder);
+	}
+
+	/**
+	 * Decode as part of an existing decode context.
+	 *
+	 * @param decoder
+	 * @throws EncodingException
+	 */
+	public final void wireDecode(TlvDecoder decoder) throws EncodingException {
+		int endOffset = decoder.readNestedTlvsStart(TLV_NEXT_HOP_RECORD);
+		this.faceId = (int) decoder.readNonNegativeIntegerTlv(Tlv.ControlParameters_FaceId);
+		this.cost = (int) decoder.readNonNegativeIntegerTlv(Tlv.ControlParameters_Cost);
+		decoder.finishNestedTlvs(endOffset);
+	}
+
+	/**
+	 * Get face ID
+	 *
+	 * @return
+	 */
+	public int getFaceId() {
+		return faceId;
+	}
+
+	/**
+	 * Set face ID
+	 *
+	 * @param faceId
+	 */
+	public void setFaceId(int faceId) {
+		this.faceId = faceId;
+	}
+
+	/**
+	 * Get cost
+	 *
+	 * @return
+	 */
+	public int getCost() {
+		return cost;
+	}
+
+	/**
+	 * Set cost
+	 *
+	 * @param cost
+	 */
+	public void setCost(int cost) {
+		this.cost = cost;
+	}
+
+	private int faceId;
+	private int cost;
+}
diff --git a/src/main/java/com/intel/jndn/management/types/RibEntry.java b/src/main/java/com/intel/jndn/management/types/RibEntry.java
new file mode 100644
index 0000000..ac53810
--- /dev/null
+++ b/src/main/java/com/intel/jndn/management/types/RibEntry.java
@@ -0,0 +1,131 @@
+/*
+ * File name: RibEntry.java
+ * 
+ * Purpose: Represent a FaceStatus object from /localhost/nfd/faces/list;
+ * see http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt for details
+ * 
+ * © Copyright Intel Corporation. All rights reserved.
+ * Intel Corporation, 2200 Mission College Boulevard,
+ * Santa Clara, CA 95052-8119, USA
+ */
+package com.intel.jndn.management.types;
+
+import com.intel.jndn.management.EncodingHelper;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+import net.named_data.jndn.Name;
+import net.named_data.jndn.encoding.EncodingException;
+import net.named_data.jndn.encoding.tlv.TlvDecoder;
+import net.named_data.jndn.encoding.tlv.TlvEncoder;
+import net.named_data.jndn.util.Blob;
+
+/**
+ * Represent a entry in the RIB; see
+ * http://redmine.named-data.net/projects/nfd/wiki/RibMgmt#RIB-Dataset for
+ * details
+ *
+ * @author Andrew Brown <andrew.brown@intel.com>
+ */
+public class RibEntry implements Decodable{
+
+	/**
+	 * TLV type, see
+	 * http://redmine.named-data.net/projects/nfd/wiki/RibMgmt#TLV-TYPE-assignments
+	 */
+	public final static int TLV_RIB_ENTRY = 128;
+
+	/**
+	 * Encode using a new TLV encoder.
+	 *
+	 * @return The encoded buffer.
+	 */
+	public final Blob wireEncode() {
+		TlvEncoder encoder = new TlvEncoder();
+		wireEncode(encoder);
+		return new Blob(encoder.getOutput(), false);
+	}
+
+	/**
+	 * Encode as part of an existing encode context.
+	 *
+	 * @param encoder
+	 */
+	public final void wireEncode(TlvEncoder encoder) {
+		int saveLength = encoder.getLength();
+		for (Route route : routes) {
+			route.wireEncode(encoder);
+		}
+		EncodingHelper.encodeName(name, encoder);
+		encoder.writeTypeAndLength(TLV_RIB_ENTRY, encoder.getLength() - saveLength);
+	}
+
+	/**
+	 * Decode the input from its TLV format.
+	 *
+	 * @param input The input buffer to decode. This reads from position() to
+	 * limit(), but does not change the position.
+	 * @throws EncodingException For invalid encoding.
+	 */
+	public final void wireDecode(ByteBuffer input) throws EncodingException {
+		TlvDecoder decoder = new TlvDecoder(input);
+		wireDecode(decoder);
+	}
+
+	/**
+	 * Decode as part of an existing decode context.
+	 *
+	 * @param decoder
+	 * @throws EncodingException
+	 */
+	@Override
+	public final void wireDecode(TlvDecoder decoder) throws EncodingException {
+		int endOffset = decoder.readNestedTlvsStart(TLV_RIB_ENTRY);
+		name = EncodingHelper.decodeName(decoder);
+		while (decoder.getOffset() < endOffset) {
+			Route route = new Route();
+			route.wireDecode(decoder);
+			routes.add(route);
+		}
+		decoder.finishNestedTlvs(endOffset);
+	}
+
+	/**
+	 * Get name
+	 *
+	 * @return
+	 */
+	public Name getName() {
+		return name;
+	}
+
+	/**
+	 * Set name
+	 *
+	 * @param name
+	 */
+	public void setName(Name name) {
+		this.name = name;
+	}
+
+	/**
+	 * Get routes
+	 *
+	 * @return
+	 */
+	public List<Route> getRoutes() {
+		return routes;
+	}
+
+	/**
+	 * Set routes
+	 *
+	 * @param routes
+	 */
+	public void setRoutes(List<Route> routes) {
+		this.routes = routes;
+	}
+
+	private Name name = new Name();
+	private List<Route> routes = new ArrayList<>();
+}
diff --git a/src/main/java/com/intel/jndn/management/types/Route.java b/src/main/java/com/intel/jndn/management/types/Route.java
new file mode 100644
index 0000000..2cbb247
--- /dev/null
+++ b/src/main/java/com/intel/jndn/management/types/Route.java
@@ -0,0 +1,186 @@
+/*
+ * File name: Route.java
+ * 
+ * Purpose: Represent a Route object from /localhost/nfd/rib/list; see
+ * http://redmine.named-data.net/projects/nfd/wiki/RibMgmt#RIB-Dataset for
+ * details.
+ * 
+ * © Copyright Intel Corporation. All rights reserved.
+ * Intel Corporation, 2200 Mission College Boulevard,
+ * Santa Clara, CA 95052-8119, USA
+ */
+package com.intel.jndn.management.types;
+
+import net.named_data.jndn.encoding.tlv.Tlv;
+import java.nio.ByteBuffer;
+import net.named_data.jndn.ForwardingFlags;
+import net.named_data.jndn.encoding.EncodingException;
+import net.named_data.jndn.encoding.tlv.TlvDecoder;
+import net.named_data.jndn.encoding.tlv.TlvEncoder;
+import net.named_data.jndn.util.Blob;
+
+/**
+ * Represent a Route object from /localhost/nfd/rib/list; see
+ * http://redmine.named-data.net/projects/nfd/wiki/RibMgmt#RIB-Dataset for
+ * details.
+ *
+ * @author Andrew Brown <andrew.brown@intel.com>
+ */
+public class Route {
+
+	/**
+	 * TLV type, see
+	 * http://redmine.named-data.net/projects/nfd/wiki/RibMgmt#TLV-TYPE-assignments
+	 */
+	public final static int TLV_ROUTE = 129;
+
+	/**
+	 * Encode using a new TLV encoder.
+	 *
+	 * @return The encoded buffer.
+	 */
+	public final Blob wireEncode() {
+		TlvEncoder encoder = new TlvEncoder();
+		wireEncode(encoder);
+		return new Blob(encoder.getOutput(), false);
+	}
+
+	/**
+	 * Encode as part of an existing encode context.
+	 *
+	 * @param encoder
+	 */
+	public final void wireEncode(TlvEncoder encoder) {
+		int saveLength = encoder.getLength();
+		encoder.writeOptionalNonNegativeIntegerTlv(Tlv.ControlParameters_ExpirationPeriod, faceId);
+		encoder.writeNonNegativeIntegerTlv(Tlv.ControlParameters_Flags, flags.getForwardingEntryFlags());
+		encoder.writeNonNegativeIntegerTlv(Tlv.ControlParameters_Cost, cost);
+		encoder.writeNonNegativeIntegerTlv(Tlv.ControlParameters_Origin, origin);
+		encoder.writeNonNegativeIntegerTlv(Tlv.ControlParameters_FaceId, faceId);
+		encoder.writeTypeAndLength(TLV_ROUTE, encoder.getLength() - saveLength);
+	}
+
+	/**
+	 * Decode the input from its TLV format.
+	 *
+	 * @param input The input buffer to decode. This reads from position() to
+	 * limit(), but does not change the position.
+	 * @throws net.named_data.jndn.encoding.EncodingException
+	 */
+	public final void wireDecode(ByteBuffer input) throws EncodingException {
+		TlvDecoder decoder = new TlvDecoder(input);
+		wireDecode(decoder);
+	}
+
+	/**
+	 * Decode as part of an existing decode context.
+	 *
+	 * @param decoder
+	 * @throws EncodingException
+	 */
+	public final void wireDecode(TlvDecoder decoder) throws EncodingException {
+		int endOffset = decoder.readNestedTlvsStart(TLV_ROUTE);
+		this.faceId = (int) decoder.readNonNegativeIntegerTlv(Tlv.ControlParameters_FaceId);
+		this.origin = (int) decoder.readNonNegativeIntegerTlv(Tlv.ControlParameters_Origin);
+		this.cost = (int) decoder.readNonNegativeIntegerTlv(Tlv.ControlParameters_Cost);
+		this.flags.setForwardingEntryFlags((int) decoder.readNonNegativeIntegerTlv(Tlv.ControlParameters_Flags));
+		this.expirationPeriod = (int) decoder.readOptionalNonNegativeIntegerTlv(Tlv.ControlParameters_ExpirationPeriod, endOffset);
+		decoder.finishNestedTlvs(endOffset);
+	}
+
+	/**
+	 * Get Face ID
+	 *
+	 * @return
+	 */
+	public int getFaceId() {
+		return faceId;
+	}
+
+	/**
+	 * Set Face ID
+	 *
+	 * @param faceId
+	 */
+	public void setFaceId(int faceId) {
+		this.faceId = faceId;
+	}
+
+	/**
+	 * Get origin
+	 *
+	 * @return
+	 */
+	public int getOrigin() {
+		return origin;
+	}
+
+	/**
+	 * Set origin
+	 *
+	 * @param origin
+	 */
+	public void setOrigin(int origin) {
+		this.origin = origin;
+	}
+
+	/**
+	 * Get cost
+	 *
+	 * @return
+	 */
+	public int getCost() {
+		return cost;
+	}
+
+	/**
+	 * Set cost
+	 *
+	 * @param cost
+	 */
+	public void setCost(int cost) {
+		this.cost = cost;
+	}
+
+	/**
+	 * Get flags
+	 *
+	 * @return
+	 */
+	public ForwardingFlags getFlags() {
+		return flags;
+	}
+
+	/**
+	 * Set flags
+	 *
+	 * @param flags
+	 */
+	public void setFlags(ForwardingFlags flags) {
+		this.flags = flags;
+	}
+
+	/**
+	 * Get expiration period
+	 *
+	 * @return
+	 */
+	public double getExpirationPeriod() {
+		return expirationPeriod;
+	}
+
+	/**
+	 * Set expiration period
+	 *
+	 * @param expirationPeriod
+	 */
+	public void setExpirationPeriod(double expirationPeriod) {
+		this.expirationPeriod = expirationPeriod;
+	}
+
+	private int faceId = -1;
+	private int origin = -1;
+	private int cost = -1;
+	private ForwardingFlags flags = new ForwardingFlags();
+	private double expirationPeriod = -1.0;
+}
diff --git a/src/main/java/com/intel/jndn/management/types/StatusDataset.java b/src/main/java/com/intel/jndn/management/types/StatusDataset.java
new file mode 100644
index 0000000..0117ee7
--- /dev/null
+++ b/src/main/java/com/intel/jndn/management/types/StatusDataset.java
@@ -0,0 +1,50 @@
+/*
+ * File name: StatusDataset.java
+ * 
+ * Purpose: Helper class to handle StatusDatasets, see 
+ * http://redmine.named-data.net/projects/nfd/wiki/StatusDataset
+ * 
+ * © Copyright Intel Corporation. All rights reserved.
+ * Intel Corporation, 2200 Mission College Boulevard,
+ * Santa Clara, CA 95052-8119, USA
+ */
+package com.intel.jndn.management.types;
+
+import java.util.ArrayList;
+import java.util.List;
+import net.named_data.jndn.encoding.EncodingException;
+import net.named_data.jndn.encoding.tlv.TlvDecoder;
+import net.named_data.jndn.util.Blob;
+
+/**
+ * Helper class to handle StatusDatasets, see
+ * http://redmine.named-data.net/projects/nfd/wiki/StatusDataset
+ *
+ * @author Andrew Brown <andrew.brown@intel.com>
+ */
+public class StatusDataset {
+
+	/**
+	 * Decode multiple status entries as part of a StatusDataset, see
+	 * http://redmine.named-data.net/projects/nfd/wiki/StatusDataset
+	 *
+	 * @param <T>
+	 * @param statusDataset
+	 * @param type
+	 * @return
+	 * @throws EncodingException
+	 * @throws InstantiationException
+	 * @throws IllegalAccessException
+	 */
+	public static final <T extends Decodable> List<T> wireDecode(Blob statusDataset, Class<T> type) throws EncodingException, InstantiationException, IllegalAccessException {
+		List<T> entries = new ArrayList<>();
+		int endOffset = statusDataset.size();
+		TlvDecoder decoder = new TlvDecoder(statusDataset.buf());
+		while (decoder.getOffset() < endOffset) {
+			T entry = type.newInstance();
+			entry.wireDecode(decoder);
+			entries.add(entry);
+		}
+		return entries;
+	}
+}